prreviewbuddy 0.95.2 → 0.96.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.
@@ -1 +1 @@
1
- import{d as e,ft as t,m as n,o as r,t as i,xt as a}from"./chunk-Cs33-tV3.js";function o(e){let t=[...document.querySelectorAll(`[data-shutdown]`)],n=document.querySelector(`[data-shutdown-dialog]`),r=document.querySelector(`[data-shutdown-confirm]`);for(let e of t)e.addEventListener(`click`,()=>n?.showModal());document.querySelector(`[data-shutdown-cancel]`)?.addEventListener(`click`,()=>n?.close()),r?.addEventListener(`click`,()=>{r.disabled=!0,r.textContent=`Stopping…`,fetch(e,{method:`POST`}).then(e=>{if(!e.ok)throw Error(`Shutdown refused: ${e.status}`);n?.close(),s(t)}).catch(()=>{r.disabled=!1,r.textContent=`Stop server`})})}function s(t){document.body.dataset.serverStopped=`true`,e(document,`unreachable`);let n=document.createElement(`div`);n.className=`prb-stopped-notice`,n.setAttribute(`role`,`status`);let r=document.body.dataset.wayBack;n.textContent=r?`Workspace server stopped. This page is no longer being served. Run ${r} to bring it back.`:`Workspace server stopped. This page is no longer being served.`,document.body.prepend(n);for(let e of t)e.disabled=!0,e.classList.contains(`prb-strip-action`)||(e.textContent=`Server stopped`)}var c=[{id:`system`,label:`System`,help:`Follow your device setting`},{id:`light`,label:`Light`,help:`Always use light mode`},{id:`dark`,label:`Dark`,help:`Always use dark mode`}];function l(e){return c.some(t=>t.id===e)}function u(e){let t=e.querySelector(`[data-settings-theme]:checked`)?.value;return l(t)?t:void 0}function d(e,t){e.documentElement.dataset.theme=t}function f(e){for(let t of e.querySelectorAll(`[data-settings-theme]`))t.addEventListener(`change`,()=>{let t=u(e);t&&d(e,t)})}var p=/^[A-Za-z0-9_\/.:=@%+,-]+$/;function m(e){return e!==``&&p.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`}function h(e){return e===`~`?`"$HOME"`:e.startsWith(`~/`)?`"$HOME"/${m(e.slice(2))}`:m(e)}var g=new Set([`connected`,`already-connected`,`replaced`,`disconnected`,`working`]);function _(e){return{agent:e.dataset.integration??``,name:e.dataset.name??``,config:e.dataset.config??``,add:e.dataset.addCommand??``,remove:e.dataset.removeCommand??``,registered:e.dataset.registered??``}}function v(e,t){return e===`connect`?{title:`Connect PR Review Buddy to ${t.name}?`,body:`This runs the command below, which adds PR Review Buddy to ${t.name}'s config at ${t.config}. Nothing else in it changes.`,command:t.add,note:`Start a new ${t.name} session afterwards to use it.`,confirm:`Connect`,danger:!1}:e===`replace`?{title:`Replace the PR Review Buddy ${t.name} uses?`,body:`${t.name} now starts ${t.registered}. This removes that registration and adds this copy of PR Review Buddy instead.`,command:`${t.remove}\n${t.add}`,note:`If the new one is not accepted, the previous registration is put back.`,confirm:`Replace`,danger:!1}:{title:`Disconnect ${t.name}?`,body:`This removes PR Review Buddy from ${t.name}'s config at ${t.config}. Your reviews are not affected.`,command:t.remove,note:`Sessions already open keep it until they end.`,confirm:`Disconnect`,danger:!0}}function y(e,t,n){let r=t.trim();return r?`${e}=${h(r)} ${n}`:``}var b={connect:`Connecting…`,replace:`Replacing…`,disconnect:`Disconnecting…`,verify:`Checking…`};function x(e,t=window){let n=e.querySelector(`[data-integrations]`),r=e.querySelector(`[data-integration-dialog]`);if(!n)return;function i(t,n,r,i){let a=t.querySelector(`[data-integration-result]`);if(a&&(a.textContent=n,a.dataset.kind=r?`ok`:`error`,i)){let t=e.createElement(`pre`),n=e.createElement(`code`);n.textContent=i,t.append(n),a.after(t)}}function a(e){if(!r)return Promise.resolve(t.confirm(`${e.title}\n\n${e.command}`));let n=(e,t)=>{let n=r.querySelector(e);n&&(n.textContent=t)};n(`[data-integration-dialog-title]`,e.title),n(`[data-integration-dialog-body]`,e.body),n(`[data-integration-dialog-command]`,e.command),n(`[data-integration-dialog-note]`,e.note);let i=r.querySelector(`[data-integration-confirm]`);return i&&(i.textContent=e.confirm,i.classList.toggle(`prb-dialog-danger`,e.danger),i.classList.toggle(`prb-dialog-primary`,!e.danger)),new Promise(e=>{let t=t=>{r.removeEventListener(`close`,o),i?.removeEventListener(`click`,n),s?.removeEventListener(`click`,a),r.open&&r.close(),e(t)},n=()=>t(!0),a=()=>t(!1),o=()=>t(!1),s=r.querySelector(`[data-integration-cancel]`);i?.addEventListener(`click`,n),s?.addEventListener(`click`,a),r.addEventListener(`close`,o),r.showModal(),s?.focus()})}async function o(e){try{let n=await t.fetch(`/settings`,{headers:{accept:`text/html`}});return n.ok?new DOMParser().parseFromString(await n.text(),`text/html`).querySelector(`[data-integration="${CSS.escape(e)}"]`):null}catch{return null}}async function s(e,n,r){let s=_(e);if(n!==`verify`&&!await a(v(n,s)))return;let c=[...e.querySelectorAll(`button`)],l=r.textContent;c.forEach(e=>e.disabled=!0),r.textContent=b[n],e.setAttribute(`aria-busy`,`true`);let u=null,d=null;try{let e=await t.fetch(`/integrations`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({agent:s.agent,action:n===`replace`?`connect`:n,replace:n===`replace`})}),r=await e.json().catch(()=>null);!e.ok||!r||typeof r.message!=`string`?d=r?.error??`Nothing was changed. The workspace server did not answer.`:u=r}catch{d=`Nothing was changed. The workspace server could not be reached.`}let f=u?await o(s.agent):null,p=f??e;f?e.replaceWith(f):(c.forEach(e=>e.disabled=!1),r.textContent=l,e.removeAttribute(`aria-busy`)),u?i(p,u.message,g.has(u.outcome),u.previousCommand):i(p,d??`Nothing was changed.`,!1),p.querySelector(`[data-integration-action], [data-integration-copy]`)?.focus()}async function c(e,n,r){try{await t.navigator.clipboard.writeText(n),i(e,`Copied. Run it in a terminal, then start a new agent session.`,!0)}catch{let n=e.querySelector(`.prb-integration-manual`);n&&(n.open=!0);let r=n?.querySelector(`code`);r&&t.getSelection()?.selectAllChildren(r),i(e,`The browser would not copy it. The command is selected below.`,!1)}r.focus()}n.addEventListener(`click`,e=>{let t=e.target,n=t.closest(`[data-integration]`);if(!n)return;let r=t.closest(`[data-integration-action]`);if(r)return void s(n,r.dataset.integrationAction,r);let i=t.closest(`[data-integration-copy]`);if(i)return void c(n,n.dataset.addCommand??``,i);let a=t.closest(`[data-profile-copy]`);if(a){let e=n.querySelector(`[data-profile-command]`)?.textContent??``;e&&c(n,e,a)}}),n.addEventListener(`input`,e=>{let t=e.target;if(!t.matches(`[data-profile-dir]`))return;let n=t.closest(`[data-integration]`),r=t.closest(`[data-integration-profile]`);if(!n||!r)return;let i=y(r.dataset.profileVariable??``,t.value,r.dataset.profileAddCommand??``),a=r.querySelector(`[data-profile-output]`),o=r.querySelector(`[data-profile-command]`),s=r.querySelector(`[data-profile-copy]`);o&&(o.textContent=i),a&&(a.hidden=!i),s&&(s.hidden=!i)})}o(`/shutdown`),t(),n(`global`,{}),i(`/restart`),f(document),x(document);var S=document.querySelector(`[data-settings-save]`),C=document.querySelector(`[data-settings-status]`),w=document.querySelector(`[data-settings-port]`),T=document.querySelector(`[data-settings-port-error]`),E=document.querySelector(`[data-settings-agent]`);function D(){let e=document.querySelector(`[data-settings-usage]:checked`);return e?e.value===`on`:void 0}function O(e,t){C&&(C.textContent=e,C.dataset.kind=t)}function k(e){T&&(T.textContent=e??``),w&&(e?(w.setAttribute(`aria-invalid`,`true`),w.focus(),w.select()):w.removeAttribute(`aria-invalid`))}async function A(){if(!S)return;let e=D(),t=u(document),n={...w?{port:w.value.trim()}:{},...E?{agent:E.value}:{},...e===void 0?{}:{usageCounts:e},...t===void 0?{}:{theme:t}};S.disabled=!0,S.textContent=`Saving`;try{let e=await(await fetch(`/settings`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(n)})).json().catch(()=>null);if(!e){O(`Nothing was saved. The workspace server did not answer.`,`error`);return}if(e.error){k(e.error),O(`Nothing was saved.`,`error`);return}k(null),w&&(w.value=String(e.port.configured)),d(document,e.theme),O(e.restartRequired?`Saved. This page is served on port ${e.port.current}; the workspace moves to ${e.port.configured} the next time it starts.`:`Saved.`,`saved`)}catch{O(`Nothing was saved. The workspace server could not be reached.`,`error`)}finally{S.disabled=!1,S.textContent=`Save changes`}}S?.addEventListener(`click`,()=>void A()),r(document,window,{paintUnread:!0}),a(window,()=>window.location.reload());
1
+ import{Ct as e,d as t,m as n,mt as r,o as i,t as a}from"./chunk-C0JUspm9.js";function o(e){let t=[...document.querySelectorAll(`[data-shutdown]`)],n=document.querySelector(`[data-shutdown-dialog]`),r=document.querySelector(`[data-shutdown-confirm]`);for(let e of t)e.addEventListener(`click`,()=>n?.showModal());document.querySelector(`[data-shutdown-cancel]`)?.addEventListener(`click`,()=>n?.close()),r?.addEventListener(`click`,()=>{r.disabled=!0,r.textContent=`Stopping…`,fetch(e,{method:`POST`}).then(e=>{if(!e.ok)throw Error(`Shutdown refused: ${e.status}`);n?.close(),s(t)}).catch(()=>{r.disabled=!1,r.textContent=`Stop server`})})}function s(e){document.body.dataset.serverStopped=`true`,t(document,`unreachable`);let n=document.createElement(`div`);n.className=`prb-stopped-notice`,n.setAttribute(`role`,`status`);let r=document.body.dataset.wayBack;n.textContent=r?`Workspace server stopped. This page is no longer being served. Run ${r} to bring it back.`:`Workspace server stopped. This page is no longer being served.`,document.body.prepend(n);for(let t of e)t.disabled=!0,t.classList.contains(`prb-strip-action`)||(t.textContent=`Server stopped`)}var c=[{id:`system`,label:`System`,help:`Follow your device setting`},{id:`light`,label:`Light`,help:`Always use light mode`},{id:`dark`,label:`Dark`,help:`Always use dark mode`}];function l(e){return c.some(t=>t.id===e)}function u(e){let t=e.querySelector(`[data-settings-theme]:checked`)?.value;return l(t)?t:void 0}function d(e,t){e.documentElement.dataset.theme=t}function f(e){for(let t of e.querySelectorAll(`[data-settings-theme]`))t.addEventListener(`change`,()=>{let t=u(e);t&&d(e,t)})}var p=/^[A-Za-z0-9_\/.:=@%+,-]+$/;function m(e){return e!==``&&p.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`}function h(e){return e===`~`?`"$HOME"`:e.startsWith(`~/`)?`"$HOME"/${m(e.slice(2))}`:m(e)}var g=new Set([`connected`,`already-connected`,`replaced`,`disconnected`,`working`]);function _(e){return{agent:e.dataset.integration??``,name:e.dataset.name??``,config:e.dataset.config??``,add:e.dataset.addCommand??``,remove:e.dataset.removeCommand??``,registered:e.dataset.registered??``}}function v(e,t){return e===`connect`?{title:`Connect PR Review Buddy to ${t.name}?`,body:`This runs the command below, which adds PR Review Buddy to ${t.name}'s config at ${t.config}. Nothing else in it changes.`,command:t.add,note:`Start a new ${t.name} session afterwards to use it.`,confirm:`Connect`,danger:!1}:e===`replace`?{title:`Replace the PR Review Buddy ${t.name} uses?`,body:`${t.name} now starts ${t.registered}. This removes that registration and adds this copy of PR Review Buddy instead.`,command:`${t.remove}\n${t.add}`,note:`If the new one is not accepted, the previous registration is put back.`,confirm:`Replace`,danger:!1}:{title:`Disconnect ${t.name}?`,body:`This removes PR Review Buddy from ${t.name}'s config at ${t.config}. Your reviews are not affected.`,command:t.remove,note:`Sessions already open keep it until they end.`,confirm:`Disconnect`,danger:!0}}function y(e,t,n){let r=t.trim();return r?`${e}=${h(r)} ${n}`:``}var b={connect:`Connecting…`,replace:`Replacing…`,disconnect:`Disconnecting…`,verify:`Checking…`};function x(e,t=window){let n=e.querySelector(`[data-integrations]`),r=e.querySelector(`[data-integration-dialog]`);if(!n)return;function i(t,n,r,i){let a=t.querySelector(`[data-integration-result]`);if(a&&(a.textContent=n,a.dataset.kind=r?`ok`:`error`,i)){let t=e.createElement(`pre`),n=e.createElement(`code`);n.textContent=i,t.append(n),a.after(t)}}function a(e){if(!r)return Promise.resolve(t.confirm(`${e.title}\n\n${e.command}`));let n=(e,t)=>{let n=r.querySelector(e);n&&(n.textContent=t)};n(`[data-integration-dialog-title]`,e.title),n(`[data-integration-dialog-body]`,e.body),n(`[data-integration-dialog-command]`,e.command),n(`[data-integration-dialog-note]`,e.note);let i=r.querySelector(`[data-integration-confirm]`);return i&&(i.textContent=e.confirm,i.classList.toggle(`prb-dialog-danger`,e.danger),i.classList.toggle(`prb-dialog-primary`,!e.danger)),new Promise(e=>{let t=t=>{r.removeEventListener(`close`,o),i?.removeEventListener(`click`,n),s?.removeEventListener(`click`,a),r.open&&r.close(),e(t)},n=()=>t(!0),a=()=>t(!1),o=()=>t(!1),s=r.querySelector(`[data-integration-cancel]`);i?.addEventListener(`click`,n),s?.addEventListener(`click`,a),r.addEventListener(`close`,o),r.showModal(),s?.focus()})}async function o(e){try{let n=await t.fetch(`/settings`,{headers:{accept:`text/html`}});return n.ok?new DOMParser().parseFromString(await n.text(),`text/html`).querySelector(`[data-integration="${CSS.escape(e)}"]`):null}catch{return null}}async function s(e,n,r){let s=_(e);if(n!==`verify`&&!await a(v(n,s)))return;let c=[...e.querySelectorAll(`button`)],l=r.textContent;c.forEach(e=>e.disabled=!0),r.textContent=b[n],e.setAttribute(`aria-busy`,`true`);let u=null,d=null;try{let e=await t.fetch(`/integrations`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({agent:s.agent,action:n===`replace`?`connect`:n,replace:n===`replace`})}),r=await e.json().catch(()=>null);!e.ok||!r||typeof r.message!=`string`?d=r?.error??`Nothing was changed. The workspace server did not answer.`:u=r}catch{d=`Nothing was changed. The workspace server could not be reached.`}let f=u?await o(s.agent):null,p=f??e;f?e.replaceWith(f):(c.forEach(e=>e.disabled=!1),r.textContent=l,e.removeAttribute(`aria-busy`)),u?i(p,u.message,g.has(u.outcome),u.previousCommand):i(p,d??`Nothing was changed.`,!1),p.querySelector(`[data-integration-action], [data-integration-copy]`)?.focus()}async function c(e,n,r){try{await t.navigator.clipboard.writeText(n),i(e,`Copied. Run it in a terminal, then start a new agent session.`,!0)}catch{let n=e.querySelector(`.prb-integration-manual`);n&&(n.open=!0);let r=n?.querySelector(`code`);r&&t.getSelection()?.selectAllChildren(r),i(e,`The browser would not copy it. The command is selected below.`,!1)}r.focus()}n.addEventListener(`click`,e=>{let t=e.target,n=t.closest(`[data-integration]`);if(!n)return;let r=t.closest(`[data-integration-action]`);if(r)return void s(n,r.dataset.integrationAction,r);let i=t.closest(`[data-integration-copy]`);if(i)return void c(n,n.dataset.addCommand??``,i);let a=t.closest(`[data-profile-copy]`);if(a){let e=n.querySelector(`[data-profile-command]`)?.textContent??``;e&&c(n,e,a)}}),n.addEventListener(`input`,e=>{let t=e.target;if(!t.matches(`[data-profile-dir]`))return;let n=t.closest(`[data-integration]`),r=t.closest(`[data-integration-profile]`);if(!n||!r)return;let i=y(r.dataset.profileVariable??``,t.value,r.dataset.profileAddCommand??``),a=r.querySelector(`[data-profile-output]`),o=r.querySelector(`[data-profile-command]`),s=r.querySelector(`[data-profile-copy]`);o&&(o.textContent=i),a&&(a.hidden=!i),s&&(s.hidden=!i)})}o(`/shutdown`),r(),n(`global`,{}),a(`/restart`),f(document),x(document);var S=document.querySelector(`[data-settings-save]`),C=document.querySelector(`[data-settings-status]`),w=document.querySelector(`[data-settings-port]`),T=document.querySelector(`[data-settings-port-error]`),E=document.querySelector(`[data-settings-agent]`);function D(){let e=document.querySelector(`[data-settings-usage]:checked`);return e?e.value===`on`:void 0}function O(e,t){C&&(C.textContent=e,C.dataset.kind=t)}function k(e){T&&(T.textContent=e??``),w&&(e?(w.setAttribute(`aria-invalid`,`true`),w.focus(),w.select()):w.removeAttribute(`aria-invalid`))}async function A(){if(!S)return;let e=D(),t=u(document),n={...w?{port:w.value.trim()}:{},...E?{agent:E.value}:{},...e===void 0?{}:{usageCounts:e},...t===void 0?{}:{theme:t}};S.disabled=!0,S.textContent=`Saving`;try{let e=await(await fetch(`/settings`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(n)})).json().catch(()=>null);if(!e){O(`Nothing was saved. The workspace server did not answer.`,`error`);return}if(e.error){k(e.error),O(`Nothing was saved.`,`error`);return}k(null),w&&(w.value=String(e.port.configured)),d(document,e.theme),O(e.restartRequired?`Saved. This page is served on port ${e.port.current}; the workspace moves to ${e.port.configured} the next time it starts.`:`Saved.`,`saved`)}catch{O(`Nothing was saved. The workspace server could not be reached.`,`error`)}finally{S.disabled=!1,S.textContent=`Save changes`}}S?.addEventListener(`click`,()=>void A()),i(document,window,{paintUnread:!0}),e(window,()=>window.location.reload());
package/static/shell.css CHANGED
@@ -7293,3 +7293,234 @@ select.prb-addreview-control { padding-right: 32px; }
7293
7293
  }
7294
7294
  .prb-tour-actions .prb-tour-next:hover { border-color: var(--brand-hover); background: var(--brand-hover); }
7295
7295
  .prb-tour-actions button[hidden] { display: none; }
7296
+
7297
+ /* ── Quick Review ──
7298
+ One review's brief over the Reviews list (client/quick_review.ts). Sized in script to the content
7299
+ area right of the sidebar, inset at most 16px and at most 2.5% each way, so the UA's own dialog
7300
+ limits are lifted here and the box is exactly what the script measured. */
7301
+ .prb-quick-review {
7302
+ position: fixed;
7303
+ inset: auto;
7304
+ left: var(--qr-left, 2.5vw);
7305
+ top: var(--qr-top, 2.5vh);
7306
+ width: var(--qr-width, 95vw);
7307
+ height: var(--qr-height, 95vh);
7308
+ max-width: none;
7309
+ max-height: none;
7310
+ margin: 0;
7311
+ padding: 0;
7312
+ box-sizing: border-box;
7313
+ border: 1px solid var(--border);
7314
+ border-radius: 12px;
7315
+ background: var(--surface-raised);
7316
+ color: var(--text-primary);
7317
+ font: inherit;
7318
+ box-shadow: 0 18px 48px var(--shadow-float);
7319
+ }
7320
+ .prb-quick-review[open] { display: flex; flex-direction: column; }
7321
+ .prb-quick-review::backdrop { background: var(--backdrop); }
7322
+ .prb-qr-head {
7323
+ display: flex;
7324
+ flex-wrap: wrap;
7325
+ align-items: center;
7326
+ gap: 8px 16px;
7327
+ padding: 14px 20px 10px;
7328
+ border-bottom: 1px solid var(--border);
7329
+ }
7330
+ .prb-qr-identity { flex: 1 1 320px; min-width: 0; }
7331
+ .prb-qr-title { margin: 0; font-size: var(--t-title); line-height: var(--lh-tight); overflow-wrap: anywhere; }
7332
+ .prb-qr-sub { margin: 2px 0 0; font-size: var(--t-meta); color: var(--text-secondary); }
7333
+ .prb-qr-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
7334
+ .prb-qr-position { margin: 0 4px 0 0; font-size: var(--t-meta); color: var(--text-secondary); font-variant-numeric: tabular-nums; }
7335
+ .prb-qr-button {
7336
+ padding: 4px 12px;
7337
+ border: 1px solid var(--border);
7338
+ border-radius: 8px;
7339
+ background: transparent;
7340
+ color: var(--text-secondary);
7341
+ font: inherit;
7342
+ font-size: var(--t-meta);
7343
+ cursor: pointer;
7344
+ }
7345
+ .prb-qr-button:hover:not(:disabled) { color: var(--text-primary); border-color: var(--border-strong); }
7346
+ .prb-qr-button:disabled { opacity: 0.5; cursor: default; }
7347
+ .prb-qr-menu-host { position: relative; display: inline-flex; align-items: center; gap: 2px; }
7348
+ /* A card places its menu in its corner; in the header it is one more control in the row. */
7349
+ .prb-qr-menu-host > .prb-menu { position: relative; top: auto; right: auto; }
7350
+ .prb-qr-menu-host:empty { display: none; }
7351
+ .prb-qr-outcomes {
7352
+ display: flex;
7353
+ flex-wrap: wrap;
7354
+ align-items: center;
7355
+ gap: 6px 12px;
7356
+ padding: 8px 20px;
7357
+ border-bottom: 1px solid var(--border);
7358
+ background: var(--surface);
7359
+ }
7360
+ .prb-qr-standing { margin: 0; font-size: var(--t-meta); color: var(--text-secondary); }
7361
+ .prb-qr-standing[data-current] { color: var(--text-primary); font-weight: 600; }
7362
+ .prb-qr-outcome-buttons { display: flex; flex-wrap: wrap; gap: 6px; }
7363
+ .prb-qr-outcome-note { margin: 0; font-size: var(--t-meta); color: var(--text-secondary); }
7364
+ .prb-qr-outcome-note:empty { display: none; }
7365
+ .prb-qr-scope { flex-basis: 100%; margin: 0; font-size: var(--t-micro); color: var(--text-muted); }
7366
+ .prb-qr-notice {
7367
+ margin: 0;
7368
+ padding: 6px 20px;
7369
+ font-size: var(--t-meta);
7370
+ background: var(--warning-subtle);
7371
+ color: var(--warning-ink);
7372
+ }
7373
+ .prb-qr-body {
7374
+ flex: 1 1 auto;
7375
+ min-height: 0;
7376
+ overflow-y: auto;
7377
+ padding: 8px 20px 32px;
7378
+ outline: none;
7379
+ scroll-behavior: auto;
7380
+ }
7381
+ .prb-qr-section { padding: 14px 0; border-bottom: 1px solid var(--border); }
7382
+ .prb-qr-section:last-child { border-bottom: none; }
7383
+ .prb-qr-heading { margin: 0 0 8px; font-size: var(--t-section); }
7384
+ .prb-qr-subheading { margin: 12px 0 6px; font-size: var(--t-meta); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-secondary); }
7385
+ .prb-qr-body p { margin: 0 0 8px; font-size: var(--t-body); line-height: var(--lh-body); }
7386
+ .prb-qr-body code { font-size: var(--t-code); }
7387
+ .prb-qr-muted, .prb-qr-body .prb-qr-muted { color: var(--text-secondary); }
7388
+ .prb-qr-list { margin: 0 0 8px; padding-left: 18px; font-size: var(--t-body); line-height: var(--lh-body); }
7389
+ .prb-qr-list li { margin: 2px 0; }
7390
+ .prb-qr-since-headline { font-weight: 600; }
7391
+ .prb-qr-stale { padding: 8px 12px; border-radius: 8px; background: var(--warning-subtle); color: var(--warning-ink); }
7392
+ .prb-qr-themes { color: var(--text-secondary); }
7393
+ .prb-qr-details { margin: 6px 0; }
7394
+ .prb-qr-details > summary { cursor: pointer; font-size: var(--t-meta); color: var(--link); }
7395
+ .prb-qr-details[open] > summary { margin-bottom: 6px; }
7396
+ .prb-qr-full > summary { cursor: pointer; padding: 12px 0; font-size: var(--t-section); font-weight: 600; }
7397
+ .prb-qr-change { display: grid; grid-template-columns: 1fr auto 1fr; gap: 12px; align-items: start; }
7398
+ .prb-qr-change-side { padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); }
7399
+ .prb-qr-change-side .prb-qr-subheading { margin-top: 0; }
7400
+ .prb-qr-change-arrow { align-self: center; color: var(--text-muted); font-size: var(--t-section); }
7401
+ .prb-qr-why-status { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: var(--t-micro); background: var(--neutral-subtle); color: var(--text-secondary); }
7402
+ .prb-qr-why-stated { background: var(--success-subtle); color: var(--success-ink); }
7403
+ .prb-qr-why-unclear { background: var(--warning-subtle); color: var(--warning-ink); }
7404
+ .prb-qr-chip {
7405
+ display: inline-block;
7406
+ margin-right: 6px;
7407
+ padding: 1px 8px;
7408
+ border-radius: 999px;
7409
+ font-size: var(--t-micro);
7410
+ background: var(--neutral-subtle);
7411
+ color: var(--text-secondary);
7412
+ white-space: nowrap;
7413
+ }
7414
+ .prb-qr-chip-state[data-pr-state="merged"] { background: var(--merged-subtle); color: var(--merged-ink); }
7415
+ .prb-qr-chip-state[data-pr-state="open"] { background: var(--success-subtle); color: var(--success-ink); }
7416
+ .prb-qr-deps, .prb-qr-findings { list-style: none; margin: 0 0 8px; padding: 0; }
7417
+ .prb-qr-dep {
7418
+ display: flex;
7419
+ flex-wrap: wrap;
7420
+ align-items: center;
7421
+ gap: 4px 6px;
7422
+ padding: 6px 0;
7423
+ border-bottom: 1px solid var(--border);
7424
+ font-size: var(--t-body);
7425
+ }
7426
+ .prb-qr-dep-title { flex: 1 1 200px; min-width: 0; }
7427
+ .prb-qr-dep-actions { display: inline-flex; flex-wrap: wrap; gap: 10px; }
7428
+ .prb-qr-evidence { flex-basis: 100%; font-size: var(--t-meta); }
7429
+ .prb-qr-suppressed .prb-qr-dep-title { color: var(--text-secondary); }
7430
+ .prb-qr-link, .prb-qr-link-button, .prb-qr-ref {
7431
+ padding: 0;
7432
+ border: none;
7433
+ background: none;
7434
+ color: var(--link);
7435
+ font: inherit;
7436
+ font-size: var(--t-meta);
7437
+ text-decoration: none;
7438
+ cursor: pointer;
7439
+ }
7440
+ .prb-qr-link:hover, .prb-qr-link-button:hover, .prb-qr-ref:hover { opacity: 0.8; text-decoration: none; }
7441
+ .prb-qr-ref { font-family: var(--font-mono, ui-monospace, monospace); }
7442
+ .prb-qr-links { display: flex; flex-wrap: wrap; gap: 16px; }
7443
+ .prb-qr-picker { display: flex; flex-wrap: wrap; align-items: end; gap: 8px 12px; }
7444
+ .prb-qr-picker-field { display: flex; flex-direction: column; gap: 2px; font-size: var(--t-meta); color: var(--text-secondary); }
7445
+ .prb-qr-picker-field select { max-width: 100%; font: inherit; font-size: var(--t-meta); }
7446
+ .prb-qr-finding {
7447
+ margin: 0 0 10px;
7448
+ padding: 10px 12px;
7449
+ border: 1px solid var(--border);
7450
+ border-radius: 8px;
7451
+ background: var(--surface);
7452
+ }
7453
+ .prb-qr-question { border-style: dashed; }
7454
+ .prb-qr-finding-meta { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
7455
+ .prb-qr-ref-label { font-family: var(--font-mono, ui-monospace, monospace); font-size: var(--t-meta); color: var(--text-secondary); }
7456
+ .prb-qr-finding-title { font-weight: 600; }
7457
+ .prb-qr-step { font-size: var(--t-body); }
7458
+ .prb-qr-code { margin-top: 6px; }
7459
+ /* The code rows are the light pane's, coloured for a light page, and Quick Review sits outside .prb-doc,
7460
+ so the frame brings that surface with it in both themes. */
7461
+ .prb-qr-code .prb-code-scroll {
7462
+ --pane-line: rgba(15, 23, 42, 0.12);
7463
+ max-height: 320px; overflow: auto; border: 1px solid var(--pane-line); border-radius: 6px;
7464
+ background: #ffffff; color: #1f2328; color-scheme: light;
7465
+ }
7466
+ .prb-qr-facts { display: grid; grid-template-columns: max-content 1fr; gap: 4px 12px; margin: 0 0 8px; font-size: var(--t-body); }
7467
+ .prb-qr-facts dt { color: var(--text-secondary); }
7468
+ .prb-qr-facts dd { margin: 0; }
7469
+ .prb-qr-clean { padding: 8px 12px; border-radius: 8px; background: var(--neutral-subtle); }
7470
+ .prb-qr-state, .prb-qr-loading { padding: 24px 0; color: var(--text-secondary); }
7471
+ .prb-card-outcome {
7472
+ display: inline-flex;
7473
+ align-items: center;
7474
+ padding: 1px 8px;
7475
+ border-radius: 999px;
7476
+ font-size: var(--t-micro);
7477
+ background: var(--neutral-subtle);
7478
+ color: var(--text-secondary);
7479
+ white-space: nowrap;
7480
+ }
7481
+ .prb-card-outcome[data-standing="current"][data-outcome="no-concerns"] { background: var(--success-subtle); color: var(--success-ink); }
7482
+ .prb-card-outcome[data-standing="current"][data-outcome="needs-changes"] { background: var(--danger-subtle); color: var(--danger-ink); }
7483
+ .prb-card-outcome[data-standing="current"][data-outcome="needs-decision"] { background: var(--warning-subtle); color: var(--warning-ink); }
7484
+ /* What you will do next: beside the verdict, never in its colours, so a Later cannot read as one. */
7485
+ .prb-card-deferral, .prb-qr-deferral {
7486
+ display: inline-flex;
7487
+ align-items: center;
7488
+ padding: 0 7px;
7489
+ border: 1px dashed var(--border-strong);
7490
+ border-radius: 999px;
7491
+ font-size: var(--t-micro);
7492
+ color: var(--text-secondary);
7493
+ white-space: nowrap;
7494
+ }
7495
+ .prb-qr-deferral[hidden] { display: none; }
7496
+ /* The key a control answers to, where it stands. Quieter than .prb-kbd: it rides inside a button. */
7497
+ .prb-qr-key {
7498
+ display: inline-block;
7499
+ min-width: 1.4em;
7500
+ margin-left: 4px;
7501
+ padding: 0 4px;
7502
+ border: 1px solid var(--border);
7503
+ border-radius: 4px;
7504
+ color: var(--text-secondary);
7505
+ font: 500 var(--t-micro) / 1.4 ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
7506
+ text-align: center;
7507
+ white-space: nowrap;
7508
+ }
7509
+ .prb-qr-key:empty { display: none; }
7510
+ .prb-qr-hint {
7511
+ display: flex;
7512
+ align-items: center;
7513
+ gap: 12px;
7514
+ padding: 6px 20px;
7515
+ font-size: var(--t-meta);
7516
+ background: var(--neutral-subtle);
7517
+ color: var(--text-primary);
7518
+ }
7519
+ .prb-qr-hint[hidden] { display: none; }
7520
+ .prb-qr-hint-text { margin: 0; flex: 1 1 auto; }
7521
+ @media (max-width: 860px) {
7522
+ .prb-qr-head, .prb-qr-outcomes, .prb-qr-notice, .prb-qr-hint { padding-left: 12px; padding-right: 12px; }
7523
+ .prb-qr-body { padding: 8px 12px 24px; }
7524
+ .prb-qr-change { grid-template-columns: 1fr; }
7525
+ .prb-qr-change-arrow { transform: rotate(90deg); justify-self: center; }
7526
+ }