pi-studio 0.9.63 → 0.10.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 (53) hide show
  1. package/BUFFER-DESIGN.md +197 -0
  2. package/CHANGELOG.md +31 -0
  3. package/PRERELEASE-CHECKLIST.md +100 -0
  4. package/README.md +110 -193
  5. package/ROADMAP.md +63 -6
  6. package/WORKFLOW.md +32 -2
  7. package/assets/screenshots/dark-workspace.png +0 -0
  8. package/assets/screenshots/light-workspace.png +0 -0
  9. package/assets/screenshots/theme-zen-code.png +0 -0
  10. package/client/studio-client.js +6694 -942
  11. package/client/studio-editor-draft-helpers.js +162 -0
  12. package/client/studio-navigation-helpers.js +31 -5
  13. package/client/studio.css +460 -12
  14. package/index.ts +1178 -79
  15. package/package.json +5 -3
  16. package/shared/STUDIO_BUFFER_FOUNDATION.md +164 -0
  17. package/shared/studio-buffer-client.js +663 -0
  18. package/shared/studio-buffer-decisions.js +129 -0
  19. package/shared/studio-buffer-lineage.js +48 -0
  20. package/shared/studio-buffer-recovery-panel.js +132 -0
  21. package/shared/studio-buffer-recovery.js +181 -0
  22. package/shared/studio-buffer-server.js +700 -0
  23. package/shared/studio-buffer-store.js +227 -0
  24. package/shared/studio-buffer-switching.js +53 -0
  25. package/shared/studio-disk-revisions.js +15 -0
  26. package/shared/studio-document-entrypoints.js +38 -0
  27. package/shared/studio-document-escrow.js +147 -0
  28. package/shared/studio-document-file-claims.js +215 -0
  29. package/shared/studio-document-host-client.js +268 -0
  30. package/shared/studio-document-hosting.js +319 -0
  31. package/shared/studio-document-launch-client.js +153 -0
  32. package/shared/studio-document-open-client.js +96 -0
  33. package/shared/studio-document-open-storage.js +21 -0
  34. package/shared/studio-document-paths.js +29 -0
  35. package/shared/studio-editor-mode.js +48 -0
  36. package/shared/studio-linked-reader-ui.js +232 -0
  37. package/shared/studio-linked-reader.js +110 -0
  38. package/shared/studio-metadata-write-order.js +35 -0
  39. package/shared/studio-read-only-media.js +24 -0
  40. package/shared/studio-resource-grants.js +3 -0
  41. package/shared/studio-run-lifecycle.js +47 -0
  42. package/shared/studio-system-theme.js +9 -0
  43. package/assets/screenshots/dark-code-mode.png +0 -0
  44. package/assets/screenshots/dark-critique.png +0 -0
  45. package/assets/screenshots/dark-fenced-code.png +0 -0
  46. package/assets/screenshots/dark-focus-mode.png +0 -0
  47. package/assets/screenshots/dark-julia-fenced.png +0 -0
  48. package/assets/screenshots/dark-math.png +0 -0
  49. package/assets/screenshots/dark-mermaid.png +0 -0
  50. package/assets/screenshots/dark-zen.png +0 -0
  51. package/assets/screenshots/light-code-mode.png +0 -0
  52. package/assets/screenshots/light-fenced-code.png +0 -0
  53. package/assets/screenshots/light-math.png +0 -0
package/client/studio.css CHANGED
@@ -294,6 +294,17 @@
294
294
  filter: brightness(0.95);
295
295
  }
296
296
 
297
+ /* Oliver, 14 Oct: from the click until Stop, Run keeps its shape and colour, dimmed, and
298
+ can't be clicked, so it doesn't flash empty while Pi starts. */
299
+ #sendRunBtn.request-pending:disabled:not(.repl-secondary-action) {
300
+ background: var(--accent);
301
+ border-color: var(--accent);
302
+ color: var(--accent-contrast);
303
+ font-weight: 600;
304
+ opacity: 0.7;
305
+ cursor: progress;
306
+ }
307
+
297
308
  #sendRunBtn.request-stop-active,
298
309
  #critiqueBtn.request-stop-active,
299
310
  #showMeBtn.request-stop-active {
@@ -681,6 +692,81 @@
681
692
  min-height: 0;
682
693
  }
683
694
 
695
+ /* Development-only two-buffer switcher; no layout change when it is absent. */
696
+ .studio-buffer-switcher {
697
+ display: flex;
698
+ flex-wrap: wrap;
699
+ align-items: center;
700
+ gap: 6px 10px;
701
+ flex: 0 0 auto;
702
+ min-width: 0;
703
+ padding-bottom: 8px;
704
+ border-bottom: 1px solid var(--panel-border);
705
+ }
706
+
707
+ .studio-buffer-tabs {
708
+ display: flex;
709
+ flex: 1 1 220px;
710
+ min-width: 0;
711
+ gap: 4px;
712
+ }
713
+
714
+ .studio-buffer-tabs button {
715
+ flex: 1 1 0;
716
+ min-width: 0;
717
+ overflow: hidden;
718
+ text-overflow: ellipsis;
719
+ white-space: nowrap;
720
+ text-align: left;
721
+ }
722
+
723
+ /* Selection is a quiet fill; the shared :focus-visible rule marks keyboard focus. */
724
+ .studio-buffer-tabs button[aria-selected="true"] {
725
+ border-color: var(--control-border);
726
+ background: var(--accent-soft);
727
+ color: var(--text);
728
+ }
729
+
730
+ @media (forced-colors: active) {
731
+ .studio-buffer-tabs button[aria-selected="true"] {
732
+ border-style: dashed;
733
+ }
734
+ }
735
+
736
+ .studio-buffer-menu-anchor {
737
+ position: relative;
738
+ flex: 0 0 auto;
739
+ }
740
+
741
+ /* Same disclosure treatment as the existing toolbar menus; help belongs
742
+ inside the popup, never in another permanent row above the editor. */
743
+ .studio-buffer-menu {
744
+ position: absolute;
745
+ right: 0;
746
+ top: calc(100% + 6px);
747
+ z-index: 80;
748
+ width: min(340px, calc(100vw - 32px));
749
+ max-height: min(440px, 65vh);
750
+ overflow-y: auto;
751
+ padding: 6px;
752
+ border: 1px solid var(--control-border);
753
+ border-radius: 8px;
754
+ background: var(--panel);
755
+ box-shadow: 0 12px 30px rgba(0, 0, 0, 0.24);
756
+ }
757
+
758
+ .studio-buffer-menu[hidden] { display: none; }
759
+ .studio-buffer-menu-item + .studio-buffer-menu-item { border-top: 1px solid var(--panel-border); }
760
+ .studio-buffer-menu-item { padding: 4px; }
761
+ .studio-buffer-menu-item button { width: 100%; text-align: left; white-space: normal; }
762
+ .studio-buffer-menu-help {
763
+ padding: 4px 6px;
764
+ color: var(--muted);
765
+ font-size: 11px;
766
+ line-height: 1.4;
767
+ overflow-wrap: anywhere;
768
+ }
769
+
684
770
  .source-body {
685
771
  display: flex;
686
772
  gap: 12px;
@@ -837,6 +923,7 @@
837
923
  background: var(--studio-header-action-hover-bg, var(--panel-2));
838
924
  }
839
925
 
926
+ #sendRunBtn[hidden],
840
927
  #sendReplBtn[hidden],
841
928
  #replSendModeSelect[hidden] {
842
929
  display: none !important;
@@ -4278,6 +4365,16 @@
4278
4365
  font-size: var(--studio-working-font-size);
4279
4366
  }
4280
4367
 
4368
+ .trace-output.trace-output-code {
4369
+ white-space: pre;
4370
+ overflow-wrap: normal;
4371
+ tab-size: 4;
4372
+ }
4373
+
4374
+ .trace-section-fold { margin-top: 8px; }
4375
+ .trace-section-fold.is-error > summary { color: var(--error); }
4376
+ .trace-section-fold > summary:focus-visible { outline: 2px solid var(--studio-info-text, var(--text)); outline-offset: -2px; }
4377
+
4281
4378
  .trace-section > .trace-output {
4282
4379
  border: 1px solid var(--panel-border);
4283
4380
  border-radius: 8px;
@@ -6478,14 +6575,16 @@
6478
6575
  line-height: 1.2;
6479
6576
  }
6480
6577
 
6481
- body.studio-ui-refresh .studio-refresh-toolbar button:not(#sendRunBtn):not(#queueSteerBtn):not(#sendReplBtn):not(.request-stop-active),
6482
- body.studio-ui-refresh .studio-refresh-toolbar select {
6578
+ body.studio-ui-refresh .studio-refresh-toolbar-actions > .studio-refresh-action-line > button:not(#sendRunBtn):not(#queueSteerBtn):not(#sendReplBtn):not(.request-stop-active),
6579
+ body.studio-ui-refresh .studio-refresh-toolbar-actions > .studio-refresh-action-line > .studio-refresh-tools > button,
6580
+ body.studio-ui-refresh .studio-refresh-toolbar-actions > .studio-refresh-action-line > select {
6483
6581
  color: color-mix(in srgb, var(--text) 72%, var(--muted));
6484
6582
  font-weight: 500;
6485
6583
  }
6486
6584
 
6487
- body.studio-ui-refresh .studio-refresh-toolbar button:not(#sendRunBtn):not(#queueSteerBtn):not(#sendReplBtn):not(.request-stop-active):hover,
6488
- body.studio-ui-refresh .studio-refresh-toolbar select:not(:disabled):hover {
6585
+ body.studio-ui-refresh .studio-refresh-toolbar-actions > .studio-refresh-action-line > button:not(#sendRunBtn):not(#queueSteerBtn):not(#sendReplBtn):not(.request-stop-active):hover,
6586
+ body.studio-ui-refresh .studio-refresh-toolbar-actions > .studio-refresh-action-line > .studio-refresh-tools > button:hover,
6587
+ body.studio-ui-refresh .studio-refresh-toolbar-actions > .studio-refresh-action-line > select:not(:disabled):hover {
6489
6588
  color: var(--text);
6490
6589
  }
6491
6590
 
@@ -6529,6 +6628,10 @@
6529
6628
  }
6530
6629
 
6531
6630
  body.studio-ui-refresh .studio-refresh-menu {
6631
+ box-sizing: border-box;
6632
+ min-width: 0;
6633
+ overflow: auto;
6634
+ overflow-wrap: anywhere;
6532
6635
  position: absolute;
6533
6636
  top: calc(100% + 8px);
6534
6637
  right: 0;
@@ -6542,7 +6645,7 @@
6542
6645
  }
6543
6646
 
6544
6647
  body.studio-ui-refresh .studio-refresh-review-anchor {
6545
- position: static;
6648
+ position: relative;
6546
6649
  }
6547
6650
 
6548
6651
  body.studio-ui-refresh .studio-refresh-review-anchor .studio-refresh-menu {
@@ -6592,6 +6695,34 @@
6592
6695
  letter-spacing: 0.06em;
6593
6696
  }
6594
6697
 
6698
+ body.studio-ui-refresh details.studio-refresh-menu-section > summary {
6699
+ cursor: pointer;
6700
+ color: var(--text);
6701
+ font-size: 13px;
6702
+ font-weight: 500;
6703
+ text-transform: none;
6704
+ letter-spacing: normal;
6705
+ }
6706
+
6707
+ body.studio-ui-refresh details.studio-refresh-menu-section > summary:focus-visible {
6708
+ outline: none;
6709
+ text-decoration: underline;
6710
+ text-underline-offset: 3px;
6711
+ }
6712
+
6713
+ body:not([data-buffer-switching="1"]) .shortcuts-buffer-switching-only {
6714
+ display: none;
6715
+ }
6716
+
6717
+ body.studio-ui-refresh .studio-prompt-run-indicator {
6718
+ color: var(--muted);
6719
+ font-size: 12px;
6720
+ line-height: 20px;
6721
+ padding: 2px 0;
6722
+ background: transparent;
6723
+ border: 0;
6724
+ }
6725
+
6595
6726
  body.studio-ui-refresh .studio-refresh-menu-item {
6596
6727
  display: flex;
6597
6728
  align-items: center;
@@ -6672,21 +6803,20 @@
6672
6803
  }
6673
6804
 
6674
6805
  body.studio-ui-refresh #sendRunBtn,
6675
- body.studio-ui-refresh #queueSteerBtn,
6676
6806
  body.studio-ui-refresh #sendReplBtn {
6677
6807
  min-width: 8.6rem;
6678
6808
  }
6679
6809
 
6810
+ /* Stop is the one filled action while running; steering stays plain. */
6680
6811
  body.studio-ui-refresh #queueSteerBtn:not(:disabled) {
6681
- background: var(--accent);
6682
- border-color: var(--accent);
6683
- color: var(--accent-contrast);
6812
+ background: transparent;
6813
+ border-color: transparent;
6814
+ color: var(--accent);
6684
6815
  font-weight: 600;
6685
6816
  }
6686
6817
 
6687
6818
  body.studio-ui-refresh #queueSteerBtn:not(:disabled):hover {
6688
- background: var(--accent);
6689
- filter: brightness(0.95);
6819
+ background: var(--studio-header-action-hover-bg, var(--panel-2));
6690
6820
  }
6691
6821
 
6692
6822
  body.studio-ui-refresh .studio-refresh-review-btn.request-stop-active {
@@ -6708,6 +6838,37 @@
6708
6838
  font-weight: 700;
6709
6839
  }
6710
6840
 
6841
+ .studio-buffer-recovery-dialog {
6842
+ width: min(800px, calc(100vw - 32px));
6843
+ max-height: 90vh;
6844
+ overflow: auto;
6845
+ box-sizing: border-box;
6846
+ padding: 20px;
6847
+ border: 1px solid var(--panel-border);
6848
+ border-radius: 14px;
6849
+ background: var(--panel);
6850
+ color: var(--text);
6851
+ font: inherit;
6852
+ box-shadow: 0 24px 70px rgba(0, 0, 0, 0.48);
6853
+ }
6854
+ .studio-buffer-recovery-dialog::backdrop { background: rgba(0, 0, 0, 0.58); }
6855
+ .studio-buffer-recovery-dialog [hidden] { display: none !important; }
6856
+ .studio-buffer-recovery-dialog h2 { margin-top: 0; font-size: 18px; }
6857
+ .studio-buffer-recovery-dialog p { font-size: 13px; line-height: 1.5; overflow-wrap: anywhere; }
6858
+ .studio-buffer-recovery-dialog label { display: block; margin: 8px 0; }
6859
+ .studio-buffer-recovery-dialog select { max-width: 100%; }
6860
+ .studio-buffer-recovery-dialog textarea {
6861
+ width: 100%; height: 180px; max-height: 40vh; box-sizing: border-box; resize: vertical;
6862
+ border: 1px solid var(--control-border); border-radius: 8px; padding: 10px;
6863
+ background: var(--panel-2); color: var(--text); font: 12px var(--font-mono);
6864
+ }
6865
+ .studio-buffer-recovery-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0; }
6866
+ .studio-buffer-recovery-note { color: var(--studio-info-text, var(--muted)); }
6867
+ .studio-buffer-recovery-dialog summary { cursor: pointer; font-size: 13px; }
6868
+ .studio-buffer-recovery-dialog [data-recovery-confirmation] { display: block; border: 1px solid var(--warn-border); border-radius: 8px; padding: 12px; margin-bottom: 14px; }
6869
+ .studio-buffer-recovery-dialog [data-recovery-confirmation] h3 { margin: 0; }
6870
+ .studio-buffer-recovery-dialog [data-recovery-confirmation] button { width: auto; margin-right: 8px; }
6871
+
6711
6872
  .studio-decision-overlay {
6712
6873
  position: fixed;
6713
6874
  inset: 0;
@@ -7141,7 +7302,7 @@
7141
7302
  opacity: 0.5;
7142
7303
  }
7143
7304
 
7144
- .side-question-actions .side-question-primary {
7305
+ .side-question-actions .side-question-primary:not(:disabled) {
7145
7306
  border-color: var(--accent);
7146
7307
  background: var(--accent);
7147
7308
  color: var(--accent-contrast);
@@ -7374,3 +7535,290 @@
7374
7535
  flex-wrap: wrap;
7375
7536
  }
7376
7537
  }
7538
+
7539
+ /* Honor existing handler eligibility after controls are regrouped. */
7540
+ body.studio-ui-refresh [hidden] { display: none !important; }
7541
+ /* Dogfood workspace: two logical rows, with normal wrapping in small panes. */
7542
+ /* Room for "Running 00:00" from the start, so nothing moves when "Starting…" becomes the clock (Oliver, 14 Oct). */
7543
+ .studio-run-status { color: var(--muted); font-size: 12px; min-width: 13ch; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
7544
+ body.studio-ui-refresh #rightSectionHeader .studio-follow-button {
7545
+ color: var(--muted); border: 0; border-radius: 0; background: transparent;
7546
+ }
7547
+ body.studio-ui-refresh #rightSectionHeader .studio-follow-button.studio-refresh-chip:hover,
7548
+ body.studio-ui-refresh #rightSectionHeader .studio-follow-button.studio-refresh-chip.is-open { color: var(--muted); background: transparent; }
7549
+ body.studio-ui-refresh #rightSectionHeader .studio-follow-button:focus-visible {
7550
+ outline: none; text-decoration: underline; text-underline-offset: 3px;
7551
+ }
7552
+ .studio-operation-notices { padding: 4px 12px; font-size: 12px; color: var(--warn); }
7553
+ .studio-operation-notice { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin: 3px 0; overflow-wrap: anywhere; }
7554
+ .studio-operation-notice button { font-size: 12px; padding: 1px 4px; }
7555
+ body.studio-workspace-layout .studio-workspace-row-one { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 6px 12px; }
7556
+ body.studio-workspace-layout .studio-workspace-tabs-host { min-width: 0; }
7557
+ body.studio-workspace-layout .studio-buffer-tabs { gap: 16px; flex-wrap: wrap; }
7558
+ body.studio-workspace-layout #leftSectionHeader .studio-buffer-tabs > .studio-buffer-menu-anchor > button {
7559
+ border: 0; border-radius: 0; background: transparent; padding: 3px 0; font-size: 14px; font-weight: 500; line-height: 20px; text-align: left; white-space: nowrap;
7560
+ }
7561
+ body.studio-workspace-layout #leftSectionHeader .studio-buffer-tabs > .studio-buffer-menu-anchor > button[aria-selected="true"] {
7562
+ background: transparent; box-shadow: none; color: var(--text); font-weight: 700;
7563
+ }
7564
+ body.studio-workspace-layout #leftSectionHeader .studio-buffer-tabs > .studio-buffer-menu-anchor > button[aria-selected="false"] {
7565
+ color: var(--muted);
7566
+ }
7567
+ /* Natural widths with a small gap (Oliver, trial48): the unselected label may shift a little on switching. */
7568
+ body.studio-workspace-layout .studio-workspace-file-controls { min-width: 0; margin-left: auto; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
7569
+ body.studio-workspace-layout .studio-workspace-filename { min-width: 0; max-width: min(180px, 35cqi); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 400; }
7570
+ body.studio-workspace-layout .studio-refresh-toolbar-main { display: block; }
7571
+ body.studio-workspace-layout .studio-refresh-toolbar-actions { gap: 0; min-width: 0; width: 100%; }
7572
+ body.studio-workspace-layout .studio-refresh-toolbar-actions > .studio-refresh-action-line { min-width: 0; width: 100%; }
7573
+ body.studio-workspace-layout .studio-refresh-toolbar-state:empty,
7574
+ body.studio-workspace-layout .studio-refresh-action-line:empty,
7575
+ body.studio-workspace-layout .response-options-row:empty,
7576
+ body.studio-workspace-layout .response-option-select-wrap:not(:has(select)) { display: none; }
7577
+ body.studio-workspace-layout .reference-meta .source-badge,
7578
+ body.studio-workspace-layout #historyIndexBadge { border: 0; border-radius: 0; background: transparent; }
7579
+ body.studio-workspace-layout .studio-refresh-action-line { flex-wrap: wrap; gap: 6px 10px; }
7580
+ body.studio-workspace-layout .studio-refresh-menu > button { display: block; width: 100%; text-align: left; white-space: normal; }
7581
+ body.studio-workspace-layout .response-result-row { flex-wrap: wrap; }
7582
+ body.studio-workspace-layout .side-question-intro h2,
7583
+ body.studio-workspace-layout .side-question-thread-header h2 { font-size: 1rem; font-weight: 500; }
7584
+ body.studio-workspace-layout .side-question-scope { color: var(--muted); font-size: 0.82rem; overflow-wrap: anywhere; margin: 12px 0 6px; }
7585
+ body.studio-workspace-layout .side-question-options { color: var(--muted); font-size: 0.85rem; }
7586
+ body.studio-workspace-layout .side-question-options > summary { cursor: pointer; width: fit-content; }
7587
+ body.studio-workspace-layout .side-question-message { border: 0; border-radius: 0; background: transparent; padding: 10px 0; }
7588
+ body.studio-workspace-layout .side-question-message-user { margin-left: 0; border-color: transparent; background: transparent; }
7589
+ body.studio-workspace-layout .side-question-message-label { font-weight: 500; }
7590
+ body.studio-workspace-layout .side-question-live { animation: none; color: var(--muted); }
7591
+ body.studio-workspace-layout .side-question-context-summary { background: transparent; border: 0; border-radius: 0; padding: 0; }
7592
+ body.studio-workspace-layout .side-question-activity { border: 0; border-radius: 0; background: transparent; padding: 0; }
7593
+ body.studio-workspace-layout .side-question-activity li > span { width: auto; }
7594
+
7595
+ /* The live pane keeps its dimensions and ownership beneath the reader. */
7596
+ #rightPane:has(.studio-reader-surface) { position: relative; }
7597
+ #rightPane[data-linked-reader-active="1"] > #critiqueView,
7598
+ #rightPane[data-linked-reader-active="1"] > .response-wrap,
7599
+ #rightPane[data-linked-reader-active="1"] > .reference-meta { visibility: hidden; }
7600
+ #rightPane[data-linked-reader-active="1"] > .studio-reader-toolbar { position: absolute; left: 0; right: 0; }
7601
+ .studio-reader-toolbar { position: relative; z-index: 4; flex: 0 0 auto; display: flex; flex-wrap: wrap; align-items: center; gap: 5px 10px; padding: 6px 11px; border-bottom: 1px solid var(--control-border); background: var(--panel); }
7602
+ .studio-reader-surface { position: absolute; z-index: 3; left: 0; right: 0; bottom: 0; display: flex; flex-direction: column; min-height: 0; background: var(--panel); }
7603
+ .studio-reader-toolbar[hidden], .studio-reader-surface[hidden] { display: none; }
7604
+ .studio-reader-content { flex: 1 1 auto; min-height: 0; }
7605
+ .studio-reader-toolbar button.studio-reader-action { min-width: 0; max-width: 100%; padding: 2px 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); background: transparent; border: 0; border-radius: 0; font-size: 12px; line-height: 20px; }
7606
+ .studio-reader-toolbar button.studio-reader-action:hover:not(:disabled) { color: var(--accent); background: transparent; }
7607
+ .studio-reader-toolbar button.studio-reader-action:disabled { color: var(--muted); }
7608
+ .studio-reader-toolbar button.studio-reader-action:focus-visible { outline: none; text-decoration: underline; text-underline-offset: 3px; }
7609
+ .studio-reader-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 5px 10px; max-width: 100%; margin-left: auto; }
7610
+ .studio-reader-snapshot { max-width: 100%; color: var(--muted); font-size: 11px; }
7611
+
7612
+ /* Trial48 style sweep (finding 3): actions and state are plain text, a fill marks only an
7613
+ enabled primary action, and keyboard focus is an underline rather than a box. */
7614
+ body.studio-workspace-layout #scratchpadBtn.has-content,
7615
+ body.studio-workspace-layout #reviewNotesBtn.has-content,
7616
+ body.studio-workspace-layout #reviewNotesBtn.is-active,
7617
+ body.studio-workspace-layout #outlineBtn.is-active,
7618
+ body.studio-workspace-layout .source-badge,
7619
+ body.studio-workspace-layout .trace-summary-badge,
7620
+ body.studio-workspace-layout .trace-summary-status,
7621
+ body.studio-workspace-layout .trace-entry-status,
7622
+ body.studio-workspace-layout .trace-kind-badge,
7623
+ body.studio-workspace-layout .trace-filter-btn,
7624
+ body.studio-workspace-layout .trace-filter-btn.is-active,
7625
+ body.studio-workspace-layout .trace-action-btn,
7626
+ body.studio-workspace-layout .files-toolbar-actions button,
7627
+ body.studio-workspace-layout .files-actions button,
7628
+ body.studio-workspace-layout .repl-journal-actions button,
7629
+ body.studio-workspace-layout .repl-journal-chip,
7630
+ body.studio-workspace-layout .repl-start-btn,
7631
+ body.studio-workspace-layout .side-question-actions .side-question-primary:disabled {
7632
+ border-color: transparent;
7633
+ background: transparent;
7634
+ box-shadow: none;
7635
+ }
7636
+ body.studio-workspace-layout .source-badge,
7637
+ body.studio-workspace-layout .trace-summary-badge,
7638
+ body.studio-workspace-layout .trace-summary-status,
7639
+ body.studio-workspace-layout .trace-entry-status,
7640
+ body.studio-workspace-layout .trace-kind-badge,
7641
+ body.studio-workspace-layout .repl-journal-chip { border-radius: 0; padding-left: 0; padding-right: 0; }
7642
+ body.studio-workspace-layout .trace-summary-badge { color: var(--text); font-size: 13px; font-weight: 700; }
7643
+ body.studio-workspace-layout .trace-filter-btn.is-active { color: var(--accent); }
7644
+ body.studio-workspace-layout #scratchpadBtn.has-content:not(:disabled):hover,
7645
+ body.studio-workspace-layout #reviewNotesBtn.has-content:not(:disabled):hover,
7646
+ body.studio-workspace-layout #reviewNotesBtn.is-active:not(:disabled):hover,
7647
+ body.studio-workspace-layout #outlineBtn.is-active:not(:disabled):hover,
7648
+ body.studio-workspace-layout .trace-filter-btn:not(:disabled):hover,
7649
+ body.studio-workspace-layout .trace-action-btn:not(:disabled):hover,
7650
+ body.studio-workspace-layout .files-toolbar-actions button:not(:disabled):hover,
7651
+ body.studio-workspace-layout .files-actions button:not(:disabled):hover,
7652
+ body.studio-workspace-layout .repl-journal-actions button:not(:disabled):hover,
7653
+ body.studio-workspace-layout .repl-start-btn:not(:disabled):hover {
7654
+ border-color: transparent;
7655
+ background: var(--studio-header-action-hover-bg, var(--panel-2));
7656
+ }
7657
+ body.studio-workspace-layout .trace-filter-btn:focus-visible,
7658
+ body.studio-workspace-layout .trace-action-btn:focus-visible,
7659
+ body.studio-workspace-layout .files-toolbar-actions button:focus-visible,
7660
+ body.studio-workspace-layout .files-actions button:focus-visible,
7661
+ body.studio-workspace-layout .repl-journal-actions button:focus-visible,
7662
+ body.studio-workspace-layout .repl-start-btn:focus-visible,
7663
+ body.studio-workspace-layout .side-question-options > summary:focus-visible {
7664
+ outline: none;
7665
+ text-decoration: underline;
7666
+ text-underline-offset: 3px;
7667
+ }
7668
+ body.studio-workspace-layout .side-question-composer-label textarea:focus,
7669
+ body.studio-workspace-layout .side-question-composer-label textarea:focus-visible {
7670
+ outline: none;
7671
+ box-shadow: none;
7672
+ border-color: var(--control-border);
7673
+ }
7674
+
7675
+ /* Oliver, 10 Oct: teal means Run Prompt only. Send to REPL and Quick send's buttons are
7676
+ plain, and the Quick send box shows focus without a ring. */
7677
+ body.studio-workspace-layout #sendReplBtn,
7678
+ body.studio-workspace-layout .repl-quick-actions button {
7679
+ min-width: 0;
7680
+ border-color: transparent;
7681
+ background: transparent;
7682
+ box-shadow: none;
7683
+ color: var(--text);
7684
+ font-weight: 500;
7685
+ }
7686
+ body.studio-workspace-layout #sendReplBtn:disabled,
7687
+ body.studio-workspace-layout .repl-quick-actions button:disabled { color: var(--muted); }
7688
+ body.studio-workspace-layout #sendReplBtn:not(:disabled):hover,
7689
+ body.studio-workspace-layout .repl-quick-actions button:not(:disabled):hover {
7690
+ border-color: transparent;
7691
+ background: var(--studio-header-action-hover-bg, var(--panel-2));
7692
+ }
7693
+ body.studio-workspace-layout #sendReplBtn:focus-visible,
7694
+ body.studio-workspace-layout .repl-quick-actions button:focus-visible {
7695
+ outline: none;
7696
+ text-decoration: underline;
7697
+ text-underline-offset: 3px;
7698
+ }
7699
+ body.studio-workspace-layout .repl-quick-composer textarea:focus,
7700
+ body.studio-workspace-layout .repl-quick-composer textarea:focus-visible {
7701
+ outline: none;
7702
+ box-shadow: none;
7703
+ border-color: var(--control-border);
7704
+ }
7705
+
7706
+ /* Oliver, 10 Oct: the side thread's model and Thinking sit beside its Ask button. */
7707
+ body.studio-workspace-layout .side-question-actions { align-items: center; }
7708
+ body.studio-workspace-layout .side-question-run-settings { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; color: var(--muted); font-size: 0.82rem; }
7709
+ body.studio-workspace-layout .side-question-run-settings label { display: inline-flex; align-items: center; gap: 6px; }
7710
+ body.studio-workspace-layout .side-question-thread-header > div:empty { flex: 1 1 auto; }
7711
+
7712
+ /* Oliver, 10 Oct: slightly less space between toolbar items, so View fits on a laptop. */
7713
+ body.studio-workspace-layout .studio-refresh-toolbar-actions .studio-refresh-action-line { column-gap: 8px; }
7714
+ body.studio-workspace-layout .studio-refresh-toolbar-actions .studio-refresh-action-line button:not(#sendRunBtn):not(#queueSteerBtn):not(#sendReplBtn):not(.request-stop-active) { padding-left: 6px; padding-right: 6px; }
7715
+
7716
+ /* Row 2 mirrors row 1: tools sit on the right and wrap on the right (Oliver, 10 Oct). */
7717
+ body.studio-workspace-layout .studio-refresh-tools { margin-left: auto; display: inline-flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 6px 8px; min-width: 0; }
7718
+
7719
+ /* Files, new layout (Oliver, 10 Oct): one plain location line, plain rows, and row actions only
7720
+ on the row under the mouse or keyboard focus. They overlay the row's end, so names keep their width. */
7721
+ body.studio-workspace-layout .files-location-line { display: flex; align-items: center; gap: 6px; min-width: 0; padding-bottom: 6px; border-bottom: 1px solid var(--panel-border); }
7722
+ body.studio-workspace-layout .files-location-line .files-up { flex: 0 0 auto; min-height: 0; padding: 0 8px; border-color: transparent; background: transparent; font-size: 16px; line-height: 1.5; }
7723
+ body.studio-workspace-layout .files-location-line .files-up:not(:disabled):hover { background: var(--studio-header-action-hover-bg, var(--panel-2)); }
7724
+ body.studio-workspace-layout .files-location-line .files-path { flex: 1 1 auto; min-width: 0; color: var(--text); font-family: var(--font-ui); font-size: 13px; }
7725
+ body.studio-workspace-layout .files-location-tools { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; }
7726
+ body.studio-workspace-layout .files-location-line :is(.files-sort-select, .files-location-select) { border-color: transparent; background: transparent; }
7727
+ body.studio-workspace-layout .files-panel-workspace .files-list { gap: 0; grid-template-columns: minmax(0, 1fr); }
7728
+ body.studio-workspace-layout .files-panel-workspace .files-row { position: relative; padding: 3px 6px; border-color: transparent; border-radius: 6px; background: transparent; }
7729
+ body.studio-workspace-layout .files-panel-workspace .files-row { min-width: 0; } /* long names shorten; rows never outgrow the pane */
7730
+ body.studio-workspace-layout .files-panel-workspace .files-row:is(:hover, :focus-within) { border-color: transparent; background: var(--studio-header-action-hover-bg, var(--panel-2)); }
7731
+ body.studio-workspace-layout .files-panel-workspace .files-row .files-actions { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); padding-left: 10px;
7732
+ background: var(--studio-header-action-hover-bg, var(--panel-2)); visibility: hidden; }
7733
+ body.studio-workspace-layout .files-panel-workspace .files-row:is(:hover, :focus-within) .files-actions,
7734
+ body.studio-workspace-layout .files-panel-workspace .files-row:has(.files-more[open]) .files-actions { visibility: visible; }
7735
+ body.studio-workspace-layout .files-panel-workspace .files-row:has(.files-more[open]) { z-index: 5; }
7736
+
7737
+ /* Undo for Add to Prompt, beside its status message (Oliver, 11 Oct). */
7738
+ .studio-status-undo { margin-left: 8px; padding: 0 2px; min-height: 0; border: 0; background: transparent; color: inherit; font: inherit; cursor: pointer;
7739
+ text-decoration: underline; text-underline-offset: 2px; }
7740
+ .studio-status-undo[hidden] { display: none; }
7741
+
7742
+ /* Trial48 wording (finding 5): menus show labels only; status has no dot. */
7743
+ body.studio-workspace-layout .studio-buffer-menu-help { display: none; }
7744
+ body.studio-workspace-layout #syncBadge::before { display: none; }
7745
+
7746
+ /* Candidate50 trial: the panel toggles are plain in their default state too (light theme showed boxes). */
7747
+ body.studio-workspace-layout #reviewNotesBtn,
7748
+ body.studio-workspace-layout #outlineBtn,
7749
+ body.studio-workspace-layout #scratchpadBtn { border-color: transparent; background: transparent; box-shadow: none; }
7750
+ body.studio-workspace-layout #reviewNotesBtn:not(:disabled):hover,
7751
+ body.studio-workspace-layout #outlineBtn:not(:disabled):hover,
7752
+ body.studio-workspace-layout #scratchpadBtn:not(:disabled):hover { background: var(--studio-header-action-hover-bg, var(--panel-2)); }
7753
+
7754
+ /* Oliver, 8 Oct: the remaining bordered buttons are plain too (polish item 13). Annotate response
7755
+ keeps its fill only as the enabled primary; header buttons show keyboard focus as an underline. */
7756
+ body.studio-workspace-layout #responseActions button:not(#annotateResponseBtn),
7757
+ body.studio-workspace-layout #responseActions #annotateResponseBtn:disabled,
7758
+ body.studio-workspace-layout .studio-operation-notice button {
7759
+ border-color: transparent;
7760
+ background: transparent;
7761
+ box-shadow: none;
7762
+ }
7763
+ body.studio-workspace-layout #responseActions button:not(#annotateResponseBtn):not(:disabled):hover,
7764
+ body.studio-workspace-layout .studio-operation-notice button:not(:disabled):hover {
7765
+ background: var(--studio-header-action-hover-bg, var(--panel-2));
7766
+ }
7767
+ body.studio-workspace-layout #responseActions button:focus-visible,
7768
+ body.studio-workspace-layout .studio-operation-notice button:focus-visible,
7769
+ body.studio-workspace-layout #leftSectionHeader button:focus-visible,
7770
+ body.studio-workspace-layout #rightSectionHeader button:focus-visible {
7771
+ outline: none;
7772
+ text-decoration: underline;
7773
+ text-underline-offset: 3px;
7774
+ }
7775
+
7776
+ /* Batch B: Files rows keep the name visible; Edit / Use as Prompt; the rest under ⋯. */
7777
+ body.studio-workspace-layout .files-row { display: flex; align-items: center; gap: 8px; }
7778
+ body.studio-workspace-layout .files-row .files-open-btn { flex: 1 1 auto; min-width: 0; display: flex; align-items: baseline; gap: 8px; text-align: left; }
7779
+ body.studio-workspace-layout .files-row .files-name { min-width: 6em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 0 1 auto; }
7780
+ body.studio-workspace-layout .files-row .files-meta { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 0; color: var(--muted); }
7781
+ body.studio-workspace-layout .files-row .files-actions { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 2px; }
7782
+ body.studio-workspace-layout .files-more { position: relative; }
7783
+ body.studio-workspace-layout .files-more > summary { list-style: none; cursor: pointer; padding: 2px 8px; border-radius: 6px; color: var(--muted); }
7784
+ body.studio-workspace-layout .files-more > summary::-webkit-details-marker { display: none; }
7785
+ body.studio-workspace-layout .files-more > summary:hover { background: var(--studio-header-action-hover-bg, var(--panel-2)); color: var(--text); }
7786
+ body.studio-workspace-layout .files-more > summary:focus-visible { outline: none; text-decoration: underline; text-underline-offset: 3px; }
7787
+ body.studio-workspace-layout .files-more-menu { position: absolute; right: 0; top: calc(100% + 4px); z-index: 6; min-width: 170px; display: flex; flex-direction: column;
7788
+ padding: 4px; background: var(--panel); border: 1px solid var(--panel-border); border-radius: 8px; box-shadow: var(--panel-shadow); }
7789
+ body.studio-workspace-layout .files-more-menu button { text-align: left; border-color: transparent; background: transparent; }
7790
+ body.studio-workspace-layout .files-more-menu button:hover { background: var(--studio-header-action-hover-bg, var(--panel-2)); }
7791
+ /* Picker mode: one obvious action per row — click the name. */
7792
+ body.studio-workspace-layout .files-picking .files-actions { display: none; }
7793
+ body.studio-workspace-layout .files-picking :is(.files-kind-pdf, .files-kind-image) .files-open-btn,
7794
+ body.studio-workspace-layout .files-picking-copy .files-kind-office .files-open-btn { opacity: 0.45; }
7795
+ body.studio-workspace-layout .files-pick-strip { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding: 8px 10px; margin-bottom: 8px;
7796
+ border-bottom: 1px solid var(--panel-border); background: var(--panel-2); }
7797
+ /* The strip and its Cancel stay in view while the list scrolls (Oliver, 10 Oct). */
7798
+ body.studio-workspace-layout .files-pick-strip { position: sticky; top: 0; z-index: 3; }
7799
+ body.studio-workspace-layout .files-pick-what { font-weight: 600; }
7800
+ /* REPL More stacks plain items like the other menus (Oliver, 10 Oct). */
7801
+ body.studio-workspace-layout .repl-more-menu { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 2px; width: max-content; min-width: 180px; max-width: min(340px, 80vw); }
7802
+ body.studio-workspace-layout .repl-more-menu button { display: block; width: 100%; min-height: 0; padding: 5px 8px; text-align: left; border-color: transparent; background: transparent; box-shadow: none; }
7803
+ body.studio-workspace-layout .repl-more-menu button:not(:disabled):hover { border-color: transparent; background: var(--studio-header-action-hover-bg, var(--panel-2)); }
7804
+ body.studio-workspace-layout .repl-more-menu button:disabled { color: var(--muted); }
7805
+ body.studio-workspace-layout .repl-more-menu button:focus-visible { outline: none; text-decoration: underline; text-underline-offset: 3px; }
7806
+ body.studio-workspace-layout .repl-more-send-mode { display: flex; align-items: center; gap: 6px; padding: 3px 8px 6px; margin-bottom: 2px; border-bottom: 1px solid var(--panel-border); color: var(--muted); font-size: 12px; }
7807
+ body.studio-workspace-layout .files-pick-path { flex: 1 1 180px; min-width: 0; padding: 4px 8px; border: 1px solid var(--control-border); border-radius: 6px;
7808
+ background: var(--panel); color: var(--text); font: 12px var(--font-mono); outline: none; }
7809
+ body.studio-workspace-layout .files-pick-strip button { border-color: transparent; background: transparent; }
7810
+
7811
+ /* Unsaved text: the name slot reads *Untitled*, in italics (Oliver, 8 Oct). */
7812
+ .studio-workspace-filename.is-untitled { font-style: italic; }
7813
+
7814
+ /* A named file's own menu: its full path, then the file actions (Oliver, 9 Oct). */
7815
+ body.studio-workspace-layout .studio-file-menu-path { padding: 4px 8px 6px; color: var(--muted); font-size: 0.82rem; font-weight: 400; overflow-wrap: anywhere; user-select: text; }
7816
+ /* Small buffer menus (view, file name, Add to Prompt) list their actions vertically. */
7817
+ body.studio-workspace-layout .studio-buffer-menu > button { display: block; width: 100%; text-align: left; }
7818
+
7819
+ /* Oliver, 13 Oct: every File ▾ item lines up with the rest. */
7820
+ body.studio-workspace-layout .studio-refresh-menu-item > #copyDraftBtn,
7821
+ body.studio-workspace-layout .studio-refresh-menu-item > button.studio-buffer-menu-item,
7822
+ body.studio-workspace-layout .studio-refresh-menu > button.studio-buffer-menu-item { padding: 8px 10px; }
7823
+ /* A row whose only control is hidden takes no space. */
7824
+ body.studio-workspace-layout .studio-refresh-menu-item:has(> :only-child[hidden]) { display: none; }