prreviewbuddy 0.82.4 → 0.85.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.
package/static/shell.css CHANGED
@@ -154,7 +154,8 @@
154
154
  --lh-body: 1.55;
155
155
  --lh-tight: 1.3;
156
156
 
157
- --rail-width: 268px;
157
+ --rail-full-width: 268px;
158
+ --rail-width: var(--rail-full-width);
158
159
  /* A proportion, not a number: the assistant is part of the workspace rather than a widget
159
160
  docked to its edge, so it should take a share of whatever room there is. The floor keeps it
160
161
  wide enough for a code block; the ceiling keeps the review itself the larger pane. A width
@@ -172,6 +173,8 @@
172
173
  :root[data-theme='dark'] { color-scheme: dark; }
173
174
 
174
175
  * { box-sizing: border-box; }
176
+ /* No link in the workspace is underlined, at rest or on hover: colour says it is a link. */
177
+ a { text-decoration: none; }
175
178
 
176
179
  html, body {
177
180
  height: 100%;
@@ -416,15 +419,6 @@ body > * { flex: 0 0 auto; }
416
419
  color: var(--text-tertiary, var(--text-secondary));
417
420
  opacity: 0.75;
418
421
  }
419
- .prb-feedback {
420
- color: inherit;
421
- text-decoration: underline;
422
- text-underline-offset: 2px;
423
- }
424
- .prb-feedback:hover { color: var(--text-primary); opacity: 1; }
425
- /* The words, and only the words, above phone width. The icon is the phone-width form, where the
426
- strip has no room for a text link; see the 600px block. */
427
- .prb-feedback-icon { display: none; }
428
422
 
429
423
  /* ── The global strip ──
430
424
  *
@@ -459,17 +453,9 @@ body > * { flex: 0 0 auto; }
459
453
  /* Quieter than the wordmark on a marketing page and quieter than the branch below it: at this size
460
454
  it is a mark saying which product this is, not a title. */
461
455
  .prb-strip .prb-wordmark { font-size: var(--t-body); }
462
- /* The push comes from the wordmark, so everything after it packs to the far end whether or not the
463
- narrow-window places are in flow. A `margin-left: auto` on the bell instead would put the bell
464
- beside the wordmark at every width the places are hidden, which is most of them. */
456
+ /* The push comes from the wordmark, so everything after it packs to the far end. */
465
457
  .prb-strip .prb-wordmark { margin-right: auto; }
466
458
  .prb-strip .prb-build { margin: 0; }
467
- /* The workspace places in the strip exist for the width at which the rail is hidden, and only then.
468
- Declared here, above the 860px block that reveals it: the two rules have the same specificity, so
469
- whichever comes last wins, and while this one sat at the foot of the file the media query could
470
- never take effect — the places were hidden at every width, including the only one that needed
471
- them. */
472
- .prb-header-nav { display: none; align-items: center; gap: 16px; font-size: var(--t-meta); }
473
459
 
474
460
  /* The workspace pages that are not a review: the same rail and the same one-viewport shell as a
475
461
  review page, with the content scrolling in its own pane beside it.
@@ -552,6 +538,17 @@ body > * { flex: 0 0 auto; }
552
538
  background: var(--border-strong);
553
539
  }
554
540
 
541
+ /* New review in the strip is the rail's labelled button standing in while the rail is hidden, so it
542
+ is drawn only then: below 860px and in a review's focus mode, both revealed further down. Declared
543
+ here, above the 860px block, so that block can win at equal specificity. Filled, as the rail's is:
544
+ wherever it is, it is the primary action. */
545
+ .prb-strip .prb-strip-new-review { display: none; background: var(--brand); color: var(--on-brand); }
546
+ .prb-strip .prb-strip-new-review:hover { background: var(--brand-hover); color: var(--on-brand); }
547
+ .prb-strip .prb-strip-new-review:focus-visible { outline-color: var(--brand-ink); }
548
+ /* Show sidebar: the way back from Hidden, and drawn only while the reader has hidden it. */
549
+ .prb-strip .prb-sidebar-restore { display: none; }
550
+ :root[data-sidebar-hidden] .prb-strip .prb-sidebar-restore { display: flex; }
551
+
555
552
  /* Why a control cannot be pressed, beside the control rather than inside a `title` nobody hovers
556
553
  and no keyboard reaches. Quiet as the strip is quiet: it is an explanation, not a warning. */
557
554
  .prb-strip-note {
@@ -763,7 +760,7 @@ body[data-server-stopped] .prb-shell { opacity: 0.55; pointer-events: none; }
763
760
  .prb-author::before { content: 'by'; color: var(--text-muted); }
764
761
  .prb-author-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
765
762
  .prb-author-handle { color: var(--text-muted); }
766
- a.prb-author:hover .prb-author-name { color: var(--text-primary); text-decoration: underline; }
763
+ a.prb-author:hover .prb-author-name { color: var(--text-primary); }
767
764
 
768
765
  .prb-pr-empty, .prb-pr-provenance, .prb-pr-truncated {
769
766
  font-size: var(--t-body);
@@ -780,7 +777,7 @@ a.prb-author:hover .prb-author-name { color: var(--text-primary); text-decoratio
780
777
  margin-bottom: 26px;
781
778
  }
782
779
  .prb-pr-provenance a { color: var(--brand); font-weight: 400; text-decoration: none; }
783
- .prb-pr-provenance a:hover { text-decoration: underline; }
780
+ .prb-pr-provenance a:hover { opacity: 0.8; }
784
781
  .prb-pr-title { color: var(--pane-ink); }
785
782
  .prb-pr-counts, .prb-pr-provenance time { color: var(--pane-ink-faint); font-size: var(--t-meta); }
786
783
 
@@ -851,7 +848,7 @@ a.prb-author:hover .prb-author-name { color: var(--text-primary); text-decoratio
851
848
  }
852
849
  .prb-pr-comment-meta { display: flex; gap: 8px; align-items: baseline; font-size: var(--t-meta); }
853
850
  .prb-pr-comment-meta a { color: var(--brand); font-weight: 400; text-decoration: none; }
854
- .prb-pr-comment-meta a:hover { text-decoration: underline; }
851
+ .prb-pr-comment-meta a:hover { opacity: 0.8; }
855
852
  .prb-pr-comment-meta time { color: var(--pane-ink-faint); }
856
853
  /* Someone else's words, rendered as the Markdown they wrote rather than as one flat block. Light
857
854
  pane, so literals throughout: see pane_palette.test.ts. */
@@ -1082,6 +1079,144 @@ a.prb-rail-item { text-decoration: none; }
1082
1079
  color: var(--text-primary);
1083
1080
  }
1084
1081
  .prb-rail-item:focus-visible { outline: 2px solid var(--brand-hover); outline-offset: -2px; }
1082
+
1083
+ /* New review, at the head of the workspace rows: the primary action, and the one filled thing in
1084
+ the sidebar, as the Buddy AI send button is in its pane. Everything else there stays neutral, so
1085
+ nothing competes with it. Inset so its icon lines up with the rows' icons. The focus ring is the
1086
+ brand's ink rather than its hover colour, which would vanish against the fill. */
1087
+ .prb-rail-new { padding: 0 12px 10px; }
1088
+ .prb-new-review {
1089
+ display: flex;
1090
+ align-items: center;
1091
+ gap: 12px;
1092
+ width: 100%;
1093
+ min-height: 36px;
1094
+ padding: 0 8px;
1095
+ border: 0;
1096
+ border-radius: 8px;
1097
+ background: var(--brand);
1098
+ color: var(--on-brand);
1099
+ font: inherit;
1100
+ font-weight: 600;
1101
+ text-align: left;
1102
+ cursor: pointer;
1103
+ }
1104
+ .prb-new-review svg { width: 16px; height: 16px; flex: none; }
1105
+ .prb-new-review-label { flex: 1; min-width: 0; }
1106
+ .prb-new-review-key { font: 500 var(--t-micro) / 1 ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace; color: var(--on-brand-quiet); }
1107
+ .prb-new-review:hover { background: var(--brand-hover); }
1108
+ .prb-new-review:focus-visible { outline: 2px solid var(--brand-ink); outline-offset: 2px; }
1109
+
1110
+ /* The sidebar's own toggle, the last row of its foot. Both drawings are on the page and the state
1111
+ says which shows, so pressing it changes nothing here but an attribute and its words. */
1112
+ .prb-sidebar-collapse-icon,
1113
+ .prb-sidebar-expand-icon { display: flex; }
1114
+ .prb-sidebar-expand-icon,
1115
+ :root[data-sidebar-compact] .prb-sidebar-collapse-icon { display: none; }
1116
+ :root[data-sidebar-compact] .prb-sidebar-expand-icon { display: flex; }
1117
+
1118
+ /* ── The sidebar's three states ──
1119
+ Expanded is the default and needs nothing. Compact and Hidden are attributes on <html>, drawn by
1120
+ the server from `ui.json` so the first paint is already right (see `sidebarAttributes`).
1121
+
1122
+ Both change only `--rail-width`, which every grid with a rail column reads, so the review page's
1123
+ three columns and the other pages' two follow without a template of their own. Hidden keeps the
1124
+ rail in grid flow at no width rather than `display: none`: out of flow, the next pane would drop
1125
+ into the rail's column, which is the defect the 860px block below had to be rewritten for. */
1126
+ :root[data-sidebar-compact] { --rail-width: 56px; }
1127
+ :root[data-sidebar-hidden] { --rail-width: 0px; }
1128
+ :root[data-sidebar-hidden] .prb-rail { visibility: hidden; overflow: hidden; padding: 0; border: 0; }
1129
+
1130
+ /* Compact is drawn by every rule below that waits on `:not([data-sidebar-peek])`. While the reader
1131
+ rests the pointer on it, or tabs into it, `client/sidebar.ts` sets `data-sidebar-peek` and those
1132
+ rules stop applying: the sidebar is drawn exactly as Expanded, at its full width, over the page
1133
+ rather than beside it. Its own column stays narrow, so nothing under it moves. It slides because
1134
+ its width is transitioned from the column's to the full one; the labels are clipped as it grows. */
1135
+ :root[data-sidebar-compact] .prb-rail {
1136
+ position: relative;
1137
+ z-index: 5;
1138
+ width: var(--rail-width);
1139
+ transition: width 0.16s ease, box-shadow 0.16s ease;
1140
+ }
1141
+ :root[data-sidebar-compact][data-sidebar-peek] .prb-rail {
1142
+ width: var(--rail-full-width);
1143
+ box-shadow: 8px 0 24px var(--shadow-float);
1144
+ }
1145
+
1146
+ /* Compact: every row is its icon, named in a tooltip beside it on hover and keyboard focus. The
1147
+ tooltip is the row's own label, moved out to the right, so the name a screen reader hears is
1148
+ the one it always heard. What has no icon (headings, the numbered review path, the folds, the
1149
+ counts) waits for Expanded. The rail lets the tooltips out past its edge, and sits above the
1150
+ pane beside it so they draw over it. */
1151
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail { overflow: visible; }
1152
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-item {
1153
+ position: relative;
1154
+ justify-content: center;
1155
+ align-items: center;
1156
+ gap: 0;
1157
+ padding: 9px 0;
1158
+ border-left-width: 0;
1159
+ }
1160
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-item .prb-rail-label {
1161
+ position: absolute;
1162
+ top: 50%;
1163
+ left: calc(100% + 6px);
1164
+ transform: translateY(-50%);
1165
+ padding: 5px 8px;
1166
+ border-radius: 6px;
1167
+ background: var(--text-primary);
1168
+ color: var(--bg);
1169
+ font-size: var(--t-micro);
1170
+ font-weight: 500;
1171
+ line-height: 1.4;
1172
+ white-space: nowrap;
1173
+ opacity: 0;
1174
+ pointer-events: none;
1175
+ z-index: 1;
1176
+ }
1177
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-item .prb-rail-label * { color: inherit; font: inherit; }
1178
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-item:hover .prb-rail-label,
1179
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-item:focus-visible .prb-rail-label { opacity: 1; transition: opacity 0.1s 0.35s; }
1180
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-count,
1181
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-selected,
1182
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-twisty,
1183
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-heading,
1184
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-subhead,
1185
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-path { display: none; }
1186
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-body { margin: 0; border-left: 0; }
1187
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-body .prb-rail-item { padding-left: 0; }
1188
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-group + .prb-rail-group { margin-top: 12px; padding-top: 12px; }
1189
+ /* New review is the square + at the top, its name and shortcut in the strip's own tooltip. */
1190
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-rail-new { padding: 0 10px 10px; }
1191
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-new-review { position: relative; justify-content: center; width: 36px; padding: 0; }
1192
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-new-review-label,
1193
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-new-review-key { display: none; }
1194
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-new-review[data-tip]::after {
1195
+ content: attr(data-tip);
1196
+ position: absolute;
1197
+ top: 50%;
1198
+ left: calc(100% + 6px);
1199
+ transform: translateY(-50%);
1200
+ padding: 5px 8px;
1201
+ border-radius: 6px;
1202
+ background: var(--text-primary);
1203
+ color: var(--bg);
1204
+ font-size: var(--t-micro);
1205
+ font-weight: 500;
1206
+ line-height: 1.4;
1207
+ white-space: nowrap;
1208
+ opacity: 0;
1209
+ pointer-events: none;
1210
+ z-index: 1;
1211
+ }
1212
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-new-review[data-tip]:hover::after,
1213
+ :root[data-sidebar-compact]:not([data-sidebar-peek]) .prb-new-review[data-tip]:focus-visible::after { opacity: 1; transition: opacity 0.1s 0.35s; }
1214
+
1215
+ /* Hidden: the strip's square New review stands in, as it does whenever the rail is not drawn. Send
1216
+ feedback belongs to the sidebar and goes with it; the strip has no copy of it at any width. */
1217
+ :root[data-sidebar-hidden] .prb-strip .prb-strip-new-review { display: flex; }
1218
+ /* The page title is set in the rail's column, so it keeps its own width while that column narrows. */
1219
+ :root:is([data-sidebar-compact], [data-sidebar-hidden]) .prb-context:has(.prb-index-controls) .prb-page-title { width: auto; }
1085
1220
  /* The pages under a review type (Issues, Questions, Files, PR context) and the links at the foot
1086
1221
  share the group rows' white, so the grey themes in the review path read as their own list.
1087
1222
  Weight still separates these from the group rows above them. Must come after `.prb-rail-item`:
@@ -2111,12 +2246,10 @@ a.prb-rail-item { text-decoration: none; }
2111
2246
  color: inherit;
2112
2247
  font: inherit;
2113
2248
  font-weight: 400;
2114
- text-decoration: underline;
2115
- text-decoration-color: var(--brand);
2116
- text-underline-offset: 3px;
2249
+ color: var(--pane-accent);
2117
2250
  cursor: pointer;
2118
2251
  }
2119
- .prb-doc-note-link:hover { color: var(--pane-ink); text-decoration-thickness: 2px; }
2252
+ .prb-doc-note-link:hover { color: var(--pane-ink); }
2120
2253
 
2121
2254
  .prb-doc-note {
2122
2255
  margin: 0 0 14px;
@@ -2263,25 +2396,21 @@ a.prb-rail-item { text-decoration: none; }
2263
2396
  /* Everything that is not the primary action. Text, not a box: as bordered buttons these competed
2264
2397
  with Update review and the panel read as four equal choices.
2265
2398
 
2266
- Resting at full contrast with a brand underline, which is where they used to arrive only on
2267
- hover. Muted grey on a grey rule was quiet to the point of being scenery: half of these are the
2268
- only way to do the thing the sentence beside them is describing, and a control nobody can see is
2269
- not restraint. Hover thickens the rule instead, so pointing at one still answers. */
2399
+ Resting in the link colour, not muted grey. Grey was quiet to the point of being scenery: half of
2400
+ these are the only way to do the thing the sentence beside them is describing, and a control
2401
+ nobody can see is not restraint. Hover takes them to the primary ink, so pointing at one answers. */
2270
2402
  .prb-fresh-quiet {
2271
2403
  padding: 2px 0;
2272
2404
  border: 0;
2273
2405
  background: none;
2274
- color: var(--text-primary);
2406
+ color: var(--link);
2275
2407
  font: inherit;
2276
2408
  font-size: var(--t-micro);
2277
- text-decoration: underline;
2278
- text-decoration-color: var(--brand);
2279
- text-underline-offset: 3px;
2280
2409
  /* It sits inside a sentence now, so it sits on that sentence's baseline. */
2281
2410
  vertical-align: baseline;
2282
2411
  cursor: pointer;
2283
2412
  }
2284
- .prb-fresh-quiet:hover:not(:disabled) { text-decoration-thickness: 2px; }
2413
+ .prb-fresh-quiet:hover:not(:disabled) { color: var(--text-primary); }
2285
2414
  .prb-fresh-quiet:disabled { opacity: 0.55; cursor: default; }
2286
2415
 
2287
2416
  /* Dismissal, at the end of the row it dismisses. An icon rather than the word `Close`, because it
@@ -2468,17 +2597,14 @@ a.prb-rail-item { text-decoration: none; }
2468
2597
  .prb-update-alt > summary,
2469
2598
  .prb-fresh-more > summary {
2470
2599
  display: inline-block;
2471
- color: var(--text-primary);
2472
- text-decoration: underline;
2473
- text-decoration-color: var(--brand);
2474
- text-underline-offset: 3px;
2600
+ color: var(--link);
2475
2601
  cursor: pointer;
2476
2602
  list-style: none;
2477
2603
  }
2478
2604
  .prb-update-alt > summary::-webkit-details-marker,
2479
2605
  .prb-fresh-more > summary::-webkit-details-marker { display: none; }
2480
2606
  .prb-update-alt > summary:hover,
2481
- .prb-fresh-more > summary:hover { text-decoration-thickness: 2px; }
2607
+ .prb-fresh-more > summary:hover { color: var(--text-primary); }
2482
2608
  /* Only this one announces itself as expandable. `Start a new review` reads as an action beside
2483
2609
  `Check review status` and a caret would advertise the disclosure rather than the choice; `More
2484
2610
  details` has nothing to offer except opening, so it says so. */
@@ -2773,9 +2899,11 @@ a.prb-guide-pick { text-decoration: none; }
2773
2899
  .prb-body:not([data-ask='open']),
2774
2900
  .prb-body[data-ask='open'] { grid-template-columns: minmax(0, 1fr); }
2775
2901
  .prb-rail { display: none; }
2902
+ .prb-strip .prb-strip-new-review { display: flex; }
2903
+ /* No sidebar fits at this width, so Show sidebar would bring back nothing. */
2904
+ :root[data-sidebar-hidden] .prb-strip .prb-sidebar-restore { display: none; }
2776
2905
  .prb-guide-picker { display: flex; }
2777
2906
  .prb-shell { grid-template-columns: minmax(0, 1fr); }
2778
- .prb-header-nav { display: flex; }
2779
2907
  /* The assistant is an overlay at this width, not a column, so there is no boundary to drag. */
2780
2908
  .prb-ask-resize { display: none; }
2781
2909
  /* Anchored to the body it covers, not to a sum of the bars above it. That sum assumed the header
@@ -2801,24 +2929,10 @@ a.prb-guide-pick { text-decoration: none; }
2801
2929
  scrolled sideways. Placed after every base rule it overrides (the header, the strip, the change
2802
2930
  ref, the stats), because at equal specificity the later rule wins. */
2803
2931
  @media (max-width: 600px) {
2804
- /* The strip keeps every control and the build; it gives up spacing and the feedback link's words.
2805
- The accessible name stays "Send feedback", from the visually hidden label. */
2932
+ /* The strip keeps every control and the build; it gives up spacing. */
2806
2933
  .prb-strip { gap: 4px; padding: 0 16px; }
2807
2934
  .prb-strip .prb-wordmark { min-width: 0; overflow: hidden; }
2808
2935
  .prb-strip .prb-build { margin-left: 4px; }
2809
- .prb-feedback { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 6px; color: var(--text-muted); opacity: 1; }
2810
- .prb-feedback:hover { background: var(--surface-2); }
2811
- .prb-feedback-icon { display: inline-flex; }
2812
- .prb-feedback-icon svg { width: 16px; height: 16px; }
2813
- .prb-feedback-label {
2814
- position: absolute;
2815
- width: 1px;
2816
- height: 1px;
2817
- margin: -1px;
2818
- overflow: hidden;
2819
- clip-path: inset(50%);
2820
- white-space: nowrap;
2821
- }
2822
2936
 
2823
2937
  /* The review bar becomes two rows: what the review is of, then its facts and controls. It grows
2824
2938
  with its content rather than clipping it; the panes below take what is left, and Buddy AI is
@@ -2971,7 +3085,7 @@ a.prb-guide-pick { text-decoration: none; }
2971
3085
  opacity: 0.8;
2972
3086
  cursor: pointer;
2973
3087
  }
2974
- .prb-code-deletion-toggle:hover { opacity: 1; text-decoration: underline; }
3088
+ .prb-code-deletion-toggle:hover { opacity: 1; }
2975
3089
  .prb-code-deleted { background: rgba(248, 81, 73, 0.1); }
2976
3090
  .prb-code-deleted .prb-code-num { box-shadow: inset 2px 0 0 #cf222e; color: #a40e26; }
2977
3091
  .prb-code-deleted .prb-code-line { color: #6e7781; }
@@ -2984,7 +3098,6 @@ a.prb-guide-pick { text-decoration: none; }
2984
3098
  background: none;
2985
3099
  font: inherit;
2986
3100
  color: #57606a;
2987
- text-decoration: underline;
2988
3101
  cursor: pointer;
2989
3102
  }
2990
3103
  .prb-code-long-toggle:hover { color: #1f2328; }
@@ -4259,7 +4372,7 @@ a.prb-guide-pick { text-decoration: none; }
4259
4372
  .prb-arch-trail { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 26px; font-size: var(--t-meta); color: #57606a; }
4260
4373
  .prb-arch-crumb { padding: 3px 0; border: 0; background: none; font: inherit; color: inherit; }
4261
4374
  button.prb-arch-crumb { color: #7e22ce; cursor: pointer; }
4262
- button.prb-arch-crumb:hover { text-decoration: underline; }
4375
+ button.prb-arch-crumb:hover { opacity: 0.8; }
4263
4376
  button.prb-arch-crumb:focus-visible { outline: 2px solid #9333ea; outline-offset: 1px; }
4264
4377
  .prb-arch-crumb[aria-current] { font-weight: 600; color: #1f2328; }
4265
4378
  .prb-arch-crumb-sep { color: #8c959f; }
@@ -4298,7 +4411,7 @@ button.prb-arch-crumb:focus-visible { outline: 2px solid #9333ea; outline-offset
4298
4411
  cursor: pointer;
4299
4412
  overflow-wrap: anywhere;
4300
4413
  }
4301
- .prb-arch-location:hover { text-decoration: underline; }
4414
+ .prb-arch-location:hover { opacity: 0.8; }
4302
4415
  .prb-arch-location:focus-visible { outline: 2px solid #9333ea; outline-offset: 1px; }
4303
4416
  span.prb-arch-location { color: #57606a; cursor: default; }
4304
4417
  span.prb-arch-location:hover { text-decoration: none; }
@@ -4537,7 +4650,7 @@ span.prb-arch-location:hover { text-decoration: none; }
4537
4650
  text-align: left;
4538
4651
  cursor: pointer;
4539
4652
  }
4540
- .prb-map-goto:hover { text-decoration: underline; }
4653
+ .prb-map-goto:hover { opacity: 0.8; }
4541
4654
 
4542
4655
  .prb-map-edges {
4543
4656
  position: absolute;
@@ -5297,7 +5410,7 @@ span.prb-arch-location:hover { text-decoration: none; }
5297
5410
  cursor: pointer;
5298
5411
  }
5299
5412
  .prb-kiss-location:hover { background: rgba(147, 51, 234, 0.14); }
5300
- .prb-kiss-location:hover .pr-helper-path-name { text-decoration: underline; }
5413
+ .prb-kiss-location:hover .pr-helper-path-name { opacity: 0.8; }
5301
5414
  /* The filename is a block, so the two markers that qualify it need a line of their own to share
5302
5415
  with it rather than one each above and below it. Baseline-aligned: they are small caps beside
5303
5416
  ordinary text and should sit on its line, not be centred against its box. */
@@ -5517,7 +5630,6 @@ select.prb-addreview-control {
5517
5630
  /* Clear of the sticky bars when arrived at by its anchor. */
5518
5631
  scroll-margin-top: 96px;
5519
5632
  }
5520
- .prb-help-topic:first-of-type { padding-top: 4px; }
5521
5633
  .prb-help-topic:last-of-type { border-bottom: 0; }
5522
5634
  .prb-help-topic h2 { margin: 0 0 12px; font-size: var(--t-section); font-weight: 600; color: var(--text-primary); }
5523
5635
  .prb-help-topic h3 { margin: 20px 0 8px; font-size: var(--t-body); font-weight: 600; color: var(--text-primary); }
@@ -5525,13 +5637,89 @@ select.prb-addreview-control {
5525
5637
  .prb-help-topic ul { margin: 0 0 10px; padding-left: 20px; }
5526
5638
  .prb-help-topic li { margin-bottom: 4px; }
5527
5639
  .prb-help-topic code { font-size: var(--t-code); color: var(--text-primary); }
5640
+ /* Welcome: a small capitalised label over the line the product stands on, and the principles as
5641
+ three short statements, each named in the primary ink and explained in the secondary. */
5642
+ .prb-help-topic .prb-help-eyebrow {
5643
+ margin: 0 0 6px;
5644
+ font-size: var(--t-micro);
5645
+ font-weight: 600;
5646
+ letter-spacing: 0.06em;
5647
+ text-transform: uppercase;
5648
+ color: var(--text-tertiary, var(--text-secondary));
5649
+ }
5650
+ .prb-help-topic h3.prb-help-eyebrow { margin-top: 24px; margin-bottom: 10px; }
5651
+ .prb-help-topic .prb-help-headline { margin: 0 0 14px; font-size: var(--t-title); line-height: 1.3; }
5652
+ .prb-help-principles { display: grid; gap: 12px; margin: 0; }
5653
+ .prb-help-principles dt { font-weight: 600; color: var(--text-primary); }
5654
+ .prb-help-principles dd { margin: 2px 0 0; }
5655
+ .prb-help-tour { margin-top: 20px; }
5656
+ /* An action, not a reference: it starts something, so it looks like the tour's own Next. */
5657
+ /* Through `.prb-help-topic a`, whose link colour would otherwise be drawn on the button's own purple. */
5658
+ .prb-help-topic a.prb-help-tour-action {
5659
+ display: inline-block;
5660
+ padding: 5px 12px;
5661
+ border-radius: 8px;
5662
+ background: var(--brand);
5663
+ color: var(--on-brand);
5664
+ font-weight: 600;
5665
+ }
5666
+ .prb-help-topic a.prb-help-tour-action:hover { background: var(--brand-hover); }
5528
5667
  .prb-help-topic a { color: var(--link); }
5529
- /* The topic index: links in a wrapping row, above the first topic and ruled off from it. */
5530
- .prb-help-contents { padding: 16px 0; border-bottom: 1px solid var(--border); }
5531
- .prb-help-contents ul { display: flex; flex-wrap: wrap; gap: 6px 20px; margin: 0; padding: 0; list-style: none; }
5532
- .prb-help-contents a { font-size: var(--t-body); color: var(--text-secondary); text-decoration: none; }
5533
- .prb-help-contents a:hover { color: var(--text-primary); text-decoration: underline; }
5534
- .prb-help-contents + .prb-help-topic { padding-top: 20px; }
5668
+ /* Wider than the 960px every other page keeps, by the index's column, so the topics keep the
5669
+ measure they had when the index sat above them. */
5670
+ .prb-shell > .prb-help {
5671
+ padding-inline: max(24px, calc((100% - 1200px) / 2 + 24px));
5672
+ container-type: inline-size;
5673
+ }
5674
+ /* The topics, and their index in a column beside them that stays in view while they scroll. The
5675
+ index comes first in the document and is placed second here. */
5676
+ .prb-help-layout {
5677
+ display: grid;
5678
+ grid-template-columns: minmax(0, 1fr) 208px;
5679
+ column-gap: 32px;
5680
+ align-items: start;
5681
+ }
5682
+ .prb-help-layout > .prb-page-panel { grid-column: 1; grid-row: 1; }
5683
+ .prb-help-contents {
5684
+ grid-column: 2;
5685
+ grid-row: 1;
5686
+ position: sticky;
5687
+ /* The pane's own top padding is the gap, at rest and stuck alike, so the index never jumps. */
5688
+ top: 0;
5689
+ max-height: calc(100dvh - 160px);
5690
+ overflow-y: auto;
5691
+ padding: 4px 0;
5692
+ }
5693
+ .prb-help-contents ul { margin: 0; padding: 0; list-style: none; border-left: 1px solid var(--border); }
5694
+ /* The rail's mark for where you are: a brand rule on the left and the tinted ground, here over the
5695
+ list's own rule so the mark sits on the track it moves along. */
5696
+ .prb-help-contents a {
5697
+ display: block;
5698
+ margin-left: -1px;
5699
+ padding: 5px 10px 5px 14px;
5700
+ border-left: 2px solid transparent;
5701
+ border-radius: 0 6px 6px 0;
5702
+ font-size: var(--t-meta);
5703
+ line-height: 1.4;
5704
+ color: var(--text-secondary);
5705
+ text-decoration: none;
5706
+ }
5707
+ .prb-help-contents a:hover { color: var(--text-primary); background: var(--surface-hover); }
5708
+ .prb-help-contents a[aria-current] {
5709
+ border-left-color: var(--brand);
5710
+ background: var(--brand-muted);
5711
+ color: var(--text-primary);
5712
+ font-weight: 500;
5713
+ }
5714
+ .prb-help-contents a:focus-visible { outline: 2px solid var(--brand-hover); outline-offset: -2px; }
5715
+ /* Too narrow for a column beside the prose: the index goes back above the topics, as a wrapping
5716
+ row, and stops following the scroll. After the rules above, which it overrides. */
5717
+ @container (max-width: 760px) {
5718
+ .prb-help-layout { display: block; }
5719
+ .prb-help-contents { position: static; max-height: none; margin: 0 0 16px; padding: 0; }
5720
+ .prb-help-contents ul { display: flex; flex-wrap: wrap; gap: 4px; border-left: 0; }
5721
+ .prb-help-contents a { margin-left: 0; padding: 4px 10px; border-left: 0; border-radius: 6px; }
5722
+ }
5535
5723
  /* A diagram's spacing is its meaning, so it never wraps: a narrow window scrolls it instead. */
5536
5724
  .prb-help-diagram {
5537
5725
  margin: 0 0 12px;
@@ -5694,7 +5882,7 @@ a.prb-notification-open:focus-visible { outline: 2px solid var(--brand-hover); o
5694
5882
  .prb-toast[data-kind='updated'] { border-left-color: var(--brand); }
5695
5883
  .prb-toast-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
5696
5884
  .prb-toast-open { flex: none; color: var(--wordmark-accent); font-weight: 600; text-decoration: none; }
5697
- .prb-toast-open:hover { text-decoration: underline; text-underline-offset: 2px; }
5885
+ .prb-toast-open:hover { opacity: 0.8; }
5698
5886
  .prb-toast-close {
5699
5887
  flex: none;
5700
5888
  width: 24px;
@@ -5723,6 +5911,10 @@ a.prb-notification-open:focus-visible { outline: 2px solid var(--brand-hover); o
5723
5911
  and without depending on this block staying last. */
5724
5912
  body .prb-body[data-focus] { grid-template-columns: minmax(0, 1fr); }
5725
5913
  body .prb-body[data-focus] .prb-rail { display: none; }
5914
+ /* The rail's New review goes with it, so the strip's square one stands in, as below 860px. */
5915
+ body:has(.prb-body[data-focus]) .prb-strip .prb-strip-new-review { display: flex; }
5916
+ /* Focus is left from the pane it expanded, so Show sidebar would bring back nothing here. */
5917
+ body:has(.prb-body[data-focus]) .prb-strip .prb-sidebar-restore { display: none; }
5726
5918
 
5727
5919
  /* A document surface, which is every view but the assistant: the review pane takes the width, and
5728
5920
  gets more room to use it. Prose stays a readable measure; a diff and a drawing are the things here
@@ -6349,7 +6541,6 @@ select.prb-addreview-control { padding-right: 32px; }
6349
6541
  color: var(--link);
6350
6542
  font: inherit;
6351
6543
  font-size: var(--t-micro);
6352
- text-decoration: underline;
6353
6544
  cursor: pointer;
6354
6545
  }
6355
6546
  .prb-addreview-retry { margin-left: calc(1em + 8px); }
@@ -6437,7 +6628,7 @@ select.prb-addreview-control { padding-right: 32px; }
6437
6628
  }
6438
6629
  .prb-selection-goto[hidden] { display: none; }
6439
6630
  .prb-selection-sep { color: var(--pane-ink-faint); white-space: pre; }
6440
- .prb-selection-goto:hover [data-feedback-goto-label] { text-decoration: underline; }
6631
+ .prb-selection-goto:hover [data-feedback-goto-label] { opacity: 0.8; }
6441
6632
  .prb-selection-spacer { flex: 1; }
6442
6633
  .prb-selection-button {
6443
6634
  padding: 6px 12px;
@@ -6614,3 +6805,85 @@ select.prb-addreview-control { padding-right: 32px; }
6614
6805
  .prb-runs-count { padding: 8px 10px; }
6615
6806
  .prb-runs-count dd { font-size: var(--t-section); }
6616
6807
  }
6808
+
6809
+
6810
+ /* ── Guided tour ──
6811
+ A modal dialog as big as the window, so everything under it is inert; the spotlight's shadow is
6812
+ the dim, and the card sits beside whatever the spotlight is on. Positions are set by tour.ts. */
6813
+ .prb-tour {
6814
+ position: fixed;
6815
+ inset: 0;
6816
+ width: 100%;
6817
+ height: 100%;
6818
+ max-width: none;
6819
+ max-height: none;
6820
+ margin: 0;
6821
+ padding: 0;
6822
+ border: 0;
6823
+ background: transparent;
6824
+ overflow: hidden;
6825
+ color: var(--text-primary);
6826
+ font: inherit;
6827
+ }
6828
+ .prb-tour::backdrop { background: transparent; }
6829
+ /* No target to light: the welcome, or a stop this layout does not draw. The whole page dims. */
6830
+ .prb-tour[data-spotless] { background: var(--backdrop); }
6831
+ .prb-tour-spot {
6832
+ position: fixed;
6833
+ border-radius: 10px;
6834
+ outline: 2px solid var(--brand);
6835
+ outline-offset: 0;
6836
+ box-shadow: 0 0 0 200vmax var(--backdrop);
6837
+ pointer-events: none;
6838
+ }
6839
+ .prb-tour-card {
6840
+ position: fixed;
6841
+ box-sizing: border-box;
6842
+ padding: 20px 22px 18px;
6843
+ border: 1px solid var(--border);
6844
+ border-radius: 12px;
6845
+ background: var(--surface-raised);
6846
+ box-shadow: 0 12px 32px var(--shadow-float);
6847
+ }
6848
+ .prb-tour[data-welcome] .prb-tour-card { padding: 26px 28px 22px; }
6849
+ .prb-tour-count {
6850
+ margin: 0 0 8px;
6851
+ font-size: var(--t-meta);
6852
+ font-weight: 600;
6853
+ letter-spacing: 0.04em;
6854
+ text-transform: uppercase;
6855
+ color: var(--brand-hover);
6856
+ }
6857
+ .prb-tour-title { margin: 0 0 8px; font-size: var(--t-section); font-weight: 650; line-height: 1.3; }
6858
+ .prb-tour[data-welcome] .prb-tour-title { font-size: 20px; }
6859
+ .prb-tour-text p { margin: 0 0 8px; font-size: var(--t-body); line-height: var(--lh-body); color: var(--text-secondary); }
6860
+ .prb-tour-actions { display: flex; align-items: center; gap: 8px; margin-top: 16px; }
6861
+ .prb-tour-actions button {
6862
+ padding: 7px 14px;
6863
+ border-radius: 8px;
6864
+ border: 1px solid var(--border);
6865
+ background: var(--surface-2);
6866
+ color: var(--text-primary);
6867
+ font: inherit;
6868
+ font-size: var(--t-body);
6869
+ cursor: pointer;
6870
+ }
6871
+ .prb-tour-actions button:hover { border-color: var(--border-strong); }
6872
+ .prb-tour-actions button:focus-visible { outline: 2px solid var(--brand-hover); outline-offset: 2px; }
6873
+ .prb-tour-actions .prb-tour-skip {
6874
+ margin-right: auto;
6875
+ padding-left: 0;
6876
+ padding-right: 0;
6877
+ border-color: transparent;
6878
+ background: transparent;
6879
+ color: var(--text-secondary);
6880
+ }
6881
+ .prb-tour-actions .prb-tour-skip:hover { border-color: transparent; color: var(--text-primary); }
6882
+ .prb-tour-actions .prb-tour-next {
6883
+ border-color: var(--brand);
6884
+ background: var(--brand);
6885
+ color: var(--on-brand);
6886
+ font-weight: 600;
6887
+ }
6888
+ .prb-tour-actions .prb-tour-next:hover { border-color: var(--brand-hover); background: var(--brand-hover); }
6889
+ .prb-tour-actions button[hidden] { display: none; }