pipeup 0.8.0 → 0.8.2
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/README.md +2 -2
- package/cli/init.mjs +3 -3
- package/cli/pipeup.mjs +127 -22
- package/cli/read.mjs +1 -1
- package/dist/addons.json +1 -1
- package/dist/pipeup.agents.js +2 -2
- package/dist/pipeup.core.js +1 -1
- package/dist/pipeup.esm.js +1 -1
- package/dist/pipeup.min.js +1 -1
- package/dist/types/core.d.ts +2 -2
- package/dist/types/ui/context.d.ts +2 -0
- package/dist/types/ui/layout.d.ts +15 -3
- package/dist/types/ui/styles.d.ts +1 -1
- package/package.json +1 -1
- package/skills/pipeup-add/SKILL.md +2 -2
- package/skills/pipeup-apply/SKILL.md +17 -7
- package/skills/pipeup-integrate/SKILL.md +11 -10
- package/skills/pipeup-send-to-git-setup/SKILL.md +1 -1
- package/skills/pipeup-summarise/SKILL.md +1 -1
package/dist/types/core.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export declare const VERSION = "0.8.
|
|
1
|
+
export declare const VERSION = "0.8.2";
|
|
2
2
|
/** The day this version was made (set with the version): Pipeup says so, once, in the console when it is over a year old. */
|
|
3
|
-
export declare const BUILT = "2026-10-
|
|
3
|
+
export declare const BUILT = "2026-10-19";
|
|
4
4
|
export { PipeupDocument, UnsavedChangeError, type Listener, type OpenOptions } from "./document";
|
|
5
5
|
export { DEFAULT_PROFILE_NAME, MemoryStore, loadOrCreateProfile, type OpStore, type Profile, } from "./storage/store";
|
|
6
6
|
export { IndexedDbStore } from "./storage/indexeddb";
|
|
@@ -140,6 +140,8 @@ export interface Ctx {
|
|
|
140
140
|
say(text: string): void;
|
|
141
141
|
/** Comment mode's hint goes, if it is showing. */
|
|
142
142
|
hideHint(): void;
|
|
143
|
+
/** Whether Pipeup waits for a tap on the page changed (the menu opened or closed): iOS is told to send taps. */
|
|
144
|
+
taps(): void;
|
|
143
145
|
/** Escape's step back: the draft, the open thread, then comment mode's own, then comment mode. */
|
|
144
146
|
back(): void;
|
|
145
147
|
/** Tells the reviewer what went wrong. */
|
|
@@ -12,7 +12,9 @@ export interface Box {
|
|
|
12
12
|
}
|
|
13
13
|
export interface Viewport {
|
|
14
14
|
width: number;
|
|
15
|
+
/** The bottom of what can be seen; `top`, its top (a phone's on-screen keyboard covers the rest). */
|
|
15
16
|
height: number;
|
|
17
|
+
top?: number;
|
|
16
18
|
/**
|
|
17
19
|
* Where the comment control's corner starts (its left and top edges, and the left of comment mode's touch hint
|
|
18
20
|
* beside it): a box reaching past `left` stays above `top`, so nothing sits under the control.
|
|
@@ -45,7 +47,16 @@ export declare const NARROW = 480;
|
|
|
45
47
|
export declare const narrow: () => boolean;
|
|
46
48
|
/** A touch screen: a finger is the main pointer (the stylesheet's `pointer: coarse`). */
|
|
47
49
|
export declare const touch: () => boolean;
|
|
48
|
-
|
|
50
|
+
export declare const setPanned: (px: number) => void;
|
|
51
|
+
/**
|
|
52
|
+
* What of the window can be seen, top to bottom: a phone's on-screen keyboard covers the bottom of the window without
|
|
53
|
+
* making it shorter (only the visual viewport shrinks), and the page may be panned within it.
|
|
54
|
+
*/
|
|
55
|
+
export declare function seen(): {
|
|
56
|
+
top: number;
|
|
57
|
+
bottom: number;
|
|
58
|
+
};
|
|
59
|
+
/** The viewport left for popovers: what can be seen, less All comments' width from the right when it is open. */
|
|
49
60
|
export declare function room(listing: boolean): Viewport;
|
|
50
61
|
export declare function placePopover(at: AnchorPoint, size: {
|
|
51
62
|
width: number;
|
|
@@ -81,8 +92,9 @@ export declare function placeBar(target: Box, size: {
|
|
|
81
92
|
};
|
|
82
93
|
/**
|
|
83
94
|
* The selection's comment icon: just past the right of its block's text, level with the selection's last line, so it
|
|
84
|
-
* covers no words; above the selection (or below) when there's no room there. On a touch screen (`below`),
|
|
85
|
-
*
|
|
95
|
+
* covers no words; above the selection (or below) when there's no room there. On a touch screen (`below`), at the
|
|
96
|
+
* window's right edge, level with the selection's last line (its first, when the last runs into that edge): the
|
|
97
|
+
* phone's own menu for a selection sits above or below it, never beside, and its handles sit at its ends.
|
|
86
98
|
*/
|
|
87
99
|
export declare function placeIcon(sel: Box, line: Box, textRight: number, size: {
|
|
88
100
|
width: number;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Pipeup's stylesheet, scoped to its shadow root. Light by default; `.dark` follows a dark page. */
|
|
2
|
-
export declare const STYLES = "\n/* Inherited page styles are reset on .layer below; custom properties pass through all:initial. */\n:host{all:initial;direction:ltr;unicode-bidi:normal}\n*{box-sizing:border-box}\nbutton{appearance:none;font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}\nsvg{display:block}\n.layer{all:initial;direction:ltr;unicode-bidi:normal;display:block;position:fixed;inset:0;pointer-events:none;font:13px/1.5 var(--pu-font,system-ui,sans-serif);color:var(--k);\n--k:#2C2C2A;--mu:#5F5E5A;--fa:#6B6A64;--ln:#E5E3DA;--ru:#ECEAE2;--so:#FAFAF7;--su:#FFFFFF;--ho:#F1EFE8;\n--as:color-mix(in srgb,var(--pu-accent,#534AB7) 12%,transparent);\n--sh:0 8px 28px rgba(44,44,42,.10);\n--in:.26s;--mv:.34s;--out:.2s;--pl:1.2s;\n--eo:cubic-bezier(.22,.61,.36,1);--eio:cubic-bezier(.4,0,.2,1);--ei:cubic-bezier(.4,0,1,1);\n--pu-text:var(--k);--pu-muted:var(--mu);--pu-faint:var(--fa);--pu-line:var(--ln);--pu-surface:var(--su);--pu-soft:var(--so);--pu-hover:var(--ho);--pu-shadow:var(--sh);--pu-ease:var(--eo)}\n.layer{transition:opacity .24s var(--eo)}.layer.fading{opacity:0;transition-duration:.16s;transition-timing-function:var(--ei)}\n.layer.dark{--k:#ECEBE6;--mu:#B4B2A9;--fa:#9A9892;--ln:#3A3936;--ru:#34332F;--so:#22221F;--su:#1B1B19;--ho:#2C2C29;--sh:0 8px 28px rgba(0,0,0,.45)}\n.layer.hidden .bub,.layer.hidden .col,.layer.hidden .pop,.layer.hidden .tip,.layer.hidden .mark,.layer.hidden .selbar{opacity:0!important;pointer-events:none!important}\n\n.tx{font-size:14px;line-height:1.5;color:var(--k);white-space:pre-wrap;overflow-wrap:anywhere}\n.tx.del,.rest,.ctx,.ago{color:var(--fa)}\n.rest,.ago{font-size:12px}\n.rest{display:block;margin-top:3px}\n/* A card's top line: avatar, who (cut short on one line, never wrapped), how long ago, then its actions. */\n.hdr{position:relative;display:flex;align-items:center;gap:7px;min-height:22px}\n.who{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:600;color:var(--k)}\n.ago{flex:none;white-space:nowrap}\n.ago::before{content:\"\u00B7\";margin-right:6px}\n.root>.tx,.it>.tx,.root>.ctx{margin-top:2px}\n.ctx[hidden]{display:none}\n.ctx{font-size:12px;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.cd>.thread .tx,.clamp{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n/* A long comment at rest in the column: its first four lines, fading out, then \"more\"; opened, it eases out to all of it. */\n.th.long .root>.tx{max-height:var(--full);overflow:hidden;transition:max-height var(--mv) var(--eio)}\n.th.long:not(.on) .root>.tx{max-height:84px;mask-image:linear-gradient(#000 calc(100% - 21px),transparent)}\n.mr{display:grid;grid-template-rows:0fr;opacity:0;font-size:12px;color:var(--pu-accent);text-align:end;transition:grid-template-rows var(--mv) var(--eio),opacity var(--in) var(--eo)}\n.mr>span{min-height:0;overflow:hidden}\n.th.long:not(.on) .mr{grid-template-rows:1fr;opacity:1}\n.tx a{color:var(--pu-accent);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}\n\n/* Actions sit at the card's top right: always on an open card, on hover (or focus) on one at rest. In All comments a\nclosed card keeps them while its \u22EF menu is open, and focus put there for the keyboard (not a click) shows them. After\nResolve (.still) the card that moves up under the pointer keeps them from it until it moves; keyboard focus shows them. */\n.acts{margin-left:auto;display:flex;flex:none;transition:opacity var(--in) var(--eo)}\n.th:not(.on):not(:hover):not(:focus-within) .acts,.cd:not(.open):not(:hover):not(:has(:focus-visible,.pm)) .acts,.still .th:not(.on):not(:has(:focus-visible)) .acts,.still .cd:not(.open):not(:has(:focus-visible,.pm)) .acts{opacity:0;pointer-events:none}\n/* On a closed card they lie over the end of the top line, on the card's own colour, so the name has the whole line\nwhile they're hidden and the card never changes size as they ease in. They take presses only once eased in: a click as\nthe pointer arrives, or a tap (which hovers as it lands), opens the card. */\n.th:not(.on) .acts,.cd:not(.open) .acts{position:absolute;right:0;padding-left:16px;background:linear-gradient(90deg,transparent,var(--bg) 14px);transition:opacity var(--in) var(--eo),pointer-events 0s var(--in);transition-behavior:allow-discrete}\n.th.on .rest{display:none}\n/* A comment's \u22EF menu: Copy thread, Edit, Delete (asked twice). */\n.pm{position:absolute;right:0;top:100%;z-index:5;display:flex;flex-direction:column;min-width:150px;padding:4px;border:1px solid var(--ln);border-radius:10px;background:var(--su);box-shadow:var(--sh)}\n.pm.in{animation:pu-in var(--in) var(--eo) both}\n.pm button{padding:6px 10px;border-radius:7px;text-align:left;font-size:13px;transition:background-color .2s var(--eo),color .2s var(--eo)}\n.pm button:hover,.pm button:focus-visible{background:var(--ho)}\n.pm .dl{color:#C9402F}.dark .pm .dl{color:#F08A7E}\n.edit{margin-top:2px}\n.ib{width:24px;height:22px;display:grid;place-items:center;border-radius:6px;color:var(--mu);transition:background-color .2s var(--eo),color .2s var(--eo)}\n.ib:hover,.ib:focus-visible{background:var(--ho);color:var(--k)}\n\n/* Replies: one level in, oldest first; the reply line ends the thread at the same indent. */\n.rps,.rbox{padding-left:14px}\n.rps .it{padding-top:8px}\n.more{display:grid;grid-template-rows:1fr;transition:grid-template-rows var(--mv) var(--eio)}\n.more>div{overflow:hidden;min-height:0}\n.th:not(.on) .more{grid-template-rows:0fr}\n\n/* Writing boxes: a rounded box that says what it's for, then Cancel and Send (named) while it is in use. */\n.row{position:relative;padding-top:6px}\n.line{display:flex;align-items:center;gap:6px;padding:3px 12px;border:1px solid var(--ln);border-radius:16px;cursor:text;transition:border-color var(--in) var(--eo),box-shadow var(--in) var(--eo)}\n.line:hover{border-color:var(--mu)}\n.line:focus-within{border-color:var(--pu-accent);box-shadow:0 0 0 1px var(--pu-accent)}\n.input{flex:1;min-width:0;height:24px;display:block;border:0;outline:none;resize:none;overflow:hidden;\nfont:inherit;font-size:14px;line-height:1.5;padding:1px 0;color:var(--k);background:transparent}\n.input::placeholder{color:var(--fa);opacity:1}\n.bts{display:flex;justify-content:flex-end;gap:4px;max-height:0;opacity:0;overflow:hidden;transition:max-height var(--in) var(--eo),opacity var(--in) var(--eo),padding var(--in) var(--eo)}\n.row:focus-within .bts,.row.has .bts{max-height:40px;opacity:1;padding-top:4px}\n.bts button{padding:2px 10px;border-radius:14px;font-size:13px;font-weight:600;color:var(--pu-accent);transition:background-color .2s var(--eo),color .2s var(--eo)}\n.cnl:hover,.cnl:focus-visible{background:var(--as)}\n.send{background:var(--pu-accent);color:var(--pu-on,#fff)!important}\n.send:not(.show){background:var(--ru);color:var(--fa)!important;cursor:default}\n.ed{display:flex;gap:10px;align-items:center;min-height:34px;padding:6px 10px}\n.ed .input,.nf .input{font-size:13px;height:22px;border-bottom:1px solid var(--ln)}\n.ed .input:focus,.nf .input:focus{border-bottom-color:var(--pu-accent)}\n\n/* Avatars: a squircle with the writer's animal (or initial) on a soft colour, at the start of the card's top line. */\n.av{flex:none;display:grid;place-items:center;width:22px;height:22px;border-radius:32%;\nfont-size:12px;font-weight:600;line-height:1;opacity:0;transform:scale(.85);transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.av.in{opacity:1;transform:none}\n/* The animal nearly fills its tint (its drawing has room round it in its 24 grid), in a lighter line so it stays thin. */\n.av svg{width:122%;height:122%;stroke-width:1.3}\n/* Ten colours (.c0 Red to .c9 Grey, as COLOURS): a soft tint and a dark drawing, swapped round on dark pages. */\n.av{--av-l:92%;--av-d:30%;--s:60%;background:hsl(var(--h) var(--s) var(--av-l));color:hsl(var(--h) var(--s) var(--av-d))}\n.dark .av{--av-l:20%;--av-d:78%}\n/* An AI's reply: a plain disc with a violet ring, all inside the avatar's own box so nothing is cropped. */\n.av.ai{position:relative;border-radius:50%;background:var(--su);color:var(--pu-accent);font-size:9px;letter-spacing:.02em}\n.av.ai::before{content:\"\";position:absolute;inset:3px;border-radius:50%;border:1.5px solid var(--pu-accent);pointer-events:none}\n.refs{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;white-space:normal}\n.refs .ref{display:inline-flex;align-items:center;gap:5px;max-width:160px;padding:1px 9px;border:1px solid var(--ln);border-radius:999px;background:var(--so);color:var(--mu);font:inherit;font-size:11.5px;line-height:1.6;text-decoration:none;cursor:pointer;transition:background-color .2s var(--eo),color .2s var(--eo),border-color .2s var(--eo)}\n.refs .ref:hover,.refs .ref:focus-visible{background:var(--as);color:var(--pu-accent);border-color:var(--pu-accent)}\n.ref span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.rxp{position:fixed;width:320px;height:340px;border-radius:12px;overflow:hidden;pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.rxp.show{opacity:1;transform:none;pointer-events:auto}\n.mn{border-radius:4px;padding:0 2px;background:var(--as);color:var(--pu-accent)}\n.mn.me{font-weight:600}\n.mnl{position:absolute;left:0;bottom:100%;margin:0 0 4px;padding:4px;list-style:none;min-width:180px;max-width:100%;border:1px solid var(--ln);border-radius:10px;background:var(--su);box-shadow:var(--sh);opacity:0;transform:translateY(4px);pointer-events:none;z-index:4;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.mnl.show{opacity:1;transform:none;pointer-events:auto}\n.mnl li{display:flex;align-items:baseline;gap:8px;padding:5px 8px;border-radius:6px;font-size:13px;color:var(--k);cursor:pointer}\n.mnl li small{font-size:11px;color:var(--fa)}\n.mnl li.on,.mnl li:hover{background:var(--as);color:var(--pu-accent)}\n.dlg{position:fixed;left:50%;top:18vh;width:min(380px,calc(100vw - 32px));padding:16px 18px;border:1px solid var(--ln);border-radius:14px;background:var(--su);box-shadow:var(--sh);color:var(--k);opacity:0;transform:translate(-50%,6px);pointer-events:none;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.dlg.show{opacity:1;transform:translate(-50%,0);pointer-events:auto}\n.toast.act{display:flex;align-items:center}.toast.show .ta{pointer-events:auto}\n/* Faded, its button is no longer a Tab stop (hidden once the fade is over). */\n.toast .ta{transition:visibility 0s .3s}.toast:not(.show) .ta{visibility:hidden}.toast.show .ta{transition-delay:0s}\n.ta{margin-left:4px;color:var(--pu-accent);text-decoration:underline;text-underline-offset:2px}\n.rx .n{font-size:11px;font-variant-numeric:tabular-nums}\n.rx.mine{background:var(--as);color:var(--pu-accent);border-color:var(--pu-accent)}\n.rx:disabled{cursor:default;opacity:.7}\n.rx{-webkit-touch-callout:none;-webkit-user-select:none}\n.rx.new,.rxq.new{animation:pu-in var(--mv) var(--eo) backwards}\n.rxs{align-items:center}\n.rxq{display:inline-flex;gap:2px}\n.rxo{padding:2px 5px;border-radius:8px;font-size:16px;line-height:1.3;transition:background-color .2s var(--eo)}\n.rxo:hover,.rxo:focus-visible,.rxo[aria-pressed=true]{background:var(--as)}\n.refs .ref{position:relative}.ref .rc{position:absolute;left:0;top:calc(100% + 6px);z-index:3;width:max-content;max-width:min(240px,70vw);padding:6px 9px;border:1px solid var(--ln);border-radius:8px;background:var(--su);box-shadow:var(--sh);color:var(--k);font-size:12px;line-height:1.45;white-space:normal;text-align:left;overflow:visible;opacity:0;visibility:hidden;transform:translateY(-3px);pointer-events:none;transition:opacity .2s var(--eo),transform .2s var(--eo),visibility 0s .2s}.ref:hover .rc,.ref:focus-visible .rc,.ref.held .rc{opacity:1;visibility:visible;transform:none;transition-delay:0s}\n.ref .sl{width:10px;height:7px;border:1.3px solid currentColor;border-radius:2px;flex:none}\n.seen{display:flex;align-items:center;gap:6px;padding:6px 0 0 14px;font-size:12px;color:var(--fa)}\n.seen button{margin-left:auto;padding:0 6px;border:0;border-radius:6px;background:none;color:var(--fa);font:inherit;cursor:pointer;transition:color .2s var(--eo),background-color .2s var(--eo)}.seen button:hover,.seen button:focus-visible{color:var(--pu-accent);background:var(--as)}\n.seen i{width:12px;height:12px;border-radius:50%;border:1.5px solid var(--pu-accent);flex:none}\n.c0{--h:0}.c1{--h:25}.c2{--h:50}.c3{--h:130}.c4{--h:175}.c5{--h:215}.c6{--h:270}.c7{--h:330}.c8{--h:28;--s:35%}.c9{--h:220;--s:8%}\nbutton.me{flex:none;display:grid;place-items:center}\nbutton.me>.av{grid-area:1/1}\n/* Who you are, at the top of a new comment; a name field eases open in its place. */\n.you{flex:1;display:grid;min-width:0;min-height:22px;font-size:12px;color:var(--fa)}\n.you .nm{font-size:13px;font-weight:600;color:var(--k)}\n.you>*{grid-area:1/1;display:flex;align-items:center;min-width:0;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.say{white-space:pre;overflow:hidden}\n.nm{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.say button{flex:none}\n.say button{color:var(--mu);text-decoration:underline;text-decoration-color:var(--ln);text-underline-offset:2px;transition:color .2s var(--eo)}\n.say button:hover,.say button:focus-visible{color:var(--pu-accent)}\n.nf{opacity:0;transform:translateY(-4px);pointer-events:none}\n.nf .input{font-size:13px;height:24px}\n.you.naming .nf{opacity:1;transform:none;pointer-events:auto}\n.you.naming .say{opacity:0;pointer-events:none}\n\n/* Bubbles, tips, popovers, marks, pulses. */\n.bub{position:fixed;left:0;top:0;width:20px;height:20px;margin:-20px 0 0 -2px;border-radius:50% 50% 50% 0;background:var(--pu-accent);\nborder:2px solid var(--su);box-shadow:0 1px 4px rgba(0,0,0,.2);pointer-events:auto;opacity:0;transform:translateY(-6px) scale(.9);transform-origin:2px 20px;\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.bub.in{opacity:1;transform:none;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.bub.in:hover,.bub.on{transform:scale(1.18)}\n.bub.done{background:var(--fa)}\n.bub.ghost{pointer-events:none}\n.tip,.pop,.menu,.all,.xp,.toast,.selbar,.namebar,.tt,.rxp{background:var(--su);border:1px solid var(--ln);box-shadow:var(--sh)}\n.tip{position:fixed;max-width:260px;border-radius:10px;padding:7px 10px;opacity:0;transform:translateY(3px);\ntransition:opacity .22s var(--eo),transform .26s var(--eo)}\n.tip.show{opacity:1;transform:none;pointer-events:auto;cursor:pointer;\ntransition:opacity .22s var(--eo),transform .26s var(--eo),left var(--mv) var(--eio),top var(--mv) var(--eio)}\n.pop{position:fixed;width:var(--pu-pop);border-radius:12px;padding:8px 10px 10px;pointer-events:none;opacity:0;transform:translateY(6px) scale(.98);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.pop.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo)}\n.pop.show.glide{transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo),left var(--mv) var(--eio),top var(--mv) var(--eio)}\n.mark{position:fixed;border:2px solid color-mix(in srgb,var(--pu-accent) 50%,transparent);background:var(--as);border-radius:8px;opacity:0;\ntransition:opacity .3s var(--eo)}\n.mark.show{opacity:1}\n.pulse{position:fixed;border:2px solid var(--pu-accent);border-radius:8px;background:var(--as);animation:pu-pulse var(--pl) var(--eio) forwards}\n@keyframes pu-pulse{0%{opacity:0;transform:scale(.985)}35%{opacity:.85;transform:scale(1)}100%{opacity:0;transform:scale(1.02)}}\n\n/* Document column. */\n.col{position:fixed;left:0;top:0;pointer-events:none;transition:opacity var(--in) var(--eo)}\n/* Each thread is a compact card; the open one lifts with a soft shadow. */\n.th,.cd{--bg:var(--su);background:var(--bg);opacity:var(--o,1)}\n.th{position:absolute;left:0;right:0;top:0;padding:8px 10px 10px;border:1px solid var(--ln);border-radius:10px;pointer-events:auto;cursor:pointer;\ntransition:transform var(--mv) var(--eio),box-shadow var(--in) var(--eo),border-color var(--in) var(--eo),opacity var(--in) var(--eo)}\n.th.hot{border-color:var(--mu)}\n.th.on{border-color:transparent;box-shadow:var(--sh);cursor:default}\n.th.dim{--o:.45}\n.th.resolved:not(.on):not(.hot){--o:.6}\n.th.lost .ctx{white-space:normal}\n.th.wait{opacity:0!important;pointer-events:none}\n.th:is(.out,.hop){opacity:0!important;pointer-events:none;transition:opacity var(--out) var(--ei)}\n/* A closed thread's button has no box of its own: the thread shows its focus. */\n.th:has(.opn:focus-visible){outline:2px solid var(--pu-accent);outline-offset:2px}\n\n/* Selection bar. */\n.selbar{position:fixed;display:flex;border-radius:10px;padding:2px;opacity:0;transform:translateY(4px);pointer-events:none;\ntransition:opacity var(--in) var(--eo),transform .3s var(--eo)}\n.selbar.show{opacity:1;transform:none;pointer-events:auto}\n.selbar button{width:32px;height:30px;display:grid;place-items:center;border-radius:8px;color:var(--pu-accent);transition:background-color .2s var(--eo)}\n.selbar button:hover,.selbar button:focus-visible{background:var(--as)}\n\n/* Comment mode's outline: glides between blocks; solid accent once chosen. */\n.pick{position:fixed;left:0;top:0;border:2px solid color-mix(in srgb,var(--pu-accent) 70%,transparent);background:color-mix(in srgb,var(--pu-accent) 6%,transparent);\nborder-radius:8px;pointer-events:none;opacity:0;transition:opacity var(--out) var(--ei),border-color var(--out) var(--ei),border-width var(--out) var(--ei),box-shadow var(--out) var(--ei)}\n.pick.show{opacity:1;transition-duration:var(--in);transition-timing-function:var(--eo)}\n.pick.show.glide{transition-property:all;transition-duration:var(--mv);transition-timing-function:var(--eio)}\n.pick.on{border-color:var(--pu-accent)}\n.pkw{position:fixed;left:0;top:0;border:2px dashed color-mix(in srgb,var(--pu-accent) 70%,transparent);border-radius:8px;pointer-events:none;opacity:0;transition:opacity var(--out) var(--ei)}\n.pkw.show{opacity:.6;transition:opacity var(--in) var(--eo)}\n.draft{transition:opacity var(--in) var(--eo)}.draft.wait:not(:focus-within){opacity:.6}\n/* The block cursor: its focus is drawn on the outline (3px accent with a surface halo, 3:1 on any page); the\nmarkers that hold focus are invisible. */\n.pick.kf{border:3px solid var(--pu-accent);box-shadow:0 0 0 2px var(--su)}\n.km{position:fixed;left:0;top:0;pointer-events:none;outline:none}\n.sr,.mn-sr,.hh{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}\n.namebar{position:fixed;left:0;top:0;display:flex;align-items:center;gap:2px;max-width:calc(100% - 16px);padding:2px 2px 2px 10px;border-radius:10px;font-size:12px;color:var(--mu);\nwhite-space:nowrap;pointer-events:none;opacity:0;transform:translateY(4px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.namebar.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform .3s var(--eo)}\n.namebar.show.glide{transition-property:all;transition-duration:var(--mv);transition-timing-function:var(--eio)}\n/* It sits over the page's words beside its block: pointed at anywhere but its icons, it fades so they can be read. */\n.namebar:hover:not(:has(.nb:hover)){opacity:.15}\n.namebar .lbl{margin-right:6px;max-width:260px;overflow:hidden;text-overflow:ellipsis}\n.namebar .nb{padding:4px;display:grid;place-items:center;border-radius:7px;transition:background-color .2s var(--eo),color .2s var(--eo)}\n.namebar .nb:hover,.namebar .nb:focus-visible{background:var(--ho);color:var(--k)}\n.namebar .nb.on{background:var(--as);color:var(--pu-accent)}\n.namebar .nb[hidden]{display:none}\n\n/* The comment control: a small square of frosted glass tucked into the page's corner (flush right and bottom, its\ntop left rounded), with the open count inside a comment bubble. Pointed at, it reaches left just far enough to show\nits shortcut (and anything add-ons say). Its layers and numbers cross-fade in place. */\n.launch{position:fixed;right:0;bottom:var(--pu-lift);display:flex;flex-direction:row-reverse;align-items:center;border-top-left-radius:10px;pointer-events:auto;transform-origin:100% 100%;\nbackground:color-mix(in srgb,var(--su) 62%,transparent);-webkit-backdrop-filter:blur(10px) saturate(1.5);backdrop-filter:blur(10px) saturate(1.5);\ntransition:opacity var(--in) var(--eo),transform var(--mv) var(--eo),background-color .3s var(--eo),color .3s var(--eo),bottom var(--mv) var(--eio)}\n.launch:has(.mode.on){background:color-mix(in srgb,var(--pu-accent) 90%,transparent);color:var(--pu-on,#fff)}\n/* While All comments is open, the control is the panel's footer: it draws in, and the footer takes its place. */\n.layer.listing .launch{opacity:0;transform:scale(.6);pointer-events:none}\n.menu.inp{--b:60px;right:8px;z-index:1}\n.menu.inp :is([data-item=comment],[data-item=all]){display:none}\n.launch .mode{position:relative;display:grid;place-items:center;width:32px;height:32px;border-radius:10px 0 0}\n.mode>*,.cnt>*{grid-area:1/1}\n.mode>*{display:grid;place-items:center;transition:opacity var(--in) var(--eo)}\n.cnt,.has>.plus{opacity:0}\n.has>.cnt{opacity:1}\n.cnt>.n{font-size:11px;font-weight:500;line-height:1;margin:-1.2px 0 0 1.2px;font-variant-numeric:tabular-nums lining-nums;opacity:0;transition:opacity var(--in) var(--eo)}\n.w>.n{margin-top:-3.4px}\n.cnt>svg{transition:opacity var(--in) var(--eo)}\n.cnt>svg+svg,.cnt.w>svg{opacity:0}\n.cnt.w>svg+svg{opacity:1}\n.n.on{opacity:1}\n.launch .mode:focus-visible{outline:2px solid var(--pu-accent);outline-offset:-2px}\n/* Open threads on other slides or views: a small dot at the bubble's top right, easing in and out. */\n.mode>.dot{position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;background:var(--pu-accent);opacity:0;transition:opacity var(--in) var(--eo),background-color .3s var(--eo)}\n.mode.else>.dot{opacity:1}\n.mode.on>.dot{background:var(--pu-on,#fff)}\n/* What it reaches out to show when pointed at: the shortcut, after anything add-ons say. Its width eases to exactly what\nthe words need (a 0fr to 1fr column), so it opens and folds evenly, and it folds at once when the pointer leaves. */\n.ttip{display:grid;grid-template-columns:minmax(0,0fr);overflow:hidden;font-size:12px;color:var(--mu);pointer-events:none;opacity:0;transition:grid-template-columns var(--out) var(--ei),opacity var(--out) var(--ei)}\n.ttip>span{min-width:0;white-space:nowrap;padding-left:10px}\n.ttip small{font-size:12px}\n.ttip small,.mi .kc{color:var(--fa)}\n.launch:has(.mode.on) :is(.ttip,.ttip small){color:inherit}\n.launch:hover .ttip{grid-template-columns:minmax(0,1fr);opacity:1;transition:grid-template-columns var(--mv) var(--eo) .4s,opacity var(--in) var(--eo) .4s}\n.launch .mode[aria-expanded=true]+.ttip{grid-template-columns:minmax(0,0fr);opacity:0}\n@media (hover:none){.ttip,.tt,.cd>.thread .acts{display:none}}\n.menu{--b:calc(40px + var(--pu-lift));position:fixed;right:8px;bottom:var(--b);width:290px;border-radius:12px;padding:4px;pointer-events:none;opacity:0;transform:translateY(6px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.menu.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo)}\n@media (max-height:600px){.menu{max-height:calc(100% - var(--b) - 8px);overflow-y:auto;overscroll-behavior:contain}}\n/* Menu rows: one line each; the explanation is a tooltip beside the menu that eases in after a moment. */\n.mi{position:relative;display:flex;gap:10px;align-items:center;width:100%;min-height:34px;text-align:left;padding:6px 10px;border-radius:8px;transition:background-color .2s var(--eo)}\n.mi:hover,.mi:focus-visible{background:var(--so)}\n.mi svg{color:var(--mu);flex:none}\n.mi small{display:block;color:var(--fa);font-size:12px}\n.lb{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.ma{flex:none;display:grid;margin:-2px 0}\n.ma .av{width:20px;height:20px;font-size:11px}\n.mi .av svg{color:inherit}\n.sep{height:1px;margin:4px 10px;background:var(--ru)}\n/* Copy comments opens to its two choices beneath it, set in under it; folding and unfolding ease. */\n.subs{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows var(--in) var(--eo),opacity var(--in) var(--eo)}\n.subs.open{grid-template-rows:1fr;opacity:1}\n.subs>div{min-height:0;overflow:hidden}\n.subs .mi{padding-left:30px}\n.chev{display:grid;transition:transform var(--in) var(--eo)}\n[aria-expanded=true]>.chev{transform:rotate(90deg)}\n.tt{position:absolute;right:calc(100% + 14px);top:50%;translate:0 -50%;width:max-content;max-width:220px;padding:4px 9px;border-radius:8px;font-size:12px;line-height:1.4;\ncolor:var(--mu);pointer-events:none;opacity:0;transform:translateX(3px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.mi:hover>.tt,.mi:focus-visible>.tt{opacity:1;transform:none;transition:opacity var(--in) var(--eo) .5s,transform var(--in) var(--eo) .5s}\n@media (max-width:600px){.tt{right:8px;top:auto;bottom:100%;translate:none;transform:translateY(3px)}}\n/* Switches: a track and a knob that slides (cross-fades with reduced motion). */\n.sw{position:relative;flex:none;width:26px;height:16px;border-radius:8px;background:var(--ln);transition:background-color var(--mv) var(--eio)}\n.sw::before,.sw::after{content:\"\";position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);\ntransition:transform var(--mv) var(--eio),opacity var(--mv) var(--eio)}\n.sw::before{opacity:0;transform:translateX(10px)}\n[aria-checked=true]>.sw{background:var(--pu-accent)}\n[aria-checked=true]>.sw::after{transform:translateX(10px)}\n.tools{display:flex;flex:none;gap:2px}\n.tools[hidden]{display:none}\n.tool[aria-pressed=true]{background:var(--as);color:var(--pu-accent)}\n.note{display:block;padding:0 0 4px;font-size:12px;color:var(--fa)}\n.note[hidden]{display:none}\n.ov{position:absolute;inset:0;pointer-events:none;overflow:hidden}\n/* An add-on's panel (.xp) is the same full-height panel as All comments (.all), with its own body. */\n.xb{flex:1;overflow-y:auto;overscroll-behavior:contain;padding:4px 16px 16px;font-size:13px}\n.xb p{margin:0 0 10px}\n/* All comments: a full-height panel on the right that slides in (fades, with reduced motion). */\n.all,.xp{position:fixed;top:0;right:0;bottom:0;width:var(--pu-panel);display:flex;flex-direction:column;border-width:0 0 0 1px;opacity:0;transform:translateX(100%);\ntransition:transform var(--out) var(--ei),opacity var(--out) var(--ei)}\n.all.show,.xp.show{opacity:1;transform:none;pointer-events:auto;transition:transform var(--mv) var(--eo),opacity var(--in) var(--eo)}\n.all.full{width:100%}\n/* The header: no title, two filters (an icon and a word in a pill: grey off, a soft accent fill on) and Close. */\n.hd{display:flex;align-items:center;gap:4px;padding:8px 8px 6px}\n.sp{flex:1}\n.tg{position:relative;display:flex;align-items:center;gap:5px;height:28px;padding:0 11px 0 9px;border-radius:99px;white-space:nowrap;line-height:1;color:var(--mu);transition:background-color .2s var(--eo),color .2s var(--eo)}\n.tg:hover{background:var(--ho);color:var(--k)}\n.tg[aria-pressed=true]{background:var(--as);color:var(--pu-accent)}\n.tg[aria-pressed=true]:hover{background:color-mix(in srgb,var(--pu-accent) 20%,transparent)}\n.tg:focus-visible{outline:2px solid var(--pu-accent);outline-offset:1px}\n/* What each filter does: a tooltip under it that eases in after a moment, on hover or focus. */\n.tg::after{content:attr(data-tip);position:absolute;left:0;top:calc(100% + 4px);z-index:3;width:max-content;max-width:220px;padding:4px 9px;border:1px solid var(--ln);border-radius:8px;background:var(--su);box-shadow:var(--sh);font-size:12px;line-height:1.4;color:var(--mu);pointer-events:none;opacity:0;transform:translateY(-3px);transition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.tg:not([aria-pressed=true]):is(:hover,:focus-visible)::after{opacity:1;transform:none;transition:opacity var(--in) var(--eo) .4s,transform var(--in) var(--eo) .4s}\n.list{flex:1;overflow-y:auto;overscroll-behavior:contain;padding:4px 8px 8px;background:var(--so)}\n/* Threads in the panel are the same cards; opened, a card shows the thread beneath the words it's about. */\n.cd{position:relative;margin-top:6px;border:1px solid var(--ln);border-radius:10px}\n/* What filters take away or bring back folds out or in, and a card opening or closing eases to its new height. */\n.list :is(.cd,[role=listitem],.sec){transition:all var(--mv) var(--eio)}\n.list .out{opacity:0!important;margin-top:0;padding-block:0;border-width:0;overflow:hidden}\n.cd.open{border-color:transparent;box-shadow:var(--sh)}\n.cd.done{--o:.6}\n/* Closed, its button lies over it (choosing the card opens it), beneath its actions and what they open. */\n.cd>.mi{position:absolute;inset:0;border-radius:10px;background:none}\n.cd>.thread :is(.acts,.refs,.edit){position:relative;z-index:1}\n.cd:not(.open,.new):is(:hover,:has(>.mi:focus-visible)){--bg:var(--so)}\n.cd.open>.mi{display:none}\n.cd.open .root>.hdr{cursor:pointer}\n.cd.new,.xr,.cd>.thread{padding:8px 10px 10px}\n/* The footer: who you are, Comment (its shortcut and switch), and \u22EF for the menu. */\n.pf{display:flex;align-items:center;gap:8px;min-height:52px;padding:0 8px 0 14px;border-top:1px solid var(--ln)}\n.fs{display:flex;align-items:center;gap:6px;padding:4px 6px;border-radius:8px;font-size:13px;transition:background-color .2s var(--eo)}\n.fs:hover,.fs:focus-visible{background:var(--ho)}\n.fs small{font-size:12px;color:var(--fa)}\n.pf .ib{width:30px;height:30px}\n/* The line from an open thread in the panel to its place on the page. */\n.cx{position:fixed;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none;opacity:0;transition:opacity var(--in) var(--eo)}\n.cx.show{opacity:1}\n.cx path{fill:none;stroke:var(--pu-accent);stroke-width:1.5;stroke-linecap:round;opacity:.7}\n.cx circle{fill:var(--pu-accent)}\n.layer.listing .col{opacity:0;transition:opacity var(--out) var(--ei)}\n.sec{padding:8px 10px 2px;font-size:12px;color:var(--fa)}\n.ag{display:flex;align-items:center;gap:8px;padding:6px 14px;font-size:12px;color:var(--fa);border-bottom:1px solid var(--ln)}\n.ag[hidden]{display:none}\n.lns{display:flex;flex-direction:column}\n.ln{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows var(--in) var(--eo),opacity var(--in) var(--eo)}\n.ln.show{grid-template-rows:1fr;opacity:1}\n.ln>.lw{overflow:hidden;min-height:0}\n.ag button{margin-left:auto;flex:none;padding:0 6px;border-radius:6px;color:var(--fa);transition:color .2s var(--eo),background-color .2s var(--eo)}.ag button:hover:not(:disabled),.ag button:focus-visible{color:var(--pu-accent);background:var(--as)}.ag button:disabled{opacity:.5;cursor:default}\n.adr{margin:8px 0 0 14px;padding:8px 10px;border-radius:8px;background:var(--so);font-size:13px;color:var(--k);animation:pu-in var(--mv) var(--eo) both}\n.adr small{display:block;font-size:12px;color:var(--fa)}\n.adr .go{display:flex;gap:6px;margin-top:6px}\n.adr .go button{padding:2px 8px;border-radius:6px;font-size:12px;color:var(--mu);transition:color .2s var(--eo),background-color .2s var(--eo)}.adr .go button:hover,.adr .go button:focus-visible{color:var(--pu-accent);background:var(--as)}\n@keyframes pu-in{0%{opacity:0;transform:translateY(3px)}100%{opacity:1;transform:none}}\n.sec b{margin-left:6px;font-weight:500;color:var(--pu-accent)}\n/* Messages sit beside the comment control, never over the page's own bottom bar; beside the panel while it is open,\nand above its footer when it fills the screen. */\n.toast{--r:40px;position:fixed;right:var(--r);bottom:calc(4px + var(--pu-lift));max-width:min(320px,calc(100vw - var(--r) - 16px));border-radius:10px;padding:8px 14px;font-size:13px;opacity:0;transform:translateY(6px);transition:.3s var(--eo)}\n.toast.show{opacity:1;transform:none}\n/* While All comments is open, messages sit inside the panel above its footer, on top of it: never over the page,\nnor a deck's own controls in the space beside it. */\n.layer:is(.listing,:has(.xp.show)) .toast{--r:12px;bottom:64px;max-width:min(320px,calc(var(--pu-panel) - 24px));z-index:2}\n/* While the menu is open, beside it (above it on a narrow screen), never under it. */\n.layer:not(.listing):has(.menu.show) .toast{--r:314px}\n@media (max-width:640px){.layer:not(.listing):has(.menu.show) .toast{--r:12px;bottom:auto;top:12px}}\n\n/* Touch: everything a finger presses is at least 44 px across. A bubble keeps its small look round a larger hit area.\nThe control is 44 px, so the menu and messages sit further from it. Shortcuts aren't shown where there is no keyboard. */\n@media (pointer:coarse){\n.mi,.ib,.rxo,.refs .ref,.mnl li,.bts button,.tg,.fs,.pm button,.ta,.nb,.selbar button,button.me,.say button,.line,.seen button,.ag button,.go button{min-height:44px}\n.ib,.rxo,.refs .ref,.nb,.selbar button,button.me,.ta{min-width:44px}\n.bub::before{content:\"\";position:absolute;inset:-14px;border-radius:50%}\n.row:focus-within .bts,.row.has .bts{max-height:52px}\n.hd{padding:4px 8px}\n.toast{--r:52px;display:flex;align-items:center;min-height:44px;padding:4px 14px;line-height:1.25}\n.ta{display:grid;place-items:center;margin:-5px -10px -5px 6px;padding:0 10px}\n.launch .mode{width:44px;height:44px}\n.menu{--b:calc(52px + var(--pu-lift))}\n}\n@media (pointer:coarse) and (hover:none){.ks{display:none}}\n\n/* Keyboard focus is always plainly marked: a 2 px ring in the accent, which reads at 4.5 to 1 on Pipeup's surfaces. */\n.layer :is(button,a):not(.mi,.opn,.mode,.tg):focus-visible{outline:2px solid var(--pu-accent);outline-offset:1px}\n.layer .mi:focus-visible{outline:2px solid var(--pu-accent);outline-offset:-2px}\n/* A look that differs from the page's keeps its see-through parts solid: a dimmed card dims its words, not the card. */\n.flip .launch{background:var(--su)}\n.flip :is(.th,.cd){opacity:1}\n.flip :is(.th,.cd)>*{opacity:var(--o,1);transition:opacity var(--in) var(--eo)}\n\n@media (forced-colors: active){\n.pick.kf{border:3px solid Highlight}\n.layer :is(.ib,.mi,.nb,.tg,.fs,.selbar button,.say button,.xb button):focus-visible{outline:2px solid Highlight}\n/* Switches, the filters, your own reactions and comment mode draw in system colours, so every state shows. */\n.sw{forced-color-adjust:none;border:1px solid CanvasText;background:Canvas}\n.sw::before,.sw::after{top:1px;left:1px;background:CanvasText}\n[aria-checked=true]>.sw{background:Highlight;border-color:Highlight}\n[aria-checked=true]>.sw::before,[aria-checked=true]>.sw::after{background:HighlightText}\n.layer :is(.tg,.rxo,.rx)[aria-pressed=true],.launch:has(.mode.on){forced-color-adjust:none;background:Highlight;color:HighlightText;border-color:Highlight}\n}\n\n@media (prefers-reduced-motion: reduce){\n.ln,.subs{transition-property:opacity}\n@keyframes pu-in{0%{opacity:0}100%{opacity:1}}\n.bub,.bub.in,.bub.in:hover,.bub.on,.tip,.pop,.selbar,.menu,.all,.xp,.tt,.toast,.ref .rc,.rxp,.mnl{transform:none!important}\n.ttip{transition-property:opacity!important}\n.dlg{transform:translate(-50%,0)!important}\n.sw::after{transform:none!important;transition-property:opacity}\n[aria-checked=true]>.sw::after{opacity:0}\n[aria-checked=true]>.sw::before{opacity:1}\n.th,.th.long .root>.tx,.mr,.list :is(.cd,[role=listitem],.sec){transition-property:opacity,box-shadow}\n.tip.show,.toast{transition-property:opacity}\n.pick,.pick.show{transition:opacity .16s ease-in-out}\n.all,.all.show,.xp,.xp.show{transition-property:opacity}\n.namebar,.namebar.show{transform:none!important;transition:opacity .16s ease-in-out}\n.av,.nf,.launch{transform:none!important}\n@keyframes pu-pulse{0%{opacity:0}35%{opacity:.85}100%{opacity:0}}\n}\n";
|
|
2
|
+
export declare const STYLES = "\n/* Inherited page styles are reset on .layer below; custom properties pass through all:initial. */\n:host{all:initial;direction:ltr;unicode-bidi:normal}\n*{box-sizing:border-box}\nbutton{appearance:none;font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}\nsvg{display:block}\n.layer{all:initial;direction:ltr;unicode-bidi:normal;display:block;position:fixed;inset:0;pointer-events:none;font:13px/1.5 var(--pu-font,system-ui,sans-serif);color:var(--k);\n--k:#2C2C2A;--mu:#5F5E5A;--fa:#6B6A64;--ln:#E5E3DA;--ru:#ECEAE2;--so:#FAFAF7;--su:#FFFFFF;--ho:#F1EFE8;\n--as:color-mix(in srgb,var(--pu-accent,#534AB7) 12%,transparent);\n--sh:0 8px 28px rgba(44,44,42,.10);\n--in:.26s;--mv:.34s;--out:.2s;--pl:1.2s;\n--eo:cubic-bezier(.22,.61,.36,1);--eio:cubic-bezier(.4,0,.2,1);--ei:cubic-bezier(.4,0,1,1);\n--pu-text:var(--k);--pu-muted:var(--mu);--pu-faint:var(--fa);--pu-line:var(--ln);--pu-surface:var(--su);--pu-soft:var(--so);--pu-hover:var(--ho);--pu-shadow:var(--sh);--pu-ease:var(--eo)}\n.layer{transition:opacity .24s var(--eo)}.layer.fading{opacity:0;transition-duration:.16s;transition-timing-function:var(--ei)}\n.layer.dark{--k:#ECEBE6;--mu:#B4B2A9;--fa:#9A9892;--ln:#3A3936;--ru:#34332F;--so:#22221F;--su:#1B1B19;--ho:#2C2C29;--sh:0 8px 28px rgba(0,0,0,.45)}\n.layer.hidden .bub,.layer.hidden .col,.layer.hidden .pop,.layer.hidden .tip,.layer.hidden .mark,.layer.hidden .selbar{opacity:0!important;pointer-events:none!important}\n/* While a phone's on-screen keyboard is up for a Pipeup box, the comment control and its messages fade out of the little\nroom left above it. */\n.layer.kb :is(.launch,.toast){opacity:0!important;pointer-events:none!important;transition:opacity var(--out) var(--ei)!important}\n\n.tx{font-size:14px;line-height:1.5;color:var(--k);white-space:pre-wrap;overflow-wrap:anywhere}\n.tx.del,.rest,.ctx,.ago{color:var(--fa)}\n.rest,.ago{font-size:12px}\n.rest{display:block;margin-top:3px}\n/* A card's top line: avatar, who (cut short on one line, never wrapped), how long ago, then its actions. */\n.hdr{position:relative;display:flex;align-items:center;gap:7px;min-height:22px}\n.who{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:600;color:var(--k)}\n.ago{flex:none;white-space:nowrap}\n.ago::before{content:\"\u00B7\";margin-right:6px}\n.root>.tx,.it>.tx,.root>.ctx{margin-top:2px}\n.ctx[hidden]{display:none}\n.ctx{font-size:12px;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.cd>.thread .tx,.clamp{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n/* A long comment at rest in the column: its first four lines, fading out, then \"more\"; opened, it eases out to all of it. */\n.th.long .root>.tx{max-height:var(--full);overflow:hidden;transition:max-height var(--mv) var(--eio)}\n.th.long:not(.on) .root>.tx{max-height:84px;mask-image:linear-gradient(#000 calc(100% - 21px),transparent)}\n.mr{display:grid;grid-template-rows:0fr;opacity:0;font-size:12px;color:var(--pu-accent);text-align:end;transition:grid-template-rows var(--mv) var(--eio),opacity var(--in) var(--eo)}\n.mr>span{min-height:0;overflow:hidden}\n.th.long:not(.on) .mr{grid-template-rows:1fr;opacity:1}\n.tx a{color:var(--pu-accent);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}\n\n/* Actions sit at the card's top right: always on an open card, on hover (or focus) on one at rest. In All comments a\nclosed card keeps them while its \u22EF menu is open, and focus put there for the keyboard (not a click) shows them. After\nResolve (.still) the card that moves up under the pointer keeps them from it until it moves; keyboard focus shows them. */\n.acts{margin-left:auto;display:flex;flex:none;transition:opacity var(--in) var(--eo)}\n.th:not(.on):not(:hover):not(:focus-within) .acts,.cd:not(.open):not(:hover):not(:has(:focus-visible,.pm)) .acts,.still .th:not(.on):not(:has(:focus-visible)) .acts,.still .cd:not(.open):not(:has(:focus-visible,.pm)) .acts{opacity:0;pointer-events:none}\n/* On a closed card they lie over the end of the top line, on the card's own colour, so the name has the whole line\nwhile they're hidden and the card never changes size as they ease in. They take presses only once eased in: a click as\nthe pointer arrives, or a tap (which hovers as it lands), opens the card. */\n.th:not(.on) .acts,.cd:not(.open) .acts{position:absolute;right:0;padding-left:16px;background:linear-gradient(90deg,transparent,var(--bg) 14px);transition:opacity var(--in) var(--eo),pointer-events 0s var(--in);transition-behavior:allow-discrete}\n.th.on .rest{display:none}\n/* A comment's \u22EF menu: Copy thread, Edit, Delete (asked twice). */\n.pm{position:absolute;right:0;top:100%;z-index:5;display:flex;flex-direction:column;min-width:150px;padding:4px;border:1px solid var(--ln);border-radius:10px;background:var(--su);box-shadow:var(--sh)}\n.pm.in{animation:pu-in var(--in) var(--eo) both}\n.pm button{padding:6px 10px;border-radius:7px;text-align:left;font-size:13px;transition:background-color .2s var(--eo),color .2s var(--eo)}\n.pm button:hover,.pm button:focus-visible{background:var(--ho)}\n.pm .dl{color:#C9402F}.dark .pm .dl{color:#F08A7E}\n.edit{margin-top:2px}\n.ib{width:24px;height:22px;display:grid;place-items:center;border-radius:6px;color:var(--mu);transition:background-color .2s var(--eo),color .2s var(--eo)}\n.ib:hover,.ib:focus-visible{background:var(--ho);color:var(--k)}\n\n/* Replies: one level in, oldest first; the reply line ends the thread at the same indent. */\n.rps,.rbox{padding-left:14px}\n.rps .it{padding-top:8px}\n.more{display:grid;grid-template-rows:1fr;transition:grid-template-rows var(--mv) var(--eio)}\n.more>div{overflow:hidden;min-height:0}\n.th:not(.on) .more{grid-template-rows:0fr}\n\n/* Writing boxes: a rounded box that says what it's for, then Cancel and Send (named) while it is in use. */\n.row{position:relative;padding-top:6px}\n.line{display:flex;align-items:center;gap:6px;padding:3px 12px;border:1px solid var(--ln);border-radius:16px;cursor:text;transition:border-color var(--in) var(--eo),box-shadow var(--in) var(--eo)}\n.line:hover{border-color:var(--mu)}\n.line:focus-within{border-color:var(--pu-accent);box-shadow:0 0 0 1px var(--pu-accent)}\n.input{flex:1;min-width:0;height:24px;display:block;border:0;outline:none;resize:none;overflow:hidden;\nfont:inherit;font-size:14px;line-height:1.5;padding:1px 0;color:var(--k);background:transparent}\n.input::placeholder{color:var(--fa);opacity:1}\n.bts{display:flex;justify-content:flex-end;gap:4px;max-height:0;opacity:0;overflow:hidden;transition:max-height var(--in) var(--eo),opacity var(--in) var(--eo),padding var(--in) var(--eo)}\n.row:focus-within .bts,.row.has .bts{max-height:40px;opacity:1;padding-top:4px}\n.bts button{padding:2px 10px;border-radius:14px;font-size:13px;font-weight:600;color:var(--pu-accent);transition:background-color .2s var(--eo),color .2s var(--eo)}\n.cnl:hover,.cnl:focus-visible{background:var(--as)}\n.send{background:var(--pu-accent);color:var(--pu-on,#fff)!important}\n.send:not(.show){background:var(--ru);color:var(--fa)!important;cursor:default}\n.ed{display:flex;gap:10px;align-items:center;min-height:34px;padding:6px 10px}\n.ed .input,.nf .input{font-size:13px;height:22px;border-bottom:1px solid var(--ln)}\n.ed .input:focus,.nf .input:focus{border-bottom-color:var(--pu-accent)}\n\n/* Avatars: a squircle with the writer's animal (or initial) on a soft colour, at the start of the card's top line. */\n.av{flex:none;display:grid;place-items:center;width:22px;height:22px;border-radius:32%;\nfont-size:12px;font-weight:600;line-height:1;opacity:0;transform:scale(.85);transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.av.in{opacity:1;transform:none}\n/* The animal nearly fills its tint (its drawing has room round it in its 24 grid), in a lighter line so it stays thin. */\n.av svg{width:122%;height:122%;stroke-width:1.3}\n/* Ten colours (.c0 Red to .c9 Grey, as COLOURS): a soft tint and a dark drawing, swapped round on dark pages. */\n.av{--av-l:92%;--av-d:30%;--s:60%;background:hsl(var(--h) var(--s) var(--av-l));color:hsl(var(--h) var(--s) var(--av-d))}\n.dark .av{--av-l:20%;--av-d:78%}\n/* An AI's reply: a plain disc with a violet ring, all inside the avatar's own box so nothing is cropped. */\n.av.ai{position:relative;border-radius:50%;background:var(--su);color:var(--pu-accent);font-size:9px;letter-spacing:.02em}\n.av.ai::before{content:\"\";position:absolute;inset:3px;border-radius:50%;border:1.5px solid var(--pu-accent);pointer-events:none}\n.refs{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;white-space:normal}\n.refs .ref{display:inline-flex;align-items:center;gap:5px;max-width:160px;padding:1px 9px;border:1px solid var(--ln);border-radius:999px;background:var(--so);color:var(--mu);font:inherit;font-size:11.5px;line-height:1.6;text-decoration:none;cursor:pointer;transition:background-color .2s var(--eo),color .2s var(--eo),border-color .2s var(--eo)}\n.refs .ref:hover,.refs .ref:focus-visible{background:var(--as);color:var(--pu-accent);border-color:var(--pu-accent)}\n.ref span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.rxp{position:fixed;width:320px;height:340px;border-radius:12px;overflow:hidden;pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.rxp.show{opacity:1;transform:none;pointer-events:auto}\n.mn{border-radius:4px;padding:0 2px;background:var(--as);color:var(--pu-accent)}\n.mn.me{font-weight:600}\n.mnl{position:absolute;left:0;bottom:100%;margin:0 0 4px;padding:4px;list-style:none;min-width:180px;max-width:100%;border:1px solid var(--ln);border-radius:10px;background:var(--su);box-shadow:var(--sh);opacity:0;transform:translateY(4px);pointer-events:none;z-index:4;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.mnl.show{opacity:1;transform:none;pointer-events:auto}\n.mnl li{display:flex;align-items:baseline;gap:8px;padding:5px 8px;border-radius:6px;font-size:13px;color:var(--k);cursor:pointer}\n.mnl li small{font-size:11px;color:var(--fa)}\n.mnl li.on,.mnl li:hover{background:var(--as);color:var(--pu-accent)}\n.dlg{position:fixed;left:50%;top:18vh;width:min(380px,calc(100vw - 32px));padding:16px 18px;border:1px solid var(--ln);border-radius:14px;background:var(--su);box-shadow:var(--sh);color:var(--k);opacity:0;transform:translate(-50%,6px);pointer-events:none;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.dlg.show{opacity:1;transform:translate(-50%,0);pointer-events:auto}\n.toast.act{display:flex;align-items:center}.toast.show .ta{pointer-events:auto}\n/* Faded, its button is no longer a Tab stop (hidden once the fade is over). */\n.toast .ta{transition:visibility 0s .3s}.toast:not(.show) .ta{visibility:hidden}.toast.show .ta{transition-delay:0s}\n/* By touch, comment mode's hint is filled with the accent; once a tap has opened a box its words fold away (their column\neases to nothing) and Done stays. */\n.toast.tap{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;background:var(--pu-accent);border-color:var(--pu-accent);color:var(--pu-on,#fff);font-size:15px;font-weight:500;transition:opacity .3s var(--eo),transform .3s var(--eo),grid-template-columns var(--mv) var(--eio),padding var(--mv) var(--eio)}\n.toast.tap .tw{min-width:0;max-height:4em;overflow:hidden;text-wrap:balance;transition:opacity var(--out) var(--ei),max-height var(--mv) var(--eio)}\n.toast.tap .ta{color:inherit;font-weight:600}\n.toast.tap.taught{grid-template-columns:minmax(0,0fr) auto;padding-left:4px}\n.toast.tap.taught .tw{opacity:0;max-height:0}\n.ta{margin-left:4px;color:var(--pu-accent);text-decoration:underline;text-underline-offset:2px}\n.rx .n{font-size:11px;font-variant-numeric:tabular-nums}\n.rx.mine{background:var(--as);color:var(--pu-accent);border-color:var(--pu-accent)}\n.rx:disabled{cursor:default;opacity:.7}\n.rx{-webkit-touch-callout:none;-webkit-user-select:none}\n.rx.new,.rxq.new{animation:pu-in var(--mv) var(--eo) backwards}\n.rxs{align-items:center}\n.rxq{display:inline-flex;gap:2px}\n.rxo{padding:2px 5px;border-radius:8px;font-size:16px;line-height:1.3;transition:background-color .2s var(--eo)}\n.rxo:hover,.rxo:focus-visible,.rxo[aria-pressed=true]{background:var(--as)}\n.refs .ref{position:relative}.ref .rc{position:absolute;left:0;top:calc(100% + 6px);z-index:3;width:max-content;max-width:min(240px,70vw);padding:6px 9px;border:1px solid var(--ln);border-radius:8px;background:var(--su);box-shadow:var(--sh);color:var(--k);font-size:12px;line-height:1.45;white-space:normal;text-align:left;overflow:visible;opacity:0;visibility:hidden;transform:translateY(-3px);pointer-events:none;transition:opacity .2s var(--eo),transform .2s var(--eo),visibility 0s .2s}.ref:hover .rc,.ref:focus-visible .rc,.ref.held .rc{opacity:1;visibility:visible;transform:none;transition-delay:0s}\n.ref .sl{width:10px;height:7px;border:1.3px solid currentColor;border-radius:2px;flex:none}\n.seen{display:flex;align-items:center;gap:6px;padding:6px 0 0 14px;font-size:12px;color:var(--fa)}\n.seen button{margin-left:auto;padding:0 6px;border:0;border-radius:6px;background:none;color:var(--fa);font:inherit;cursor:pointer;transition:color .2s var(--eo),background-color .2s var(--eo)}.seen button:hover,.seen button:focus-visible{color:var(--pu-accent);background:var(--as)}\n.seen i{width:12px;height:12px;border-radius:50%;border:1.5px solid var(--pu-accent);flex:none}\n.c0{--h:0}.c1{--h:25}.c2{--h:50}.c3{--h:130}.c4{--h:175}.c5{--h:215}.c6{--h:270}.c7{--h:330}.c8{--h:28;--s:35%}.c9{--h:220;--s:8%}\nbutton.me{flex:none;display:grid;place-items:center}\nbutton.me>.av{grid-area:1/1}\n/* Who you are, at the top of a new comment; a name field eases open in its place. */\n.you{flex:1;display:grid;min-width:0;min-height:22px;font-size:12px;color:var(--fa)}\n.you .nm{font-size:13px;font-weight:600;color:var(--k)}\n.you>*{grid-area:1/1;display:flex;align-items:center;min-width:0;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.say{white-space:pre;overflow:hidden}\n.nm{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.say button{flex:none}\n.say button{color:var(--mu);text-decoration:underline;text-decoration-color:var(--ln);text-underline-offset:2px;transition:color .2s var(--eo)}\n.say button:hover,.say button:focus-visible{color:var(--pu-accent)}\n.nf{opacity:0;transform:translateY(-4px);pointer-events:none}\n.nf .input{font-size:13px;height:24px}\n.you.naming .nf{opacity:1;transform:none;pointer-events:auto}\n.you.naming .say{opacity:0;pointer-events:none}\n\n/* Bubbles, tips, popovers, marks, pulses. */\n.bub{position:fixed;left:0;top:0;width:20px;height:20px;margin:-20px 0 0 -2px;border-radius:50% 50% 50% 0;background:var(--pu-accent);\nborder:2px solid var(--su);box-shadow:0 1px 4px rgba(0,0,0,.2);pointer-events:auto;opacity:0;transform:translateY(-6px) scale(.9);transform-origin:2px 20px;\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.bub.in{opacity:1;transform:none;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.bub.in:hover,.bub.on{transform:scale(1.18)}\n.bub.done{background:var(--fa)}\n.bub.ghost{pointer-events:none}\n.tip,.pop,.menu,.all,.xp,.toast,.selbar,.namebar,.tt,.rxp{background:var(--su);border:1px solid var(--ln);box-shadow:var(--sh)}\n.tip{position:fixed;max-width:260px;border-radius:10px;padding:7px 10px;opacity:0;transform:translateY(3px);\ntransition:opacity .22s var(--eo),transform .26s var(--eo)}\n.tip.show{opacity:1;transform:none;pointer-events:auto;cursor:pointer;\ntransition:opacity .22s var(--eo),transform .26s var(--eo),left var(--mv) var(--eio),top var(--mv) var(--eio)}\n.pop{position:fixed;width:var(--pu-pop);border-radius:12px;padding:8px 10px 10px;pointer-events:none;opacity:0;transform:translateY(6px) scale(.98);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.pop.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo)}\n.pop.show.glide{transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo),left var(--mv) var(--eio),top var(--mv) var(--eio)}\n.mark{position:fixed;border:2px solid color-mix(in srgb,var(--pu-accent) 50%,transparent);background:var(--as);border-radius:8px;opacity:0;\ntransition:opacity .3s var(--eo)}\n.mark.show{opacity:1}\n.pulse{position:fixed;border:2px solid var(--pu-accent);border-radius:8px;background:var(--as);animation:pu-pulse var(--pl) var(--eio) forwards}\n@keyframes pu-pulse{0%{opacity:0;transform:scale(.985)}35%{opacity:.85;transform:scale(1)}100%{opacity:0;transform:scale(1.02)}}\n\n/* Document column. */\n.col{position:fixed;left:0;top:0;pointer-events:none;transition:opacity var(--in) var(--eo)}\n/* Each thread is a compact card; the open one lifts with a soft shadow. */\n.th,.cd{--bg:var(--su);background:var(--bg);opacity:var(--o,1)}\n.th{position:absolute;left:0;right:0;top:0;padding:8px 10px 10px;border:1px solid var(--ln);border-radius:10px;pointer-events:auto;cursor:pointer;\ntransition:transform var(--mv) var(--eio),box-shadow var(--in) var(--eo),border-color var(--in) var(--eo),opacity var(--in) var(--eo)}\n.th.hot{border-color:var(--mu)}\n.th.on{border-color:transparent;box-shadow:var(--sh);cursor:default}\n.th.dim{--o:.45}\n.th.resolved:not(.on):not(.hot){--o:.6}\n.th.lost .ctx{white-space:normal}\n.th.wait{opacity:0!important;pointer-events:none}\n.th:is(.out,.hop){opacity:0!important;pointer-events:none;transition:opacity var(--out) var(--ei)}\n/* A closed thread's button has no box of its own: the thread shows its focus. */\n.th:has(.opn:focus-visible){outline:2px solid var(--pu-accent);outline-offset:2px}\n\n/* Selection bar. */\n.selbar{position:fixed;display:flex;border-radius:10px;padding:2px;opacity:0;transform:translateY(4px);pointer-events:none;\ntransition:opacity var(--in) var(--eo),transform .3s var(--eo)}\n.selbar.show{opacity:1;transform:none;pointer-events:auto}\n.selbar button{width:32px;height:30px;display:grid;place-items:center;border-radius:8px;color:var(--pu-accent);transition:background-color .2s var(--eo)}\n.selbar button:hover,.selbar button:focus-visible{background:var(--as)}\n\n/* Comment mode's outline: glides between blocks; solid accent once chosen. */\n.pick{position:fixed;left:0;top:0;border:2px solid color-mix(in srgb,var(--pu-accent) 70%,transparent);background:color-mix(in srgb,var(--pu-accent) 6%,transparent);\nborder-radius:8px;pointer-events:none;opacity:0;transition:opacity var(--out) var(--ei),border-color var(--out) var(--ei),border-width var(--out) var(--ei),box-shadow var(--out) var(--ei)}\n.pick.show{opacity:1;transition-duration:var(--in);transition-timing-function:var(--eo)}\n.pick.show.glide{transition-property:all;transition-duration:var(--mv);transition-timing-function:var(--eio)}\n.pick.on{border-color:var(--pu-accent)}\n.pkw{position:fixed;left:0;top:0;border:2px dashed color-mix(in srgb,var(--pu-accent) 70%,transparent);border-radius:8px;pointer-events:none;opacity:0;transition:opacity var(--out) var(--ei)}\n.pkw.show{opacity:.6;transition:opacity var(--in) var(--eo)}\n.draft{transition:opacity var(--in) var(--eo)}.draft.wait:not(:focus-within){opacity:.6}\n/* The block cursor: its focus is drawn on the outline (3px accent with a surface halo, 3:1 on any page); the\nmarkers that hold focus are invisible. */\n.pick.kf{border:3px solid var(--pu-accent);box-shadow:0 0 0 2px var(--su)}\n.km{position:fixed;left:0;top:0;pointer-events:none;outline:none}\n.sr,.mn-sr,.hh{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}\n.namebar{position:fixed;left:0;top:0;display:flex;align-items:center;gap:2px;max-width:calc(100% - 16px);padding:2px 2px 2px 10px;border-radius:10px;font-size:12px;color:var(--mu);\nwhite-space:nowrap;pointer-events:none;opacity:0;transform:translateY(4px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.namebar.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform .3s var(--eo)}\n.namebar.show.glide{transition-property:all;transition-duration:var(--mv);transition-timing-function:var(--eio)}\n/* It sits over the page's words beside its block: pointed at anywhere but its icons, it fades so they can be read. */\n.namebar:hover:not(:has(.nb:hover)){opacity:.15}\n.namebar .lbl{margin-right:6px;max-width:260px;overflow:hidden;text-overflow:ellipsis}\n.namebar .nb{padding:4px;display:grid;place-items:center;border-radius:7px;transition:background-color .2s var(--eo),color .2s var(--eo)}\n.namebar .nb:hover,.namebar .nb:focus-visible{background:var(--ho);color:var(--k)}\n.namebar .nb.on{background:var(--as);color:var(--pu-accent)}\n.namebar .nb[hidden]{display:none}\n\n/* The comment control: a small square of frosted glass tucked into the page's corner (flush right and bottom, its\ntop left rounded), with the open count inside a comment bubble. Pointed at, it reaches left just far enough to show\nits shortcut (and anything add-ons say). Its layers and numbers cross-fade in place. */\n.launch{position:fixed;right:0;bottom:var(--pu-lift);display:flex;flex-direction:row-reverse;align-items:center;border-top-left-radius:10px;pointer-events:auto;transform-origin:100% 100%;\nbackground:color-mix(in srgb,var(--su) 62%,transparent);-webkit-backdrop-filter:blur(10px) saturate(1.5);backdrop-filter:blur(10px) saturate(1.5);\ntransition:opacity var(--in) var(--eo),transform var(--mv) var(--eo),background-color .3s var(--eo),color .3s var(--eo),bottom var(--mv) var(--eio)}\n.launch:has(.mode.on){background:color-mix(in srgb,var(--pu-accent) 90%,transparent);color:var(--pu-on,#fff)}\n/* While All comments is open, the control is the panel's footer: it draws in, and the footer takes its place. */\n.layer.listing .launch{opacity:0;transform:scale(.6);pointer-events:none}\n.menu.inp{--b:60px;right:8px;z-index:1}\n.menu.inp :is([data-item=comment],[data-item=all]){display:none}\n.launch .mode{position:relative;display:grid;place-items:center;width:32px;height:32px;border-radius:10px 0 0}\n.mode>*,.cnt>*{grid-area:1/1}\n.mode>*{display:grid;place-items:center;transition:opacity var(--in) var(--eo)}\n.cnt,.has>.plus{opacity:0}\n.has>.cnt{opacity:1}\n.cnt>.n{font-size:11px;font-weight:500;line-height:1;margin:-1.2px 0 0 1.2px;font-variant-numeric:tabular-nums lining-nums;opacity:0;transition:opacity var(--in) var(--eo)}\n.w>.n{margin-top:-3.4px}\n.cnt>svg{transition:opacity var(--in) var(--eo)}\n.cnt>svg+svg,.cnt.w>svg{opacity:0}\n.cnt.w>svg+svg{opacity:1}\n.n.on{opacity:1}\n.launch .mode:focus-visible{outline:2px solid var(--pu-accent);outline-offset:-2px}\n/* Open threads on other slides or views: a small dot at the bubble's top right, easing in and out. */\n.mode>.dot{position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;background:var(--pu-accent);opacity:0;transition:opacity var(--in) var(--eo),background-color .3s var(--eo)}\n.mode.else>.dot{opacity:1}\n.mode.on>.dot{background:var(--pu-on,#fff)}\n/* What it reaches out to show when pointed at: the shortcut, after anything add-ons say. Its width eases to exactly what\nthe words need (a 0fr to 1fr column), so it opens and folds evenly, and it folds at once when the pointer leaves. */\n.ttip{display:grid;grid-template-columns:minmax(0,0fr);overflow:hidden;font-size:12px;color:var(--mu);pointer-events:none;opacity:0;transition:grid-template-columns var(--out) var(--ei),opacity var(--out) var(--ei)}\n.ttip>span{min-width:0;white-space:nowrap;padding-left:10px}\n.ttip small{font-size:12px}\n.ttip small,.mi .kc{color:var(--fa)}\n.launch:has(.mode.on) :is(.ttip,.ttip small){color:inherit}\n.launch:hover .ttip{grid-template-columns:minmax(0,1fr);opacity:1;transition:grid-template-columns var(--mv) var(--eo) .4s,opacity var(--in) var(--eo) .4s}\n.launch .mode[aria-expanded=true]+.ttip{grid-template-columns:minmax(0,0fr);opacity:0}\n@media (hover:none){.ttip,.tt,.cd>.thread .acts{display:none}}\n.menu{--b:calc(40px + var(--pu-lift));position:fixed;right:8px;bottom:var(--b);width:290px;border-radius:12px;padding:4px;pointer-events:none;opacity:0;transform:translateY(6px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.menu.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo)}\n@media (max-height:600px){.menu{max-height:calc(100% - var(--b) - 8px);overflow-y:auto;overscroll-behavior:contain}}\n/* Menu rows: one line each; the explanation is a tooltip beside the menu that eases in after a moment. */\n.mi{position:relative;display:flex;gap:10px;align-items:center;width:100%;min-height:34px;text-align:left;padding:6px 10px;border-radius:8px;transition:background-color .2s var(--eo)}\n.mi:hover,.mi:focus-visible{background:var(--so)}\n.mi svg{color:var(--mu);flex:none}\n.mi small{display:block;color:var(--fa);font-size:12px}\n.lb{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.ma{flex:none;display:grid;margin:-2px 0}\n.ma .av{width:20px;height:20px;font-size:11px}\n.mi .av svg{color:inherit}\n.sep{height:1px;margin:4px 10px;background:var(--ru)}\n/* Copy comments opens to its two choices beneath it, set in under it; folding and unfolding ease. */\n.subs{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows var(--in) var(--eo),opacity var(--in) var(--eo)}\n.subs.open{grid-template-rows:1fr;opacity:1}\n.subs>div{min-height:0;overflow:hidden}\n.subs .mi{padding-left:30px}\n.chev{display:grid;transition:transform var(--in) var(--eo)}\n[aria-expanded=true]>.chev{transform:rotate(90deg)}\n.tt{position:absolute;right:calc(100% + 14px);top:50%;translate:0 -50%;width:max-content;max-width:220px;padding:4px 9px;border-radius:8px;font-size:12px;line-height:1.4;\ncolor:var(--mu);pointer-events:none;opacity:0;transform:translateX(3px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.mi:hover>.tt,.mi:focus-visible>.tt{opacity:1;transform:none;transition:opacity var(--in) var(--eo) .5s,transform var(--in) var(--eo) .5s}\n@media (max-width:600px){.tt{right:8px;top:auto;bottom:100%;translate:none;transform:translateY(3px)}}\n/* Switches: a track and a knob that slides (cross-fades with reduced motion). */\n.sw{position:relative;flex:none;width:26px;height:16px;border-radius:8px;background:var(--ln);transition:background-color var(--mv) var(--eio)}\n.sw::before,.sw::after{content:\"\";position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);\ntransition:transform var(--mv) var(--eio),opacity var(--mv) var(--eio)}\n.sw::before{opacity:0;transform:translateX(10px)}\n[aria-checked=true]>.sw{background:var(--pu-accent)}\n[aria-checked=true]>.sw::after{transform:translateX(10px)}\n.tools{display:flex;flex:none;gap:2px}\n.tools[hidden]{display:none}\n.tool[aria-pressed=true]{background:var(--as);color:var(--pu-accent)}\n.note{display:block;padding:0 0 4px;font-size:12px;color:var(--fa)}\n.note[hidden]{display:none}\n.ov{position:absolute;inset:0;pointer-events:none;overflow:hidden}\n/* An add-on's panel (.xp) is the same full-height panel as All comments (.all), with its own body. */\n.xb{flex:1;overflow-y:auto;overscroll-behavior:contain;padding:4px 16px 16px;font-size:13px}\n.xb p{margin:0 0 10px}\n/* All comments: a full-height panel on the right that slides in (fades, with reduced motion). */\n.all,.xp{position:fixed;top:0;right:0;bottom:0;width:var(--pu-panel);display:flex;flex-direction:column;border-width:0 0 0 1px;opacity:0;transform:translateX(100%);\ntransition:transform var(--out) var(--ei),opacity var(--out) var(--ei)}\n.all.show,.xp.show{opacity:1;transform:none;pointer-events:auto;transition:transform var(--mv) var(--eo),opacity var(--in) var(--eo)}\n.all.full{width:100%}\n/* The header: no title, two filters (an icon and a word in a pill: grey off, a soft accent fill on) and Close. */\n.hd{display:flex;align-items:center;gap:4px;padding:8px 8px 6px}\n.sp{flex:1}\n.tg{position:relative;display:flex;align-items:center;gap:5px;height:28px;padding:0 11px 0 9px;border-radius:99px;white-space:nowrap;line-height:1;color:var(--mu);transition:background-color .2s var(--eo),color .2s var(--eo)}\n.tg:hover{background:var(--ho);color:var(--k)}\n.tg[aria-pressed=true]{background:var(--as);color:var(--pu-accent)}\n.tg[aria-pressed=true]:hover{background:color-mix(in srgb,var(--pu-accent) 20%,transparent)}\n.tg:focus-visible{outline:2px solid var(--pu-accent);outline-offset:1px}\n/* What each filter does: a tooltip under it that eases in after a moment, on hover or focus. */\n.tg::after{content:attr(data-tip);position:absolute;left:0;top:calc(100% + 4px);z-index:3;width:max-content;max-width:220px;padding:4px 9px;border:1px solid var(--ln);border-radius:8px;background:var(--su);box-shadow:var(--sh);font-size:12px;line-height:1.4;color:var(--mu);pointer-events:none;opacity:0;transform:translateY(-3px);transition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.tg:not([aria-pressed=true]):is(:hover,:focus-visible)::after{opacity:1;transform:none;transition:opacity var(--in) var(--eo) .4s,transform var(--in) var(--eo) .4s}\n.list{flex:1;overflow-y:auto;overscroll-behavior:contain;padding:4px 8px 8px;background:var(--so)}\n/* Threads in the panel are the same cards; opened, a card shows the thread beneath the words it's about. */\n.cd{position:relative;margin-top:6px;border:1px solid var(--ln);border-radius:10px}\n/* What filters take away or bring back folds out or in, and a card opening or closing eases to its new height. */\n.list :is(.cd,[role=listitem],.sec){transition:all var(--mv) var(--eio)}\n.list .out{opacity:0!important;margin-top:0;padding-block:0;border-width:0;overflow:hidden}\n.cd.open{border-color:transparent;box-shadow:var(--sh)}\n.cd.done{--o:.6}\n/* Closed, its button lies over it (choosing the card opens it), beneath its actions and what they open. */\n.cd>.mi{position:absolute;inset:0;border-radius:10px;background:none}\n.cd>.thread :is(.acts,.refs,.edit){position:relative;z-index:1}\n.cd:not(.open,.new):is(:hover,:has(>.mi:focus-visible)){--bg:var(--so)}\n.cd.open>.mi{display:none}\n.cd.open .root>.hdr{cursor:pointer}\n.cd.new,.xr,.cd>.thread{padding:8px 10px 10px}\n/* The footer: who you are, Comment (its shortcut and switch), and \u22EF for the menu. */\n.pf{display:flex;align-items:center;gap:8px;min-height:52px;padding:0 8px 0 14px;border-top:1px solid var(--ln)}\n.fs{display:flex;align-items:center;gap:6px;padding:4px 6px;border-radius:8px;font-size:13px;transition:background-color .2s var(--eo)}\n.fs:hover,.fs:focus-visible{background:var(--ho)}\n.fs small{font-size:12px;color:var(--fa)}\n.pf .ib{width:30px;height:30px}\n/* The line from an open thread in the panel to its place on the page. */\n.cx{position:fixed;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none;opacity:0;transition:opacity var(--in) var(--eo)}\n.cx.show{opacity:1}\n.cx path{fill:none;stroke:var(--pu-accent);stroke-width:1.5;stroke-linecap:round;opacity:.7}\n.cx circle{fill:var(--pu-accent)}\n.layer.listing .col{opacity:0;transition:opacity var(--out) var(--ei)}\n.sec{padding:8px 10px 2px;font-size:12px;color:var(--fa)}\n.ag{display:flex;align-items:center;gap:8px;padding:6px 14px;font-size:12px;color:var(--fa);border-bottom:1px solid var(--ln)}\n.ag[hidden]{display:none}\n.lns{display:flex;flex-direction:column}\n.ln{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows var(--in) var(--eo),opacity var(--in) var(--eo)}\n.ln.show{grid-template-rows:1fr;opacity:1}\n.ln>.lw{overflow:hidden;min-height:0}\n.ag button{margin-left:auto;flex:none;padding:0 6px;border-radius:6px;color:var(--fa);transition:color .2s var(--eo),background-color .2s var(--eo)}.ag button:hover:not(:disabled),.ag button:focus-visible{color:var(--pu-accent);background:var(--as)}.ag button:disabled{opacity:.5;cursor:default}\n.adr{margin:8px 0 0 14px;padding:8px 10px;border-radius:8px;background:var(--so);font-size:13px;color:var(--k);animation:pu-in var(--mv) var(--eo) both}\n.adr small{display:block;font-size:12px;color:var(--fa)}\n.adr .go{display:flex;gap:6px;margin-top:6px}\n.adr .go button{padding:2px 8px;border-radius:6px;font-size:12px;color:var(--mu);transition:color .2s var(--eo),background-color .2s var(--eo)}.adr .go button:hover,.adr .go button:focus-visible{color:var(--pu-accent);background:var(--as)}\n@keyframes pu-in{0%{opacity:0;transform:translateY(3px)}100%{opacity:1;transform:none}}\n.sec b{margin-left:6px;font-weight:500;color:var(--pu-accent)}\n/* Messages sit beside the comment control, never over the page's own bottom bar; beside the panel while it is open,\nand above its footer when it fills the screen. */\n.toast{--r:40px;position:fixed;right:var(--r);bottom:calc(4px + var(--pu-lift));max-width:min(320px,calc(100vw - var(--r) - 16px));border-radius:10px;padding:8px 14px;font-size:13px;opacity:0;transform:translateY(6px);transition:.3s var(--eo)}\n.toast.show{opacity:1;transform:none}\n/* While All comments is open, messages sit inside the panel above its footer, on top of it: never over the page,\nnor a deck's own controls in the space beside it. */\n.layer:is(.listing,:has(.xp.show)) .toast{--r:12px;bottom:64px;max-width:min(320px,calc(var(--pu-panel) - 24px));z-index:2}\n/* While the menu is open, beside it (above it on a narrow screen), never under it. */\n.layer:not(.listing):has(.menu.show) .toast{--r:314px}\n@media (max-width:640px){.layer:not(.listing):has(.menu.show) .toast{--r:12px;bottom:auto;top:12px}}\n\n/* Touch: everything a finger presses is at least 44 px across. A bubble keeps its small look round a larger hit area.\nThe control is 44 px, so the menu and messages sit further from it. Shortcuts aren't shown where there is no keyboard. */\n@media (pointer:coarse){\n.mi,.ib,.rxo,.refs .ref,.mnl li,.bts button,.tg,.fs,.pm button,.ta,.nb,.selbar button,button.me,.say button,.line,.seen button,.ag button,.go button{min-height:44px}\n.ib,.rxo,.refs .ref,.nb,.selbar button,button.me,.ta{min-width:44px}\n.bub::before{content:\"\";position:absolute;inset:-14px;border-radius:50%}\n.row:focus-within .bts,.row.has .bts{max-height:52px}\n.hd{padding:4px 8px}\n.toast{--r:52px;display:flex;align-items:center;min-height:44px;padding:4px 14px;line-height:1.25}\n.ta{display:grid;place-items:center;margin:-5px -10px -5px 6px;padding:0 10px}\n.launch .mode{width:44px;height:44px}\n.menu{--b:calc(52px + var(--pu-lift))}\n}\n@media (pointer:coarse) and (hover:none){.ks{display:none}}\n\n/* Keyboard focus is always plainly marked: a 2 px ring in the accent, which reads at 4.5 to 1 on Pipeup's surfaces. */\n.layer :is(button,a):not(.mi,.opn,.mode,.tg):focus-visible{outline:2px solid var(--pu-accent);outline-offset:1px}\n.layer .mi:focus-visible{outline:2px solid var(--pu-accent);outline-offset:-2px}\n/* A look that differs from the page's keeps its see-through parts solid: a dimmed card dims its words, not the card. */\n.flip .launch{background:var(--su)}\n.flip :is(.th,.cd){opacity:1}\n.flip :is(.th,.cd)>*{opacity:var(--o,1);transition:opacity var(--in) var(--eo)}\n\n@media (forced-colors: active){\n.pick.kf{border:3px solid Highlight}\n.layer :is(.ib,.mi,.nb,.tg,.fs,.selbar button,.say button,.xb button):focus-visible{outline:2px solid Highlight}\n/* Switches, the filters, your own reactions and comment mode draw in system colours, so every state shows. */\n.sw{forced-color-adjust:none;border:1px solid CanvasText;background:Canvas}\n.sw::before,.sw::after{top:1px;left:1px;background:CanvasText}\n[aria-checked=true]>.sw{background:Highlight;border-color:Highlight}\n[aria-checked=true]>.sw::before,[aria-checked=true]>.sw::after{background:HighlightText}\n.layer :is(.tg,.rxo,.rx)[aria-pressed=true],.launch:has(.mode.on){forced-color-adjust:none;background:Highlight;color:HighlightText;border-color:Highlight}\n}\n\n@media (prefers-reduced-motion: reduce){\n.ln,.subs{transition-property:opacity}\n@keyframes pu-in{0%{opacity:0}100%{opacity:1}}\n.bub,.bub.in,.bub.in:hover,.bub.on,.tip,.pop,.selbar,.menu,.all,.xp,.tt,.toast,.ref .rc,.rxp,.mnl{transform:none!important}\n.ttip{transition-property:opacity!important}\n.dlg{transform:translate(-50%,0)!important}\n.sw::after{transform:none!important;transition-property:opacity}\n[aria-checked=true]>.sw::after{opacity:0}\n[aria-checked=true]>.sw::before{opacity:1}\n.th,.th.long .root>.tx,.mr,.list :is(.cd,[role=listitem],.sec){transition-property:opacity,box-shadow}\n.tip.show,.toast{transition-property:opacity}\n.pick,.pick.show{transition:opacity .16s ease-in-out}\n.all,.all.show,.xp,.xp.show{transition-property:opacity}\n.namebar,.namebar.show{transform:none!important;transition:opacity .16s ease-in-out}\n.av,.nf,.launch{transform:none!important}\n@keyframes pu-pulse{0%{opacity:0}35%{opacity:.85}100%{opacity:0}}\n}\n";
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@ description: Use when someone asks you to add comments to an HTML page, make it
|
|
|
5
5
|
|
|
6
6
|
# Add Pipeup to this page
|
|
7
7
|
|
|
8
|
-
Written for Pipeup 0.8.
|
|
8
|
+
Written for Pipeup 0.8.2 This skill is published at https://pipeup-ai.github.io/pipeup/skills/pipeup-add/SKILL.md. Its companions: [integrate](https://pipeup-ai.github.io/pipeup/skills/pipeup-integrate/SKILL.md) (the full reference: layouts, decks, tabs, every option), [apply](https://pipeup-ai.github.io/pipeup/skills/pipeup-apply/SKILL.md) (answering the comments) and [summarise](https://pipeup-ai.github.io/pipeup/skills/pipeup-summarise/SKILL.md).
|
|
9
9
|
|
|
10
10
|
Pipeup lets people comment on an HTML page in place. **When the page already exists, never change its layout, styling or behaviour to make room for Pipeup**: it draws in its own layer, and you only add attributes and one script tag. Edit the HTML file only; don't download, fetch or run anything yourself.
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ Pipeup lets people comment on an HTML page in place. **When the page already exi
|
|
|
14
14
|
1. **Pin the script.** Just before `</body>`:
|
|
15
15
|
|
|
16
16
|
```html
|
|
17
|
-
<script src="https://cdn.jsdelivr.net/npm/pipeup@0.8.
|
|
17
|
+
<script src="https://cdn.jsdelivr.net/npm/pipeup@0.8.2/dist/pipeup.min.js"
|
|
18
18
|
integrity="sha384-…" crossorigin="anonymous"></script>
|
|
19
19
|
```
|
|
20
20
|
|
|
@@ -5,14 +5,14 @@ description: Use when someone asks you to act on Pipeup feedback for an HTML pag
|
|
|
5
5
|
|
|
6
6
|
# Apply Pipeup feedback
|
|
7
7
|
|
|
8
|
-
Written for Pipeup 0.8.
|
|
8
|
+
Written for Pipeup 0.8.2 This skill is published at https://pipeup-ai.github.io/pipeup/skills/pipeup-apply/SKILL.md. Its companions: [integrate](https://pipeup-ai.github.io/pipeup/skills/pipeup-integrate/SKILL.md), [summarise](https://pipeup-ai.github.io/pipeup/skills/pipeup-summarise/SKILL.md).
|
|
9
9
|
|
|
10
10
|
## 1. Read the comments
|
|
11
11
|
|
|
12
12
|
Use the first of these that works:
|
|
13
13
|
|
|
14
|
-
0. **A live link** (the author runs `npx pipeup watch report.html --agent Claude` on this computer, opens the page it
|
|
15
|
-
prints, and switches on **Share with my agent**): run `npx pipeup comments report.html` (add `--all` for resolved
|
|
14
|
+
0. **A live link** (the author runs `npx --yes pipeup@0 watch report.html --agent Claude` on this computer, opens the page it
|
|
15
|
+
prints, and switches on **Share with my agent**): run `npx --yes pipeup@0 comments report.html` (add `--all` for resolved
|
|
16
16
|
threads, `--json` for data). No browser needed. If it says nothing is shared, ask the author to switch the switch on.
|
|
17
17
|
Your replies below reach the open page within seconds. The link lists your key for the page while it runs.
|
|
18
18
|
1. **Run the page** in a browser (you can drive one, or the author has it open) and evaluate
|
|
@@ -42,21 +42,31 @@ Answer a question with an answer, not a change.
|
|
|
42
42
|
You answer in the page's **replies file**, next to the page (`report.html` → `report.replies.js`), signed with your
|
|
43
43
|
own key. The key stays on this computer in `~/.pipeup/agent.json`; never put it in the page or its folder.
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
Run these commands exactly as written: `--yes` stops npx asking "Ok to proceed?", and `pipeup@0` takes any release npm
|
|
46
|
+
will give (some computers only accept packages a few days old). Every release from 0.6 answers them the same way. A
|
|
47
|
+
pre-release page's prompt names its pre-release; if npm refuses that one, use `pipeup@0`.
|
|
48
|
+
|
|
49
|
+
`--page` is **the HTML file that runs Pipeup**, the one the author opened, never a file it shows: on a viewer such as
|
|
50
|
+
`wiki/viewer.html?file=notes.md`, pass `wiki/viewer.html`. The prompt the author copies names it. If you can't tell,
|
|
51
|
+
ask; if the command says the file doesn't run Pipeup, it names the page to use instead.
|
|
52
|
+
|
|
53
|
+
First time only — ask the author whether you may list yourself on the page. After their yes, this makes your key (once)
|
|
54
|
+
and lists it; without `--yes` it only shows the change. The author also needs the **agents add-on**
|
|
46
55
|
(`@pipeup/agents`), which is what shows your replies in the page (neither is needed under a live link, which lists your
|
|
47
56
|
key and adds the add-on for you):
|
|
48
57
|
|
|
49
58
|
```bash
|
|
50
|
-
npx pipeup agent --name Claude
|
|
51
|
-
# prints: <html data-pipeup-agents="<your public key>"> (the author adds this to the page's <html> tag)
|
|
59
|
+
npx --yes pipeup@0 agent --name Claude --page report.html --yes
|
|
52
60
|
```
|
|
53
61
|
|
|
54
62
|
Then, for each thread:
|
|
55
63
|
|
|
56
64
|
```bash
|
|
57
|
-
npx pipeup reply --page report.html --thread <Thread id> "Changed the 20% to 15 to 20%, in the second paragraph." --addressed "addressed in revision 2"
|
|
65
|
+
npx --yes pipeup@0 reply --page report.html --thread <Thread id> "Changed the 20% to 15 to 20%, in the second paragraph." --addressed "addressed in revision 2"
|
|
58
66
|
```
|
|
59
67
|
|
|
68
|
+
It says where it wrote the replies, and, if the page doesn't list you yet, that the page will ignore them until it does.
|
|
69
|
+
|
|
60
70
|
- The words say plainly what changed and where. If you did not make the change, say why, and leave out `--addressed`.
|
|
61
71
|
- `--addressed` marks the thread addressed: the author sees your note and chooses **Resolve** or **Still not right**.
|
|
62
72
|
- Your replies show under your own name (for example "Claude" or "Codex") with the AI marking. The page ignores replies from a key it doesn't list,
|
|
@@ -5,7 +5,7 @@ description: Use when creating or editing an HTML document, slide deck, report,
|
|
|
5
5
|
|
|
6
6
|
# Add Pipeup to a page: the full reference
|
|
7
7
|
|
|
8
|
-
Written for Pipeup 0.8.
|
|
8
|
+
Written for Pipeup 0.8.2 For a quick "add comments to this page", [pipeup-add](https://pipeup-ai.github.io/pipeup/skills/pipeup-add/SKILL.md) is the short version; this is the full reference. This skill is published at https://pipeup-ai.github.io/pipeup/skills/pipeup-integrate/SKILL.md. Its companions: [summarise](https://pipeup-ai.github.io/pipeup/skills/pipeup-summarise/SKILL.md), [apply](https://pipeup-ai.github.io/pipeup/skills/pipeup-apply/SKILL.md).
|
|
9
9
|
|
|
10
10
|
Pipeup lets people comment on an HTML page in place: select text, click any element (including
|
|
11
11
|
buttons and charts) or drop a pin on a slide. Your job is to make the page *reviewable* while it
|
|
@@ -75,7 +75,7 @@ Then choose the options (see "Options" below): usually just the defaults.
|
|
|
75
75
|
- Just before `</body>`, add the script pinned to an exact version:
|
|
76
76
|
|
|
77
77
|
```html
|
|
78
|
-
<script src="https://cdn.jsdelivr.net/npm/pipeup@0.8.
|
|
78
|
+
<script src="https://cdn.jsdelivr.net/npm/pipeup@0.8.2/dist/pipeup.min.js"
|
|
79
79
|
integrity="sha384-…" crossorigin="anonymous"></script>
|
|
80
80
|
```
|
|
81
81
|
|
|
@@ -140,7 +140,7 @@ Then choose the options (see "Options" below): usually just the defaults.
|
|
|
140
140
|
never a revision, version or date: those change for every comment already made, which then counts as
|
|
141
141
|
somewhere else.
|
|
142
142
|
|
|
143
|
-
8. **Check, and fix until it passes:** once it ships, run `npx pipeup check page.html`; until then, open the page and check the items below by eye. Fix every `fail`; fix
|
|
143
|
+
8. **Check, and fix until it passes:** once it ships, run `npx --yes pipeup@0 check page.html`; until then, open the page and check the items below by eye. Fix every `fail`; fix
|
|
144
144
|
`warn` items unless the author says otherwise. Typical fixes:
|
|
145
145
|
- *layout changed* — you edited styles or wrappers; undo that.
|
|
146
146
|
- *closed UI overlaps content* — add `data-pipeup-ignore` to a floating element that shouldn't be covered, or set
|
|
@@ -159,7 +159,7 @@ Then choose the options (see "Options" below): usually just the defaults.
|
|
|
159
159
|
- Don't wrap content in new elements or add classes for Pipeup.
|
|
160
160
|
- Don't add inline styles, z-index changes or padding "for the comment column".
|
|
161
161
|
- Don't load the script from anywhere but the pinned CDN URL
|
|
162
|
-
(`https://cdn.jsdelivr.net/npm/pipeup@0.8.
|
|
162
|
+
(`https://cdn.jsdelivr.net/npm/pipeup@0.8.2/dist/pipeup.min.js`, with the `integrity` value from
|
|
163
163
|
the release notes) or a copy of that same file next to the page. Never use an unpinned URL.
|
|
164
164
|
- Don't put secrets in `data-pipeup-doc`; it *is* the document's key — anyone with the file can
|
|
165
165
|
read its feedback, which is the intended audience.
|
|
@@ -177,7 +177,7 @@ page opened from disk and in any script order, and they are released with Pipeup
|
|
|
177
177
|
|
|
178
178
|
- **Ask first, and say in plain words what it sends and to whom** (the line above, and the add-on's README). Never
|
|
179
179
|
pick a sharing service yourself: the author chooses one.
|
|
180
|
-
- Add it as one more `<script>` after Pipeup's, pinned the same way (`https://cdn.jsdelivr.net/npm/@pipeup/share@0.8.
|
|
180
|
+
- Add it as one more `<script>` after Pipeup's, pinned the same way (`https://cdn.jsdelivr.net/npm/@pipeup/share@0.8.2/dist/share.min.js`
|
|
181
181
|
with its `integrity` from the release notes), or use the combined file `pipeup+share.min.js` instead of Pipeup's.
|
|
182
182
|
- Sharing is set up by the author with the command line (`npx @pipeup/share create page.html --server …`), which writes
|
|
183
183
|
`data-pipeup-share` into the file and prints a stop key once. **Never write `data-pipeup-share` yourself and never
|
|
@@ -197,9 +197,10 @@ page opened from disk and in any script order, and they are released with Pipeup
|
|
|
197
197
|
- **Letting an agent answer comments.** Only when the author asks. Agents read a page's comments with
|
|
198
198
|
`await Pipeup.comments()` (part of Pipeup itself) and answer in a replies file next to the page (`pipeup-apply` is the
|
|
199
199
|
skill for that). Showing those answers in the page is the **agents add-on**, so listing an agent means two things:
|
|
200
|
-
1.
|
|
201
|
-
`data-pipeup-agents
|
|
202
|
-
|
|
200
|
+
1. With the author's yes, the agent lists itself: `npx --yes pipeup@0 agent --name Claude --page page.html --yes`
|
|
201
|
+
adds its public key to `<html>` as `data-pipeup-agents` (appended to an existing list) and changes nothing else.
|
|
202
|
+
Or add a key you were given by hand, keeping every entry. Never write a key you weren't given, and never put an
|
|
203
|
+
agent's private key in the page.
|
|
203
204
|
2. Add the agents add-on after the Pipeup script, pinned with its `integrity` hash like any add-on:
|
|
204
205
|
`<script src="https://cdn.jsdelivr.net/npm/@pipeup/agents@<version>/dist/agents.min.js" integrity="…" crossorigin="anonymous"></script>`,
|
|
205
206
|
and add `agents` to `data-pipeup-addons` if the page has that list. Say in plain words what it does: it reads the
|
|
@@ -207,9 +208,9 @@ page opened from disk and in any script order, and they are released with Pipeup
|
|
|
207
208
|
sends the page's comments to the program on their computer; nothing leaves the computer. It also lets the agent
|
|
208
209
|
reply in threads and mark them addressed, never resolve or change anyone's comment. The page ignores replies from
|
|
209
210
|
keys it doesn't list. Without the add-on the page says so once in the browser console and no replies show.
|
|
210
|
-
On their own computer the author can instead run `npx pipeup watch page.html --agent Claude`: it shows the page with a
|
|
211
|
+
On their own computer the author can instead run `npx --yes pipeup@0 watch page.html --agent Claude`: it shows the page with a
|
|
211
212
|
**Share with my agent** switch (off until they turn it on), lists the agent while it runs, **adds the agents add-on to
|
|
212
|
-
the page it shows itself**, and lets the agent read with `npx pipeup comments page.html`. Nothing is written into the
|
|
213
|
+
the page it shows itself**, and lets the agent read with `npx --yes pipeup@0 comments page.html`. Nothing is written into the
|
|
213
214
|
page file. (It refuses a page whose Pipeup is older than 0.6 and says what to change; a 0.6.x page already has agent
|
|
214
215
|
support built in.)
|
|
215
216
|
- `data-pipeup-live="auto"` makes "Go live" the default, but nobody connects before they have seen the sentence
|
|
@@ -5,7 +5,7 @@ description: Use when someone wants Pipeup reviews saved as Markdown files in th
|
|
|
5
5
|
|
|
6
6
|
# Set up "Save to GitHub" or "Send to Git"
|
|
7
7
|
|
|
8
|
-
Written for Pipeup 0.8.
|
|
8
|
+
Written for Pipeup 0.8.2 This skill is published at https://pipeup-ai.github.io/pipeup/skills/pipeup-send-to-git-setup/SKILL.md.
|
|
9
9
|
|
|
10
10
|
Two example add-ons (written the way a company writes its own; **not** from the Pipeup project) get a review into Git as a
|
|
11
11
|
Markdown file, the same Markdown that Copy comments › As Markdown makes (each comment says where it is, ready for an AI to act on):
|
|
@@ -5,7 +5,7 @@ description: Use when someone has Pipeup feedback on an HTML page — text a rev
|
|
|
5
5
|
|
|
6
6
|
# Summarise Pipeup feedback
|
|
7
7
|
|
|
8
|
-
Written for Pipeup 0.8.
|
|
8
|
+
Written for Pipeup 0.8.2 This skill is published at https://pipeup-ai.github.io/pipeup/skills/pipeup-summarise/SKILL.md. Its companions: [integrate](https://pipeup-ai.github.io/pipeup/skills/pipeup-integrate/SKILL.md), [apply](https://pipeup-ai.github.io/pipeup/skills/pipeup-apply/SKILL.md).
|
|
9
9
|
|
|
10
10
|
## 1. Get the feedback as text
|
|
11
11
|
|