software-defence-factory 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,6 +19,7 @@ Choose the part you need:
19
19
 
20
20
  | Outcome | Command / guide |
21
21
  | --- | --- |
22
+ | Set up an operator, worker and application | [Setup plan and acceptance checklist](docs/setup.md) |
22
23
  | Use the method with your existing agent | `software-defence-factory kit --output ./factory-kit` — exports a new staging directory |
23
24
  | Try the runtime without inference | `software-defence-factory demo` — Docker required; synthetic sample only |
24
25
  | Connect an existing repository | [Runtime quickstart](docs/quickstart.md) |
@@ -74,3 +75,9 @@ Managed Linux services can also opt into daily updates that reserve idle control
74
75
  This is a test release. Synthetic qualification demonstrates control flow and isolation, not model quality, application correctness or production readiness. Follow [AGENTS.md](AGENTS.md) for contributions and [SECURITY.md](SECURITY.md) for the trust boundaries.
75
76
 
76
77
  MIT for original code and method. Included dashboard components and fonts retain their licenses in [third-party notices](THIRD_PARTY_NOTICES.md).
78
+
79
+ ## Contributing
80
+
81
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for source setup and checks, the
82
+ [self-development recipe](docs/development.md) for running project work through
83
+ Factory, and [todo.md](todo.md) for the ordered issue backlog.
@@ -224,6 +224,7 @@ Runtime commands accept --state PATH. Default: ${DEFAULT_STATE}
224
224
  Demo default: ${DEFAULT_DEMO_STATE}
225
225
  The npm CLI keeps state outside the package; updates wait for stopped installations.
226
226
  Dashboard binds only to loopback; use SSH for remote access.
227
- See docs/quickstart.md for inference, hosting, evidence and recovery.`);
227
+ Setup plan: ${join(ROOT, 'docs/setup.md')}
228
+ See docs/quickstart.md for task execution, evidence and recovery.`);
228
229
  else throw new Error(`Unknown command: ${command}`);
229
230
  } catch(error) {console.error(`Factory: ${error.message}`);process.exitCode=1;}
@@ -1,5 +1,7 @@
1
1
  # Runtime quickstart
2
2
 
3
+ For a new worker or remote operator, start with the [setup plan](setup.md).
4
+
3
5
  Install Node 22.13+, Git and Docker Engine/Desktop. Use an unprivileged account with Docker access. Install `software-defence-factory` through npm, or invoke the same package with npx. No factory source checkout is required.
4
6
 
5
7
  ## Qualify a synthetic installation
@@ -55,7 +57,7 @@ ssh -N -L 127.0.0.1:7331:127.0.0.1:7331 your-host
55
57
 
56
58
  Open http://127.0.0.1:7331 on the client. Use the same local/remote port because the HTTP service validates its Host header. The SSH connection must remain open. Access also works across different networks when your configured private network connects the hosts.
57
59
 
58
- Use `status`, `cancel JOB_ID`, `retry JOB_ID` and `stop`, always with the selected `--state`. `service` prints a systemd user-service definition; review and install it through the host's normal service management. It is not enabled by printing it. See [recovery](recovery.md).
60
+ Use `status`, `cancel JOB_ID`, `retry JOB_ID` and `stop`, always with the selected `--state`. `service install --state PATH` installs and enables the supported Linux user service; `service status`, `service logs` and `service uninstall` operate it. Bare `service` only prints a definition. For managed startup, persistent SSH tunnels and daily idle updates, follow [services](services.md). See [recovery](recovery.md) for interrupted attempts.
59
61
 
60
62
  ## Native application builds
61
63
 
package/docs/services.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Persistent controllers and remote dashboards
2
2
 
3
- Install the npm CLI first. A Factory controller is a Linux systemd **user**
3
+ For the complete host-to-application sequence and reboot checklist, start with
4
+ [the setup plan](setup.md). Install the npm CLI first. A Factory controller is a Linux systemd **user**
4
5
  service; SSH tunnels support Linux systemd and macOS launchd. Neither needs a
5
6
  root controller. macOS can still run a local controller with `up`.
6
7
 
package/docs/setup.md ADDED
@@ -0,0 +1,235 @@
1
+ # Setup plan: operator, worker and application
2
+
3
+ Use this plan for a new installation or when moving an existing Factory to a
4
+ worker machine. Complete the applicable checkpoints in order and record the
5
+ result in a **private** copy of the checklist below. The plan applies to any
6
+ operator/worker names and any suitable private network; it requires no personal
7
+ context system, particular VPN provider or Factory source checkout.
8
+
9
+ The operator owns access and infrastructure choices. Factory maintainers own
10
+ this plan and the linked command guides and update them with behavior changes.
11
+ Paths beginning `/private/state` or `/absolute/path` below are placeholders;
12
+ replace them with user-owned absolute directories outside the application and
13
+ installed package.
14
+
15
+ ## 1. Choose the scope and hosts
16
+
17
+ | Choice | Record before installation |
18
+ | --- | --- |
19
+ | Method only or runtime | Method export needs no Docker, background service or model |
20
+ | Operator/client | Local machine, user and how the dashboard will be opened |
21
+ | Worker | Linux/systemd for managed controllers; macOS can use manual `up` |
22
+ | Applications | Canonical repository, branch, preserved WIP and responsible owner |
23
+ | Runtime | Stable Node executable (22.13+), Git, Docker, CPU/RAM/disk budget |
24
+ | State | Private state path and unused loopback port for each installation |
25
+ | Inference | Provider/model, credential reference, job image and network path |
26
+ | Automation | Which controllers may start, update policy and who may submit work |
27
+ | Recovery | Private backup location, retained runtime/image and recovery contact |
28
+
29
+ One installation owns one repository and port. A synthetic qualification
30
+ installation can provide a running dashboard while product controllers remain
31
+ stopped. There is no multi-project controller or second scheduler hidden in
32
+ this plan. Keep unrelated personal agent configuration on its existing host.
33
+
34
+ For method-only adoption, run `software-defence-factory kit --output NEW_DIRECTORY`
35
+ and follow [the adoption guide](../kit/README.md). The remaining host/runtime
36
+ steps apply only when using Factory's optional controller.
37
+
38
+ ## 2. Establish host access and boot prerequisites
39
+
40
+ Use an unprivileged operator account. Check `node --version`, `git --version`
41
+ and `docker info` from the actual login/SSH session. Install dependencies using
42
+ the host's supported method. For a Linux worker, Docker, SSH and any private
43
+ network client must start at boot; inspect their actual unit names instead of
44
+ assuming every distribution uses the same service names.
45
+
46
+ For remote access:
47
+
48
+ 1. Establish a reachable private address, including across networks if needed.
49
+ 2. Enroll the worker's verified SSH host key and configure key authentication.
50
+ 3. Create an SSH alias such as `factory-worker`; verify
51
+ `ssh -o BatchMode=yes factory-worker 'id -un'` from the operator machine.
52
+ 4. Verify firewall/interface scope. Keep the dashboard on loopback; do not
53
+ expose it publicly or disable host-key checking to make the tunnel work.
54
+
55
+ Administrator access is a separate host choice. Installing/running Factory user
56
+ services does **not** require root or unrestricted passwordless sudo. If the
57
+ owner deliberately chooses passwordless administration, inspect `sudo -n -l`
58
+ for the intended `NOPASSWD` policy and repeat the permitted command after a
59
+ fresh reboot. A successful `sudo -n` command can merely reuse cached
60
+ credentials. A missing rule must be installed by an authenticated administrator;
61
+ record that remaining step without blocking unprivileged Factory operation.
62
+
63
+ Record disk unlock, login and power behavior explicitly. Linux user lingering
64
+ can start services without desktop login **after the OS and home are available**;
65
+ it cannot unlock an encrypted disk. A sleeping laptop is not an available
66
+ worker. Choose AC/battery/sleep behavior with the owner; do not disable disk
67
+ security or change power policy as a side effect of Factory setup.
68
+
69
+ Checkpoint: noninteractive SSH (when needed), Docker and the chosen Node binary
70
+ work, and required host dependencies have a documented startup/recovery owner.
71
+
72
+ ## 3. Install the package and qualify the runtime
73
+
74
+ ```sh
75
+ npm install --global software-defence-factory
76
+ software-defence-factory --version
77
+ software-defence-factory help
78
+ ```
79
+
80
+ Use a user-writable npm prefix or the existing Node manager; do not turn the
81
+ controller into a root process to work around installation permissions. For
82
+ example, Linux users choosing `--prefix "$HOME/.local"` must also make
83
+ `$HOME/.local/bin` available in their login PATH. `npx` uses the same package;
84
+ managed services retain a runtime outside its cache. Keep the service's recorded
85
+ Node executable available. See [installation and updates](npm.md).
86
+
87
+ Use a **separate synthetic state and unused port** to exercise the runtime:
88
+
89
+ ```sh
90
+ software-defence-factory demo --state /private/state/runtime-proof --port 7345
91
+ # Inspect and finish the sample handoff before qualification.
92
+ software-defence-factory qualify --state /private/state/runtime-proof
93
+ ```
94
+
95
+ These commands deliberately create synthetic jobs, including failed/interrupted
96
+ attempts. Never use application state for `demo` or `qualify`. They make no model
97
+ calls and prove neither model quality nor application readiness. Preserve the
98
+ qualification record; stop this controller unless it is the selected dashboard.
99
+
100
+ ## 4. Prepare each application and inference profile
101
+
102
+ Preserve existing commits, branches, uncommitted work and licenses before moving
103
+ anything. Verify the canonical GitHub origin and main branch's tracking target;
104
+ a fork may still track its upstream product. Move application sources into the
105
+ chosen workspace, not into the npm package or private runtime state.
106
+
107
+ Before admitting development work, establish:
108
+
109
+ - Reproducible toolchain/dependency pins and an actual build/check command.
110
+ - A compatible job image for native libraries, browser/mobile tools or custom
111
+ model adapters; the standard image does not supply every application stack.
112
+ - Meaningful checks in GitHub CI on the selected revision, plus the intended
113
+ review/branch policy. Record plan/access limits if enforcement is unavailable.
114
+ - Applicable application instructions, design/scope, resource limits, secret
115
+ references and a clear delivery destination. Keep unfinished WIP separate
116
+ until intentionally integrated; jobs clone committed source only.
117
+
118
+ Configure a new installation using [the quickstart](quickstart.md):
119
+
120
+ ```sh
121
+ software-defence-factory init --repo /absolute/path/to/app --agent pi --check "npm ci && npm test" --state /private/state/my-app --port 7331
122
+ software-defence-factory install --state /private/state/my-app
123
+ software-defence-factory doctor --state /private/state/my-app
124
+ ```
125
+
126
+ Replace the agent/check/paths with the accepted application profile. `install`
127
+ builds the standard image: do not use it to overwrite an existing custom image
128
+ selection. Follow the application image's own build/pinning procedure instead.
129
+ `init` does not edit the app, install personal skills or submit a task. Runtime
130
+ jobs receive the bundled method and six skills automatically.
131
+
132
+ For a local model, verify the existing model service, intended model name and
133
+ its startup. Test the model API from a disposable container using the **selected
134
+ job image and network**. Host `127.0.0.1` inside a container is not the host's
135
+ loopback. Any host bridge/proxy and narrow firewall rule are explicit machine
136
+ infrastructure; they need their own startup and reboot checks. A bridge address may appear
137
+ after the user service manager starts; configure retry/readiness and verify
138
+ recovery rather than assuming startup order from enablement alone. Avoid duplicate
139
+ model servers, public listeners, Docker socket mounts or whole account folders.
140
+ Cloud inference likewise needs a real provider/model connectivity check without
141
+ printing credentials. A model-list/health response is connectivity evidence;
142
+ qualifying model output requires a separately accepted bounded task.
143
+
144
+ Checkpoint: record the exact source revision, image ID, check command, resource
145
+ limits, inference connectivity and CI result. Keep product controllers stopped
146
+ until their tasks are explicitly ready to run.
147
+
148
+ ## 5. Enable only the intended background services
149
+
150
+ A newly initialized state has no jobs. Before adopting older state, establish
151
+ that its queue may resume; starting **any** controller executes queued work.
152
+ If queue ownership/state is uncertain, reconcile it before enabling autostart.
153
+
154
+ On the Linux worker, select the state that should stay available:
155
+
156
+ ```sh
157
+ software-defence-factory stop --state /private/state/runtime-proof
158
+ software-defence-factory service install --state /private/state/runtime-proof
159
+ software-defence-factory service status --state /private/state/runtime-proof
160
+ software-defence-factory service updates --auto on
161
+ software-defence-factory service updates --auto status
162
+ ```
163
+
164
+ Follow [services](services.md) for user lingering, existing Docker group
165
+ membership, logs, stop/start, uninstall and maintenance recovery. A user manager
166
+ started before Docker group membership changed may need `--group docker`; this
167
+ applies an existing group and grants no new membership. Enable lingering only
168
+ for the intended account through the host's administrator.
169
+
170
+ On the operator machine, stop any old manual tunnel, then:
171
+
172
+ ```sh
173
+ software-defence-factory tunnel install --host factory-worker --port 7345
174
+ software-defence-factory tunnel status --host factory-worker --port 7345
175
+ ```
176
+
177
+ Use the actual selected dashboard port on both sides. macOS tunnels start at
178
+ user login; Linux uses its user service manager. Open `http://127.0.0.1:7345`.
179
+ This is the worker's loopback dashboard forwarded through SSH.
180
+
181
+ Managed daily updates reserve idle controllers and preserve the prior running
182
+ set; they defer when busy and attempt rollback if the new runtime is unhealthy.
183
+ A deliberate `service stop` leaves boot enablement in place: use `uninstall`
184
+ when a controller must also remain disabled across reboots. Preserve private
185
+ state and previous releases. The timer does not rebuild application images,
186
+ start product tasks, change a model or publish application changes.
187
+
188
+ ## 6. Prove reboot recovery and hand over
189
+
190
+ Choose a reboot window with disk unlock/recovery available. Save a private
191
+ baseline of the boot ID (`cat /proc/sys/kernel/random/boot_id`), runtime version,
192
+ job IDs/states/attempts, selected enabled services and paused installations.
193
+ After the owner reboots/unlocks the worker, check **before manually starting
194
+ anything**:
195
+
196
+ - SSH returns and a changed boot ID confirms a new boot.
197
+ - Docker, private network and model/proxy services are healthy, with no relevant
198
+ failed units or repeated restart loop. Inspect their current-boot logs.
199
+ - `service status --state PATH` reports enabled/running/healthy, the intended
200
+ runtime version and no unexpected maintenance reservation.
201
+ - The update timer is enabled and has a next execution time.
202
+ - The operator's tunnel reconnects and the dashboard responds at the same URL.
203
+ - Job history is unchanged and intentionally disabled product controllers have
204
+ no listeners or executor processes. Probe model connectivity from the job
205
+ container again without starting a product agent.
206
+ - The intended administrator policy still works, if that capability was chosen.
207
+
208
+ Record actual observations and failures separately. An observed boot after
209
+ manual unlock/login does not prove an unattended cold boot; a worker reboot
210
+ does not prove operator-machine login startup. Process crash recovery and tests
211
+ across two physical networks are also distinct checks. Use [recovery](recovery.md)
212
+ and [service recovery](services.md#recovery-and-proof-limits) for failures; do not
213
+ start a second controller or clear unknown process locks to make status green.
214
+
215
+ Copy this private completion record into the installation's handoff:
216
+
217
+ | Checkpoint | Result | Evidence / remaining action |
218
+ | --- | --- | --- |
219
+ | Host roles, owner, source and private state selected | Pending | |
220
+ | SSH, Docker, Node and host startup prerequisites | Pending | |
221
+ | Synthetic runtime qualification | Pending | |
222
+ | Application image, real checks/CI and preserved WIP | Pending | |
223
+ | Inference path and chosen model | Pending | |
224
+ | Controller/tunnel/timer installation and recovery | Pending | |
225
+ | Worker reboot after required unlock/login | Pending | |
226
+ | Operator login recovery / separate networks | Pending | Record separately |
227
+ | History and intentionally stopped products preserved | Pending | |
228
+ | Backups, logs, stop/update/rollback owner and guide | Pending | |
229
+ | First bounded application task | Not started | Separate task authority and proof |
230
+
231
+ Use Pass, Fail or Not applicable with a reason; never infer success from an
232
+ installed file. Keep host identities, credentials, raw logs and customer details
233
+ out of public issues and package contents. A ready worker is only the foundation:
234
+ follow [the method](../kit/README.md#first-real-task) for the first explicitly
235
+ accepted application task and revision-bound checks/review/handoff.
@@ -0,0 +1 @@
1
+ @font-face{font-family:Manrope Variable;font-style:normal;font-display:swap;font-weight:200 800;src:url(/assets/manrope-cyrillic-ext-wght-normal-C8S-KRRz.woff2)format("woff2-variations");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Manrope Variable;font-style:normal;font-display:swap;font-weight:200 800;src:url(/assets/manrope-cyrillic-wght-normal-Dvxsihut.woff2)format("woff2-variations");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:Manrope Variable;font-style:normal;font-display:swap;font-weight:200 800;src:url(/assets/manrope-greek-wght-normal-DL7QRZyv.woff2)format("woff2-variations");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:Manrope Variable;font-style:normal;font-display:swap;font-weight:200 800;src:url(/assets/manrope-vietnamese-wght-normal-usUDDRr7.woff2)format("woff2-variations");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Manrope Variable;font-style:normal;font-display:swap;font-weight:200 800;src:url(/assets/manrope-latin-ext-wght-normal-Ch3YOpNY.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Manrope Variable;font-style:normal;font-display:swap;font-weight:200 800;src:url(/assets/manrope-latin-wght-normal-DHIcAJRg.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:"Manrope Variable", ui-sans-serif, system-ui, sans-serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--container-sm:24rem;--container-2xl:42rem;--container-4xl:56rem;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-wider:.05em;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:"Manrope Variable", ui-sans-serif, system-ui, sans-serif;--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.sticky{position:sticky}.top-0{top:0}.top-14{top:calc(var(--spacing) * 14)}.z-20{z-index:20}.z-30{z-index:30}.col-span-2{grid-column:span 2/span 2}.col-start-2{grid-column-start:2}.row-start-1{grid-row-start:1}.row-start-2{grid-row-start:2}.mx-auto{margin-inline:auto}.my-4{margin-block:calc(var(--spacing) * 4)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.-mb-px{margin-bottom:-1px}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.-ml-3{margin-left:calc(var(--spacing) * -3)}.ml-4{margin-left:calc(var(--spacing) * 4)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-flex{display:inline-flex}.table{display:table}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.max-h-96{max-height:calc(var(--spacing) * 96)}.max-h-\[60vh\]{max-height:60vh}.min-h-24{min-height:calc(var(--spacing) * 24)}.min-h-32{min-height:calc(var(--spacing) * 32)}.min-h-48{min-height:calc(var(--spacing) * 48)}.min-h-screen{min-height:100vh}.w-fit{width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-\[1000px\]{max-width:1000px}.max-w-\[1500px\]{max-width:1500px}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.grid-cols-\[minmax\(8rem\,1fr\)_minmax\(8rem\,1fr\)_10rem_12rem\]{grid-template-columns:minmax(8rem,1fr) minmax(8rem,1fr) 10rem 12rem}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-7>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 7) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 7) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-x-6{column-gap:calc(var(--spacing) * 6)}.gap-y-1{row-gap:var(--spacing)}.gap-y-3{row-gap:calc(var(--spacing) * 3)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-border>:not(:last-child)){border-color:var(--border)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-border,.border-border\/70{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\/70{border-color:color-mix(in oklab, var(--border) 70%, transparent)}}.border-danger\/25{border-color:var(--danger)}@supports (color:color-mix(in lab, red, red)){.border-danger\/25{border-color:color-mix(in oklab, var(--danger) 25%, transparent)}}.border-danger\/35{border-color:var(--danger)}@supports (color:color-mix(in lab, red, red)){.border-danger\/35{border-color:color-mix(in oklab, var(--danger) 35%, transparent)}}.border-danger\/40{border-color:var(--danger)}@supports (color:color-mix(in lab, red, red)){.border-danger\/40{border-color:color-mix(in oklab, var(--danger) 40%, transparent)}}.border-primary,.border-primary\/25{border-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.border-primary\/25{border-color:color-mix(in oklab, var(--primary) 25%, transparent)}}.border-success\/25{border-color:var(--success)}@supports (color:color-mix(in lab, red, red)){.border-success\/25{border-color:color-mix(in oklab, var(--success) 25%, transparent)}}.border-transparent{border-color:#0000}.border-warning\/25{border-color:var(--warning)}@supports (color:color-mix(in lab, red, red)){.border-warning\/25{border-color:color-mix(in oklab, var(--warning) 25%, transparent)}}.bg-background,.bg-background\/95{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/95{background-color:color-mix(in oklab, var(--background) 95%, transparent)}}.bg-current{background-color:currentColor}.bg-danger\/5{background-color:var(--danger)}@supports (color:color-mix(in lab, red, red)){.bg-danger\/5{background-color:color-mix(in oklab, var(--danger) 5%, transparent)}}.bg-danger\/10{background-color:var(--danger)}@supports (color:color-mix(in lab, red, red)){.bg-danger\/10{background-color:color-mix(in oklab, var(--danger) 10%, transparent)}}.bg-muted,.bg-muted\/20{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/20{background-color:color-mix(in oklab, var(--muted) 20%, transparent)}}.bg-muted\/35{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/35{background-color:color-mix(in oklab, var(--muted) 35%, transparent)}}.bg-muted\/40{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/40{background-color:color-mix(in oklab, var(--muted) 40%, transparent)}}.bg-muted\/60{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/60{background-color:color-mix(in oklab, var(--muted) 60%, transparent)}}.bg-primary,.bg-primary\/5{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.bg-primary\/5{background-color:color-mix(in oklab, var(--primary) 5%, transparent)}}.bg-sidebar{background-color:var(--sidebar)}.bg-success\/10{background-color:var(--success)}@supports (color:color-mix(in lab, red, red)){.bg-success\/10{background-color:color-mix(in oklab, var(--success) 10%, transparent)}}.bg-surface{background-color:var(--surface)}.bg-transparent{background-color:#0000}.bg-warning\/10{background-color:var(--warning)}@supports (color:color-mix(in lab, red, red)){.bg-warning\/10{background-color:color-mix(in oklab, var(--warning) 10%, transparent)}}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-8{padding:calc(var(--spacing) * 8)}.p-12{padding:calc(var(--spacing) * 12)}.px-0{padding-inline:0}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-14{padding-block:calc(var(--spacing) * 14)}.py-16{padding-block:calc(var(--spacing) * 16)}.pt-1{padding-top:var(--spacing)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pl-4{padding-left:calc(var(--spacing) * 4)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:Manrope Variable,ui-sans-serif,system-ui,sans-serif}.text-2xl{font-size:2.25rem;line-height:var(--tw-leading,2.5rem)}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:.875rem;line-height:var(--tw-leading,1.25rem)}.text-xl{font-size:1.375rem;line-height:var(--tw-leading,1.75rem)}.text-xs{font-size:.75rem;line-height:var(--tw-leading,1rem)}.text-xs\!{font-size:.75rem!important;line-height:var(--tw-leading,1rem)!important}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-danger{color:var(--danger)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-success{color:var(--success)}.text-warning{color:var(--warning)}.capitalize{text-transform:capitalize}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.shadow-xs{--tw-shadow:0 1px 2px var(--tw-shadow-color,#0f172a0d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.last\:border-0:last-child{border-style:var(--tw-border-style);border-width:0}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:bg-muted:hover,.hover\:bg-muted\/35:hover{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/35:hover{background-color:color-mix(in oklab, var(--muted) 35%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--primary) 90%, transparent)}}.hover\:text-danger:hover{color:var(--danger)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:decoration-2:hover{text-decoration-thickness:2px}}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring\/40:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/40:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 40%, transparent)}}.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\:outline-ring:focus-visible{outline-color:var(--ring)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-inset:focus-visible{--tw-ring-inset:inset}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}@media (width>=40rem){.sm\:grid{display:grid}.sm\:hidden{display:none}.sm\:w-40{width:calc(var(--spacing) * 40)}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-\[minmax\(8rem\,1fr\)_minmax\(8rem\,1fr\)_10rem_12rem\]{grid-template-columns:minmax(8rem,1fr) minmax(8rem,1fr) 10rem 12rem}.sm\:grid-cols-\[minmax\(12rem\,1fr\)_minmax\(12rem\,1fr\)_10rem\]{grid-template-columns:minmax(12rem,1fr) minmax(12rem,1fr) 10rem}.sm\:flex-col{flex-direction:column}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:items-end{align-items:flex-end}.sm\:items-start{align-items:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:gap-4{gap:calc(var(--spacing) * 4)}.sm\:p-5{padding:calc(var(--spacing) * 5)}.sm\:p-6{padding:calc(var(--spacing) * 6)}.sm\:px-5{padding-inline:calc(var(--spacing) * 5)}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}.sm\:text-right{text-align:right}.sm\:text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.sm\:text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.sm\:text-sm{font-size:.875rem;line-height:var(--tw-leading,1.25rem)}}@media (width>=48rem){.md\:top-0{top:0}.md\:mt-9{margin-top:calc(var(--spacing) * 9)}.md\:ml-0{margin-left:0}.md\:block{display:block}.md\:flex{display:flex}.md\:hidden{display:none}.md\:h-screen{height:100vh}.md\:w-56{width:calc(var(--spacing) * 56)}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:flex-col{flex-direction:column}.md\:items-stretch{align-items:stretch}.md\:overflow-visible{overflow:visible}.md\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.md\:border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.md\:px-4{padding-inline:calc(var(--spacing) * 4)}.md\:py-5{padding-block:calc(var(--spacing) * 5)}}@media (width>=64rem){.lg\:grid-cols-\[minmax\(0\,1\.4fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:justify-between{justify-content:space-between}.lg\:justify-end{justify-content:flex-end}.lg\:p-8{padding:calc(var(--spacing) * 8)}.lg\:px-8{padding-inline:calc(var(--spacing) * 8)}}@media (width>=80rem){.xl\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--background:#f3f4f1;--foreground:#1a1d1e;--surface:#fafbf8;--sidebar:#e8eae7;--muted:#e4e7e4;--muted-foreground:#626a6b;--border:#c7cdca;--primary:#1d6683;--primary-foreground:#f8fcfd;--success:#326b51;--warning:#8a651b;--danger:#a54237;--ring:#1d6683}.dark{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--background:#151819;--foreground:#edf1ef;--surface:#1c2021;--sidebar:#111415;--muted:#252a2b;--muted-foreground:#9ba4a4;--border:#373e3e;--primary:#66a9c2;--primary-foreground:#102128;--success:#78ad91;--warning:#d0a75c;--danger:#df8075;--ring:#66a9c2}*{border-color:var(--border)}html{background:var(--background)}body{background:var(--background);min-width:320px;min-height:100vh;color:var(--foreground);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;margin:0}button,input,textarea,select{font:inherit}button{cursor:pointer}button:disabled{cursor:not-allowed}::selection{background:var(--primary)}@supports (color:color-mix(in lab, red, red)){::selection{background:color-mix(in srgb, var(--primary) 25%, transparent)}}.app-sidebar{box-shadow:inset -1px 0 var(--foreground)}@supports (color:color-mix(in lab, red, red)){.app-sidebar{box-shadow:inset -1px 0 color-mix(in srgb, var(--foreground) 4%, transparent)}}.workshop{background:var(--background)}.brand-wordmark{font-family:var(--font-sans);letter-spacing:-.02em;font-size:1.125rem;font-weight:600}.factory-mark{width:2.6rem;height:auto;color:var(--foreground);overflow:visible}.factory-mark path{fill:none;stroke-width:5px;stroke-linecap:square;stroke-linejoin:round}.factory-mark .factory-mark-piece-a{stroke:currentColor}.factory-mark .factory-mark-piece-b{stroke:var(--primary)}.page-heading{border-bottom:1px solid var(--border);padding-bottom:1.35rem}main h1{font-family:var(--font-sans);letter-spacing:-.02em;font-size:1.5rem;font-weight:600;line-height:1.35}main h2{letter-spacing:-.012em}.nav-item{height:2.4rem;color:var(--muted-foreground);border-radius:0;flex-shrink:0;align-items:center;gap:.625rem;padding:0 .625rem;font-size:.8125rem;line-height:1.25rem;transition:color .15s,background .15s;display:flex;position:relative}.nav-item:hover{background:var(--muted)}@supports (color:color-mix(in lab, red, red)){.nav-item:hover{background:color-mix(in srgb, var(--muted) 65%, transparent)}}.nav-item:hover{color:var(--foreground)}.nav-item-active{color:var(--foreground);box-shadow:none;background:0 0}.nav-item-active:before{background:var(--primary);content:"";width:2px;height:1.15rem;position:absolute;left:-.25rem}.crafted-card{box-shadow:0 1px 0 var(--foreground), 0 10px 30px var(--foreground)}@supports (color:color-mix(in lab, red, red)){.crafted-card{box-shadow:0 1px 0 color-mix(in srgb, var(--foreground) 6%, transparent), 0 10px 30px color-mix(in srgb, var(--foreground) 3%, transparent)}}.run-column{border-radius:8px}.quiet-state{min-height:11rem}.quiet-state-mark{height:1.25rem;color:var(--primary);align-items:flex-end;gap:3px;display:flex}.quiet-state-mark i{background:currentColor;width:2px;height:.65rem;display:block}.quiet-state-mark i:nth-child(2){height:1.2rem}.quiet-state-mark i:nth-child(3){height:.9rem}.field-label{color:var(--muted-foreground);letter-spacing:normal;margin-bottom:.375rem;font-size:.75rem;font-weight:500;line-height:1rem;display:block}.field-control{border:1px solid var(--border);background:var(--background);width:100%;min-height:2.5rem;color:var(--foreground);box-shadow:inset 0 1px 0 var(--foreground);border-radius:8px;outline:none;padding:.625rem .75rem;font-size:.875rem;line-height:1.25rem}@supports (color:color-mix(in lab, red, red)){.field-control{box-shadow:inset 0 1px 0 color-mix(in srgb, var(--foreground) 3%, transparent)}}.field-control{transition:border-color .15s,box-shadow .15s}.field-control::placeholder{color:var(--muted-foreground);opacity:.7}.field-control:focus{border-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.field-control:focus{border-color:color-mix(in srgb, var(--primary) 60%, transparent)}}.field-control:focus{box-shadow:0 0 0 3px var(--primary)}@supports (color:color-mix(in lab, red, red)){.field-control:focus{box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 14%, transparent)}}@media (width<=767px){.brand-wordmark{display:none}body{padding-bottom:calc(4.15rem + env(safe-area-inset-bottom))}.app-sidebar{box-shadow:inset 0 -1px var(--foreground)}@supports (color:color-mix(in lab, red, red)){.app-sidebar{box-shadow:inset 0 -1px color-mix(in srgb, var(--foreground) 4%, transparent)}}.app-sidebar nav{z-index:40;border-top:1px solid var(--border);background:var(--sidebar);grid-template-columns:repeat(5,minmax(0,1fr));gap:0;margin:0;display:grid;position:fixed;bottom:0;left:0;right:0;overflow:visible}@supports (color:color-mix(in lab, red, red)){.app-sidebar nav{background:color-mix(in srgb, var(--sidebar) 94%, transparent)}}.app-sidebar nav{padding:.4rem .3rem max(.4rem, env(safe-area-inset-bottom));-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}.app-sidebar nav .nav-item{flex-direction:column;justify-content:center;gap:.2rem;height:3.1rem;padding:0 .1rem;font-size:.625rem}.app-sidebar nav .nav-item>.ml-auto{display:none}.app-sidebar nav .nav-item-active:before{width:1.5rem;height:2px;top:-.4rem;left:50%;transform:translate(-50%)}.mobile-theme{border:1px solid #0000}.mobile-theme:hover{border-color:var(--border);color:var(--foreground)}}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}