@sobree/core 0.1.6 → 0.1.7
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/dist/embed/gestureHost.d.ts +13 -0
- package/dist/embed/touchGestures.d.ts +38 -0
- package/dist/embed/viewport.d.ts +40 -69
- package/dist/embed/wheelGestures.d.ts +54 -0
- package/dist/index.css +1 -1
- package/dist/index.js +1330 -1257
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The narrow surface gesture controllers drive the Viewport through.
|
|
3
|
+
* Controllers translate raw input events into these calls; the Viewport
|
|
4
|
+
* owns all transform state, clamping, and raster behaviour.
|
|
5
|
+
*/
|
|
6
|
+
export interface GestureHost {
|
|
7
|
+
/** Pan the stage by `(dx, dy)` CSS pixels. */
|
|
8
|
+
panBy(dx: number, dy: number): void;
|
|
9
|
+
/** Zoom to `scale`, anchoring the point at (clientX, clientY). */
|
|
10
|
+
zoomTo(scale: number, clientX: number, clientY: number): void;
|
|
11
|
+
/** Current visual scale (zoom deltas are multiplicative on this). */
|
|
12
|
+
getScale(): number;
|
|
13
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { GestureHost } from './gestureHost';
|
|
2
|
+
/**
|
|
3
|
+
* Touch gestures (mobile): one-finger drag pans, two-finger pinch zooms
|
|
4
|
+
* anchored at the finger midpoint, and translating both fingers pans.
|
|
5
|
+
* Mouse/pen pointers are deliberately ignored — their drag is text
|
|
6
|
+
* selection, not pan. The container has `touch-action: none`, so without
|
|
7
|
+
* this controller touch devices could neither scroll nor zoom.
|
|
8
|
+
*/
|
|
9
|
+
export declare class TouchGestures {
|
|
10
|
+
private readonly container;
|
|
11
|
+
private readonly host;
|
|
12
|
+
/** Live touch pointers (pointerId → last client position). */
|
|
13
|
+
private readonly points;
|
|
14
|
+
/** `idle` → no touches; `tap` → one finger down, within slop; `pan` →
|
|
15
|
+
* one finger past slop; `pinch` → two fingers. */
|
|
16
|
+
private mode;
|
|
17
|
+
/** First touch's start position — slop is measured from here. */
|
|
18
|
+
private startX;
|
|
19
|
+
private startY;
|
|
20
|
+
/** Finger distance and scale captured when a pinch begins. */
|
|
21
|
+
private pinchStartDist;
|
|
22
|
+
private pinchStartScale;
|
|
23
|
+
/** Set when a pan/pinch actually moved the stage — the synthetic click
|
|
24
|
+
* browsers fire after the touch sequence must not reach the editor
|
|
25
|
+
* (it would teleport the caret to wherever the drag ended). */
|
|
26
|
+
private suppressNextClick;
|
|
27
|
+
private readonly onPointerDown;
|
|
28
|
+
private readonly onPointerMove;
|
|
29
|
+
private readonly onPointerEnd;
|
|
30
|
+
private readonly onClickCapture;
|
|
31
|
+
constructor(container: HTMLElement, host: GestureHost);
|
|
32
|
+
destroy(): void;
|
|
33
|
+
private handleDown;
|
|
34
|
+
private handleMove;
|
|
35
|
+
private movePinch;
|
|
36
|
+
private handleEnd;
|
|
37
|
+
private beginPinch;
|
|
38
|
+
}
|
package/dist/embed/viewport.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GestureHost } from './gestureHost';
|
|
1
2
|
export interface ViewportOptions {
|
|
2
3
|
minScale?: number;
|
|
3
4
|
maxScale?: number;
|
|
@@ -31,19 +32,18 @@ export interface ViewportOptions {
|
|
|
31
32
|
* └ stage (absolutely positioned, transform: translate(tx,ty) scale(s))
|
|
32
33
|
* └ slot (where the embedded content lives — caller mounts here)
|
|
33
34
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* these handlers touch devices could neither scroll nor zoom.
|
|
35
|
+
* Input handling lives in two controllers driving this class through the
|
|
36
|
+
* GestureHost interface:
|
|
37
|
+
* - WheelGestures: zoom on shift/ctrl/meta+wheel (macOS pinch emits
|
|
38
|
+
* ctrlKey), pan on bare wheel with axis-locking.
|
|
39
|
+
* - TouchGestures (mobile): one-finger drag pans (after a small slop so
|
|
40
|
+
* taps still place the caret); two-finger pinch zooms anchored at the
|
|
41
|
+
* finger midpoint. Mouse/pen drag stays text selection.
|
|
42
|
+
*
|
|
43
|
+
* Viewport itself implements GestureHost — panBy / zoomTo / getScale are
|
|
44
|
+
* its public API, so the controllers just receive `this`.
|
|
45
45
|
*/
|
|
46
|
-
export declare class Viewport {
|
|
46
|
+
export declare class Viewport implements GestureHost {
|
|
47
47
|
readonly container: HTMLElement;
|
|
48
48
|
readonly slot: HTMLElement;
|
|
49
49
|
private readonly stage;
|
|
@@ -52,56 +52,19 @@ export declare class Viewport {
|
|
|
52
52
|
private ty;
|
|
53
53
|
private readonly minScale;
|
|
54
54
|
private readonly maxScale;
|
|
55
|
-
private readonly wheelZoomSensitivity;
|
|
56
|
-
private readonly pinchZoomSensitivity;
|
|
57
55
|
private readonly onScaleChange;
|
|
58
56
|
private readonly onRenderTierChange;
|
|
59
57
|
private readonly onTransformChange;
|
|
60
|
-
private readonly
|
|
58
|
+
private readonly wheelGestures;
|
|
59
|
+
private readonly touchGestures;
|
|
61
60
|
/** Current layout-side zoom factor (integer ≥ 1). See ViewportOptions. */
|
|
62
61
|
private renderTier;
|
|
63
62
|
/** Suppresses `onTransformChange` during the constructor's initial
|
|
64
63
|
* `applyTransform` so consumers can capture `viewport` in their
|
|
65
64
|
* callback without TDZ traps. Flipped true at the end of the ctor. */
|
|
66
65
|
private constructed;
|
|
67
|
-
/**
|
|
68
|
-
private
|
|
69
|
-
/** Dominant axis for the current gesture. Null until detected, cleared at gesture end. */
|
|
70
|
-
private gesturePrimaryAxis;
|
|
71
|
-
/**
|
|
72
|
-
* Signed cumulative dx within the current gesture. Drives lock release:
|
|
73
|
-
* wobble (±3-5px back-and-forth) cancels out; sustained one-way motion
|
|
74
|
-
* accumulates past the threshold quickly. Reset at gesture end.
|
|
75
|
-
*/
|
|
76
|
-
private gestureSignedDx;
|
|
77
|
-
/**
|
|
78
|
-
* Sticky horizontal-lock flag. Engaged by `fitTo` so alignment survives
|
|
79
|
-
* gentle diagonal trackpad gestures; broken when the gesture's signed
|
|
80
|
-
* cumulative dx crosses `X_RELEASE_THRESHOLD` — the user clearly intends
|
|
81
|
-
* sustained horizontal motion.
|
|
82
|
-
*/
|
|
83
|
-
private horizontalLock;
|
|
84
|
-
/** Live touch pointers (pointerId → last client position). Mouse and
|
|
85
|
-
* pen never enter this map — their drag is text selection, not pan. */
|
|
86
|
-
private readonly touchPoints;
|
|
87
|
-
/** `idle` → no touches; `tap` → one finger down, within slop (a tap
|
|
88
|
-
* must still reach the editor to place the caret); `pan` → one finger
|
|
89
|
-
* past slop; `pinch` → two fingers. */
|
|
90
|
-
private touchMode;
|
|
91
|
-
/** First touch's start position — slop is measured from here. */
|
|
92
|
-
private touchStartX;
|
|
93
|
-
private touchStartY;
|
|
94
|
-
/** Finger distance and scale captured when a pinch begins. */
|
|
95
|
-
private pinchStartDist;
|
|
96
|
-
private pinchStartScale;
|
|
97
|
-
private readonly onPointerDown;
|
|
98
|
-
private readonly onPointerMove;
|
|
99
|
-
private readonly onPointerEnd;
|
|
100
|
-
private readonly onClickCapture;
|
|
101
|
-
/** Set when a pan/pinch actually moved the stage — the synthetic click
|
|
102
|
-
* browsers fire after the touch sequence must not reach the editor
|
|
103
|
-
* (it would teleport the caret to wherever the drag ended). */
|
|
104
|
-
private suppressNextClick;
|
|
66
|
+
/** Debounce handle for the crisp-text settle pass (see scheduleSettle). */
|
|
67
|
+
private settleTimer;
|
|
105
68
|
constructor(container: HTMLElement, options?: ViewportOptions);
|
|
106
69
|
/** Reset pan to origin and scale to 1. */
|
|
107
70
|
reset(): void;
|
|
@@ -129,24 +92,32 @@ export declare class Viewport {
|
|
|
129
92
|
/** Zoom to `nextScale`, anchoring the point at (clientX, clientY) in container space. */
|
|
130
93
|
zoomTo(nextScale: number, clientX: number, clientY: number): void;
|
|
131
94
|
destroy(): void;
|
|
132
|
-
private
|
|
133
|
-
private handleTouchDown;
|
|
134
|
-
private handleTouchMove;
|
|
135
|
-
private handleTouchEnd;
|
|
136
|
-
private beginPinch;
|
|
95
|
+
private applyTransform;
|
|
137
96
|
/**
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
97
|
+
* The stage transform, expressed in the render tier's coordinate space.
|
|
98
|
+
* Chrome applies transforms post-`zoom`, so a `translate(tx, ty)` on an
|
|
99
|
+
* element with `zoom: k` moves by `(tx*k, ty*k)` screen px. We store
|
|
100
|
+
* tx/ty in pre-zoom (container) pixels — the scheme cursor-anchored
|
|
101
|
+
* zoomTo relies on — so divide by the tier to cancel zoom's translate
|
|
102
|
+
* multiplication. (Tier is permanently 1; kept for the single code path.)
|
|
103
|
+
*
|
|
104
|
+
* `threeD` selects the gesture-time form (`translate3d` — forces a
|
|
105
|
+
* compositor layer) vs the settled form (plain `translate` — lets the
|
|
106
|
+
* compositor drop the layer pin and re-rasterise text at the effective
|
|
107
|
+
* scale). Same matrix either way; only raster-cache behaviour differs.
|
|
147
108
|
*/
|
|
148
|
-
private
|
|
149
|
-
|
|
109
|
+
private transformCss;
|
|
110
|
+
/**
|
|
111
|
+
* Crisp-text pass: once no transform has been written for SETTLE_MS,
|
|
112
|
+
* drop `will-change` and the 3D form so the compositor re-rasterises
|
|
113
|
+
* the (now static) stage at `devicePixelRatio × scale` — text is then
|
|
114
|
+
* as sharp at 3× as a 3×-laid-out page, with zero layout involvement.
|
|
115
|
+
* Both pins are needed: either `will-change: transform` or a 3D
|
|
116
|
+
* transform alone keeps browsers (Safari especially) stretching the
|
|
117
|
+
* stale 1× texture. The next gesture frame re-pins before moving.
|
|
118
|
+
*/
|
|
119
|
+
private scheduleSettle;
|
|
120
|
+
private settle;
|
|
150
121
|
/**
|
|
151
122
|
* Apply the current transform with a CSS transition. Used only for
|
|
152
123
|
* programmatic fits — wheel pan/zoom must stay instant or feel sluggish.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { GestureHost } from './gestureHost';
|
|
2
|
+
export interface WheelGestureOptions {
|
|
3
|
+
/** Scale change per unit of wheel deltaY for shift+wheel. */
|
|
4
|
+
wheelZoomSensitivity: number;
|
|
5
|
+
/** Scale change per unit of wheel deltaY for pinch (ctrlKey). */
|
|
6
|
+
pinchZoomSensitivity: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Wheel gestures: zoom on shift/ctrl/meta+wheel (macOS trackpad pinch
|
|
10
|
+
* synthesises ctrlKey wheel events), pan on bare wheel — with an
|
|
11
|
+
* axis-lock so a nearly-vertical swipe doesn't drift the paper sideways.
|
|
12
|
+
*/
|
|
13
|
+
export declare class WheelGestures {
|
|
14
|
+
private readonly container;
|
|
15
|
+
private readonly host;
|
|
16
|
+
private readonly opts;
|
|
17
|
+
/** Timestamp of the last wheel event, used to delimit gestures. */
|
|
18
|
+
private gestureLastTime;
|
|
19
|
+
/** Dominant axis for the current gesture. Null until detected, cleared at gesture end. */
|
|
20
|
+
private gesturePrimaryAxis;
|
|
21
|
+
/**
|
|
22
|
+
* Signed cumulative dx within the current gesture. Drives lock release:
|
|
23
|
+
* wobble (±3-5px back-and-forth) cancels out; sustained one-way motion
|
|
24
|
+
* accumulates past the threshold quickly. Reset at gesture end.
|
|
25
|
+
*/
|
|
26
|
+
private gestureSignedDx;
|
|
27
|
+
/**
|
|
28
|
+
* Sticky horizontal-lock flag. Engaged by `fitTo` so alignment survives
|
|
29
|
+
* gentle diagonal trackpad gestures; broken when the gesture's signed
|
|
30
|
+
* cumulative dx crosses `X_RELEASE_THRESHOLD` — the user clearly
|
|
31
|
+
* intends sustained horizontal motion.
|
|
32
|
+
*/
|
|
33
|
+
private horizontalLock;
|
|
34
|
+
private readonly onWheel;
|
|
35
|
+
constructor(container: HTMLElement, host: GestureHost, opts: WheelGestureOptions);
|
|
36
|
+
destroy(): void;
|
|
37
|
+
/** Engage the sticky horizontal lock (fit-* picked an X alignment). */
|
|
38
|
+
engageHorizontalLock(): void;
|
|
39
|
+
/** Clear all gesture and lock state (viewport reset). */
|
|
40
|
+
resetLocks(): void;
|
|
41
|
+
private handleWheel;
|
|
42
|
+
/**
|
|
43
|
+
* Axis-lock for pan gestures:
|
|
44
|
+
* - Within a gesture (events ≤ GESTURE_GAP_MS apart), a clear dominant
|
|
45
|
+
* axis zeros the other axis so a nearly-vertical swipe doesn't also
|
|
46
|
+
* drift the paper sideways.
|
|
47
|
+
* - An explicit `horizontalLock` set by `fitTo` survives across gestures,
|
|
48
|
+
* keeping fit-page / fit-width alignment stable.
|
|
49
|
+
* - Both locks release when the gesture's signed cumulative dx crosses
|
|
50
|
+
* `X_RELEASE_THRESHOLD`. Signed sum cancels wobble (back-and-forth
|
|
51
|
+
* averages to zero) while sustained one-way motion accumulates fast.
|
|
52
|
+
*/
|
|
53
|
+
private applyScrollAxisLock;
|
|
54
|
+
}
|
package/dist/index.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.paper-stack{display:flex;flex-direction:column;padding:48px;gap:28px;outline:none}.paper-row{display:flex;flex-direction:row;align-items:flex-start;gap:24px}.paper{position:relative;background:#fff;border:1px solid rgba(0,0,0,.3);box-shadow:0 1px 2px #00000014,0 18px 60px #0000001f;padding-top:var(--margin-top, 25mm);padding-right:var(--margin-right, 20mm);padding-bottom:var(--margin-bottom, 25mm);padding-left:var(--margin-left, 20mm);overflow:hidden;flex:none}.paper-header,.paper-footer{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);font-size:10pt;color:#555;white-space:pre-wrap}.paper-header{top:0;min-height:var(--margin-top, 25mm);padding-top:var(--header-offset-mm, 12.7mm);padding-bottom:4mm;border-bottom:1px dashed transparent}.paper-footer{bottom:0;min-height:var(--margin-bottom, 25mm);padding-top:4mm;text-align:center;border-top:1px dashed transparent}.paper-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:1}.paper-anchors.is-empty{display:none}.paper-anchors-behind{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:0}.paper-anchors-behind.is-empty{display:none}.paper-zone-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:2}.paper-zone-anchors.is-empty{display:none}.paper-anchor{position:absolute;box-sizing:border-box;overflow:hidden}.paper-header>p,.paper-footer>p,.paper-header>ul,.paper-header>ol,.paper-footer>ul,.paper-footer>ol{margin:0}.paper-footnotes{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);bottom:var(--margin-bottom, 25mm);font-size:.85em;padding-top:.5em;border-top:1pt solid currentColor;background:#fffffff5;z-index:1;max-height:40%;overflow:hidden}.paper-footnotes.is-empty{display:none}.paper-comments{flex:0 0 70mm;max-width:70mm;font-size:.85em;padding:0 .5em;align-self:stretch;overflow-y:auto}.paper-comments.is-empty{display:none}.paper-footnotes .sobree-footnotes__list{margin:0;padding-left:1.5em}.paper-footnotes .sobree-footnotes__item{margin:.25em 0}.paper-content a{color:inherit;text-decoration:none}.paper-content{position:relative;height:100%;min-height:100px;display:flow-root}.paper-content td p:not([style*=line-height]),.paper-content td li:not([style*=line-height]),.paper-content th p:not([style*=line-height]),.paper-content th li:not([style*=line-height]){line-height:1}.paper-content td p:not([style*=margin]),.paper-content th p:not([style*=margin]){margin:0}.paper-content .sobree-hang>li{list-style:none}.paper-content .sobree-hang>li:before{display:inline-block;box-sizing:border-box;width:var(--sobree-list-hang, 0);margin-left:calc(-1 * var(--sobree-list-hang, 0));white-space:nowrap;color:var(--sobree-marker-color, currentColor);font-family:var(--sobree-marker-font, inherit);font-size:var(--sobree-marker-size, inherit)}.paper-content .sobree-hang.lst-bullet>li:before{content:var(--sobree-bullet, "•")}.paper-content .sobree-hang.lst-decimal>li:before{content:var(--mk-pre, "") counter(list-item,decimal) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-decimal-zero>li:before{content:var(--mk-pre, "") counter(list-item,decimal-leading-zero) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-latin>li:before{content:var(--mk-pre, "") counter(list-item,lower-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-latin>li:before{content:var(--mk-pre, "") counter(list-item,upper-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-roman>li:before{content:var(--mk-pre, "") counter(list-item,lower-roman) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-roman>li:before{content:var(--mk-pre, "") counter(list-item,upper-roman) var(--mk-suf, ".")}.paper-content .sobree-tab-spread{display:flex;justify-content:space-between;align-items:baseline;gap:1em;white-space:nowrap}.paper-content .sobree-tab-spread .sobree-tab-spread__before,.paper-content .sobree-tab-spread .sobree-tab-spread__after{white-space:pre-wrap;min-width:0}.paper-content table.sobree-table-bordered td,.paper-content table.sobree-table-bordered th{border:var(--table-cell-border, none);padding:0 4px}.sobree-editor{position:relative;outline:none}.sobree-editor>:first-child{margin-top:0}.sobree-editor p,.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6,.sobree-editor ul,.sobree-editor ol,.sobree-editor li,.sobree-editor blockquote,.sobree-editor pre{margin:0;padding:0}.sobree-editor ul,.sobree-editor ol{padding-left:1.5em}.sobree-editor li.sobree-li-continuation{list-style-type:none}.sobree-editor li.sobree-li-continuation::marker{content:""}.sobree-editor .sobree-fragment-continued{text-align-last:justify}.sobree-editor .sobree-footnote-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-footnote-ref a:hover{text-decoration:underline}.sobree-editor .sobree-footnotes{margin-top:2em;padding-top:.5em;border-top:1pt solid currentColor;font-size:.85em}.sobree-editor .sobree-footnotes__list{padding-left:1.5em}.sobree-editor .sobree-footnotes__item{margin:.25em 0}.sobree-editor ins.sobree-revision-ins{text-decoration:underline}.sobree-editor del.sobree-revision-del{text-decoration:line-through}.sobree-editor .sobree-revision-format{text-decoration:underline dashed var(--sobree-format-revision-color, currentColor);text-underline-offset:3px}.sobree-editor [data-block-revision=ins]:after,.sobree-editor [data-block-revision=del]:after{content:" ¶";color:var(--sobree-block-revision-color, currentColor);opacity:.65;font-weight:600;-webkit-user-select:none;user-select:none}.sobree-editor [data-block-revision=del]:after{text-decoration:line-through}.sobree-editor .sobree-comment-range{background:var(--sobree-comment-range-bg, rgba(255, 217, 0, .25));border-bottom:1px dotted var(--sobree-comment-range-border, rgba(180, 130, 0, .5))}.sobree-editor .sobree-comment-ref{display:inline;font-size:.85em;margin:0 .1em}.sobree-editor .sobree-comment-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-comment-ref a:hover{filter:brightness(.7)}.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6{font-size:inherit;font-weight:inherit}.sobree-editor table{border-collapse:collapse;width:100%;position:relative}.sobree-editor th,.sobree-editor td{border:none;padding:0 .08in;vertical-align:top;transition:border-color .12s ease}.sobree-editor .sobree-section-break{display:flex;align-items:center;gap:8px;margin:8px 0;color:var(--fg-subtle, #7c7764);font-size:11px;letter-spacing:.04em;text-transform:uppercase;-webkit-user-select:none;user-select:none}.sobree-editor .sobree-section-break--continuous{visibility:hidden;height:0;margin:0;padding:0;border:none;overflow:hidden;font-size:0;line-height:0}.sobree-editor .sobree-section-break:before,.sobree-editor .sobree-section-break:after{content:"";flex:1;border-top:1px dashed var(--border, #dedbd0)}.sobree-editor .sobree-section-break__label{flex:none;padding:0 6px;background:var(--bg-elevated, #fff)}.sobree-editor .sobree-textbox-frame p{line-height:1.2}.sobree-editor .paper-content p,.sobree-editor .paper-content li,.sobree-editor .paper-header p,.sobree-editor .paper-header li,.sobree-editor .paper-footer p,.sobree-editor .paper-footer li,.sobree-editor .sobree-textbox-frame p{white-space:pre-wrap}.sobree-editor .sobree-section-trailer-empty{height:0;line-height:0;font-size:0;margin:0;padding:0;overflow:hidden}.sobree-editor .sobree-textbox-frame--placeholder{border:1px solid var(--border, #c8c4b8)}.sobree-editor .sobree-textbox-frame--placeholder.sobree-textbox-frame--filled{border:none;z-index:-1}.sobree-editor img.is-selected{outline:2px solid var(--sobree-primary, #d4521f);outline-offset:2px}.sobree-image-resize-handle{position:absolute;width:16px;height:16px;background:var(--sobree-primary, #d4521f);border:2px solid #fff;border-radius:3px;cursor:nwse-resize;z-index:1000;-webkit-user-select:none;user-select:none}.sobree-viewport{position:relative;overflow:hidden;overscroll-behavior:contain;touch-action:none;background:#ececee}.sobree-viewport__stage{position:absolute;top:0;left:0;transform-origin:0 0
|
|
1
|
+
.paper-stack{display:flex;flex-direction:column;padding:48px;gap:28px;outline:none}.paper-row{display:flex;flex-direction:row;align-items:flex-start;gap:24px}.paper{position:relative;background:#fff;border:1px solid rgba(0,0,0,.3);box-shadow:0 1px 2px #00000014,0 18px 60px #0000001f;padding-top:var(--margin-top, 25mm);padding-right:var(--margin-right, 20mm);padding-bottom:var(--margin-bottom, 25mm);padding-left:var(--margin-left, 20mm);overflow:hidden;flex:none}.paper-header,.paper-footer{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);font-size:10pt;color:#555;white-space:pre-wrap}.paper-header{top:0;min-height:var(--margin-top, 25mm);padding-top:var(--header-offset-mm, 12.7mm);padding-bottom:4mm;border-bottom:1px dashed transparent}.paper-footer{bottom:0;min-height:var(--margin-bottom, 25mm);padding-top:4mm;text-align:center;border-top:1px dashed transparent}.paper-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:1}.paper-anchors.is-empty{display:none}.paper-anchors-behind{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:0}.paper-anchors-behind.is-empty{display:none}.paper-zone-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:2}.paper-zone-anchors.is-empty{display:none}.paper-anchor{position:absolute;box-sizing:border-box;overflow:hidden}.paper-header>p,.paper-footer>p,.paper-header>ul,.paper-header>ol,.paper-footer>ul,.paper-footer>ol{margin:0}.paper-footnotes{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);bottom:var(--margin-bottom, 25mm);font-size:.85em;padding-top:.5em;border-top:1pt solid currentColor;background:#fffffff5;z-index:1;max-height:40%;overflow:hidden}.paper-footnotes.is-empty{display:none}.paper-comments{flex:0 0 70mm;max-width:70mm;font-size:.85em;padding:0 .5em;align-self:stretch;overflow-y:auto}.paper-comments.is-empty{display:none}.paper-footnotes .sobree-footnotes__list{margin:0;padding-left:1.5em}.paper-footnotes .sobree-footnotes__item{margin:.25em 0}.paper-content a{color:inherit;text-decoration:none}.paper-content{position:relative;height:100%;min-height:100px;display:flow-root}.paper-content td p:not([style*=line-height]),.paper-content td li:not([style*=line-height]),.paper-content th p:not([style*=line-height]),.paper-content th li:not([style*=line-height]){line-height:1}.paper-content td p:not([style*=margin]),.paper-content th p:not([style*=margin]){margin:0}.paper-content .sobree-hang>li{list-style:none}.paper-content .sobree-hang>li:before{display:inline-block;box-sizing:border-box;width:var(--sobree-list-hang, 0);margin-left:calc(-1 * var(--sobree-list-hang, 0));white-space:nowrap;color:var(--sobree-marker-color, currentColor);font-family:var(--sobree-marker-font, inherit);font-size:var(--sobree-marker-size, inherit)}.paper-content .sobree-hang.lst-bullet>li:before{content:var(--sobree-bullet, "•")}.paper-content .sobree-hang.lst-decimal>li:before{content:var(--mk-pre, "") counter(list-item,decimal) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-decimal-zero>li:before{content:var(--mk-pre, "") counter(list-item,decimal-leading-zero) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-latin>li:before{content:var(--mk-pre, "") counter(list-item,lower-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-latin>li:before{content:var(--mk-pre, "") counter(list-item,upper-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-roman>li:before{content:var(--mk-pre, "") counter(list-item,lower-roman) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-roman>li:before{content:var(--mk-pre, "") counter(list-item,upper-roman) var(--mk-suf, ".")}.paper-content .sobree-tab-spread{display:flex;justify-content:space-between;align-items:baseline;gap:1em;white-space:nowrap}.paper-content .sobree-tab-spread .sobree-tab-spread__before,.paper-content .sobree-tab-spread .sobree-tab-spread__after{white-space:pre-wrap;min-width:0}.paper-content table.sobree-table-bordered td,.paper-content table.sobree-table-bordered th{border:var(--table-cell-border, none);padding:0 4px}.sobree-editor{position:relative;outline:none}.sobree-editor>:first-child{margin-top:0}.sobree-editor p,.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6,.sobree-editor ul,.sobree-editor ol,.sobree-editor li,.sobree-editor blockquote,.sobree-editor pre{margin:0;padding:0}.sobree-editor ul,.sobree-editor ol{padding-left:1.5em}.sobree-editor li.sobree-li-continuation{list-style-type:none}.sobree-editor li.sobree-li-continuation::marker{content:""}.sobree-editor .sobree-fragment-continued{text-align-last:justify}.sobree-editor .sobree-footnote-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-footnote-ref a:hover{text-decoration:underline}.sobree-editor .sobree-footnotes{margin-top:2em;padding-top:.5em;border-top:1pt solid currentColor;font-size:.85em}.sobree-editor .sobree-footnotes__list{padding-left:1.5em}.sobree-editor .sobree-footnotes__item{margin:.25em 0}.sobree-editor ins.sobree-revision-ins{text-decoration:underline}.sobree-editor del.sobree-revision-del{text-decoration:line-through}.sobree-editor .sobree-revision-format{text-decoration:underline dashed var(--sobree-format-revision-color, currentColor);text-underline-offset:3px}.sobree-editor [data-block-revision=ins]:after,.sobree-editor [data-block-revision=del]:after{content:" ¶";color:var(--sobree-block-revision-color, currentColor);opacity:.65;font-weight:600;-webkit-user-select:none;user-select:none}.sobree-editor [data-block-revision=del]:after{text-decoration:line-through}.sobree-editor .sobree-comment-range{background:var(--sobree-comment-range-bg, rgba(255, 217, 0, .25));border-bottom:1px dotted var(--sobree-comment-range-border, rgba(180, 130, 0, .5))}.sobree-editor .sobree-comment-ref{display:inline;font-size:.85em;margin:0 .1em}.sobree-editor .sobree-comment-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-comment-ref a:hover{filter:brightness(.7)}.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6{font-size:inherit;font-weight:inherit}.sobree-editor table{border-collapse:collapse;width:100%;position:relative}.sobree-editor th,.sobree-editor td{border:none;padding:0 .08in;vertical-align:top;transition:border-color .12s ease}.sobree-editor .sobree-section-break{display:flex;align-items:center;gap:8px;margin:8px 0;color:var(--fg-subtle, #7c7764);font-size:11px;letter-spacing:.04em;text-transform:uppercase;-webkit-user-select:none;user-select:none}.sobree-editor .sobree-section-break--continuous{visibility:hidden;height:0;margin:0;padding:0;border:none;overflow:hidden;font-size:0;line-height:0}.sobree-editor .sobree-section-break:before,.sobree-editor .sobree-section-break:after{content:"";flex:1;border-top:1px dashed var(--border, #dedbd0)}.sobree-editor .sobree-section-break__label{flex:none;padding:0 6px;background:var(--bg-elevated, #fff)}.sobree-editor .sobree-textbox-frame p{line-height:1.2}.sobree-editor .paper-content p,.sobree-editor .paper-content li,.sobree-editor .paper-header p,.sobree-editor .paper-header li,.sobree-editor .paper-footer p,.sobree-editor .paper-footer li,.sobree-editor .sobree-textbox-frame p{white-space:pre-wrap}.sobree-editor .sobree-section-trailer-empty{height:0;line-height:0;font-size:0;margin:0;padding:0;overflow:hidden}.sobree-editor .sobree-textbox-frame--placeholder{border:1px solid var(--border, #c8c4b8)}.sobree-editor .sobree-textbox-frame--placeholder.sobree-textbox-frame--filled{border:none;z-index:-1}.sobree-editor img.is-selected{outline:2px solid var(--sobree-primary, #d4521f);outline-offset:2px}.sobree-image-resize-handle{position:absolute;width:16px;height:16px;background:var(--sobree-primary, #d4521f);border:2px solid #fff;border-radius:3px;cursor:nwse-resize;z-index:1000;-webkit-user-select:none;user-select:none}.sobree-viewport{position:relative;overflow:hidden;overscroll-behavior:contain;touch-action:none;background:#ececee}.sobree-viewport__stage{position:absolute;top:0;left:0;transform-origin:0 0}.sobree-viewport__stage.is-gesturing,.sobree-viewport__stage.is-animating{will-change:transform}.sobree-viewport__stage.is-animating{transition:transform .32s cubic-bezier(.2,.7,.2,1)}.sobree-viewport__slot{display:block}.paper-stack .paper-content,.paper-stack .paper-header,.paper-stack .paper-footer{transition:opacity .2s ease}.paper-stack.is-zone-editing .paper-content,.paper-stack.is-zone-editing .paper-header,.paper-stack.is-zone-editing .paper-footer{opacity:.2}.paper-stack.is-zone-editing .paper-header[contenteditable=true],.paper-stack.is-zone-editing .paper-footer[contenteditable=true]{opacity:1}.paper-header[contenteditable=true],.paper-footer[contenteditable=true]{outline:2px dotted var(--primary, #c96f22);outline-offset:4px;background:var(--primary-soft, #fdf6ee);color:var(--fg-strong, #14130f);border-radius:2px}
|