@overglaze/web 0.0.0-stage → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +98 -0
  2. package/README.md +63 -2
  3. package/desktops/desktop.js +40 -0
  4. package/desktops/fonts/DMMono-Medium.woff2 +0 -0
  5. package/desktops/fonts/DMMono-Regular.woff2 +0 -0
  6. package/desktops/fonts/NotoSerif-VF.woff2 +0 -0
  7. package/desktops/fonts/OFL-DMMono.txt +93 -0
  8. package/desktops/fonts/OFL-NotoSerif.txt +93 -0
  9. package/desktops/fonts/OFL-SpaceGrotesk.txt +93 -0
  10. package/desktops/fonts/SpaceGrotesk-Bold.woff2 +0 -0
  11. package/desktops/fonts/SpaceGrotesk-Medium.woff2 +0 -0
  12. package/desktops/fonts/SpaceGrotesk-Regular.woff2 +0 -0
  13. package/desktops/wallpapers.js +227 -0
  14. package/embed.css +53 -0
  15. package/embed.js +6 -0
  16. package/engine/core.js +6 -0
  17. package/engine/cursor.js +6 -0
  18. package/engine/descriptor.js +6 -0
  19. package/engine/files.js +6 -0
  20. package/engine/globals.js +6 -0
  21. package/engine/golden-globals.js +6 -0
  22. package/engine/imgui-ops.js +6 -0
  23. package/engine/keys.js +6 -0
  24. package/engine/modules.js +6 -0
  25. package/engine/naga.wasm +0 -0
  26. package/engine/naga.wasm.notices.txt +2344 -0
  27. package/engine/ops.js +6 -0
  28. package/engine/param-store.js +6 -0
  29. package/engine/plugin-js.wasm +0 -0
  30. package/engine/plugin-js.wasm.notices.txt +4411 -0
  31. package/engine/plugin-storage.js +6 -0
  32. package/engine/session.js +9 -0
  33. package/engine/shaders.js +7 -0
  34. package/engine/tex.js +6 -0
  35. package/engine/uniforms.js +6 -0
  36. package/engine/worker.js +74 -0
  37. package/host/api.js +30 -0
  38. package/host/assets.js +6 -0
  39. package/host/bootstrap.js +7 -0
  40. package/host/imgui.js +6 -0
  41. package/host/params.js +6 -0
  42. package/host/seeded_random.js +6 -0
  43. package/host/storage.js +6 -0
  44. package/host/webio.js +6 -0
  45. package/host/webshim.js +6 -0
  46. package/package.json +19 -4
  47. package/player/fill.js +6 -0
  48. package/player/panel.css +92 -0
  49. package/player/panel.js +6 -0
  50. package/player/player.css +210 -0
  51. package/player/player.js +6 -0
package/LICENSE ADDED
@@ -0,0 +1,98 @@
1
+ The Overglaze web engine (@overglaze/web) is licensed under the PolyForm Noncommercial
2
+ License 1.0.0, which follows below unmodified, together with the additional permission
3
+ in this preamble.
4
+
5
+ Additional permission for plugin authors
6
+
7
+ In addition to the permissions of the license below, the licensor grants you permission
8
+ to load and run this software, unmodified, in a web browser -- from any page, including
9
+ the preview of a code sandbox, an online editor or a development server -- to develop,
10
+ test, preview and demonstrate plugins for Overglaze, including plugins you sell.
11
+
12
+ This permission covers no other use. It does not permit you to distribute the software
13
+ as part of another product, or to run it on a page or in an application for any other
14
+ purpose; any such use is governed by the license below alone.
15
+
16
+ Plugins you write are yours: running a plugin in this software places no part of it
17
+ under these terms.
18
+
19
+ The preamble above adds a permission and takes none away. The license itself follows
20
+ below, unmodified.
21
+
22
+ --------------------------------------------------------------------------------
23
+
24
+ # PolyForm Noncommercial License 1.0.0
25
+
26
+ <https://polyformproject.org/licenses/noncommercial/1.0.0>
27
+
28
+ Required Notice: Copyright (c) 2026 Svetlozar Kostadinov
29
+
30
+ ## Acceptance
31
+
32
+ In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
33
+
34
+ ## Copyright License
35
+
36
+ The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it for any permitted purpose. However, you may only distribute the software according to [Distribution License](#distribution-license) and make changes or new works based on the software according to [Changes and New Works License](#changes-and-new-works-license).
37
+
38
+ ## Distribution License
39
+
40
+ The licensor grants you an additional copyright license to distribute copies of the software. Your license to distribute covers distributing the software with changes and new works permitted by [Changes and New Works License](#changes-and-new-works-license).
41
+
42
+ ## Notices
43
+
44
+ You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above, as well as copies of any plain-text lines beginning with `Required Notice:` that the licensor provided with the software. For example:
45
+
46
+ > Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
47
+
48
+ ## Changes and New Works License
49
+
50
+ The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
51
+
52
+ ## Patent License
53
+
54
+ The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
55
+
56
+ ## Noncommercial Purposes
57
+
58
+ Any noncommercial purpose is a permitted purpose.
59
+
60
+ ## Personal Uses
61
+
62
+ Personal use for research, experiment, and testing for the benefit of public knowledge, personal study, private entertainment, hobby projects, amateur pursuits, or religious observance, without any anticipated commercial application, is use for a permitted purpose.
63
+
64
+ ## Noncommercial Organizations
65
+
66
+ Use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization, or government institution is use for a permitted purpose regardless of the source of funding or obligations resulting from the funding.
67
+
68
+ ## Fair Use
69
+
70
+ You may have "fair use" rights for the software under the law. These terms do not limit them.
71
+
72
+ ## No Other Rights
73
+
74
+ These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
75
+
76
+ ## Patent Defense
77
+
78
+ If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
79
+
80
+ ## Violations
81
+
82
+ The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
83
+
84
+ ## No Liability
85
+
86
+ ***As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.***
87
+
88
+ ## Definitions
89
+
90
+ The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
91
+
92
+ **You** refers to the individual or entity agreeing to these terms.
93
+
94
+ **Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. **Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
95
+
96
+ **Your licenses** are all the licenses granted to you for the software under these terms.
97
+
98
+ **Use** means anything you do with the software requiring one of your licenses.
package/README.md CHANGED
@@ -1,3 +1,64 @@
1
- # Temporary Holding Version
1
+ # @overglaze/web
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The Overglaze web engine: an [Overglaze](https://overglaze.io) plugin, run from its own files,
4
+ live in a player's box on any page. It runs the desktop's own host JS in a browser Worker over
5
+ WebGPU, so a plugin behaves here as it does on the desktop, and where it would not, the box
6
+ says so.
7
+
8
+ Overglaze is a fullscreen overlay that re-renders the live desktop through GPU shader effects;
9
+ its plugins are thin npm packages of JavaScript or TypeScript and WGSL. This package is what
10
+ lets you write one in a code sandbox and see it run before you install it.
11
+
12
+ ## On a page
13
+
14
+ Import the embed by its URL, from a CDN that serves npm packages:
15
+
16
+ ```html
17
+ <div id="box"></div>
18
+ <script type="module">
19
+ import { mount } from "https://cdn.jsdelivr.net/npm/@overglaze/web@0.9/embed.js";
20
+ const og = mount(document.querySelector("#box"), {
21
+ files: { "index.wgsl": document.querySelector("#shader").textContent },
22
+ });
23
+ </script>
24
+ ```
25
+
26
+ `https://unpkg.com/@overglaze/web@0.9/embed.js` serves the same files. The embed finds the rest
27
+ of the engine beside itself, so import it from where the whole package is served.
28
+
29
+ `mount(element, options)` fills `element` with the box, its controls and the diagnostics, and
30
+ starts the plugin over a mock desktop whose windows the pointer moves. It returns at once and
31
+ never throws for the plugin: a fault shows in the box and in the diagnostics. The options:
32
+
33
+ - `files`: the plugin's files, an object (or a `Map`) of relative `/`-separated names to their
34
+ contents. A string is text; an `ArrayBuffer`, a typed array or a `Blob` is bytes; a `URL` is
35
+ fetched.
36
+ - `entry`: the file it runs, in place of `package.json`'s `main`. Without a `package.json`, a
37
+ `.wgsl` entry is a sketch.
38
+ - `storage`: a name to keep the plugin's storage and saved parameters under, in this origin.
39
+ Without one, nothing outlives the page.
40
+ - `panel`: `true` for the parameter panel beside the box.
41
+
42
+ It returns `pause()`, `resume()`, `fullscreen()`, `theme("light" | "dark")`, `compare(at)` (the
43
+ before/after divider at a fraction of the box, or `null`), `stop()`, and two readings: `state`
44
+ (`"loading"`, `"live"` from the plugin's first frame, `"stopped"`) and `diagnostics`.
45
+
46
+ ## In a plugin folder
47
+
48
+ `overglaze dev`, from the [`overglaze`](https://www.npmjs.com/package/overglaze) CLI, which
49
+ depends on this package, serves your plugin folder in the same box and reloads it on every
50
+ save:
51
+
52
+ ```sh
53
+ npx overglaze dev
54
+ ```
55
+
56
+ ## Licence
57
+
58
+ The PolyForm Noncommercial License 1.0.0, with an added permission: anyone may load and run the
59
+ engine, unmodified, in a browser to develop, test, preview and demonstrate Overglaze plugins,
60
+ including plugins they sell. Plugins you write are yours. See `LICENSE` for the terms.
61
+
62
+ The fonts in `desktops/fonts/` are under the SIL Open Font License, each beside its licence.
63
+ `engine/plugin-js.wasm` and `engine/naga.wasm` are built from open-source crates, each listed
64
+ with its licence in the `.notices.txt` beside it.
@@ -0,0 +1,40 @@
1
+ /*! Overglaze web engine. Licensed under the PolyForm Noncommercial License 1.0.0
2
+ * <https://polyformproject.org/licenses/noncommercial/1.0.0>
3
+ * Required Notice: Copyright (c) 2026 Svetlozar Kostadinov
4
+ * With an added permission to run it to develop and preview Overglaze plugins: see LICENSE in @overglaze/web
5
+ */
6
+ var Rt=Object.defineProperty;var x=(e,t)=>Rt(e,"name",{value:t,configurable:!0});import{SCENES as At}from"./wallpapers.js";const bt=1,Bt=[1920,1080],dt=48,st=30,nt=24,N=10,Z=4,Dt=280,zt=4,V=120,J=6,Lt=14,ct=420,ut=240,Gt=400,It=[["Desk Sans","400","SpaceGrotesk-Regular.woff2"],["Desk Sans","500","SpaceGrotesk-Medium.woff2"],["Desk Sans","700","SpaceGrotesk-Bold.woff2"],["Desk Mono","400","DMMono-Regular.woff2"],["Desk Mono","500","DMMono-Medium.woff2"],["Desk Serif","400 700","NotoSerif-VF.woff2"]],at={light:{"wall-0":"#dce6f1","wall-1":"#b9cfea","wall-2":"#f4d2bb","wall-3":"#d4c3f2","wall-4":"#a8d6cd","wall-sheen":"#ffffff",win:"#ffffff",chrome:"#f1f2f5",toolbar:"#fafbfc",field:"#e9ebef",line:"#dadde3",grid:"#e4e7eb",edge:"rgba(20, 28, 40, 0.14)",ink:"#1b1e24","ink-2":"#4a505b",muted:"#7a818d",faint:"#a9afb9",sel:"#dbe7ff",curline:"#f3f5f9",guide:"#e6e8ec",shadow:"0 24px 64px rgba(28, 38, 58, 0.26), 0 4px 14px rgba(28, 38, 58, 0.12)","shadow-active":"0 30px 80px rgba(28, 38, 58, 0.34), 0 6px 18px rgba(28, 38, 58, 0.16)",browser:"#d9542e",sheet:"#1f9358",editor:"#6a52ee",files:"#d79a1c",music:"#d2457f",paper:"#fbfaf7","paper-ink":"#201e1b","paper-ink-2":"#4b4741","paper-muted":"#8a847b","paper-line":"#e7e3dc",hdr:"#f4f5f7","hdr-hi":"#dff1e7","row-head":"#eaf6ef","bar-fill":"rgba(31, 147, 88, 0.2)",ferry:"#2f72d6",train:"#7553e8",bus:"#c98a12",foot:"#23905a",kw:"#8a2bb8",ty:"#0e7686",st:"#2f7d32",nu:"#b5560b",fn:"#2758c4",pr:"#a3402a",cm:"#8a909a",pu:"#4a505b",warn:"#c98a12",bar:"rgba(248, 249, 251, 0.74)","bar-line":"rgba(255, 255, 255, 0.7)","bar-field":"rgba(20, 28, 40, 0.07)","bar-hi":"rgba(20, 28, 40, 0.08)"},dark:{"wall-0":"#0a1120","wall-1":"#10294a","wall-2":"#3a1a48","wall-3":"#0d3d47","wall-4":"#2a1f5c","wall-sheen":"#8fe3ff",win:"#1b1d23",chrome:"#22252c",toolbar:"#262930",field:"#191b20",line:"#343842",grid:"#2d3038",edge:"rgba(255, 255, 255, 0.09)",ink:"#e7e9ee","ink-2":"#b6bbc5",muted:"#8a909b",faint:"#5c626d",sel:"#263f6b",curline:"#23262d",guide:"#2c2f37",shadow:"0 24px 64px rgba(0, 0, 0, 0.55), 0 4px 14px rgba(0, 0, 0, 0.35)","shadow-active":"0 30px 80px rgba(0, 0, 0, 0.65), 0 6px 18px rgba(0, 0, 0, 0.4)",browser:"#ff7a52",sheet:"#3cc07c",editor:"#9583ff",files:"#f0b440",music:"#ff6fa6",paper:"#16171b","paper-ink":"#e8e5df","paper-ink-2":"#b9b4ab","paper-muted":"#857f76","paper-line":"#2c2d33",hdr:"#22252b","hdr-hi":"#1d3a2b","row-head":"#1c2c24","bar-fill":"rgba(60, 192, 124, 0.26)",ferry:"#6aa6ff",train:"#a58cff",bus:"#f0b440",foot:"#4fd08e",kw:"#d38cff",ty:"#5fd4d0",st:"#a3d97c",nu:"#f5a25d",fn:"#7fb2ff",pr:"#ff9e83",cm:"#6c7380",pu:"#b6bbc5",warn:"#f0b440",bar:"rgba(16, 18, 24, 0.72)","bar-line":"rgba(255, 255, 255, 0.07)","bar-field":"rgba(255, 255, 255, 0.07)","bar-hi":"rgba(255, 255, 255, 0.09)"}},Ft=`<svg class="wall" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
7
+ <defs>
8
+ <linearGradient id="w-base" x1="0" y1="0" x2="1" y2="1">
9
+ <stop offset="0" style="stop-color: var(--wall-1)"/>
10
+ <stop offset="0.5" style="stop-color: var(--wall-0)"/>
11
+ <stop offset="1" style="stop-color: var(--wall-2)"/>
12
+ </linearGradient>
13
+ <linearGradient id="w-flow-a" x1="0" y1="0" x2="1" y2="0">
14
+ <stop offset="0" style="stop-color: var(--wall-4)"/>
15
+ <stop offset="0.5" style="stop-color: var(--wall-3)"/>
16
+ <stop offset="1" style="stop-color: var(--wall-2)"/>
17
+ </linearGradient>
18
+ <linearGradient id="w-flow-b" x1="0" y1="0" x2="1" y2="0">
19
+ <stop offset="0" style="stop-color: var(--wall-2)"/>
20
+ <stop offset="1" style="stop-color: var(--wall-4)"/>
21
+ </linearGradient>
22
+ <filter id="w-blur-l" x="-30%" y="-30%" width="160%" height="160%"><feGaussianBlur stdDeviation="110"/></filter>
23
+ <filter id="w-blur-m" x="-20%" y="-40%" width="140%" height="180%"><feGaussianBlur stdDeviation="38"/></filter>
24
+ <filter id="w-blur-s" x="-10%" y="-40%" width="120%" height="180%"><feGaussianBlur stdDeviation="5"/></filter>
25
+ </defs>
26
+ <rect width="1920" height="1080" fill="url(#w-base)"/>
27
+ <g filter="url(#w-blur-l)">
28
+ <ellipse cx="1560" cy="160" rx="560" ry="300" style="fill: var(--wall-3)" opacity="0.85"/>
29
+ <ellipse cx="240" cy="960" rx="640" ry="330" style="fill: var(--wall-4)" opacity="0.9"/>
30
+ <ellipse cx="980" cy="640" rx="460" ry="260" style="fill: var(--wall-2)" opacity="0.55"/>
31
+ </g>
32
+ <g filter="url(#w-blur-m)" opacity="0.8">
33
+ <path d="M-120 900 C 220 700, 560 1080, 940 930 S 1560 640, 2040 760" fill="none" stroke="url(#w-flow-a)" stroke-width="170"/>
34
+ <path d="M-120 250 C 380 60, 820 480, 1300 260 S 1900 110, 2040 200" fill="none" stroke="url(#w-flow-b)" stroke-width="95"/>
35
+ </g>
36
+ <g filter="url(#w-blur-s)" opacity="0.55">
37
+ <path d="M-120 838 C 220 640, 560 1020, 940 868 S 1560 580, 2040 698" fill="none" style="stroke: var(--wall-sheen)" stroke-width="5"/>
38
+ <path d="M-120 214 C 380 24, 820 444, 1300 224 S 1900 74, 2040 164" fill="none" style="stroke: var(--wall-sheen)" stroke-width="3"/>
39
+ </g>
40
+ </svg>`;let K=null;function Ht(e=new URL("fonts/",import.meta.url).href){if(!K){const t=typeof document=="object"?document:self;K=Promise.all(It.map(async([s,n,i])=>{const a=await fetch(new URL(i,e));if(!a.ok)throw new Error("no font at "+a.url+" ("+a.status+")");const r=new FontFace(s,await a.arrayBuffer(),{weight:n});await r.load(),t.fonts.add(r)})),K.catch(()=>{K=null})}return K}x(Ht,"loadFonts");function X(e,t,s,n,i,a){e.beginPath(),e.roundRect(t,s,n,i,a)}x(X,"rr");function c(e,t,s,n,i,a,r=0){e.fillStyle=t,r?(X(e,s,n,i,a,r),e.fill()):e.fillRect(s,n,i,a)}x(c,"fill");function m(e,t,s,n,i,a,r="left"){return e.font=i,e.fillStyle=a,e.textAlign=r,e.textBaseline="middle",e.fillText(t,s,n),e.measureText(t).width}x(m,"text");function q(e,t,s,n){if(e.font=n,e.measureText(t).width<=s)return t;for(;t.length>1&&e.measureText(t+"...").width>s;)t=t.slice(0,-1);return t+"..."}x(q,"fit");function Q(e,t,s,n){e.font=n;const i=[];let a="";for(const r of t.split(" ")){const l=a?a+" "+r:r;e.measureText(l).width>s&&a?(i.push(a),a=r):a=l}return a&&i.push(a),i}x(Q,"wrap");const yt={min:"M6 12h12",max:"M8 6h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z",restore:"M9 9h7a1.5 1.5 0 0 1 1.5 1.5V17a1.5 1.5 0 0 1-1.5 1.5H9A1.5 1.5 0 0 1 7.5 17v-6.5A1.5 1.5 0 0 1 9 9zM10.5 6h7A1.5 1.5 0 0 1 19 7.5v7",close:"M7 7l10 10M17 7 7 17",back:"M19 12H5M11 6l-6 6 6 6",fwd:"M5 12h14M13 6l6 6-6 6",reload:"M19 12a7 7 0 1 1-2.1-5M19 4.5V9h-4.5",lock:"M7.5 10.5h9a2 2 0 0 1 2 2v5.5a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2v-5.5a2 2 0 0 1 2-2zM8.5 10.5V8a3.5 3.5 0 0 1 7 0v2.5",search:"M10.5 4a6.5 6.5 0 1 1 0 13 6.5 6.5 0 0 1 0-13zM15.5 15.5 20 20",plus:"M12 6v12M6 12h12",dots:"M12 6v.01M12 12v.01M12 18v.01",table:"M5 5h14v14H5zM5 10h14M5 15h14M10 5v14",braces:"M9 5c-2 0-2 1.5-2 3v1.5c0 1-.8 2.5-2 2.5 1.2 0 2 1.5 2 2.5V16c0 1.5 0 3 2 3M15 5c2 0 2 1.5 2 3v1.5c0 1 .8 2.5 2 2.5-1.2 0-2 1.5-2 2.5V16c0 1.5 0 3-2 3",compass:"M12 3a9 9 0 1 1 0 18 9 9 0 0 1 0-18zM15.5 8.5l-2 5-5 2 2-5z",folder:"M4 7a2 2 0 0 1 2-2h4l2 2h6a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z",note:"M9 18V6l10-2v12M9 18a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0zM19 16a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0z",sliders:"M5 7h14M5 12h14M5 17h14M9 5v4M15 10v4M8 15v4",file:"M7 3.5h7l4 4v13H7zM14 3.5v4h4",down:"M7 10l5 5 5-5",branch:"M7 5v14M7 15a4 4 0 0 0 4-4h2a4 4 0 0 0 4-4M17 5v2",launch:"M6 6h.01M12 6h.01M18 6h.01M6 12h.01M12 12h.01M18 12h.01M6 18h.01M12 18h.01M18 18h.01",dot:"M12 12h.01",prompt:"M5 7l5 5-5 5M12 17h7",pulse:"M3 12h4l2-6 4 12 2-6h6"},rt=new Map;function B(e,t,s,n,i,a,r=1.7){rt.has(t)||rt.set(t,new Path2D(yt[t]||yt.dot)),e.save(),e.translate(s,n),e.scale(i/24,i/24),e.strokeStyle=a,e.lineWidth=r*24/i,e.lineCap="round",e.lineJoin="round",e.stroke(rt.get(t)),e.restore()}x(B,"glyph");const Wt={fjord:{sky:["#2f4b7c","#8e6c93","#ee9f74","#ffd197"],hills:["#9a85a8","#5c5075","#2c283e"],water:["#6d5a78","#1c1d30"],sun:[.66,.34,"#ffbe78"]},mist:{sky:["#8fa3c9","#e9b9c4","#fbe3cf"],hills:["#9aa7c4","#6f8aa0","#3f5d63","#1f3337"],sun:[.3,.5,"#ffd6c2"]},aurora:{sky:["#040814","#0b1d33","#163a4a"],hills:["#0e1826","#070c14"],water:["#0b2030","#03060c"],glow:"#5cf2a8"},cliffs:{sky:["#3c77c3","#bcd9f0"],hills:["#7d9bb5"],water:["#2f6f9e","#0f3456"],cliff:"#6a5646"}};function xt(e,t,s,n,i,a){const r=Wt[a];e.save(),e.beginPath(),e.rect(t,s,n,i),e.clip();const l=e.createLinearGradient(0,s,0,s+i*.7);if(r.sky.forEach((o,h)=>l.addColorStop(h/(r.sky.length-1),o)),e.fillStyle=l,e.fillRect(t,s,n,i),r.sun){const[o,h,f]=r.sun,w=e.createRadialGradient(t+o*n,s+h*i,0,t+o*n,s+h*i,i*.6);w.addColorStop(0,f),w.addColorStop(1,"rgba(255,255,255,0)"),e.fillStyle=w,e.fillRect(t,s,n,i)}if(r.glow){e.globalAlpha=.35;const o=e.createLinearGradient(0,s+i*.15,0,s+i*.6);o.addColorStop(0,"rgba(0,0,0,0)"),o.addColorStop(.5,r.glow),o.addColorStop(1,"rgba(0,0,0,0)"),e.fillStyle=o,e.fillRect(t,s,n,i),e.globalAlpha=1}if(r.hills.forEach((o,h)=>{const f=s+i*(r.water?.5+h*.07:.45+h*.16),w=i*(.16-h*.03);e.beginPath(),e.moveTo(t,s+i);for(let p=0;p<=64;p++){const d=p/64,b=Math.sin(d*7.1+h*2.3)*.5+Math.sin(d*17.3+h)*.25+Math.sin(d*41+h*5)*.1;e.lineTo(t+d*n,f-Math.abs(b)*w)}e.lineTo(t+n,s+i),e.closePath(),e.fillStyle=o,e.fill()}),r.water){const o=s+i*.68,h=e.createLinearGradient(0,o,0,s+i);h.addColorStop(0,r.water[0]),h.addColorStop(1,r.water[1]),e.fillStyle=h,e.fillRect(t,o,n,i-(o-s))}r.cliff&&(e.beginPath(),e.moveTo(t+n*.55,s+i),e.lineTo(t+n*.7,s+i*.55),e.lineTo(t+n,s+i*.5),e.lineTo(t+n,s+i),e.fillStyle=r.cliff,e.fill()),e.restore()}x(xt,"photo");const A=x((e,t)=>e+" "+t+'px "Desk Sans"',"SANS"),O=x((e,t)=>e+" "+t+'px "Desk Mono"',"MONO"),j=x((e,t)=>e+" "+t+'px "Desk Serif"',"SERIF");function it(e,t,s,n,i,a,r){c(e,t.chrome,0,0,s,40),c(e,t.line,0,39,s,1),c(e,t[n],14,10,20,20,6),B(e,{sheet:"table",editor:"braces",term:"prompt",mon:"pulse"}[n],17.5,13.5,13,"#fff",2);const l=m(e,q(e,i,s-200,A(500,13)),44,20,A(500,13),r?t.ink:t["ink-2"]);a&&m(e,a,50+l,20,A(400,12),t.muted)}x(it,"titlebar");const pt=[["Twelve days along the northern coast - Northbound","browser","northbound.example","/journeys/northern-coast"],["Tide tables - Harbour office","ferry","harbour.example","/tides/ostmere"],["Night trains, summer timetable","foot","rail.example","/night/summer"]],jt=["Journeys","Maps","Field kit","Letters"],Ut=["The first ferry leaves Ostmere at ten past six, while the harbour is still blue and the gulls have the quay to themselves. By the time the engines settle into their long hum, the town has shrunk to a row of lit windows under the hill, and the sound opens out ahead, flat and silver as a sheet of tin.","We had planned every leg in advance: departure times, connections, the price of each bunk. The tides had other ideas. On the outer islands the boats sail when the water allows, and a timetable is a statement of hope."],_t=[["A week of mist in the Brannoch hills","9 min read","mist"],["Under the lights at Kelder lake","6 min read","aurora"],["The cliff path, end to end","11 min read","cliffs"]];function gt(e,t,s,n,i){const a=i.state;c(e,t.chrome,0,0,s,42);const r=Math.min(228,(s-260)/3);pt.forEach(([b,S],g)=>{const u=8+g*(r+4);g===a.tab&&c(e,t.win,u,6,r,36,9),c(e,t[S],u+14,20,10,10,3),m(e,q(e,b,r-68,A(400,12.5)),u+32,25,A(400,12.5),g===a.tab?t.ink:t["ink-2"]),B(e,"close",u+r-24,18,14,t.muted,1.6),i.hit("tab"+g,u,6,r,36,()=>a.tab=g)}),B(e,"plus",8+3*(r+4)+6,15,16,t.muted),c(e,t.toolbar,0,42,s,48),c(e,t.line,0,89,s,1),["back","fwd","reload"].forEach((b,S)=>B(e,b,14+S*36,58,16,S===1?t.faint:t["ink-2"])),c(e,t.field,124,50,s-190,32,16),B(e,"lock",138,58,16,t.muted);const[,,l,o]=pt[a.tab],h=m(e,l,162,66,A(500,13),t.ink);m(e,o,162+h,66,A(400,13),t.muted),B(e,"dots",s-46,58,16,t["ink-2"]);const f=90;c(e,t.paper,0,f,s,n-f),e.fillStyle=t.browser,e.beginPath(),e.moveTo(52,f+18),e.lineTo(60,f+40),e.lineTo(52,f+35),e.lineTo(44,f+40),e.closePath(),e.fill(),m(e,"Northbound",70,f+30,j(700,22),t["paper-ink"]);let w=250;jt.forEach((b,S)=>{const g=S===a.nav,u=m(e,b,w,f+30,A(g?500:400,13.5),g?t["paper-ink"]:t["paper-ink-2"]);g&&c(e,t.browser,w,f+42,u,2),i.hit("nav"+S,w-6,f+14,u+12,32,()=>a.nav=S),w+=u+28}),s>760&&(c(e,t["paper-ink"],s-140,f+16,104,30,15),m(e,"Subscribe",s-88,f+31,A(500,13),t.paper,"center"),i.hit("subscribe",s-140,f+16,104,30,null)),xt(e,0,f+60,s,330,"fjord"),m(e,"Evening light over Ostmere sound, day four.",20,f+372,A(400,12.5),"#ffffff");const p=s>1e3?660:Math.max(200,s-80);let d=f+420;m(e,"JOURNEYS - 14 MIN READ",40,d,A(700,11.5),t.browser),d+=38;for(const b of Q(e,"Twelve days along the northern coast",p,j(700,40)))m(e,b,40,d,j(700,40),t["paper-ink"]),d+=46;d+=4;for(const b of Q(e,"Six ferries, two night trains and one long walk over the headland: a slow route north, planned to the minute and abandoned by day three.",p,A(400,17)))m(e,b,40,d,A(400,17),t["paper-ink-2"]),d+=25;d+=10,m(e,q(e,"Updated 29 October - Words and photographs by the Northbound desk",p,A(400,12)),40,d,A(400,12),t["paper-muted"]),d+=18,c(e,t["paper-line"],40,d,p,1),d+=28;for(const b of Ut){for(const S of Q(e,b,p,j(400,17))){if(d>n-10)break;m(e,S,40,d,j(400,17),t["paper-ink"]),d+=28}d+=12}s>1e3&&(m(e,"MORE JOURNEYS",750,f+420,A(700,11.5),t["paper-muted"]),_t.forEach(([b,S,g],u)=>{const v=f+446+u*96;e.save(),X(e,750,v,84,72,6),e.clip(),xt(e,750,v,84,72,g),e.restore(),Q(e,b,s-900,j(600,15)).slice(0,2).forEach((y,T)=>m(e,y,846,v+14+T*20,j(600,15),t["paper-ink"])),m(e,S,846,v+58,A(400,12),t["paper-muted"]),i.hit("card"+u,744,v-6,s-780,84,null)}))}x(gt,"paintBrowser");const Y=[["Sat 3 May","Ostmere","Varn","ferry",1,46,"Early boat, 06:10"],["Sun 4 May","Varn","Holm Ness","ferry",2,38.5,"Sails on the tide"],["Tue 6 May","Holm Ness","Brannoch","bus",1,12.8,"Change at Aird"],["Wed 7 May","Brannoch","Kelder","foot",2,0,"Headland path, 19 km"],["Fri 9 May","Kelder","Lowra","train",1,64.2,"Night train, bunk"],["Sat 10 May","Lowra","Finnmouth","ferry",1,52,""],["Sun 11 May","Finnmouth","Ard Sound","bus",1,9.4,""],["Mon 12 May","Ard Sound","Tarrow","ferry",2,41.75,"Book a day ahead"],["Wed 14 May","Tarrow","Elsby","train",1,58.9,""],["Thu 15 May","Elsby","Norrhaven","ferry",1,47.3,"Last sailing 21:40"],["Fri 16 May","Norrhaven","Saltreach","bus",1,14.6,""],["Sat 17 May","Saltreach","Ostmere","train",0,72.1,"Night train home"]],Vt=["Budget","Packing","Stays"],kt="ABCDEFGH";function Mt(e,t){if(e===13)return t===5?"=SUM(F2:F13)":t===6?"=SUM(G2:G13)":t===0?"Total":"";if(e===0)return["Leg","Date","From","To","By","Nights","Cost","Notes"][t];const s=Y[e-1];return s?[String(e),s[0],s[1],s[2],s[3],String(s[4]),s[5].toFixed(2),s[6]][t]:""}x(Mt,"cellValue");function qt(e,t,s,n,i){const a=i.state;it(e,t,s,"sheet","Trip budget","Saved",i.active),c(e,t.toolbar,0,40,s,44),c(e,t.line,0,83,s,1);let r=12;for(const u of["undo","redo","|","Desk Sans","11","|","B","I","U","|","S","%"]){if(r>s-40)break;if(u==="|"){c(e,t.line,r+4,52,1,20),r+=10;continue}const v=u==="Desk Sans"?96:u.length>2?50:30;u.length>2?(c(e,t.field,r,50,v,24,6),m(e,u,r+10,62,A(400,12.5),t["ink-2"])):(a.format.includes(u)&&c(e,t.sel,r,50,v,24,6),m(e,u,r+v/2,62,A(700,13),t["ink-2"],"center"),"BIU".includes(u)&&i.hit("fmt"+u,r,50,v,24,()=>{a.format=a.format.includes(u)?a.format.replace(u,""):a.format+u})),r+=v+4}c(e,t.win,0,84,s,30),c(e,t.line,0,113,s,1),m(e,kt[a.cell[1]]+(a.cell[0]+1),18,99,O(500,12),t["ink-2"]),c(e,t.line,64,88,1,22),m(e,"fx",78,99,j(400,13),t.muted),m(e,Mt(a.cell[0],a.cell[1]),100,99,O(400,12.5),t.ink);const l=[34,44,92,100,100,84,64,92,Math.max(60,s-610)],o=[0];for(const u of l)o.push(o[o.length-1]+u);const h=22,f=114;c(e,t.hdr,0,f,s,h),kt.split("").forEach((u,v)=>{const y=v===a.cell[1];y&&c(e,t["hdr-hi"],o[v+1],f,l[v+1],h),m(e,u,o[v+1]+l[v+1]/2,f+11,A(500,11.5),y?t.sheet:t.muted,"center")});const w=Math.max(...Y.map(u=>u[5])),p={ferry:t.ferry,train:t.train,bus:t.bus,foot:t.foot},d=a.format.includes("B")?700:400,b=Math.min(16,Math.floor((n-f-h-30)/h));for(let u=0;u<b;u++){const v=f+h*(u+1),y=u===13;c(e,u===0?t["row-head"]:t.win,o[1],v,s,h),c(e,t.hdr,0,v,34,h),m(e,String(u+1),17,v+11,A(400,11.5),u===a.cell[0]?t.sheet:t.muted,"center");const T=u>=1&&u<=12?Y[u-1]:null;for(let M=0;M<8;M++){const P=o[M+1],R=Mt(u,M),D=M===0||M===5||M===6;if(T&&M===6&&c(e,t["bar-fill"],P+2,v+4,(l[7]-4)*(T[5]/w),h-8,3),T&&M===4){const k=R[0].toUpperCase()+R.slice(1);e.font=A(500,11);const E=e.measureText(k).width+22;c(e,p[R]+"33",P+6,v+4,E,14,7),c(e,p[R],P+11,v+8,6,6,3),m(e,k,P+20,v+11.5,A(500,11),t.ink)}else if(y){const k=M===0?"Total":M===5?String(Y.reduce((E,C)=>E+C[4],0)):M===6?Y.reduce((E,C)=>E+C[5],0).toFixed(2):"";k&&m(e,k,D?P+l[M+1]-8:P+8,v+11,A(700,12.5),t.ink,D?"right":"left")}else R&&u<=12&&m(e,q(e,R,l[M+1]-12,A(d,12.5)),D?P+l[M+1]-8:P+8,v+11,u===0?A(500,12):A(d,12.5),u===0?t["ink-2"]:t.ink,D?"right":"left");i.hit("cell"+u+","+M,P,v,l[M+1],h,()=>a.cell=[u,M])}for(let M=1;M<o.length;M++)c(e,t.grid,o[M],v,1,h);c(e,t.grid,0,v+h-1,s,1)}const[S,g]=a.cell;S<b&&(e.strokeStyle=t.sheet,e.lineWidth=2,e.strokeRect(o[g+1]+1,f+h*(S+1)+1,l[g+1]-2,h-2)),c(e,t.chrome,0,n-30,s,30),c(e,t.line,0,n-30,s,1),B(e,"plus",10,n-22,14,t.muted),Vt.forEach((u,v)=>{const y=34+v*82,T=v===a.sheetTab;T&&(c(e,t.win,y,n-29,82,29),c(e,t.sheet,y,n-2,82,2)),m(e,u,y+41,n-15,A(T?500:400,12),T?t.sheet:t["ink-2"],"center"),i.hit("sheet"+v,y,n-30,82,30,()=>a.sheetTab=v)}),s>600&&m(e,"Sum 457.55 - Average 38.13 - Count 12",s-14,n-15,A(400,12),t.muted,"right")}x(qt,"paintSheet");const wt=[["data",0,"dir"],["ferries.csv",1,"dat"],["stays.json",1,"dat"],["src",0,"dir"],["budget.ts",1,"ts"],["route.ts",1,"ts"],["tides.ts",1,"ts"],["package.json",0,"js"],["README.md",0,"md"]],vt=[[],[["k","export interface"],[""," "],["t","Leg"],[""," {"]],[[""," "],["p","from"],["",": "],["t","string"],["",";"]],[[""," "],["p","to"],["",": "],["t","string"],["",";"]],[[""," "],["p","by"],["",": "],["s",'"ferry"'],[""," | "],["s",'"train"'],[""," | "],["s",'"bus"'],[""," | "],["s",'"foot"'],["",";"]],[[""," "],["p","departs"],["",": "],["t","Date"],["",";"]],[["","}"]],[],[["cm","/** The first sailing after high water, or null if none is left today. */"]],[["k","export function"],[""," "],["f","nextSailing"],["","("],["p","leg"],["",": "],["t","Leg"],["",", "],["p","day"],["",": "],["t","Tide"],["","[]): "],["t","Date"],[""," | "],["k","null"],[""," {"]],[[""," "],["k","const"],[""," "],["p","high"],[""," = day."],["f","find"],["","(("],["p","t"],["",") => t.kind === "],["s",'"high"'],[""," && t.at > leg.departs);"]],[[""," "],["k","if"],[""," (!high) "],["k","return"],[""," "],["k","null"],["",";"]],[[""," "],["k","const"],[""," "],["p","wait"],[""," = budget."],["warn","minutesAfterHigh"],[""," ?? "],["n","40"],["",";"]],[[""," "],["k","return new"],[""," "],["t","Date"],["","(high.at."],["f","getTime"],["","() + wait * "],["n","60_000"],["",");"]]];function Ct(e,t,s,n,i){const a=i.state,r=wt[a.file][0];it(e,t,s,"editor",r,"northbound",i.active);const l=230;c(e,t.chrome,0,40,l,n-66),c(e,t.line,l,40,1,n-66),m(e,"NORTHBOUND",16,60,A(700,11),t.muted);const o={dir:t.muted,dat:t.sheet,ts:t.ferry,js:t.files,md:t.muted};wt.forEach(([d,b,S],g)=>{const u=76+g*24;u+24>n-26||(g===a.file&&c(e,t.sel,6,u,l-12,24,6),B(e,S==="dir"?"down":"file",14+b*16,u+4,16,o[S]),m(e,d,36+b*16,u+12,A(400,13),t.ink),i.hit("file"+g,6,u,l-12,24,S==="dir"?null:()=>a.file=g))});const h=l+1;c(e,t.chrome,h,40,s-h,34),e.font=A(500,12.5);const f=Math.max(120,e.measureText(r).width+64);c(e,t.win,h,40,f,34),c(e,t.editor,h,72,f,2),B(e,"file",h+12,49,16,t.ferry),m(e,r,h+34,57,A(500,12.5),t.ink),c(e,t.ink,h+f-20,54,6,6,3),m(e,"src > "+r+(r==="route.ts"?" > nextSailing":""),h+16,88,A(400,12),t.muted);const w={k:t.kw,t:t.ty,s:t.st,p:t.pr,f:t.fn,n:t.nu,cm:t.cm,warn:t.warn,"":t.pu};(r==="route.ts"?vt:vt.slice(0,7)).forEach((d,b)=>{const S=106+b*21;if(S>n-36)return;const g=b===11;g&&c(e,t.curline,h,S-10,s-h,21),m(e,String(b+3),h+40,S+1,O(400,13),g?t["ink-2"]:t.faint,"right");let u=h+60;for(const[v,y]of d){const T=m(e,y,u,S+1,v==="cm"?"italic "+O(400,13):O(400,13),w[v]);if(v==="warn"){e.strokeStyle=t.warn,e.lineWidth=1,e.beginPath();for(let M=0;M<=T;M+=4)e.lineTo(u+M,S+9+(M/4%2?1.5:0));e.stroke()}u+=T}g&&c(e,t.editor,u+2,S-8,2,18)}),c(e,t.chrome,0,n-26,s,26),c(e,t.line,0,n-26,s,1),B(e,"branch",12,n-20,14,t["ink-2"]),m(e,"main",32,n-13,A(400,12),t["ink-2"]),m(e,"! 1",82,n-13,A(500,12),t.warn),s>640&&m(e,"Ln 14, Col 29 Spaces: 2 UTF-8 TypeScript",s-40,n-13,A(400,12),t["ink-2"],"right")}x(Ct,"paintEditor");const ot=[["st","ana"],["pu","@"],["fn","lumen"],[""," "],["kw","~/dots"],["pu"," $ "]],lt=[["st","ana"],["pu","@"],["fn","lumen"],[""," "],["kw","~/src/tide"],["pu"," $ "]],mt=[["zsh","~/dots",[[...ot,["","sysinfo"]],"summary",[...ot,["","git log --oneline -5"]],[["nu","3f9c2e1"],[""," bar: mark the workspaces that hold windows"]],[["nu","a41d7b0"],[""," term: a softer cursor, two pixels of padding"]],[["nu","9be0c55"],[""," theme: night palette, warmer reds"]],[["nu","71c2a9e"],[""," tiler: gaps follow the screen's scale"]],[["nu","0d5e3f8"],[""," first light"]],[],[...ot,"cursor"]]],["build","~/src/tide",[[...lt,["","make -j16"]],[["ty"," CC "],["","src/tide.c"]],[["ty"," CC "],["","src/table.c"]],[["ty"," CC "],["","src/harbour.c"]],[["ty"," CC "],["","src/print.c"]],[["warn","src/table.c:212:9: warning: "],["","unused variable 'slack'"]],[["ty"," LD "],["","tide"]],[["st","built tide in 2.41 s"]],[...lt,["","./tide --next ostmere"]],[["","high water 06:42 ferry 07:20 "],["cm","(in 38 min)"]],[],[...lt,"cursor"]]]],Jt=[["os","Lumen 3.2 (rolling)"],["host","lumen"],["kernel","6.18.4"],["wm","tiler 0.9"],["shell","zsh 5.9"],["term","glass 1.4"],["cpu","16 cores, 4.8 GHz"],["memory","5.1 / 31.2 GiB"],["uptime","3 days, 4 hours"]];function Kt(e,t,s,n,i){const a=i>520?s+136:s;if(i>520){const l=s+58,o=n+96;e.save(),e.lineWidth=3.5,e.lineCap="round",[[46,t.nu],[33,t.warn],[20,t.pr]].forEach(([h,f])=>{e.strokeStyle=f,e.beginPath(),e.arc(l,o,h,Math.PI,2*Math.PI),e.stroke()}),[0,12,24].forEach((h,f)=>{e.strokeStyle=t.fn,e.globalAlpha=1-f*.3,e.beginPath(),e.moveTo(l-52+f*10,o+12+h),e.lineTo(l+52-f*10,o+12+h),e.stroke()}),e.restore()}const r=m(e,"ana@lumen",a,n,O(500,13),t.term);c(e,t.faint,a,n+11,r,1),n+=26;for(const[l,o]of Jt)m(e,l,a,n,O(500,13),t.fn),m(e,o,a+72,n,O(400,13),t.ink),n+=20;return n+=6,["pr","nu","warn","st","ty","fn","kw","ink"].forEach((l,o)=>c(e,t[l],a+o*26,n-8,22,16,3)),n+30}x(Kt,"summary");function Yt(e,t,s,n,i){const a=i.state,[,r,l]=mt[a.tab];it(e,t,s,"term","terminal","ana@lumen: "+r,i.active),c(e,t.chrome,0,40,s,30),c(e,t.line,0,69,s,1);let o=10;mt.forEach(([w],p)=>{const d=p===a.tab,b=p+1+" "+w;e.font=O(500,12);const S=e.measureText(b).width+28;d&&(c(e,t.win,o,44,S,26,6),c(e,t.term,o+10,67,S-20,2)),m(e,b,o+14,57,O(d?500:400,12),d?t.ink:t.muted),i.hit("tab"+p,o,42,S,28,()=>a.tab=p),o+=S+4});const h={st:t.st,pu:t.pu,fn:t.fn,kw:t.kw,nu:t.nu,ty:t.ty,warn:t.warn,cm:t.cm,"":t.ink};let f=94;for(const w of l){if(f>n-12)break;if(w==="summary"){f=Kt(e,t,16,f,s);continue}let p=16;for(const d of w)d==="cursor"?c(e,t.term,p+1,f-9,8,18):p+=m(e,d[1],p,f,O(400,13),h[d[0]]);f+=20}}x(Yt,"paintTerminal");const St=[34,12,58,7,22,81,15,9,44,3,27,66,11,5,39,18],Xt=[[1823,"ana",24.6,3.1,"2:14.07","tide --watch"],[944,"ana",8.9,2.2,"12:40.18","compositor"],[1102,"ana",7.3,6.4,"41:02.55","editor"],[2210,"ana",6.1,1.4,"0:51.33","glass"],[1530,"ana",4.4,9.8,"82:09.40","browser"],[611,"root",2,.6,"8:11.92","audio-server"],[2207,"ana",1.6,.3,"0:04.10","zsh"],[812,"ana",1.1,.5,"3:33.71","bar"],[402,"root",.7,.2,"1:02.48","netd"],[733,"ana",.4,1,"0:40.09","notes"],[2301,"ana",.3,.1,"0:00.62","monitor"],[518,"root",.2,.3,"0:12.77","logd"],[1,"root",.1,.1,"0:03.21","init"],[1999,"ana",0,.8,"0:09.15","music"]],ht=[["PID",0,44,"up"],["USER",1,58,null],["CPU%",2,160,"down"],["MEM%",3,214,"down"],["TIME",4,300,null],["COMMAND",5,316,null]];function $t(e,t,s,n,i){const a=i.state;it(e,t,s,"mon","monitor","16 cores, up 3 days",i.active);const r=16,l=s-32;let o=62;const h=Math.max(1,Math.min(4,Math.floor((l+28)/180))),f=(l-(h-1)*28)/h,w=Math.ceil(St.length/h);St.forEach((y,T)=>{const M=r+Math.floor(T/w)*(f+28),P=o+T%w*18;m(e,String(T+1),M+16,P,O(400,11.5),t.muted,"right");const R=f-26-44;c(e,t.field,M+26,P-5,R,10,3),c(e,y>=75?t.pr:y>=45?t.warn:t.st,M+26,P-5,Math.max(4,R*y/100),10,3),m(e,y+"%",M+f,P,O(400,11.5),t["ink-2"],"right")}),o+=w*18+10;for(const[y,T,M,P]of[["mem",5.1,31.2,t.fn],["swp",.2,8,t.kw]]){m(e,y,r,o,O(500,11.5),t.muted);const R=l-42-128;c(e,t.field,r+42,o-5,R,10,3),c(e,P,r+42,o-5,Math.max(4,R*T/M),10,3),m(e,T.toFixed(1)+" / "+M.toFixed(1)+" GiB",r+l,o,O(400,11.5),t["ink-2"],"right"),o+=20}o+=4;const p=70;c(e,t.field,r,o,l,p,6);const d=x((y,T)=>{e.beginPath();for(let M=0;M<=60;M++){const P=r+l*M/60,R=o+p-6-Math.min(.95,Math.max(.03,y(M)))*(p-14);M?e.lineTo(P,R):e.moveTo(P,R)}e.strokeStyle=T,e.lineWidth=1.6,e.stroke()},"graph");d(y=>.42+.26*Math.sin(y*.37)+.14*Math.sin(y*1.3+1),t.ty),d(y=>.14+.07*Math.sin(y*.5+2)+.05*Math.sin(y*1.7),t.kw),m(e,"down 4.2 MiB/s",r+10,o+13,O(400,11),t.ty),m(e,"up 310 KiB/s",r+l-10,o+13,O(400,11),t.kw,"right"),o+=p+12;const b=ht.filter((y,T)=>T!==4||l>440),S=x(y=>r+ht[y][2]-(y===5&&l<=440?86:0),"at"),g=x(y=>y!==1&&y!==5,"right");c(e,t.chrome,0,o,s,24);for(const[y,T,,M]of b){const P=a.sort===T,R=m(e,y+(P?M==="up"?" ^":" v":""),S(T),o+12,O(500,11.5),P?t.mon:t.muted,g(T)?"right":"left");M&&i.hit("sort"+T,g(T)?S(T)-R-6:S(T)-6,o,R+12,24,()=>a.sort=T)}o+=24;const u=ht[a.sort][3]==="up"?1:-1,v=[...Xt].sort((y,T)=>u*(y[a.sort]-T[a.sort])||y[0]-T[0]);for(const y of v){if(o+20>n-26)break;y[0]===a.pid&&c(e,t.sel,0,o,s,20);for(const[,T]of b){const M=T===2||T===3?y[T].toFixed(1):String(y[T]),P=T===2&&y[2]>=20;m(e,q(e,M,T===5?s-S(5)-12:200,O(400,12)),S(T),o+10,O(400,12),P?t.warn:T===5?t.ink:t["ink-2"],g(T)?"right":"left")}i.hit("proc"+y[0],0,o,s,20,()=>a.pid=y[0]),o+=20}c(e,t.chrome,0,n-26,s,26),c(e,t.line,0,n-26,s,1),m(e,"214 tasks, 3 running",14,n-13,O(400,11.5),t["ink-2"]),s>480&&m(e,"load 1.84 1.62 1.40",s-14,n-13,O(400,11.5),t["ink-2"],"right")}x($t,"paintMonitor");const Tt=[{id:"browser",app:0,at:{left:56,top:44},w:1100,h:840,title:42,ctl:24,paint:gt,ui:{tab:0,nav:0}},{id:"sheet",app:1,at:{right:44,top:56,tall:.42},w:836,h:520,title:40,ctl:20,paint:qt,ui:{cell:[13,6],sheetTab:0,format:""}},{id:"editor",app:2,at:{right:80,bottom:12},w:980,h:420,title:40,ctl:20,paint:Ct,ui:{file:5}}];function Zt({at:e,w:t,h:s},[n,i],a){const r=a.h,l=Math.min(n,Math.max(Math.min(ct,n),Math.min(t,n-2*nt))),o=Math.min(r,Math.max(Math.min(ut,r),Math.min(s,r-2*nt))),h=e.left!==void 0?e.left:n-e.right-l,f=i>n&&e.tall?i*e.tall:e.top!==void 0?e.top:r-e.bottom-o,w=x((p,d,b,S)=>{const g=S?Math.min(nt,(b-d)/2):0;return Math.round(Math.max(g,Math.min(p,b-g-d)))},"keep");return{x:w(h,l,n,l<t),y:a.y+w(f,o,r,o<s),w:l,h:o}}x(Zt,"placement");const Qt=[["browser","compass"],["sheet","table"],["editor","braces"],["files","folder"],["music","note"],["#6b7686","sliders"]],te=328,ee=50,Et=["min","max","close"];function se(e,t,s,n){c(e,t.bar,0,0,s,dt),c(e,t["bar-line"],0,0,s,1),B(e,"launch",20,14,20,t.ink,2.4),c(e,t["bar-field"],56,7,250,34,17),B(e,"search",70,16,16,t.muted),m(e,"Search apps and files",95,24,A(400,13),t.muted),Qt.forEach(([i,a],r)=>{const l=te+r*ee,o=n.windows.find(d=>d.app===r),h=o&&!o.closed,f=o&&n.active===o.id&&!o.min,w=n.pressed("app"+r),p=n.hovered("app"+r);(f||w||p)&&c(e,t["bar-hi"],l,4,46,40,9),w&&c(e,t["bar-hi"],l,4,46,40,9),c(e,i[0]==="#"?i:t[i],l+9,w?11:10,28,28,8),B(e,a,l+15,w?17:16,16,"#fff",2),h&&c(e,f?t.editor:t.muted,l+23-(f?8:3),42,f?16:6,3,2),n.hit("app"+r,l,0,46,dt,()=>n.app(r))}),m(e,"76%",s-130,24,A(400,12.5),t["ink-2"],"right"),m(e,"14:32",s-16,17,A(400,12.5),t.ink,"right"),m(e,"Thu 29 Oct",s-16,33,A(400,11.5),t["ink-2"],"right")}x(se,"paintTaskbar");function ie(e,t,s,n){c(e,t.bar,0,0,s,st),c(e,t["bar-line"],0,st-1,s,1);for(let a=1;a<=zt;a++){const r=8+(a-1)*30,l="ws"+a,o=a===n.ws,h=n.windows.some(f=>f.ws===a);o?c(e,t.focus,r,5,26,20,6):(n.pressed(l)||n.hovered(l))&&c(e,t["bar-hi"],r,5,26,20,6),m(e,String(a),r+13,15.5,O(500,12.5),o?t.win:h?t.ink:t.faint,"center"),h&&!o&&c(e,t.focus,r+10,23,6,2,1),n.hit(l,r,0,26,st,()=>n.workspace(a))}let i=s-14;i-=m(e,"Thu 29 Oct 14:32",i,15.5,O(500,12.5),t.ink,"right")+24;for(const[a,r]of[["vol","60%"],["net","4.2M"],["mem","5.1G"],["cpu","18%"]]){e.font=O(400,12.5);const l=e.measureText(a+" "+r).width;if(i-l<420)break;const o=m(e,r,i,15.5,O(400,12.5),t.ink,"right");m(e,a+" ",i-o,15.5,O(400,12.5),t.muted,"right"),i-=l+20}n.title&&m(e,q(e,n.title,i-154,O(400,12.5)),140,15.5,O(400,12.5),t["ink-2"])}x(ie,"paintTopBar");const ne=[{id:"editor",ws:1,title:40,paint:Ct,ui:{file:5},label:x(e=>"editor - "+wt[e.file][0],"label")},{id:"term",ws:1,title:40,paint:Yt,ui:{tab:0},label:x(e=>"terminal - "+mt[e.tab][0],"label")},{id:"mon",ws:1,title:40,paint:$t,ui:{pid:1823,sort:2},label:x(()=>"monitor","label")},{id:"browser",ws:2,title:42,paint:gt,ui:{tab:0,nav:0},label:x(e=>"browser - "+pt[e.tab][0],"label")}];function ae([e,t],s,n){const i={x:s.x+N,y:s.y+N,w:s.w-2*N,h:s.h-2*N},a=new Map([["browser",i]]),r=t>e,l=r?i.h:i.w,o=Math.round((l-N)*n.main);if(!r){const p=i.x+o+N,d=i.w-o-N,b=Math.round((i.h-N)*n.side);return a.set("editor",{x:i.x,y:i.y,w:o,h:i.h}),a.set("term",{x:p,y:i.y,w:d,h:b}),a.set("mon",{x:p,y:i.y+b+N,w:d,h:i.h-b-N}),{rects:a,splits:[{key:"main",axis:"x",ws:1,x:i.x+o,y:i.y,w:N,h:i.h,from:i.x,span:i.w},{key:"side",axis:"y",ws:1,x:p,y:i.y+b,w:d,h:N,from:i.y,span:i.h}]}}const h=i.y+o+N,f=i.h-o-N,w=Math.round((i.w-N)*n.side);return a.set("editor",{x:i.x,y:i.y,w:i.w,h:o}),a.set("term",{x:i.x,y:h,w,h:f}),a.set("mon",{x:i.x+w+N,y:h,w:i.w-w-N,h:f}),{rects:a,splits:[{key:"main",axis:"y",ws:1,x:i.x,y:i.y+o,w:i.w,h:N,from:i.y,span:i.h},{key:"side",axis:"x",ws:1,x:i.x+w,y:h,w:N,h:f,from:i.x,span:i.w}]}}x(ae,"tiling");const re={light:{win:"#fbf8f1",chrome:"#f1ece1",toolbar:"#f6f2e9",field:"#e9e3d6",line:"#ddd5c5",grid:"#e6dfd1",edge:"rgba(60, 48, 30, 0.16)",ink:"#2b2620","ink-2":"#5a5247",muted:"#8a8173",faint:"#b4ab9b",sel:"#efe1bf",curline:"#f4efe4",guide:"#e8e1d3",shadow:"0 4px 12px rgba(60, 48, 30, 0.16)","shadow-active":"0 6px 16px rgba(60, 48, 30, 0.24)",editor:"#7a5cd6",term:"#2f8f6a",mon:"#c4622d",focus:"#d07a2e",kw:"#9c3fb0",ty:"#1f7c80",st:"#4c7d23",nu:"#b25a12",fn:"#2f5fb8",pr:"#b03a2e",cm:"#9a9080",pu:"#5a5247",warn:"#b5800f",bar:"rgba(250, 246, 238, 0.88)","bar-line":"rgba(60, 48, 30, 0.1)","bar-field":"rgba(60, 48, 30, 0.07)","bar-hi":"rgba(60, 48, 30, 0.1)"},dark:{win:"#17181f",chrome:"#1d1f28",toolbar:"#20222c",field:"#262935",line:"#2b2e3a",grid:"#262935",edge:"rgba(255, 255, 255, 0.07)",ink:"#d8dcef","ink-2":"#a9aec8",muted:"#7c819c",faint:"#4e5370",sel:"#2b3352",curline:"#1f2130",guide:"#262838",shadow:"0 4px 12px rgba(0, 0, 0, 0.4)","shadow-active":"0 6px 16px rgba(0, 0, 0, 0.5)",editor:"#a48bff",term:"#5fd3a5",mon:"#ff9f6e",focus:"#8fa8ff",kw:"#c39bff",ty:"#79d6e6",st:"#9ed98a",nu:"#ffb072",fn:"#86a8ff",pr:"#ff8a7a",cm:"#5f6585",pu:"#a9aec8",warn:"#f0c060",bar:"rgba(14, 15, 21, 0.84)","bar-line":"rgba(255, 255, 255, 0.06)","bar-field":"rgba(255, 255, 255, 0.06)","bar-hi":"rgba(255, 255, 255, 0.1)"}},U=[{id:"everyday",name:"Everyday",wallpaper:"flow",bar:{edge:"bottom",height:dt,paint:se},tiled:!1,inset:0,radius:10,palettes:{light:{},dark:{}},windows:Tt,active:"editor",split:{},layout:x((e,t)=>({rects:new Map(Tt.map(s=>[s.id,Zt(s,e,t)])),splits:[]}),"layout")},{id:"tiling",name:"Tiling",wallpaper:"city",bar:{edge:"top",height:st,paint:ie},tiled:!0,inset:N,radius:8,palettes:re,windows:ne,active:"editor",split:{main:.58,side:.5},layout:ae}],me=U.map(({id:e,name:t,wallpaper:s})=>({id:e,name:t,wallpaper:s})),oe={x:"col-resize",y:"row-resize"};function le(e){return e.split(/,(?![^(]*\))/).map(t=>{const s=/(-?[\d.]+)(?:px)?\s+(-?[\d.]+)(?:px)?\s+([\d.]+)(?:px)?\s+(rgba?\([^)]*\))/.exec(t);return{x:+s[1],y:+s[2],blur:+s[3],color:s[4]}})}x(le,"shadows");const he={n:"ns-resize",s:"ns-resize",e:"ew-resize",w:"ew-resize",ne:"nesw-resize",sw:"nesw-resize",nw:"nwse-resize",se:"nwse-resize"},Ot=x(e=>e==="dark"?{...at.light,...at.dark}:at.light,"palette"),tt=[{id:"flow",name:"Flow"},...At.map(({id:e,name:t})=>({id:e,name:t}))],ft=new Map;function fe(e,t){const s=At.find(a=>a.id===e);if(!s)return{svg:Ft,colours:Ot(t)};ft.has(e)||ft.set(e,s.draw());const{svg:n,palettes:i}=ft.get(e);return{svg:n,colours:i[t]}}x(fe,"wallpaper");function de(e,t,s,n){e=e.replace(/var\(--([a-z0-9-]+)\)/g,(k,E)=>{if(!(E in t))throw new Error("the wallpaper names --"+E+", which its palette lacks");return t[E]});const a=new DOMParser().parseFromString(e.replace("<svg ",'<svg xmlns="http://www.w3.org/2000/svg" '),"image/svg+xml").documentElement,[,,r,l]=a.getAttribute("viewBox").trim().split(/\s+/).map(Number),o=/\bslice\b/.test(a.getAttribute("preserveAspectRatio")||""),h=Math.max(s/r,n/l),f=o?[h,h]:[s/r,n/l],[w,p]=(a.getAttribute("data-focus")||"0.5 0.5").trim().split(/\s+/).map(Number),d=x((k,E,C)=>Math.min(0,Math.max(k-E,k/2-C*E)),"crop"),b=o?[d(s,r*h,w),d(n,l*h,p)]:[0,0],S=x((k,E)=>{const C=new RegExp("(?:^|;)\\s*"+E+":\\s*([^;]+)").exec(k.getAttribute("style")||"");return C?C[1].trim():k.getAttribute(E)},"prop"),g=x(k=>(/url\(#([^)]+)\)/.exec(k||"")||[])[1],"ref"),u=new Map;for(const k of a.querySelectorAll("linearGradient")){const E=x((C,z)=>Number(k.getAttribute(C)??z),"at");u.set(k.id,{line:[E("x1",0),E("y1",0),E("x2",1),E("y2",0)],stops:[...k.querySelectorAll("stop")].map(C=>[Number(C.getAttribute("offset")),S(C,"stop-color")])})}const v=new Map;for(const k of a.querySelectorAll("filter"))v.set(k.id,Number(k.querySelector("feGaussianBlur").getAttribute("stdDeviation")));const y=x((k,E)=>Number(k.getAttribute(E)||0),"num"),T=x(k=>{const E=new Path2D;if(k.tagName==="rect"){const[F,I,W,H]=[y(k,"x"),y(k,"y"),y(k,"width"),y(k,"height")];return E.rect(F,I,W,H),{path:E,box:[F,I,W,H]}}if(k.tagName==="ellipse"){const[F,I,W,H]=[y(k,"cx"),y(k,"cy"),y(k,"rx"),y(k,"ry")];return E.ellipse(F,I,W,H,0,0,2*Math.PI),{path:E,box:[F-W,I-H,2*W,2*H]}}const C=k.getAttribute("d"),z=(C.match(/-?[\d.]+/g)||[]).map(Number),L=z.filter((F,I)=>I%2===0),G=z.filter((F,I)=>I%2===1),_=Math.min(...L),$=Math.min(...G);return{path:new Path2D(C),box:[_,$,Math.max(...L)-_,Math.max(...G)-$]}},"shape"),M=x((k,E,[C,z,L,G])=>{const _=u.get(g(E));if(!_)return E;const[$,F,I,W]=_.line,H=k.createLinearGradient(C+$*L,z+F*G,C+I*L,z+W*G);for(const[Pt,Nt]of _.stops)H.addColorStop(Pt,Nt);return H},"paint"),P=x((k,E)=>{const{path:C,box:z}=T(E);k.globalAlpha=E.hasAttribute("opacity")?Number(E.getAttribute("opacity")):1;const L=S(E,"fill")??"#000";L!=="none"&&(k.fillStyle=M(k,L,z),k.fill(C));const G=S(E,"stroke");G&&G!=="none"&&(k.lineWidth=Number(E.getAttribute("stroke-width")||1),k.strokeStyle=M(k,G,z),k.stroke(C)),k.globalAlpha=1},"draw"),R=new OffscreenCanvas(s,n),D=R.getContext("2d");for(const k of a.children){if(k.tagName==="defs")continue;if(k.tagName!=="g"){D.setTransform(f[0],0,0,f[1],b[0],b[1]),P(D,k);continue}const E=(v.get(g(k.getAttribute("filter")))||0)*(f[0]+f[1])/2,C=Math.ceil(3*E),z=new OffscreenCanvas(s+2*C,n+2*C),L=z.getContext("2d");L.setTransform(f[0],0,0,f[1],C+b[0],C+b[1]);for(const G of k.children)P(L,G);D.setTransform(1,0,0,1,0,0),D.globalAlpha=k.hasAttribute("opacity")?Number(k.getAttribute("opacity")):1,D.filter=E?"blur("+E+"px)":"none",D.drawImage(z,-C,-C),D.filter="none",D.globalAlpha=1}return R}x(de,"paintSvg");async function ce(e,t,s,n,i){const[a,r]=e,{svg:l,colours:o}=fe(s,n),h=de(l,o,a,r),f=new OffscreenCanvas(a,Math.round(i.height*t)),w=f.getContext("2d"),p=60*t,d=i.edge==="top"?0:r-f.height;return w.filter="blur("+26*t+"px) saturate(1.5)",w.drawImage(h,0,d-p,a,f.height+2*p,0,-p,a,f.height+2*p),{wall:h,back:f}}x(ce,"paintWall");const et=x((e,t,s)=>e>=s.x&&e<s.x+s.w&&t>=s.y&&t<s.y+s.h,"inside"),ue=x((e,t)=>[Math.max(1,Math.round(e[0]/t)),Math.max(1,Math.round(e[1]/t))],"layout");class be{static{x(this,"Desktop")}constructor({theme:t="light",scene:s=Bt,wallpaper:n,preset:i="everyday",fonts:a,scale:r=bt}={}){const l=U.find(o=>o.id===i)||U[0];this.theme=t==="dark"?"dark":"light",this.wallpaper=tt.some(o=>o.id===n)?n:l.wallpaper,this.fonts=a,this.scale=r>0?r:bt,this.want={theme:this.theme,scene:[Math.max(1,Math.round(s[0])),Math.max(1,Math.round(s[1]))],wallpaper:this.wallpaper,preset:l.id},this.queue=Promise.resolve(),this.#c(l),this.cursor="",this.scene=[0,0],this.size=[0,0]}async ready(){await Ht(this.fonts),await this.#s({})}get palette(){return{...Ot(this.theme),...this.spec.palettes[this.theme]}}async setTheme(t){await this.#s({theme:t==="dark"?"dark":"light"})}async setScene(t){await this.#s({scene:[Math.max(1,Math.round(t[0])),Math.max(1,Math.round(t[1]))]})}async setWallpaper(t){if(!tt.some(s=>s.id===t))throw new Error("no wallpaper "+JSON.stringify(t));await this.#s({wallpaper:t})}async setPreset(t,s){const n=U.find(a=>a.id===t);if(!n)throw new Error("no preset "+JSON.stringify(t));const i=s===void 0?n.wallpaper:s;if(!tt.some(a=>a.id===i))throw new Error("no wallpaper "+JSON.stringify(i));await this.#s({preset:t,wallpaper:i})}async open({preset:t=U[0].id,wallpaper:s,scene:n=this.want.scene}={}){const i=U.find(l=>l.id===t);if(!i)throw new Error("no preset "+JSON.stringify(t));const a=s===void 0?i.wallpaper:s;if(!tt.some(l=>l.id===a))throw new Error("no wallpaper "+JSON.stringify(a));const r=[Math.max(1,Math.round(n[0])),Math.max(1,Math.round(n[1]))];await this.#s({preset:t,wallpaper:a,scene:r,fresh:!0})}render(){const t=this.canvas.getContext("2d");t.drawImage(this.wall,0,0);for(const s of this.windows)this.#e(s)&&t.drawImage(this.layers.get(s.id),Math.round((s.x-V)*this.sx),Math.round((s.y-V)*this.sy));return t.drawImage(this.barLayer,0,Math.round(this.#f().y*this.sy)),this.canvas}pointer(t,s,n){let i;t==="down"?i=this.#u(s,n):t==="move"?i=this.drag?this.#p(s,n):this.#r(s,n):t==="up"?i=this.#m(s,n):i=this.#r(-1,-1);const a=this.drag,r=a?null:this.hitTest(s,n),l=a?a.mode==="resize"?a.edge:"":r.kind==="edge"?r.edge:"",o=a?a.mode==="split"?a.split.axis:"":r.kind==="split"?r.split.axis:"";return this.cursor=l?he[l]:o?oe[o]:"",i}hitTest(t,s){const n=this.#f();if(n.y===0?s<n.h:s>=n.y){for(const a of this.barHits)if(et(t,s-n.y,a))return{kind:"bar-ui",hit:a};return{kind:"bar"}}if(!this.windows.some(a=>a.max&&this.#e(a))){for(const a of this.splits)if(a.ws===this.ws&&et(t,s,{x:a.x-Z,y:a.y-Z,w:a.w+2*Z,h:a.h+2*Z}))return{kind:"split",split:a}}const i=this.spec.tiled?0:J;for(let a=this.windows.length-1;a>=0;a--){const r=this.windows[a];if(!this.#e(r))continue;const l={x:r.x-i,y:r.y-i,w:r.w+2*i,h:r.h+2*i};if(!et(t,s,l))continue;const o=t-r.x,h=s-r.y;if(!r.max&&!this.spec.tiled){const f=Lt,w=h<J,p=h>=r.h-J,d=o<J,b=o>=r.w-J,S=h<f,g=h>=r.h-f,u=o<f,v=o>=r.w-f,y=(w||(d||b)&&S?"n":p||(d||b)&&g?"s":"")+(d||(w||p)&&u?"w":b||(w||p)&&v?"e":"");if(y)return{kind:"edge",win:r,edge:y}}if(r.ctl&&h>=r.ctl-14&&h<r.ctl+14&&o>=r.w-122&&o<r.w-8){const f=Math.min(2,Math.floor((o-(r.w-122))/38));return{kind:"ctl",win:r,which:f}}for(const f of r.hits)if(et(o,h,f))return{kind:"ui",win:r,hit:f};return h<r.title?{kind:"title",win:r}:{kind:"body",win:r}}return{kind:"desk"}}#u(t,s){const n=this.hitTest(t,s);let i=!1;if(n.kind==="bar-ui")return this.press={kind:"bar-ui",id:n.hit.id},this.#i(),!0;if(n.kind==="split")return this.drag={mode:"split",split:n.split},!1;if(!n.win)return!1;i=this.#a(n.win);const a=n.win;if(n.kind==="ctl")return this.press={kind:"ctl",win:a,which:n.which},this.#t(a),!0;if(n.kind==="ui")return this.press={kind:"ui",win:a,id:n.hit.id},this.#t(a),!0;if(n.kind==="edge")return this.drag={mode:"resize",win:a,edge:n.edge,x:t,y:s,rect:{x:a.x,y:a.y,w:a.w,h:a.h}},i;if(n.kind==="title"){const r=performance.now(),l=this.lastDown;if(this.lastDown={win:a,t:r,x:t,y:s},l&&l.win===a&&r-l.t<Gt&&Math.abs(l.x-t)<6&&Math.abs(l.y-s)<6)return this.lastDown=null,this.#l(a),!0;this.spec.tiled||(this.drag={mode:"move",win:a,dx:t-a.x,dy:s-a.y,x:t,y:s,moved:!1})}return i}#p(t,s){const n=this.drag;if(n.mode==="split")return this.#w(n,t,s);const i=n.win,a=this.#n();if(n.mode==="move"){if(!n.moved&&Math.abs(t-n.x)<3&&Math.abs(s-n.y)<3)return!1;if(n.moved=!0,i.max){const b=n.dx/i.w;Object.assign(i,{w:i.max.w,h:i.max.h,max:null}),n.dx=Math.round(b*i.w),this.#t(i)}return i.x=Math.round(Math.min(this.size[0]-80,Math.max(80-i.w,t-n.dx))),i.y=Math.round(Math.min(a.y+a.h-40,Math.max(a.y,s-n.dy))),!0}const r=n.rect,l=t-n.x,o=s-n.y;let h=r.x,f=r.y,w=r.w,p=r.h;if(n.edge.includes("e")&&(w=Math.max(ct,r.w+l)),n.edge.includes("s")&&(p=Math.max(ut,Math.min(a.y+a.h-r.y,r.h+o))),n.edge.includes("w")&&(w=Math.max(ct,r.w-l),h=r.x+r.w-w),n.edge.includes("n")&&(p=Math.max(ut,r.h-o),f=Math.max(a.y,r.y+r.h-p),p=r.y+r.h-f),h=Math.round(h),f=Math.round(f),w=Math.round(w),p=Math.round(p),h===i.x&&f===i.y&&w===i.w&&p===i.h)return!1;const d=w!==i.w||p!==i.h;return Object.assign(i,{x:h,y:f,w,h:p}),d&&this.#t(i),!0}#w(t,s,n){const i=t.split,a=i.span-N,r=Math.min(.5,Dt/a),l=Math.min(1-r,Math.max(r,((i.axis==="x"?s:n)-i.from-N/2)/a));if(l===this.split[i.key])return!1;this.split={...this.split,[i.key]:l};const o=this.#M();return t.split=this.splits.find(h=>h.key===i.key),o}#m(t,s){const n=this.press;if(this.press=null,this.drag=null,!n)return!1;const i=this.hitTest(t,s);if(n.kind==="bar-ui")return i.kind==="bar-ui"&&i.hit.id===n.id&&i.hit.act(),this.#i(),!0;const a=n.win;if(n.kind==="ctl"&&i.win===a&&i.kind==="ctl"&&i.which===n.which){const r=Et[n.which];r==="max"?this.#l(a):this.#h(a,r==="min"?"min":"closed")}else n.kind==="ui"&&i.win===a&&i.kind==="ui"&&i.hit.id===n.id&&i.hit.act&&i.hit.act();return this.#e(a)&&this.#t(a),this.#i(),!0}#r(t,s){const n=this.hitTest(t,s),i=n.kind==="ctl"?{win:n.win,which:n.which}:n.kind==="bar-ui"?{bar:n.hit.id}:null,a=this.hover;if(x((l,o)=>!l&&!o||l&&o&&l.win===o.win&&l.which===o.which&&l.bar===o.bar,"same")(a,i))return!1;this.hover=i;for(const l of[a,i])l&&(l.win&&this.#e(l.win)?this.#t(l.win):l.bar!==void 0&&this.#i());return!0}#a(t){const s=this.windows.indexOf(t);return s===this.windows.length-1&&this.active===t.id?!1:(this.windows.splice(s,1),this.windows.push(t),this.#o(t),!0)}#o(t){const s=this.windows.find(n=>n.id===this.active);this.active=t?t.id:null,s&&s!==t&&this.#e(s)&&this.#t(s),t&&this.#t(t),this.#i()}#l(t){t.max?Object.assign(t,t.max,{max:null}):Object.assign(t,{max:{x:t.x,y:t.y,w:t.w,h:t.h},...this.#d()}),this.#t(t)}#h(t,s){if(t[s]=!0,s==="closed"){const i=this.spec.windows.find(r=>r.id===t.id),a=this.spec.layout(this.size,this.#n(),this.split).rects.get(t.id);Object.assign(t,{...a,max:null,ui:structuredClone(i.ui)})}const n=[...this.windows].reverse().find(i=>this.#e(i));this.#o(n||null)}#b(t){const s=this.windows.find(n=>n.app===t);s&&(s.min||s.closed?(s.min=!1,s.closed=!1,this.#a(s)||this.#t(s)):this.active===s.id?this.#h(s,"min"):this.#a(s))}#y(t){if(t===this.ws)return;this.ws=t,this.drag=null;const s=[...this.windows].reverse().find(n=>this.#e(n));this.active=s?s.id:null;for(const n of this.windows)this.#e(n)&&this.#t(n)}#e(t){return!t.min&&!t.closed&&t.ws===this.ws}#n(){const t=this.spec.bar;return{x:0,y:t.edge==="top"?t.height:0,w:this.size[0],h:this.size[1]-t.height}}#f(){const t=this.spec.bar;return{x:0,y:t.edge==="top"?0:this.size[1]-t.height,w:this.size[0],h:t.height}}#d(){const t=this.#n(),s=this.spec.inset;return{x:t.x+s,y:t.y+s,w:t.w-2*s,h:t.h-2*s}}#s(t){Object.assign(this.want,t);const s=this.queue.then(async()=>{const{theme:n,scene:i,wallpaper:a,preset:r,fresh:l}=this.want;this.want.fresh=!1;const o=i[0]===this.scene[0]&&i[1]===this.scene[1];if(!l&&o&&n===this.theme&&a===this.wallpaper&&r===this.preset&&this.canvas)return;const h=U.find(d=>d.id===r),f=ue(i,this.scale),w=await ce(i,i[1]/f[1],a,n,h.bar);this.theme=n,this.wallpaper=a;const p=l||r!==this.preset;p&&this.#c(h),this.#x(i,f,w,p)});return this.queue=s.catch(()=>{}),s}#c(t){this.spec=t,this.preset=t.id,this.windows=t.windows.map(s=>({...s,ui:structuredClone(s.ui),ws:s.ws||1,x:0,y:0,min:!1,max:null,closed:!1,hits:[]})),this.active=t.active,this.ws=1,this.split={...t.split},this.splits=[],this.layers=new Map,this.barHits=[],this.hover=null,this.press=null,this.drag=null,this.lastDown=null}#x(t,s,{wall:n,back:i},a){(t[0]!==this.scene[0]||t[1]!==this.scene[1]||!this.canvas)&&(this.canvas=new OffscreenCanvas(t[0],t[1]));const r=a||s[0]!==this.size[0]||s[1]!==this.size[1];this.scene=t,this.size=s,this.sx=t[0]/s[0],this.sy=t[1]/s[1],this.wall=n,this.barBack=i,r&&this.#k(),this.#i();for(const l of this.windows)this.#t(l)}#k(){this.drag=null;const{rects:t,splits:s}=this.spec.layout(this.size,this.#n(),this.split);this.splits=s;for(const n of this.windows){const i=t.get(n.id);n.max?Object.assign(n,{max:i,...this.#d()}):Object.assign(n,i)}}#M(){const{rects:t,splits:s}=this.spec.layout(this.size,this.#n(),this.split);this.splits=s;let n=!1;for(const i of this.windows){const a=t.get(i.id);if(i.max){i.max=a;continue}if(a.x===i.x&&a.y===i.y&&a.w===i.w&&a.h===i.h)continue;const r=a.w!==i.w||a.h!==i.h;Object.assign(i,a),r&&this.#t(i),n=!0}return n}#i(){const t=this.palette,s=this.barLayer,n=s&&s.width===this.barBack.width&&s.height===this.barBack.height?s:new OffscreenCanvas(this.barBack.width,this.barBack.height),i=n.getContext("2d");i.setTransform(1,0,0,1,0,0),i.clearRect(0,0,n.width,n.height),i.drawImage(this.barBack,0,0),i.scale(this.sx,this.sy);const a=this.press,r=this.windows.find(l=>l.id===this.active);this.barHits=[],this.spec.bar.paint(i,t,this.size[0],{windows:this.windows,active:this.active,title:r&&r.label?r.label(r.ui):"",ws:this.ws,hit:x((l,o,h,f,w,p)=>this.barHits.push({id:l,x:o,y:h,w:f,h:w,act:p}),"hit"),pressed:x(l=>!!(a&&a.kind==="bar-ui"&&a.id===l),"pressed"),hovered:x(l=>!!(this.hover&&this.hover.bar===l),"hovered"),app:x(l=>this.#b(l),"app"),workspace:x(l=>this.#y(l),"workspace")}),this.barLayer=n}#t(t){const s=this.palette,{sx:n,sy:i}=this,a=t.id===this.active,r=Math.ceil((t.w+2*V)*n),l=Math.ceil((t.h+2*V)*i);let o=this.layers.get(t.id);(!o||o.width!==r||o.height!==l)&&(o=new OffscreenCanvas(r,l),this.layers.set(t.id,o));const h=o.getContext("2d");h.setTransform(1,0,0,1,0,0),h.clearRect(0,0,r,l),h.setTransform(n,0,0,i,V*n,V*i);const f=t.max&&!this.spec.tiled,w=f?0:this.spec.radius;if(!f){const d=(n+i)/2;for(const b of le(s[a?"shadow-active":"shadow"]))h.save(),h.shadowColor=b.color,h.shadowBlur=b.blur*d,h.shadowOffsetX=b.x*d,h.shadowOffsetY=b.y*d,c(h,s.win,0,0,t.w,t.h,w),h.restore()}h.save(),X(h,0,0,t.w,t.h,w),h.clip(),c(h,s.win,0,0,t.w,t.h),t.hits=[];const p=this.press;if(t.paint(h,s,t.w,t.h,{state:t.ui,active:a,hit:x((d,b,S,g,u,v)=>t.hits.push({id:d,x:b,y:S,w:g,h:u,act:v}),"hit")}),p&&p.kind==="ui"&&p.win===t){const d=t.hits.find(b=>b.id===p.id);d&&c(h,this.theme==="dark"?"rgba(255,255,255,0.10)":"rgba(20,28,40,0.10)",d.x,d.y,d.w,d.h,6)}if(t.ctl&&this.#v(h,s,t),h.restore(),!f){const d=this.spec.tiled&&a;h.strokeStyle=d?s.focus:s.edge,h.lineWidth=d?2:1,d?X(h,-1,-1,t.w+2,t.h+2,w+1):X(h,-.5,-.5,t.w+1,t.h+1,w+.5),h.stroke()}}#v(t,s,n){Et.forEach((i,a)=>{const r=n.w-122+a*38,l=n.ctl-14,o=this.hover&&this.hover.win===n&&this.hover.which===a,h=this.press&&this.press.kind==="ctl"&&this.press.win===n&&this.press.which===a,f=i==="close";(o||h)&&c(t,f?h?"#c4383d":"#e5484d":h?s.line:s.field,r,l,36,28,7),B(t,i==="max"&&n.max?"restore":i,r+11,l+7,14,f&&(o||h)?"#ffffff":s.muted,1.6)})}}export{be as Desktop,at as PALETTES,me as PRESETS,bt as UI_SCALE,Ft as WALLPAPER,tt as WALLPAPERS,Ht as loadFonts};
@@ -0,0 +1,93 @@
1
+ Copyright 2020 The DM Mono Project Authors (https://www.github.com/googlefonts/dm-mono)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
1
+ Copyright 2022 The Noto Project Authors (https://github.com/notofonts/latin-greek-cyrillic)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
1
+ Copyright 2020 The Space Grotesk Project Authors (https://github.com/floriankarsten/space-grotesk)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.