Compare commits

..
29 Commits
Author SHA1 Message Date
Laan Tungir e577de4e2d v0.1.27 - Entropy audit: remediate 3 findings (F-006 RP2040 xorshift fallback, F-007 PQ DRBG docs, F-008 SLH-DSA SK.prf domain separation) 2026-08-13 08:30:55 -04:00
Laan Tungir 44a87432b7 v0.1.26 - Security audit remediation: mlock fatal on failure, hybrid auth replay protection, HTTP Content-Length safe parsing, OTP sscanf validation, compiler hardening flags 2026-08-13 08:05:58 -04:00
Laan Tungir 6aa42d4387 v0.1.25 - Fix submodule dirty state in feather_s3_tft secp256k1; clean release v0.1.25 2026-08-11 10:06:19 -04:00
Laan Tungir 0b1c3ea382 v0.1.24 - Migrate Teensy 4.1 signer to role+path authorization model (deprecate nostr_index) 2026-08-08 13:55:02 -04:00
Laan Tungir fd895db0c9 v0.1.23 - Make role-as-password the default authorization model; remove interactive approval prompts from wizard; add Makefile guard to direct agents to build_static.sh; optimize build_static.sh with content-hash skip and fix .dockerignore to exclude 1.3GB of unnecessary files from Docker context 2026-08-08 08:09:56 -04:00
Laan Tungir e4087441a5 v0.1.22 - Fix connections display EINTR handling with tui_get_key; add qrexec usage example to client help; simplify deploy_local.sh by removing confirmation prompt 2026-08-06 17:41:10 -04:00
Laan Tungir 5a16c4e1bf v0.1.21 - Refactor n_signer_client to use nostr_core_lib high-level wrappers; sync vendored lib with selector rewrite + 10 new algorithm-verb wrappers + from_client/last_error APIs 2026-08-06 11:41:08 -04:00
Laan Tungir 9afbb8fcbd Refactor n_signer_client to use nostr_core_lib high-level wrappers
The CLI was hand-building cJSON params and calling the low-level
nsigner_client_call for all 16 verbs. Now it uses the high-level
nostr_signer_t typed wrappers from nostr_core_lib for 14 of 16 verbs:
get_info, get_public_key (alg + nostr), sign_event, mine_event,
nip04/44 encrypt+decrypt, sign, verify, derive, encapsulate,
decapsulate, derive_shared_secret, otp encrypt/decrypt.

The 'call' verb (raw passthrough) and 'derive --algorithm' still use
the low-level nsigner_client_call on the shared connection (created via
nostr_signer_nsigner_from_client). The 'list' verb uses
nsigner_transport_list_unix directly.

The client shrank from 945 to ~840 lines, with the per-verb cJSON
building logic now in the library. Error messages use
nostr_signer_last_error() to surface the raw n_signer RPC error text
(path_not_allowed, unknown_role, etc.).

Also adds two plan docs:
- plans/client_breaking_change_audit.md: audit of n_signer breaking
  changes vs all ~/lt/ client repos
- plans/nostr_core_lib_full_verb_coverage.md: analysis of the library
  verb coverage gap that motivated this refactor

Tests: 45/45 pass, 0 fail, 2 skip (test_n_signer_client.sh).
2026-08-06 10:17:47 -04:00
Laan Tungir fa98de12e4 v0.1.20 - Removed @ prefix from all user-facing socket name output (startup message, list command, error messages, connection display) 2026-08-06 09:19:13 -04:00
Laan Tungir e459e98beb v0.1.19 - Added --register-role CLI flag for non-interactive template-role registration; expanded CLI test suite with template-role distinct-pubkey, path-rejection, ml-dsa-65 and slh-dsa-128s sign/verify tests (45 pass, 0 fail) 2026-08-06 09:11:46 -04:00
Laan Tungir 32151b3ffd v0.1.18 - Fixed template-role pubkey caching: re-derive on each concrete path request (nostr_range wildcard was returning the same key for all account indices) 2026-08-06 08:00:25 -04:00
Laan Tungir 75dddac223 v0.1.17 - Changed role menu option 2 to NIP-06 compatible Nostr range m/44'/1237'/*'/0/0 2026-08-06 07:44:16 -04:00
Laan Tungir 697a79dc25 v0.1.16 - Re-upload release with new Gitea token - nsigner + nsigner_client static binaries 2026-08-05 19:28:32 -04:00
Laan Tungir e65ed5c5d6 v0.1.15 - Rename binaries to nsigner/nsigner_client, integrate client into release pipeline, update role+path authorization model with wizard presets and wildcard path support 2026-08-05 18:59:47 -04:00
Laan Tungir 821245ac1d v0.1.14 - Update README with named path-roles documentation, wizard changes, set syntax, fixed paths 2026-08-04 21:31:18 -04:00
Laan Tungir 7cbefe13ec v0.1.13 - Change default index to 0 in wizard (when 0 is in range/set) 2026-08-04 21:29:58 -04:00
Laan Tungir d7fb3787e6 v0.1.12 - Fix if-else chain bug preventing SELECTOR_ROLE_PATH derivation; fix parser to not treat 44' as variable; handle hardened markers on range/set segments 2026-08-04 21:21:33 -04:00
Laan Tungir f0e90e0ea6 v0.1.11 - Fix named path-role display and allow fixed paths without range/set 2026-08-04 20:53:12 -04:00
Laan Tungir 86a97aee01 v0.1.10 - Add unified hardware-signer broker plan for Qubes OS sharing across qubes 2026-08-04 09:31:52 -04:00
Laan Tungir d7eb6b5ec0 v0.1.9 - Add AGENT_CLIENT.md reference doc and n_signer_client.roo skill for agent access to n_signer 2026-08-01 21:09:05 -04:00
Laan Tungir e04196f1f1 v0.1.8 - Consolidated USB test page, fixed OTP round-trip, reformatted SD card, added pad checksum logging 2026-08-01 05:26:42 -04:00
Laan Tungir 0ea3e60391 v0.1.7 - Teensy 4.1 OTP SD pad: complete implementation with UI pad selection
Solution D: 4 KB chunk cap, dropped boot-time checksum verify (can't scale
to 900 GB), increased transport frame + req/resp buffers to 8 KB.
test_otp_sd.py: 10/10 pass (ASCII + binary round-trips, offset advance,
2 KB large plaintext, tamper detection).

Phase 6: ui_pick_pad() LVGL pad-selection screen with chksum prefix + size
display, Skip button, 30s timeout. otp_pad_sd_list_pads() scans /pads and
returns chksums + sizes. Wired into the non-debug boot flow in signer.ino
(DEBUG_AUTO_GENERATE=0 path). DEBUG_AUTO_GENERATE=1 stays headless with
auto-bind_first.

README: added comprehensive memory management section documenting the
FlexRAM architecture, custom linker script, .rodata-to-FLASH move,
build-time stack gauge, and current memory layout.
2026-07-30 18:20:30 -04:00
Laan Tungir ac2e6347a2 v0.1.6 - Teensy 4.1 SD-card OTP pad: real implementation working on hardware
- otppad_embedded: bit-compatible port of libotppad (2386/2386 host tests pass)
- otp_pad_sd: SdFat-direct SD card pad reader (FAT-only, ASCII armor + binary .otp)
- pad_gen.ino: TRNG-sourced 1 MB pad generator using i.MX RT1062 TRNG registers
- Linker script: moved .rodata from DTCM to FLASH (EXCLUDE_FILE ed25519),
  reclaiming 124 KB DTCM, free stack 5.9 KB -> 130.9 KB
- check_stack.sh: build-time FlexRAM stack gauge, wired into build_signer.sh
- test_otp_sd.py: 8/9 hardware tests pass (ASCII + binary round-trips,
  offset advance, tamper detection; 10 KB plaintext times out on perf)
- test_classical.py: 16/16 pass with new memory layout (ed25519 OK)
- Memory evaluation document: plans/teensy41_memory_evaluation.md
2026-07-30 17:10:50 -04:00
Laan Tungir d7369646fb Added remaining-todo document for Teensy 4.1 signer: captures v0.1.1-v0.1.5 fixes, current 20/24 suite score, and next steps for ml-dsa-65 sign hang (NTT correctness in matvec/scalar wrappers) and OTP decrypt mismatch 2026-07-27 19:14:22 -04:00
Laan Tungir b1f8076b1d v0.1.5 - Fixed ml-dsa-65 SHAKE re-squeeze domain separation bug: poly_challenge, poly_eta, and poly_uniform_gamma1 re-absorbed the same seed on buffer exhaustion, producing identical output and potentially hanging the SampleInBall rejection loop; added a monotonic re-squeeze counter to the absorb buffer so each re-squeeze produces fresh bytes; note: ml-dsa-65 sign still hangs because the rejection loop never accepts a candidate — this is a separate NTT-correctness bug in the matvec/scalar multiplication wrappers that requires comparison against a PQClean reference implementation 2026-07-27 19:07:51 -04:00
Laan Tungir 314f1c520a v0.1.4 - Teensy 4.1 PQ stack fixes: moved ml-kem-768 NTT working polys (polyvec_matrix_pointwise 6656B, indcpa enc 9728B, indcpa dec 5120B, poly_mul_negacyclic 1024B) and ml-dsa-65 sign poly c (1024B) + SHAKE out buffers (2688B) from DTCM stack to DMAMEM (RAM2) static workspace; fixed ml-kem-768 keygen crash (verified on hardware); added ml-dsa-65 rejection-loop DMAMEM counter diagnostic; ml-dsa-65 sign no longer crashes but hangs due to pre-existing NTT correctness bug (rejection loop runs to exhaustion) — next milestone is to compare NTT output against host reference 2026-07-27 18:46:09 -04:00
Laan Tungir ea2f1cd78e v0.1.3 - Fixed Teensy 4.1 ed25519 sign/verify stack overflow: moved ed_add's 12 gf arrays (1536B), ed_frombytes' 9 gf arrays (1152B), sc_reduce/sc_muladd int64_t x[64] (512B), and ed25519_sign/verify SHA-512 ctx (328B) from DTCM stack to DMAMEM (RAM2) workspace; added persistent crash diagnostics (DMAMEM op marker + stack/heap measurement); full classical+Nostr suite now passes 16/16 in one uninterrupted boot (get_info, secp256k1/ed25519/x25519 pubkeys, schnorr+ecdsa sign/verify, ed25519 sign/verify, x25519 shared secret, derive, nostr pubkey/sign_event, nip04+nip44 round-trips) 2026-07-27 16:34:02 -04:00
Laan Tungir 9282e22b00 v0.1.2 - Teensy 4.1 secp256k1 stack reductions + shared context: reduced WINDOW_A 5->4 (Strauss ecmult tables 8->4 entries, fixes schnorr verify stack overflow) and ECMULT_CONST_GROUP_SIZE 5->4 (ECDH tables 16->8, fixes nip04 crash); added secp256k1_get_shared_context() and reused it in dispatch.cpp ECDSA/schnorr helpers to eliminate per-request secp256k1_context_create/destroy heap fragmentation; reordered test_signer.py to test classical+nostr verbs before PQ verbs and added nostr_sign_event/nip04/nip44 round-trip tests 2026-07-27 12:18:38 -04:00
Laan Tungir 2ba81c4bc8 v0.1.1 - Fixed Teensy 4.1 NIP-04 crash and NIP-44 dispatch bug: reduced secp256k1 ECMULT_CONST_GROUP_SIZE 5->4 to halve ECDH stack usage (~3.5KB->~1.7KB) preventing DTCM stack overflow in secp256k1_ecmult_const during nip04/nip44 ECDH; fixed is_nip44 selector in dispatch.cpp (method[7] was always 'i', digit is at method[9]) so nostr_nip44_* verbs now reach the nip44 implementation instead of silently calling nip04; verified nip04+nip44 round-trip on hardware 2026-07-27 07:16:53 -04:00
402 changed files with 116433 additions and 1462 deletions
+23
View File
@@ -4,3 +4,26 @@ build/
/*.a
!resources/
!resources/**
# Exclude nested .git and bare repos inside resources/nostr_core_lib.
# These are not needed for the build and add ~1.3 GB to the Docker context.
resources/nostr_core_lib/.git/
resources/nostr_core_lib/rewrite_mirror/
resources/nostr_core_lib/verify_remote_size/
resources/nostr_core_lib/verify_remote_size_now/
resources/nostr_core_lib/backups/
resources/nostr_core_lib/examples/
resources/nostr_core_lib/tests/
resources/nostr_core_lib/plans/
resources/nostr_core_lib/pool.log
resources/nostr_core_lib/Trash/
resources/nostr_core_lib/node_modules/
resources/nostr_core_lib/nips/
resources/nostr_core_lib/nak/
resources/nostr_core_lib/nostr-tools/
resources/nostr_core_lib/libsodium/
resources/nostr_core_lib/monocypher-4.0.2/
resources/nostr_core_lib/tiny-AES-c/
resources/nostr_core_lib/blossom/
resources/nostr_core_lib/ndk/
resources/nostr_core_lib/cline_history/
+199
View File
@@ -0,0 +1,199 @@
---
description: "Call n_signer to sign Nostr events, get public keys, encrypt/decrypt, and perform crypto operations across all transports (qrexec, unix socket, TCP, HTTP, USB/serial)."
---
# n_signer Client Skill
This skill tells an agent how to call [`n_signer`](../README.md) — a hardware/software signing oracle that holds BIP-39 keys in locked memory. The signer may be running on the same machine (Unix socket), in another Qubes qube (qrexec), on a hardware device (USB/serial), or reachable over TCP/HTTP.
## 1. Transport overview
| Transport | Scope | Auth required | Best for |
|-----------|-------|---------------|----------|
| **qrexec** | Cross-qube (Qubes OS) | No (identity from `QREXEC_REMOTE_DOMAIN`) | Agents in caller qubes |
| **Unix abstract socket** | Same machine | No (identity from `SO_PEERCRED`) | Local processes |
| **TCP (FIPS mesh)** | Cross-qube or network | Yes (kind-27235 auth envelope) | Remote callers, FIPS networks |
| **HTTP** | Cross-qube or network | Yes (kind-27235 auth envelope) | curl-friendly, REST clients |
| **USB/serial** | Hardware signer (Feather, Teensy, CYD) | No (physical possession) | Embedded/air-gap |
| **Stdio** | One-shot via pipe | No | Scripted one-off calls |
## 2. Wire protocol (all transports)
Every request/response uses **length-prefixed framing**:
```
[4-byte big-endian payload length][UTF-8 JSON payload]
```
The JSON payload is a JSON-RPC 2.0-style object:
```json
{ "id": "<string>", "method": "<verb>", "params": [<arg0>, <arg1>, ..., {<options>}] }
```
Response (success):
```json
{ "id": "<string>", "result": "<value>" }
```
Response (error):
```json
{ "id": "<string>", "error": { "code": <int>, "message": "<string>" } }
```
## 3. Transport-specific invocation
### 3.1 Qubes qrexec (easiest cross-qube)
```bash
# Pipe framed JSON-RPC through qrexec-client-vm
printf '\x00\x00\x00\x3f'"$(echo '{"id":"1","method":"get_public_key","params":[{"nostr_index":0}]}')" | qrexec-client-vm <signer_qube> qubes.NsignerRpc | tail -c +5
```
Python (stdlib only, zero deps):
```python
import json, struct, subprocess
def call_nsigner(target_qube, request):
payload = json.dumps(request, separators=(",", ":")).encode()
frame = struct.pack(">I", len(payload)) + payload
proc = subprocess.Popen(
["qrexec-client-vm", target_qube, "qubes.NsignerRpc"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
)
out, _ = proc.communicate(frame)
length = struct.unpack(">I", out[:4])[0]
return json.loads(out[4:4+length])
```
See [`client/demo_python.py`](../client/demo_python.py) for a full working demo (get_public_key → sign_event → nip44 → mine_event).
### 3.2 Local Unix abstract socket (same machine)
```bash
# Find running signers
nsigner list
# Connect via socat or the nsigner client subcommand
nsigner client '<json>' --socket-name <name>
```
C (using `nostr_core_lib`):
```c
nsigner_transport_t *t = nsigner_transport_open_unix("nsigner", 5000);
nsigner_client_t *c = nsigner_client_new(t);
cJSON *result = NULL;
nsigner_client_call(c, "nostr_get_public_key", params, &result);
```
See [`examples/get_public_key_client.c`](../examples/get_public_key_client.c) and [`examples/sign_event_client.c`](../examples/sign_event_client.c).
### 3.3 TCP (FIPS mesh, cross-qube)
Requires a **kind-27235 auth envelope** (signed Nostr event proving caller identity).
Python (with `coincurve`):
```python
import hashlib, json, socket, struct, time
from coincurve import PrivateKey
# Build auth envelope
sk = PrivateKey(caller_privkey_bytes)
pubkey_x = sk.public_key.format(compressed=False)[1:33].hex()
body_hash = hashlib.sha256(json.dumps(params, separators=(",",":")).encode()).hexdigest()
tags = [["nsigner_rpc","1"],["nsigner_method","get_public_key"],["nsigner_body_hash",body_hash]]
serialized = json.dumps([0, pubkey_x, created_at, 27235, tags, content], separators=(",",":")).encode()
event_id = hashlib.sha256(serialized).hexdigest()
sig = sk.sign_schnorr(bytes.fromhex(event_id), aux_randomness=b"\x00"*32).hex()
request = {"id":"1","method":"get_public_key","params":params,"auth":{"id":event_id,"pubkey":pubkey_x,"created_at":created_at,"kind":27235,"tags":tags,"content":"py-min","sig":sig}}
```
See [`examples/get_pubkey_fips.py`](../examples/get_pubkey_fips.py) and [`examples/n_signer_qube_example_fips.js`](../examples/n_signer_qube_example_fips.js).
### 3.4 HTTP listener
```bash
curl -X POST http://<host>:<port>/ \
-H "Content-Type: application/json" \
-d '{"id":"1","method":"get_public_key","params":[],"auth":{...}}'
```
### 3.5 USB/serial (hardware signers)
For Feather S3, Teensy 4.1, CYD ESP32, etc. — connect over USB CDC serial with the same framing.
See [`examples/feather_get_public_key.py`](../examples/feather_get_public_key.py) and [`examples/feather_sign_event.py`](../examples/feather_sign_event.py).
## 4. Key verbs
| Verb | What it does | Params |
|------|-------------|--------|
| `get_public_key` | Get pubkey for algorithm+index | `[{"algorithm":"secp256k1","index":0}]` |
| `nostr_get_public_key` | Get secp256k1 pubkey by nostr_index | `[{"nostr_index":0}]` |
| `nostr_sign_event` | Sign a Nostr event | `["<event_json>",{"nostr_index":0}]` |
| `sign` | Sign arbitrary bytes (any algorithm) | `["<hex>",{"algorithm":"ed25519","index":0}]` |
| `nostr_nip44_encrypt` | NIP-44 encrypt | `["<peer_hex>","<plaintext>",{"nostr_index":0}]` |
| `nostr_nip44_decrypt` | NIP-44 decrypt | `["<peer_hex>","<ciphertext>",{"nostr_index":0}]` |
| `nostr_mine_event` | NIP-13 PoW mine + sign | `["<event_json>",{"nostr_index":0,"difficulty":4}]` |
| `encapsulate` | ML-KEM-768 encapsulate | `["<peer_pubkey_hex>",{"algorithm":"ml-kem-768"}]` |
| `decapsulate` | ML-KEM-768 decapsulate | `["<ciphertext_hex>",{"algorithm":"ml-kem-768","index":0}]` |
| `derive` | HMAC-SHA256(privkey, data) | `["<data>",{"algorithm":"secp256k1","index":0}]` |
| `get_info` | Signer metadata | `[]` |
Full verb table: [`README.md §4.3`](../README.md#43-verbs)
## 5. Algorithms
| Algorithm | Key type | FIPS | Derivation path |
|-----------|----------|------|-----------------|
| `secp256k1` | Signature (Nostr) | — | `m/44'/1237'/<n>'/0/0` |
| `ed25519` | Signature (SSH) | — | `m/44'/102001'/<n>'/0/0'` |
| `x25519` | Key agreement (age) | — | `m/44'/102002'/<n>'/0/0'` |
| `ml-dsa-65` | PQ signature | FIPS 204 | DRBG from seed |
| `slh-dsa-128s` | PQ hash-based sig | FIPS 205 | DRBG from seed |
| `ml-kem-768` | PQ KEM | FIPS 203 | DRBG from seed |
| `otp` | One-time pad | — | USB pad, no derivation |
## 6. Publishing a Nostr event (end-to-end)
```python
import json, struct, subprocess, time
def call_nsigner(target_qube, request):
payload = json.dumps(request, separators=(",", ":")).encode()
frame = struct.pack(">I", len(payload)) + payload
proc = subprocess.Popen(
["qrexec-client-vm", target_qube, "qubes.NsignerRpc"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
)
out, _ = proc.communicate(frame)
length = struct.unpack(">I", out[:4])[0]
return json.loads(out[4:4+length])
# 1. Get pubkey
pub = call_nsigner("nostr_signer", {"id":"1","method":"get_public_key","params":[{"nostr_index":0}]})["result"]
# 2. Build and sign event
event = {"kind":1,"content":"Hello from my agent!","created_at":int(time.time()),"tags":[],"pubkey":pub}
result = call_nsigner("nostr_signer", {"id":"2","method":"nostr_sign_event","params":[json.dumps(event),{"nostr_index":0}]})
signed = json.loads(result["result"])
# 3. Broadcast to relay(s)
# signed["id"] and signed["sig"] are now populated
```
## 7. Reference files
| File | What it shows |
|------|---------------|
| [`client/demo_python.py`](../client/demo_python.py) | Full Python demo (qrexec, stdlib only) |
| [`client/demo_javascript.js`](../client/demo_javascript.js) | Full Node.js demo (qrexec) |
| [`client/demo_c99.c`](../client/demo_c99.c) | Full C99 demo (qrexec, nostr_core_lib) |
| [`examples/get_pubkey_fips.py`](../examples/get_pubkey_fips.py) | Minimal TCP/FIPS with auth envelope |
| [`examples/get_pubkey_qrexec.c`](../examples/get_pubkey_qrexec.c) | Minimal qrexec in C |
| [`examples/get_pubkey_tcp.c`](../examples/get_pubkey_tcp.c) | Minimal TCP in C with auth envelope |
| [`examples/n_signer_qube_example_fips.js`](../examples/n_signer_qube_example_fips.js) | TCP/FIPS in Node.js |
| [`examples/n_signer_qube_example_qrexec.js`](../examples/n_signer_qube_example_qrexec.js) | qrexec in Node.js |
| [`documents/CLIENT_IMPLEMENTATION.md`](../documents/CLIENT_IMPLEMENTATION.md) | Full wire contract spec |
| [`documents/AGENT_CLIENT.md`](../documents/AGENT_CLIENT.md) | Comprehensive agent reference |
+25 -3
View File
@@ -55,11 +55,13 @@ RUN if [ "$(uname -m)" = "aarch64" ] && ! command -v aarch64-linux-gnu-gcc >/dev
# Copy source files
COPY src/ /build/src/
COPY client/ /build/client/
COPY libotppad/ /build/libotppad/
COPY resources/tui_continuous/ /build/resources/tui_continuous/
COPY resources/pqclean/ /build/resources/pqclean/
# Build nsigner as a fully static binary
# Also build nsigner_client as a fully static binary
RUN ARCH="$(uname -m)"; \
case "$ARCH" in \
aarch64|arm64) NOSTR_LIB="/build/nostr_core_lib/libnostr_core_arm64.a" ;; \
@@ -124,9 +126,29 @@ RUN ARCH="$(uname -m)"; \
$(pkg-config --static --libs libcurl openssl) \
-lsecp256k1 -lsqlite3 -lz -lpthread -lm
RUN strip /build/nsigner_static || true
RUN file /build/nsigner_static && \
(ldd /build/nsigner_static 2>&1 || true)
# Build nsigner_client (links nostr_core_lib, much smaller than nsigner)
RUN ARCH="$(uname -m)"; \
case "$ARCH" in \
aarch64|arm64) NOSTR_LIB="/build/nostr_core_lib/libnostr_core_arm64.a" ;; \
x86_64|amd64) NOSTR_LIB="/build/nostr_core_lib/libnostr_core_x64.a" ;; \
*) echo "Unsupported build arch: $ARCH"; exit 1 ;; \
esac; \
gcc -static -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -s -Wall -Wextra -std=c99 \
-DNOSTR_ENABLE_NSIGNER_CLIENT=1 -D_GNU_SOURCE \
-I/build/nostr_core_lib \
-I/build/nostr_core_lib/nostr_core \
-I/build/nostr_core_lib/cjson \
/build/client/n_signer_client.c \
"$NOSTR_LIB" \
-o /build/nsigner_client_static \
$(pkg-config --static --libs libcurl openssl) \
-lsecp256k1 -lz -lpthread -lm
RUN strip /build/nsigner_static /build/nsigner_client_static || true
RUN file /build/nsigner_static /build/nsigner_client_static && \
(ldd /build/nsigner_static 2>&1 || true) && \
(ldd /build/nsigner_client_static 2>&1 || true)
FROM scratch AS output
COPY --from=builder /build/nsigner_static /nsigner_static
COPY --from=builder /build/nsigner_client_static /nsigner_client_static
+61 -6
View File
@@ -1,6 +1,17 @@
CC := gcc
CFLAGS := -Wall -Wextra -std=c99 -Os -ffunction-sections -fdata-sections -DNOSTR_ENABLE_NSIGNER_CLIENT=1 -D_GNU_SOURCE -Isrc -Ilibotppad -Iresources/nostr_core_lib -Iresources/nostr_core_lib/nostr_core -Iresources/nostr_core_lib/cjson -Iresources/tui_continuous -Iresources/pqclean -Iresources/pqclean/crypto_sign/ml-dsa-65 -Iresources/pqclean/crypto_sign/slh-dsa-128s -Iresources/pqclean/crypto_kem/ml-kem-768 -Iresources/pqclean/common
LDFLAGS := -Wl,--gc-sections resources/nostr_core_lib/libnostr_core_x64.a -lz -ldl -lpthread -lm -lssl -lcrypto -lcurl -lsecp256k1
CFLAGS := -Wall -Wextra -std=c99 -Os -ffunction-sections -fdata-sections \
-fstack-protector-strong -D_FORTIFY_SOURCE=2 -fPIE \
-fstack-clash-protection \
-DNOSTR_ENABLE_NSIGNER_CLIENT=1 -D_GNU_SOURCE \
-Isrc -Ilibotppad -Iresources/nostr_core_lib \
-Iresources/nostr_core_lib/nostr_core -Iresources/nostr_core_lib/cjson \
-Iresources/tui_continuous -Iresources/pqclean \
-Iresources/pqclean/crypto_sign/ml-dsa-65 \
-Iresources/pqclean/crypto_sign/slh-dsa-128s \
-Iresources/pqclean/crypto_kem/ml-kem-768 -Iresources/pqclean/common
LDFLAGS := -Wl,--gc-sections -pie -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack \
resources/nostr_core_lib/libnostr_core_x64.a \
-lz -ldl -lpthread -lm -lssl -lcrypto -lcurl -lsecp256k1
SRC_DIR := src
BUILD_DIR := build
@@ -80,6 +91,7 @@ TEST_SLH_DSA_128S_TARGET := $(BUILD_DIR)/test_slh_dsa_128s
TEST_ML_KEM_768_TARGET := $(BUILD_DIR)/test_ml_kem_768
TEST_PUBKEY_FORMAT_TARGET := $(BUILD_DIR)/test_pubkey_format
TEST_ALGORITHM_API_TARGET := $(BUILD_DIR)/test_algorithm_api
TEST_PATH_WHITELIST_TARGET := $(BUILD_DIR)/test_path_whitelist
EXAMPLE_GET_PUBLIC_KEY_TARGET := $(BUILD_DIR)/example_get_public_key_client
EXAMPLE_SIGN_EVENT_TARGET := $(BUILD_DIR)/example_sign_event_client
EXAMPLE_GET_PUBKEY_TCP_TARGET := $(BUILD_DIR)/example_get_pubkey_tcp
@@ -88,15 +100,42 @@ EXAMPLE_PQ_SIGN_TARGET := $(BUILD_DIR)/example_pq_sign
EXAMPLE_PQ_KEM_TARGET := $(BUILD_DIR)/example_pq_kem
EXAMPLE_SSH_SIGN_TARGET := $(BUILD_DIR)/example_ssh_sign
DEMO_C99_TARGET := $(BUILD_DIR)/demo_c99
N_SIGNER_CLIENT_TARGET := $(BUILD_DIR)/nsigner_client
.PHONY: all lib dev static static-debug static-arm64 firmware-feather test test-integration test-mnemonic test-mnemonic-input test-role test-selector test-enforcement test-dispatcher test-policy test-socket-name test-auth-envelope test-qrexec-auth test-mine-event test-pq-crypto test-ed25519-x25519 test-ml-dsa-65 test-slh-dsa-128s test-ml-kem-768 test-pubkey-format test-algorithm-api examples test-client clean
.PHONY: all lib dev static static-debug static-arm64 firmware-feather test test-integration test-mnemonic test-mnemonic-input test-role test-selector test-enforcement test-dispatcher test-policy test-socket-name test-auth-envelope test-qrexec-auth test-mine-event test-pq-crypto test-ed25519-x25519 test-ml-dsa-65 test-slh-dsa-128s test-ml-kem-768 test-pubkey-format test-algorithm-api test-path-whitelist test-n-signer-client examples clients test-client clean
all: dev
# Guard for non-static build targets.
# The canonical build is `make static` (runs build_static.sh).
# To use dev/test targets, set NSIGNER_ALLOW_DEV_BUILD=1 in your environment.
# This prevents AI agents from accidentally using the wrong build path.
define BUILD_GUARD
@if [ -z "$$NSIGNER_ALLOW_DEV_BUILD" ]; then \
echo "=========================================================="; \
echo "ERROR: This target is blocked for non-interactive agents."; \
echo " For testing and deployment, use:"; \
echo ""; \
echo " ./build_static.sh"; \
echo " or"; \
echo " make static"; \
echo ""; \
echo " The static build produces the canonical binary that"; \
echo " matches production deployments."; \
echo ""; \
echo " To override (human developers only):"; \
echo " NSIGNER_ALLOW_DEV_BUILD=1 make <target>"; \
echo "=========================================================="; \
exit 1; \
fi
endef
all: dev clients
lib:
$(BUILD_GUARD)
cd resources/nostr_core_lib && ./build.sh --nips=1,4,6,13,19,44
dev: lib $(TARGET_DEV)
$(BUILD_GUARD)
$(TARGET_DEV): $(SOURCES)
@mkdir -p $(BUILD_DIR)
@@ -117,7 +156,7 @@ static-arm64:
firmware-feather:
cd firmware/feather_s3_tft && idf.py build
test: lib test-mnemonic test-mnemonic-input test-role test-selector test-enforcement test-dispatcher test-policy test-socket-name test-auth-envelope test-qrexec-auth test-mine-event test-pq-crypto test-ed25519-x25519 test-ml-dsa-65 test-slh-dsa-128s test-ml-kem-768 test-pubkey-format test-client
test: lib test-mnemonic test-mnemonic-input test-role test-selector test-enforcement test-dispatcher test-policy test-socket-name test-auth-envelope test-qrexec-auth test-mine-event test-pq-crypto test-ed25519-x25519 test-ml-dsa-65 test-slh-dsa-128s test-ml-kem-768 test-pubkey-format test-path-whitelist test-n-signer-client test-client
test-integration: $(TEST_INTEGRATION_TARGET) $(TARGET_DEV)
./$(TEST_INTEGRATION_TARGET)
@@ -176,10 +215,22 @@ test-pubkey-format: $(TEST_PUBKEY_FORMAT_TARGET)
test-algorithm-api: $(TEST_ALGORITHM_API_TARGET)
./$(TEST_ALGORITHM_API_TARGET)
test-client: examples
test-path-whitelist: $(TEST_PATH_WHITELIST_TARGET)
./$(TEST_PATH_WHITELIST_TARGET)
test-n-signer-client: clients $(TARGET_DEV)
./$(TEST_DIR)/test_n_signer_client.sh
test-client: examples clients
examples: $(EXAMPLE_GET_PUBLIC_KEY_TARGET) $(EXAMPLE_SIGN_EVENT_TARGET) $(EXAMPLE_GET_PUBKEY_TCP_TARGET) $(EXAMPLE_GET_PUBKEY_QREXEC_TARGET) $(EXAMPLE_PQ_SIGN_TARGET) $(EXAMPLE_PQ_KEM_TARGET) $(EXAMPLE_SSH_SIGN_TARGET) $(DEMO_C99_TARGET)
clients: $(N_SIGNER_CLIENT_TARGET)
$(N_SIGNER_CLIENT_TARGET): $(CLIENT_DIR)/n_signer_client.c
@mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) $(CLIENT_DIR)/n_signer_client.c -o $(N_SIGNER_CLIENT_TARGET) $(LDFLAGS)
$(TEST_MNEMONIC_TARGET): $(TEST_DIR)/test_mnemonic.c $(SRC_DIR)/mnemonic.c $(SRC_DIR)/secure_mem.c
@mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) $(TEST_DIR)/test_mnemonic.c $(SRC_DIR)/mnemonic.c $(SRC_DIR)/secure_mem.c $(SRC_DIR)/otp_pad.c libotppad/libotppad.c -o $(TEST_MNEMONIC_TARGET) $(LDFLAGS)
@@ -256,6 +307,10 @@ $(TEST_ALGORITHM_API_TARGET): $(TEST_DIR)/test_algorithm_api.c $(SRC_DIR)/pq_cry
@mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) $(TEST_DIR)/test_algorithm_api.c $(SRC_DIR)/pq_crypto.c $(SRC_DIR)/pq_drbg.c $(PQCLEAN_SOURCES) $(SRC_DIR)/key_store.c $(SRC_DIR)/dispatcher.c $(SRC_DIR)/miner.c $(SRC_DIR)/selector.c $(SRC_DIR)/enforcement.c $(SRC_DIR)/role_table.c $(SRC_DIR)/mnemonic.c $(SRC_DIR)/secure_mem.c $(SRC_DIR)/policy.c $(SRC_DIR)/otp_pad.c libotppad/libotppad.c -o $(TEST_ALGORITHM_API_TARGET) $(LDFLAGS)
$(TEST_PATH_WHITELIST_TARGET): $(TEST_DIR)/test_path_whitelist.c $(SRC_DIR)/server.c $(SRC_DIR)/pq_crypto.c $(SRC_DIR)/pq_drbg.c $(PQCLEAN_SOURCES) $(SRC_DIR)/key_store.c $(SRC_DIR)/dispatcher.c $(SRC_DIR)/miner.c $(SRC_DIR)/selector.c $(SRC_DIR)/enforcement.c $(SRC_DIR)/role_table.c $(SRC_DIR)/mnemonic.c $(SRC_DIR)/secure_mem.c $(SRC_DIR)/policy.c $(SRC_DIR)/auth_envelope.c $(SRC_DIR)/transport_frame.c $(SRC_DIR)/socket_name.c $(SRC_DIR)/http_listener.c $(SRC_DIR)/otp_pad.c libotppad/libotppad.c
@mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) $(TEST_DIR)/test_path_whitelist.c $(SRC_DIR)/server.c $(SRC_DIR)/pq_crypto.c $(SRC_DIR)/pq_drbg.c $(PQCLEAN_SOURCES) $(SRC_DIR)/key_store.c $(SRC_DIR)/dispatcher.c $(SRC_DIR)/miner.c $(SRC_DIR)/selector.c $(SRC_DIR)/enforcement.c $(SRC_DIR)/role_table.c $(SRC_DIR)/mnemonic.c $(SRC_DIR)/secure_mem.c $(SRC_DIR)/policy.c $(SRC_DIR)/auth_envelope.c $(SRC_DIR)/transport_frame.c $(SRC_DIR)/socket_name.c $(SRC_DIR)/http_listener.c $(SRC_DIR)/otp_pad.c libotppad/libotppad.c -o $(TEST_PATH_WHITELIST_TARGET) $(LDFLAGS)
$(EXAMPLE_GET_PUBLIC_KEY_TARGET): $(EXAMPLES_DIR)/get_public_key_client.c
@mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) $(EXAMPLES_DIR)/get_public_key_client.c -o $(EXAMPLE_GET_PUBLIC_KEY_TARGET) $(LDFLAGS)
+141 -51
View File
@@ -60,13 +60,12 @@ When started, `n_signer` immediately enters terminal input mode:
1. Choose mnemonic source: `[E]nter existing mnemonic` (default) or `[G]enerate new mnemonic`.
- On `E`: prompt for mnemonic with terminal echo disabled, then validate.
- On `G`: generate a fresh 12-word BIP-39 mnemonic from `getrandom(2)`, display it numbered with a "WRITE THIS DOWN — IT WILL NOT BE SHOWN AGAIN" warning, then continue. There is no confirmation step.
2. Build in-memory role/selector state from the mnemonic.
2. **Define roles** (mandatory): interactive preset menu wizard — choose from 10 presets (Standard Nostr, hardened range, agent range, SSH, Age, ML-DSA-65, SLH-DSA-128s, ML-KEM-768, OTP, Custom). At least one role must be defined. See [`documents/nsigner_menus.md`](documents/nsigner_menus.md) for the full menu reference.
3. **Interactive transport selection** (if no `--listen` flag given and stdin is a TTY): choose one or more of: Local Unix socket, Qubes qrexec bridge, FIPS/TCP listener (framed JSON), HTTP listener (curl-friendly).
4. **Index whitelist** (optional): restrict which `nostr_index` values this session can access.
5. **OTP pad selection** (optional): auto-scans attached USB drives for OTP pads and offers to bind one. See [`plans/otp_nostr_integration.md`](plans/otp_nostr_integration.md).
6. Pick the abstract socket name (random BIP-39 pair, or `--socket-name` / `--name` / `-n` override).
7. Initialize transport endpoints and bind the socket.
8. Switch to running status display.
4. Pick the abstract socket name (random BIP-39 pair, or `--socket-name` / `--name` / `-n` override).
5. Initialize transport endpoints and bind the socket.
6. Switch to running status display.
7. (Optional) Bind an OTP pad via `--otp-pad-dir` / `--otp-pad` flags if an OTP role was defined. See [`plans/otp_nostr_integration.md`](plans/otp_nostr_integration.md).
No startup files are read or written. The mnemonic — typed or generated — lives only in `mlock`'d memory and is zeroized on shutdown or crash.
@@ -87,25 +86,24 @@ n_signer v0.0.53 > Main Menu
Roles:
Role Purpose Curve Derivation path
main nostr secp256k1 m/44'/1237'/0'/0/0
nostr_idx_1 nostr secp256k1 m/44'/1237'/1'/0/0
backup bitcoin secp256k1 m/84'/0'/0'/0/5
nostr_agent nostr secp256k1 m/44'/1237'/*'/1'/0'
ssh ssh ed25519 m/44'/102001'/0'/0'/0'
Activity (latest first):
16:03:11 allow caller=uid:1000 method=nostr_get_public_key role=main
16:02:44 prompt caller=uid:1000 method=nostr_sign_event role=ops
16:02:46 allow caller=uid:1000 method=nostr_sign_event role=ops
16:03:11 allow caller=uid:1000 method=nostr_get_public_key role=main path=m/44'/1237'/0'/0/0
16:02:44 prompt caller=uid:1000 method=nostr_sign_event role=main path=m/44'/1237'/0'/0/0
16:02:46 allow caller=uid:1000 method=nostr_sign_event role=main path=m/44'/1237'/0'/0/0
15:59:10 deny caller=uid:1001 method=nostr_sign_event error=unauthorized
session=unlocked (12 words) signer=nsigner_hairy_dog derived=3 auto-approve=OFF
session=unlocked (12 words) signer=nsigner_hairy_dog derived=3
l lock/reunlock
r refresh
a toggle auto-approve
d display connections
q/x quit
```
The **Derivation path** column shows the full BIP-44 path for each role's key. For `nostr_index` roles this is `m/44'/1237'/<n>'/0/0` (NIP-06); for `role_path` roles it's the explicit path.
The **Derivation path** column shows the full BIP-44 path for each role's key. For roles derived via `role_path` this is the explicit path; for named path-roles it's the template path.
The signer's name (`nsigner_hairy_dog` in this example) appears in the **status line** at the bottom (`signer=nsigner_hairy_dog`). See [§4.1](#41-linux-desktop-abstract-namespace-unix-socket) for how the name is generated.
@@ -115,7 +113,6 @@ Pressing `d` clears the screen and shows each active transport as a titled block
Hotkeys (active while the status display is shown):
- `a` — toggle auto-approve (prompt) for this session
- `r` — refresh the display
- `d` — display connection instructions (press any key to return)
- `l` — lock / re-unlock the session
@@ -129,10 +126,11 @@ When a request needs confirmation, `n_signer` interrupts the status view with a
Approval required
caller: uid:1000
method: nostr_sign_event
selector: role=ops
purpose/curve: nostr/secp256k1
role: main
path: m/44'/1237'/0'/0/0
purpose: nostr
[y] allow once [n] deny [a] always allow this session
y: allow once n: deny e: allow this caller+role+verb for session a: allow this caller+role for session (all verbs)
```
No response is emitted to caller until the local user decides.
@@ -191,13 +189,20 @@ Error codes:
| 1008 | `mining_failed` | Internal error during proof-of-work mining. |
| 1009 | `not_yet_implemented` | Verb+algorithm combination is reserved but not yet implemented. |
| 1010 | `algorithm_not_supported_for_verb` | The `algorithm` value is not valid for this verb. |
| 2003 | `path_not_allowed` | `role_path` does not match any registered role or allowed path. |
| 2005 | `index_out_of_range` | `index` outside the named role's `[lo,hi]` range. |
| 2006 | `nostr_index_deprecated` | `nostr_index` is removed — use `role` + `role_path` instead. |
| 2007 | `index_deprecated` | `index` is removed for nostr verbs — use `role_path` with the full path. |
| 2008 | `role_required` | `role` is required when using `role_path`. |
| 2009 | `path_required` | `role_path` is required for roles with variable path templates. |
### 4.3 Verbs
All verbs take their arguments as positional `params` and their options in a trailing options object. Most verbs select a key via the `algorithm` + `index` options (see [§4.4](#44-algorithms)). The `nostr_*` verbs select a secp256k1 NIP-06 key via `nostr_index` and implement Nostr-protocol-specific serialization on top of the raw crypto.
All verbs take their arguments as positional `params` and their options in a trailing options object. Most verbs select a key via the `algorithm` + `index` options (see [§4.4](#44-algorithms)). The `nostr_*` verbs select a secp256k1 NIP-06 key via `role` + `role_path` and implement Nostr-protocol-specific serialization on top of the raw crypto.
| Verb | Algorithms | Positional params | Options |
|-------------------------|-----------------------------------------------|----------------------------------|----------------------------------|
| `get_info` | n/a (metadata) | — | — |
| `get_public_key` | all key-deriving algorithms | — | `algorithm`, `index` |
| `sign` | secp256k1, ed25519, ml-dsa-65, slh-dsa-128s | `<message_hex>` | `algorithm`, `index`, `scheme`* |
| `verify` | secp256k1, ed25519, ml-dsa-65, slh-dsa-128s | `<message_hex>`, `<signature_hex>` | `algorithm`, `index`, `scheme`* |
@@ -207,13 +212,13 @@ All verbs take their arguments as positional `params` and their options in a tra
| `derive` | secp256k1 | `<data>` | `algorithm`, `index` (required) |
| `encrypt` | otp | `<plaintext_base64>` | `algorithm`, `encoding` |
| `decrypt` | otp | `<ciphertext>` | `algorithm`, `encoding` |
| `nostr_get_public_key` | secp256k1 (NIP-06) | — | `nostr_index`, `format` |
| `nostr_sign_event` | secp256k1 (NIP-06) | `<event_json>` | `nostr_index` |
| `nostr_mine_event` | secp256k1 (NIP-06) | `<event_json>` | `nostr_index`, `difficulty`, `timeout_sec`, `threads` |
| `nostr_nip04_encrypt` | secp256k1 (NIP-06) | `<peer_pubkey_hex>`, `<plaintext>` | `nostr_index` |
| `nostr_nip04_decrypt` | secp256k1 (NIP-06) | `<peer_pubkey_hex>`, `<ciphertext>` | `nostr_index` |
| `nostr_nip44_encrypt` | secp256k1 (NIP-06) | `<peer_pubkey_hex>`, `<plaintext>` | `nostr_index` |
| `nostr_nip44_decrypt` | secp256k1 (NIP-06) | `<peer_pubkey_hex>`, `<ciphertext>` | `nostr_index` |
| `nostr_get_public_key` | secp256k1 (NIP-06) | — | `role`, `role_path`, `format` |
| `nostr_sign_event` | secp256k1 (NIP-06) | `<event_json>` | `role`, `role_path` |
| `nostr_mine_event` | secp256k1 (NIP-06) | `<event_json>` | `role`, `role_path`, `difficulty`, `timeout_sec`, `threads` |
| `nostr_nip04_encrypt` | secp256k1 (NIP-06) | `<peer_pubkey_hex>`, `<plaintext>` | `role`, `role_path` |
| `nostr_nip04_decrypt` | secp256k1 (NIP-06) | `<peer_pubkey_hex>`, `<ciphertext>` | `role`, `role_path` |
| `nostr_nip44_encrypt` | secp256k1 (NIP-06) | `<peer_pubkey_hex>`, `<plaintext>` | `role`, `role_path` |
| `nostr_nip44_decrypt` | secp256k1 (NIP-06) | `<peer_pubkey_hex>`, `<ciphertext>` | `role`, `role_path` |
\* `scheme` is secp256k1-only: `"schnorr"` (default, BIP-340) or `"ecdsa"`.
@@ -262,6 +267,20 @@ The `otp` algorithm is a stream-style one-time pad, not a key-derivation scheme.
### 4.5 Examples
#### `get_info`
Returns signer metadata: `name`, `implementation`, `version`, `git_hash` (firmware only), `api`, and the supported `verbs` / `algorithms` arrays. Safe to call before the mnemonic is loaded — clients use it to feature-detect and to confirm which firmware is running on a connected device.
```json
{ "id": "0", "method": "get_info", "params": [] }
```
Response (CYD firmware):
```json
{ "id": "0", "result": { "name": "n_signer", "implementation": "cyd_esp32_2432s028", "version": "0.0.2", "git_hash": "dev", "api": "json-rpc-2.0", "verbs": ["get_info", "get_public_key", "sign", "verify", "encapsulate", "decapsulate", "derive_shared_secret", "derive", "encrypt", "decrypt", "nostr_get_public_key", "nostr_sign_event", "nostr_mine_event", "nostr_nip04_encrypt", "nostr_nip04_decrypt", "nostr_nip44_encrypt", "nostr_nip44_decrypt"], "algorithms": ["secp256k1", "ed25519", "x25519", "ml-dsa-65", "slh-dsa-128s", "ml-kem-768", "otp"] } }
```
#### `get_public_key`
```json
@@ -386,7 +405,7 @@ If no pad is bound at startup, the error is `-32601` `otp_pad_not_bound`.
#### `nostr_get_public_key`
```json
{ "id": "10", "method": "nostr_get_public_key", "params": [ { "nostr_index": 0 } ] }
{ "id": "10", "method": "nostr_get_public_key", "params": [ { "role": "main" } ] }
```
Response (default): a plain 64-hex-char secp256k1 public key string.
@@ -397,7 +416,7 @@ Response with `{"format":"structured"}` in options: `{"algorithm":"secp256k1","p
Serializes the event to canonical form (`[0, pubkey, created_at, kind, tags, content]`), SHA-256 hashes it to produce the event `id`, signs the hash with BIP-340 Schnorr, and returns the complete signed event.
```json
{ "id": "11", "method": "nostr_sign_event", "params": [ "<event_json>", { "nostr_index": 0 } ] }
{ "id": "11", "method": "nostr_sign_event", "params": [ "<event_json>", { "role": "main" } ] }
```
`<event_json>` is the unsigned event object:
@@ -415,7 +434,7 @@ Mines NIP-13 proof-of-work (adds a `nonce` tag) and signs the event in one step.
{
"id": "12",
"method": "nostr_mine_event",
"params": [ "<event_json>", { "difficulty": 20, "threads": 4, "timeout_sec": 30, "nostr_index": 0 } ]
"params": [ "<event_json>", { "difficulty": 20, "threads": 4, "timeout_sec": 30, "role": "main" } ]
}
```
@@ -444,8 +463,8 @@ Errors:
NIP-04 encryption (deprecated in Nostr but still widely used): ECDH + AES-256-CBC, base64 payload.
```json
{ "id": "13", "method": "nostr_nip04_encrypt", "params": [ "<peer_pubkey_hex>", "<plaintext>", { "nostr_index": 0 } ] }
{ "id": "14", "method": "nostr_nip04_decrypt", "params": [ "<peer_pubkey_hex>", "<ciphertext>", { "nostr_index": 0 } ] }
{ "id": "13", "method": "nostr_nip04_encrypt", "params": [ "<peer_pubkey_hex>", "<plaintext>", { "role": "main" } ] }
{ "id": "14", "method": "nostr_nip04_decrypt", "params": [ "<peer_pubkey_hex>", "<ciphertext>", { "role": "main" } ] }
```
`encrypt` returns the NIP-04 ciphertext string; `decrypt` returns the plaintext string.
@@ -455,8 +474,8 @@ NIP-04 encryption (deprecated in Nostr but still widely used): ECDH + AES-256-CB
NIP-44 encryption (current Nostr standard): ECDH + HKDF + ChaCha20-Poly1305 + specific payload format.
```json
{ "id": "15", "method": "nostr_nip44_encrypt", "params": [ "<peer_pubkey_hex>", "<plaintext>", { "nostr_index": 0 } ] }
{ "id": "16", "method": "nostr_nip44_decrypt", "params": [ "<peer_pubkey_hex>", "<ciphertext>", { "nostr_index": 0 } ] }
{ "id": "15", "method": "nostr_nip44_encrypt", "params": [ "<peer_pubkey_hex>", "<plaintext>", { "role": "main" } ] }
{ "id": "16", "method": "nostr_nip44_decrypt", "params": [ "<peer_pubkey_hex>", "<ciphertext>", { "role": "main" } ] }
```
`encrypt` returns the NIP-44 ciphertext string; `decrypt` returns the plaintext string.
@@ -467,11 +486,68 @@ The `nostr_*` verbs select a secp256k1 NIP-06 key via the options object. Suppor
| Selector | Meaning |
|----------------|--------------------------------------------------|
| `nostr_index` | NIP-06 index `n` → path `m/44'/1237'/<n>'/0/0` |
| `role` | Name of a pre-registered role entry |
| `role_path` | Full BIP-44 derivation path (must match a registered role) |
| `role` | Name of a pre-registered role entry (required) |
| `role_path` | Full BIP-44 derivation path (required) |
Selector resolution order: `role``nostr_index``role_path` → default role `main`. Conflicting selectors are rejected with `ambiguous_role_selector` (1001). The role's `(purpose, curve)` must be `(nostr, secp256k1)` — any other combination is rejected with `purpose_mismatch` (1004) or `curve_mismatch` (1005).
**Selector resolution**: both `role` and `role_path` are required together — they form a single combined selector. The server verifies that the supplied `role_path` matches the role's registered template (expanding any wildcard). There is no resolution order and no default role: omitting either field is rejected (`2008 role_required` / `2009 path_required`). The role's `(purpose, curve)` must be `(nostr, secp256k1)` — any other combination is rejected with `purpose_mismatch` (1004) or `curve_mismatch` (1005).
#### Named path-roles
In the interactive wizard, you define **named path-roles** that bind a role name (which acts as an access token for clients) to a derivation path template. The derivation path template is hidden from clients — they only know the role name and send the full concrete `role_path` with each request.
The wizard presents a **preset menu** of 10 options covering the common role types. You can still define custom roles manually via the "Custom path" option.
```
Wizard preset menu:
1. Standard Nostr (NIP-06): secp256k1, m/44'/1237'/0'/0/0
2. Standard Nostr range: secp256k1, m/44'/1237'/*'/0/0
3. Nostr agent range (hardened): secp256k1, m/44'/1237'/*'/1'/0'
4. SSH role: ed25519, m/44'/102001'/0'/0'/0'
5. Age/x25519 role: x25519, m/44'/102002'/0'/0'/0'
6. ML-DSA-65 role: post-quantum signatures, m/44'/102003'/0'/0'/0'
7. SLH-DSA-128s role: post-quantum signatures, m/44'/102004'/0'/0'/0'
8. ML-KEM-768 role: post-quantum KEM, m/44'/102005'/0'/0'/0'
9. OTP role (one-time pad encryption)
10. Custom path
```
Purpose is auto-detected from the path prefix (e.g. `m/44'/1237'` → nostr, `m/44'/102001'` → ssh). The path template is pre-filled from the chosen preset and can be edited inline with arrow keys, backspace, and delete.
**Path template syntax:**
- **Wildcard**: `m/44'/1237'/*'/0'/0'` — any non-negative integer, hardened. No range limit.
- **Range**: `m/44'/1237'/0-3/1/0` — index 0..3, hardened if segment ends with `'` (e.g. `0-3'`)
- **Set**: `m/44'/1237'/1+34+54/1/0` — specific indices 1, 34, 54
- **Fixed path**: `m/44'/1237'/0'/0/0` — no variable segment, single fixed key
- The first segment that is a plain number, range (`N-M`), set (`A+B+C`), or wildcard (`*`) becomes the variable. Segments with `'` (like `44'`, `1237'`) are treated as literal hardened constants.
**`requires_approval`**: Each named path-role is marked in the wizard as requiring explicit approval at the signer terminal before any operation is performed (`Requires approval? [y/N]`). Roles with `requires_approval=false` skip the prompt — the role name itself acts as a password: any caller that knows the role name and supplies a matching `role_path` is served without attendant interaction. Roles with `requires_approval=true` always prompt the attendant.
Clients request keys by supplying both `role` and the full concrete `role_path`:
```json
{"id":"1","method":"nostr_get_public_key","params":[{"role":"myrole","role_path":"m/44'/1237'/0'/1/0"}]}
```
→ derives `m/44'/1237'/0'/1/0`, verified against the `myrole` template.
```json
{"id":"2","method":"nostr_get_public_key","params":[{"role":"myrole","role_path":"m/44'/1237'/5'/1/0"}]}
```
`2003 path_not_allowed` (5 is outside the registered template, if the template was a fixed path or limited range).
```json
{"id":"3","method":"nostr_get_public_key","params":[{"role":"unknown","role_path":"m/44'/1237'/0'/0/0"}]}
```
`1002 unknown_role` (name not registered).
```json
{"id":"4","method":"nostr_get_public_key","params":[{"role":"myrole"}]}
```
`2009 path_required` (`role_path` is required).
```json
{"id":"5","method":"nostr_get_public_key","params":[{"role_path":"m/44'/1237'/0'/0/0"}]}
```
`2008 role_required` (`role` is required when using `role_path`).
### 4.7 Pre-approval
@@ -485,10 +561,10 @@ nsigner --preapprove caller=uid:1000,algorithm=ml-kem-768,index=0,verb=decapsula
Nostr (role-based):
```bash
nsigner --preapprove caller=uid:1000,nostr_index=0,verb=nostr_sign_event,nostr_get_public_key
nsigner --preapprove caller=uid:1000,role=main,verb=nostr_sign_event,nostr_get_public_key
```
A `*` wildcard matches any caller, role, or verb. Index ranges use `min-max` syntax. Unmatched requests fall through to the default policy (prompt for same-uid, deny for others).
A `*` wildcard matches any caller, role, or verb. Unmatched requests fall through to the default policy (prompt for same-uid, deny for others).
## 5. Transports
@@ -518,7 +594,7 @@ curl -s -X POST http://127.0.0.1:11111/ -H 'Content-Type: application/json' \
Sign a Nostr event:
```bash
curl -s -X POST http://127.0.0.1:11111/ -H 'Content-Type: application/json' \
-d '{"id":"1","method":"nostr_sign_event","params":[{"pubkey":"...","created_at":1234567890,"kind":1,"tags":[],"content":"hello"},{"nostr_index":0}]}'
-d '{"id":"1","method":"nostr_sign_event","params":[{"pubkey":"...","created_at":1234567890,"kind":1,"tags":[],"content":"hello"},{"role":"main"}]}'
```
OTP encrypt:
@@ -536,7 +612,7 @@ nsigner --socket-name nsigner client \
# Sign a Nostr event
nsigner --socket-name nsigner client \
'{"id":"2","method":"nostr_sign_event","params":[{"pubkey":"...","created_at":1234567890,"kind":1,"tags":[],"content":"hello"},{"nostr_index":0}]}'
'{"id":"2","method":"nostr_sign_event","params":[{"pubkey":"...","created_at":1234567890,"kind":1,"tags":[],"content":"hello"},{"role":"main"}]}'
# ed25519 sign
nsigner --socket-name nsigner client \
@@ -661,16 +737,22 @@ nsigner --listen unix --socket-name nsigner --bridge-source-trusted
### 7.2 Send a request (client mode)
From another terminal, target the signer by its socket name:
The standalone `nsigner_client` binary is the recommended client. See [`client/n_signer_client_README.md`](client/n_signer_client_README.md) for full documentation.
```bash
nsigner --socket-name nsigner_hairy_dog client '{"id":"1","method":"nostr_get_public_key","params":[]}'
nsigner_client --role main --path "m/44'/1237'/0'/0/0" get-public-key
```
If only one signer is running you can omit the override and the client will use the default discovery rule.
If only one signer is running you can omit the `--socket-name` override and the client will use the default discovery rule.
Example signing request:
```bash
nsigner -n nsigner_hairy_dog client '{"id":"2","method":"nostr_sign_event","params":["<event_json>",{"role":"main"}]}'
nsigner_client --role main --path "m/44'/1237'/0'/0/0" sign-event '<event_json>'
```
The raw `nsigner client` subcommand (sending a hand-built JSON-RPC object over the socket) is still available for scripting:
```bash
nsigner --socket-name nsigner_hairy_dog client '{"id":"2","method":"nostr_sign_event","params":["<event_json>",{"role":"main","role_path":"m/44'"'"'1237'"'"'/0'"'"'/0'"'"'/0"}]}'
```
### 7.3 List running signers
@@ -679,25 +761,27 @@ nsigner -n nsigner_hairy_dog client '{"id":"2","method":"nostr_sign_event","para
nsigner list
```
Prints the abstract socket names of any currently running `nsigner` instances, e.g.:
Prints the names of any currently running `nsigner` instances, e.g.:
```text
@nsigner_hairy_dog
@nsigner_brave_canyon
nsigner_hairy_dog
nsigner_brave_canyon
```
`nsigner_client list` is an equivalent alternative that uses the same discovery mechanism.
### 7.4 Example session
Terminal A:
```text
$ nsigner
[unlock] enter mnemonic:
System is ready and waiting for connections on @nsigner_hairy_dog.
[prompt] caller=uid:1000 method=nostr_sign_event role=main -> allow? (y/n)
System is ready and waiting for connections on nsigner_hairy_dog.
[prompt] caller=uid:1000 method=nostr_sign_event role=main path=m/44'/1237'/0'/0/0 -> allow? (y/n)
```
Terminal B:
```text
$ nsigner --socket-name nsigner_hairy_dog client '{"id":"2","method":"nostr_sign_event","params":["<event_json>",{"role":"main"}]}'
$ nsigner_client --role main --path "m/44'/1237'/0'/0/0" sign-event '<event_json>'
{"id":"2","result":"<signed_event_json>"}
```
@@ -723,3 +807,9 @@ Static build:
./build_static.sh
./build/nsigner_static_x86_64 --version
```
Client build (`nsigner_client`):
```bash
make clients
```
See [`client/n_signer_client_README.md`](client/n_signer_client_README.md) for client build details.
+254
View File
@@ -0,0 +1,254 @@
# n_signer Security Audit — Consolidated Remediation Report
**Date:** 2026-08-13
**Scope:** Full static security audit of [`src/`](../src/), [`client/`](../client/), [`libotppad/`](../libotppad/), build configuration, and entropy/key-derivation paths
**Result:** 8 findings identified, all remediated and verified
---
## Executive Summary
A comprehensive security audit of the `n_signer` codebase identified **8 security findings** across memory safety, network parsing, authentication, build hardening, and entropy/key-derivation. All findings have been remediated, code-reviewed, and verified against the existing test suite.
| Severity | Count | Status |
|----------|-------|--------|
| High | 2 | ✅ All Remediated |
| Medium | 5 | ✅ All Remediated |
| Low | 1 | ✅ All Remediated |
| **Total** | **8** | **All Fixed** |
---
## Findings and Remediations
### F-001: mlock Failure Silently Degraded to Pageable Memory
| | |
|---|---|
| **Severity** | Medium |
| **File** | [`src/secure_mem.c`](../src/secure_mem.c):762798 |
| **Status** | ✅ Remediated |
**Problem.** [`secure_buf_alloc()`](../src/secure_mem.c:762) called `mlock()` to pin secret material (mnemonic, private keys) in RAM. On failure (e.g., `RLIMIT_MEMLOCK` exhausted, missing `CAP_IPC_LOCK`), it printed a warning and **returned success with the buffer unlocked**. No caller checked `buf->locked`, so the process continued with secrets in pageable memory — silently undermining the "crash = total wipe" and "no filesystem footprint" guarantees. An attacker with disk access after the fact could recover key material from swap.
**Fix.** mlock failure is now **fatal by default**. The function prints a diagnostic with `strerror(errno)` and returns `-1`, causing startup to abort. A new opt-in escape hatch, `secure_buf_allow_unlocked()`, is wired to the `--allow-unlocked-memory` CLI flag in [`src/main.c`](../src/main.c):3653 for development/container environments where `mlock` is unavailable.
**Files changed:**
- [`src/secure_mem.c`](../src/secure_mem.c) — fatal-by-default logic, `secure_buf_allow_unlocked()`, added `<errno.h>`
- [`src/main.c`](../src/main.c) — `--allow-unlocked-memory` argument parsing + declaration
---
### F-002: HTTP Content-Length Parsed with `atol()` — No Error Detection
| | |
|---|---|
| **Severity** | Medium |
| **File** | [`src/http_listener.c`](../src/http_listener.c):75163 |
| **Status** | ✅ Remediated |
**Problem.** The HTTP request parser read `Content-Length` using `atol()`, which has **no error detection**: it returns `0` for non-numeric input (indistinguishable from a real `0`), and silently truncates values exceeding `LONG_MAX`. The value was stored in a signed `long` and compared against a `size_t` limit, creating signed/unsigned confusion. A `Content-Length` near `LONG_MAX` could trigger a giant allocation attempt (DoS via OOM or NULL-deref crash).
**Fix.** Replaced `atol()` with `strtoull()` and full validation:
- Rejects empty/non-numeric values (`endptr == p`)
- Rejects trailing garbage (only whitespace/CR allowed after digits)
- Rejects values exceeding `SIZE_MAX`
- Changed `content_length` from `long` to `size_t`, eliminating signed/unsigned confusion
- Added a `has_content_length` flag to distinguish "missing header" from "zero length"
**Files changed:**
- [`src/http_listener.c`](../src/http_listener.c) — safe parsing, type fix, drain loop type fix
---
### F-003: Auth Envelope Nonce Cache Replay After Wrap
| | |
|---|---|
| **Severity** | **High** |
| **Files** | [`src/auth_envelope.h`](../src/auth_envelope.h), [`src/auth_envelope.c`](../src/auth_envelope.c) |
| **Status** | ✅ Remediated |
**Problem.** Replay protection used a **bounded FIFO cache of 1024 event IDs** ([`AUTH_NONCE_CACHE_SIZE`](../src/auth_envelope.h):10). When full, the oldest entry was evicted (circular overwrite). An attacker who captured 1024 valid auth envelopes could replay any of them after the cache wrapped — the evicted nonce would no longer be detected as a duplicate. Combined with the 30-second timestamp skew window, this allowed impersonation of any previously-seen caller.
**Fix.** Replaced the bounded FIFO cache with a **hybrid per-pubkey replay tracker**:
1. **Monotonic timestamp per pubkey** — tracks the highest `created_at` seen for each of up to 64 pubkeys. Any envelope with `created_at < max_seen` is rejected as a replay. This has **no wrap-around weakness**.
2. **Event ID set for the current second** — because `created_at` has 1-second granularity, a per-(pubkey, second) set of up to 32 event IDs allows multiple legitimate concurrent requests within the same second while still rejecting exact duplicates.
3. When `created_at > max_seen`, the event ID set is cleared and the timestamp advances.
The initial monotonic-only version was caught by the existing test suite ([`tests/test_auth_envelope.c`](../tests/test_auth_envelope.c)) which builds multiple same-second requests — the hybrid design passes all 13 tests.
**Files changed:**
- [`src/auth_envelope.h`](../src/auth_envelope.h) — new `auth_pubkey_entry_t` structure with `max_created_at` + `event_ids[]`
- [`src/auth_envelope.c`](../src/auth_envelope.c) — new `auth_nonce_cache_check_and_update()` implementing the hybrid check; event ID extracted from the signed envelope's `id` field
---
### F-004: OTP Binary Header Checksum Parsed with `sscanf` — Return Value Ignored
| | |
|---|---|
| **Severity** | Low |
| **File** | [`src/otp_pad.c`](../src/otp_pad.c):408416 |
| **Status** | ✅ Remediated |
**Problem.** When building a binary `.otp` output header, the hex pad checksum was converted to bytes using `sscanf("%02x")` in a loop, but the **return value was never checked**. If the checksum string were ever malformed, `sscanf` would leave the destination variable uninitialized, producing garbage in the output header.
**Fix.** Added a return-value check: if `sscanf` does not return exactly 1, the function zeroizes the scratch buffer and returns an error. (An earlier version of this fix incorrectly called `free(blob)` before `blob` was declared — this was caught in code review and corrected.)
**Files changed:**
- [`src/otp_pad.c`](../src/otp_pad.c) — `sscanf` return value checked with proper error cleanup
---
### F-005: Missing Compiler Hardening Flags
| | |
|---|---|
| **Severity** | Medium |
| **File** | [`Makefile`](../Makefile):110 |
| **Status** | ✅ Remediated |
**Problem.** The build used only `-Wall -Wextra -Os` with no exploit-mitigation flags. The resulting binary had no stack canaries, no `_FORTIFY_SOURCE` bounds checking, no PIE (fixed load address — trivial ROP), writable GOT (no RELRO), and a potentially executable stack. For a program that parses untrusted network input while holding signing keys, these gaps significantly raise the impact of any memory-corruption bug.
**Fix.** Added the standard hardening flag set to `CFLAGS` and `LDFLAGS`:
- `-fstack-protector-strong` — stack canaries
- `-D_FORTIFY_SOURCE=2` — compile-time + runtime bounds checking for libc functions
- `-fPIE` / `-pie` — position-independent executable (ASLR for code)
- `-Wl,-z,relro -Wl,-z,now` — full RELRO (read-only GOT after startup)
- `-Wl,-z,noexecstack` — non-executable stack (NX)
- `-fstack-clash-protection` — stack-clash probing
**Verification.** The rebuilt binary is confirmed as `ELF 64-bit LSB pie executable`. Notably, the new `-fstack-protector-strong` flag **immediately caught a pre-existing latent buffer overflow** in [`tests/test_selector.c`](../tests/test_selector.c) (stack smashing detected at runtime) — a bug that was previously silent. This validates the value of the hardening flags.
**Files changed:**
- [`Makefile`](../Makefile) — hardening flags in `CFLAGS` and `LDFLAGS`
---
### F-006: RP2040 Fallback RNG Uses Cryptographically Weak xorshift32
| | |
|---|---|
| **Severity** | **High** |
| **File** | [`firmware/kb2040_hidden_signer/src/platform/rp2040.c`](../firmware/kb2040_hidden_signer/src/platform/rp2040.c):3178 |
| **Status** | ✅ Remediated |
**Problem.** [`nostr_platform_random()`](../firmware/kb2040_hidden_signer/src/platform/rp2040.c:31) is the sole entropy source for the KB2040 hidden signer, used to generate private keys, mnemonic entropy, secp256k1 context randomization, NIP-04 IVs, and NIP-44 nonces. When the Pico SDK's hardware RNG (`get_rand_32()`) is unavailable, it fell through to a **deterministic xorshift32 PRNG** seeded from a hardcoded constant XOR'd with `micros()`, `millis()`, a stack address, and ADC temperature sensor readings. xorshift32 is not cryptographically secure — its 32-bit state is trivially brute-forceable. An attacker who observes boot timing could reconstruct all keys.
**Fix.** Removed the xorshift32 fallback entirely. If `get_rand_32()` is unavailable, the function now returns `-1` and refuses to generate keys. The Pico SDK's ring-oscillator-based RNG is available on all official RP2040 boards. The ADC and Arduino timing code was also removed since it was only used to seed the xorshift.
**Files changed:**
- [`firmware/kb2040_hidden_signer/src/platform/rp2040.c`](../firmware/kb2040_hidden_signer/src/platform/rp2040.c) — removed xorshift32 fallback, fail closed on missing `get_rand_32()`
---
### F-007: PQ DRBG is Not a NIST SP 800-90A Compliant Construction
| | |
|---|---|
| **Severity** | Medium |
| **File** | [`src/pq_drbg.c`](../src/pq_drbg.c):1134 |
| **Status** | ✅ Remediated |
**Problem.** The PQ deterministic DRBG uses a custom `SHAKE-256(seed || counter)` construction rather than a NIST SP 800-90A DRBG. While cryptographically sound for single-shot keygen, it had issues: (1) the buffer-size comment confused SHAKE-256's rate (136 bytes) with SHAKE-128's rate (168 bytes); (2) the non-standard nature was documented but the rationale for why it's acceptable could be clearer.
**Fix.** Fixed the rate comment to correctly explain that 168 is the requested output length, not the SHAKE-256 rate (136 bytes). Strengthened the file header documentation with a detailed security argument listing 5 reasons why this non-standard construction is acceptable for this use case. Domain separation across algorithm types is not needed because the DRBG is initialized once per keygen and zeroized after — different algorithm types use different seeds.
**Files changed:**
- [`src/pq_drbg.c`](../src/pq_drbg.c) — fixed comment, strengthened documentation
---
### F-008: SLH-DSA-128s SK.prf Used as Both PRF Key and DRBG Seed
| | |
|---|---|
| **Severity** | Medium |
| **File** | [`src/pq_crypto.c`](../src/pq_crypto.c):14571471 |
| **Status** | ✅ Remediated |
**Problem.** In the SLH-DSA-128s signing path, `SK.prf` (bytes 16..31 of the secret key) was used for two distinct purposes: (1) as the PRF key for `PRF_msg()` per FIPS 205, and (2) as the raw seed for the deterministic DRBG that produces `opt_rand`. This dual use was non-standard — if the DRBG output were ever compromised, `SK.prf` would also be compromised, breaking the `PRF_msg` security guarantee.
**Fix.** Replaced the direct `pq_drbg_init(sk_prf, ...)` call with a domain-separated derivation:
```c
drbg_seed = HMAC-SHA256(SK.prf, "slh-dsa-drbg-seed")
pq_drbg_init(drbg_seed, 32)
```
This ensures that even if the DRBG output is somehow compromised, `SK.prf` remains secret and `PRF_msg` remains secure. The HMAC key is `SK.prf` (16 bytes), the message is the ASCII string `"slh-dsa-drbg-seed"`, and the output is a 32-byte DRBG seed that is zeroized after initialization.
**Files changed:**
- [`src/pq_crypto.c`](../src/pq_crypto.c):14571471 — domain-separated DRBG seed from SK.prf via HMAC-SHA256
---
## Post-Remediation Defects Caught in Review
During code review of the initial fixes, 5 defects were identified and corrected before final verification:
| # | Defect | File | Resolution |
|---|--------|------|-----------|
| 1 | `errno` used without `#include <errno.h>` (compile error) | [`src/secure_mem.c`](../src/secure_mem.c) | Added include |
| 2 | `free(blob)` referenced before `blob` was declared (compile error) | [`src/otp_pad.c`](../src/otp_pad.c) | Removed erroneous `free()`; only `secure_memzero` needed on that path |
| 3 | Duplicated pubkey validation block (dead code) | [`src/auth_envelope.c`](../src/auth_envelope.c) | Removed duplicate |
| 4 | `secure_buf_allow_unlocked()` not declared in main.c's headerless block (compile error) | [`src/main.c`](../src/main.c) | Added declaration |
| 5 | Monotonic-only timestamp rejected same-second requests (test failure) | [`src/auth_envelope.c`](../src/auth_envelope.c) | Upgraded to hybrid timestamp + event-ID design |
---
## Verification
### Build
- Compiles cleanly with all hardening flags enabled
- Output binary confirmed as PIE: `ELF 64-bit LSB pie executable, x86-64`
### Test Suite
| Test | Result |
|------|--------|
| `test_auth_envelope` | ✅ 13/13 passed (validates F-003 hybrid design) |
| `test_mnemonic` | ✅ All passed |
| `test_role_table` | ✅ All passed |
| `test_enforcement` | ✅ 10/10 passed |
| `test_policy` | ✅ 43/43 passed |
| `test_socket_name` | ✅ All passed |
| `test_mnemonic_input` | ✅ All passed |
| `test_path_whitelist` | ✅ 40/41 (1 pre-existing failure, unrelated) |
| `test_selector` | ⚠️ Stack smashing detected — **hardening caught a pre-existing latent bug** (unrelated to remediations) |
| `test_ml_dsa_65` | ✅ 26/26 passed |
| `test_ml_kem_768` | ✅ 29/29 passed |
| `test_pq_crypto` | ✅ All passed |
---
## Remaining Recommendations (Non-Blocking)
These items were noted during the audit but are not security findings:
1. **Fix the latent `test_selector` buffer overflow** now exposed by `-fstack-protector-strong`. This is a pre-existing bug in the test code, not in production code.
2. **Apply the same hardening flags to the musl-static build** in [`Dockerfile.alpine-musl`](../Dockerfile.alpine-musl) / [`build_static.sh`](../build_static.sh) (verify musl-gcc supports `-fstack-clash-protection`, GCC 8+).
3. **Pin vendored dependency versions** (cJSON, nostr_core_lib, PQClean, secp256k1) to specific commits and track known CVEs.
4. **Add fuzz testing** for the HTTP parser and transport frame parser.
5. **Document the `--allow-unlocked-memory` flag** in the README security section.
---
## Files Changed Summary
| File | Finding(s) |
|------|-----------|
| [`src/secure_mem.c`](../src/secure_mem.c) | F-001 |
| [`src/main.c`](../src/main.c) | F-001 (flag wiring) |
| [`src/http_listener.c`](../src/http_listener.c) | F-002 |
| [`src/auth_envelope.h`](../src/auth_envelope.h) | F-003 |
| [`src/auth_envelope.c`](../src/auth_envelope.c) | F-003 |
| [`src/otp_pad.c`](../src/otp_pad.c) | F-004 |
| [`Makefile`](../Makefile) | F-005 |
| [`firmware/kb2040_hidden_signer/src/platform/rp2040.c`](../firmware/kb2040_hidden_signer/src/platform/rp2040.c) | F-006 |
| [`firmware/kb2040_hidden_signer/src/nostr_core/nip006.c`](../firmware/kb2040_hidden_signer/src/nostr_core/nip006.c) | F-006 (propagation) |
| [`src/pq_drbg.c`](../src/pq_drbg.c) | F-007 |
| [`src/pq_crypto.c`](../src/pq_crypto.c) | F-008 |
+103 -8
View File
@@ -1,21 +1,26 @@
#!/bin/bash
# Build fully static MUSL binary for nsigner using Alpine Docker
#
# Speed optimization: if nothing changed since the last successful build,
# skip the Docker build entirely and reuse the existing binaries.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD_DIR="$SCRIPT_DIR/build"
DOCKERFILE="$SCRIPT_DIR/Dockerfile.alpine-musl"
HASH_FILE="$BUILD_DIR/.nsigner_build_hash"
TARGET_ARCH=""
FORCE=0
while [[ $# -gt 0 ]]; do
case "$1" in
--arch)
if [[ -z "${2:-}" ]]; then
echo "ERROR: --arch requires a value"
echo "Usage: $0 [--arch <x86_64|arm64|armv7>]"
echo "Usage: $0 [--arch <x86_64|arm64|armv7>] [--force]"
exit 1
fi
case "$2" in
@@ -30,9 +35,13 @@ while [[ $# -gt 0 ]]; do
esac
shift 2
;;
--force)
FORCE=1
shift
;;
*)
echo "ERROR: Unknown argument '$1'"
echo "Usage: $0 [--arch <x86_64|arm64|armv7>]"
echo "Usage: $0 [--arch <x86_64|arm64|armv7>] [--force]"
exit 1
;;
esac
@@ -70,14 +79,17 @@ case "$ARCH" in
x86_64)
PLATFORM="linux/amd64"
OUTPUT_NAME="nsigner_static_x86_64"
CLIENT_NAME="nsigner_client_static_x86_64"
;;
arm64)
PLATFORM="linux/arm64"
OUTPUT_NAME="nsigner_static_arm64"
CLIENT_NAME="nsigner_client_static_arm64"
;;
armv7)
PLATFORM="linux/arm/v7"
PLATFORM="linux/v7"
OUTPUT_NAME="nsigner_static_armv7"
CLIENT_NAME="nsigner_client_static_armv7"
;;
*)
echo "ERROR: Unsupported target architecture '$ARCH'"
@@ -103,8 +115,65 @@ echo "Project root: $SCRIPT_DIR"
echo "Dockerfile: $DOCKERFILE"
echo "Platform: $PLATFORM"
echo "Output: $BUILD_DIR/$OUTPUT_NAME"
echo "Client: $BUILD_DIR/$CLIENT_NAME"
echo ""
# ---- Change detection ----
# Compute a hash of all files that feed into the Docker build.
# If the hash matches the last successful build and the output binaries
# exist, skip the Docker build entirely.
compute_source_hash() {
{
# Dockerfile itself
cat "$DOCKERFILE"
# .dockerignore
cat "$SCRIPT_DIR/.dockerignore" 2>/dev/null || true
# All source files
find "$SCRIPT_DIR/src" "$SCRIPT_DIR/client" "$SCRIPT_DIR/libotppad" \
"$SCRIPT_DIR/resources/tui_continuous" "$SCRIPT_DIR/resources/pqclean" \
-type f -not -path '*/.git/*' 2>/dev/null | sort | xargs cat 2>/dev/null
# nostr_core_lib source (exclude .git, backups, bare repos, examples, tests)
find "$SCRIPT_DIR/resources/nostr_core_lib" \
-type f \
-not -path '*/.git/*' \
-not -path '*/rewrite_mirror/*' \
-not -path '*/verify_remote_size*' \
-not -path '*/backups/*' \
-not -path '*/examples/*' \
-not -path '*/tests/*' \
-not -path '*/Trash/*' \
-not -path '*/node_modules/*' \
-not -path '*/nips/*' \
-not -path '*/nak/*' \
-not -path '*/nostr-tools/*' \
-not -path '*/libsodium/*' \
-not -path '*/monocypher*' \
-not -path '*/tiny-AES-c/*' \
-not -path '*/blossom/*' \
-not -path '*/ndk/*' \
-not -path '*/cline_history/*' \
2>/dev/null | sort | xargs cat 2>/dev/null
} | sha256sum | awk '{print $1}'
}
CURRENT_HASH="$(compute_source_hash)"
OUTPUT_PATH="$BUILD_DIR/$OUTPUT_NAME"
CLIENT_PATH="$BUILD_DIR/$CLIENT_NAME"
if [[ "$FORCE" -eq 0 ]] && \
[[ -f "$OUTPUT_PATH" ]] && \
[[ -f "$CLIENT_PATH" ]] && \
[[ -f "$HASH_FILE" ]] && \
[[ "$(cat "$HASH_FILE" 2>/dev/null)" == "$CURRENT_HASH" ]]; then
echo "No changes detected since last successful build."
echo "Skipping Docker build. Existing binaries:"
echo " $OUTPUT_PATH"
echo " $CLIENT_PATH"
echo ""
echo "Use --force to rebuild anyway."
exit 0
fi
if [ "$ARCH" != "$HOST_ARCH" ]; then
echo "[0/3] Preparing buildx + QEMU for cross-architecture build"
if ! docker buildx inspect >/dev/null 2>&1; then
@@ -122,6 +191,10 @@ if [ "$ARCH" != "$HOST_ARCH" ]; then
fi
echo "[1/3] Building builder stage from project root context"
# Note: we no longer docker rmi before building. The buildx cache handles
# layer reuse, and the prune at the end prevents dangling images. Removing
# the image here forced a full --load re-export (~370MB) every time even
# when all layers were cache hits.
docker buildx build \
--platform "$PLATFORM" \
--target builder \
@@ -130,22 +203,44 @@ docker buildx build \
--load \
"$SCRIPT_DIR"
echo "[2/3] Extracting static binary"
echo "[2/3] Extracting static binaries"
CONTAINER_NAME="$(docker create "$IMAGE_TAG")"
docker cp "$CONTAINER_NAME:/build/nsigner_static" "$BUILD_DIR/$OUTPUT_NAME"
chmod +x "$BUILD_DIR/$OUTPUT_NAME"
strip "$BUILD_DIR/$OUTPUT_NAME" >/dev/null 2>&1 || true
echo "[3/3] Verifying static binary"
docker cp "$CONTAINER_NAME:/build/nsigner_client_static" "$BUILD_DIR/$CLIENT_NAME"
chmod +x "$BUILD_DIR/$CLIENT_NAME"
strip "$BUILD_DIR/$CLIENT_NAME" >/dev/null 2>&1 || true
echo "[3/3] Verifying static binaries"
file "$BUILD_DIR/$OUTPUT_NAME"
file "$BUILD_DIR/$CLIENT_NAME"
LDD_OUTPUT="$(ldd "$BUILD_DIR/$OUTPUT_NAME" 2>&1 || true)"
echo "$LDD_OUTPUT"
if echo "$LDD_OUTPUT" | grep -Eq "not a dynamic executable|statically linked"; then
echo "Static check: PASS"
echo "nsigner static check: PASS"
else
echo "Static check: WARNING (verify manually)"
echo "nsigner static check: WARNING (verify manually)"
fi
LDD_OUTPUT_CLIENT="$(ldd "$BUILD_DIR/$CLIENT_NAME" 2>&1 || true)"
echo "$LDD_OUTPUT_CLIENT"
if echo "$LDD_OUTPUT_CLIENT" | grep -Eq "not a dynamic executable|statically linked"; then
echo "nsigner_client static check: PASS"
else
echo "nsigner_client static check: WARNING (verify manually)"
fi
echo ""
echo "Build complete: $BUILD_DIR/$OUTPUT_NAME"
echo "Build complete:"
echo " $BUILD_DIR/$OUTPUT_NAME"
echo " $BUILD_DIR/$CLIENT_NAME"
# Record the source hash so the next run can skip if nothing changed.
echo "$CURRENT_HASH" > "$HASH_FILE"
# Prune stale build cache older than 24h to prevent unbounded cache growth
# from repeated buildx builds. Recent layers are kept for fast rebuilds.
docker builder prune -af --filter "until=24h" >/dev/null 2>&1 || true
+855
View File
@@ -0,0 +1,855 @@
/*
* n_signer_client.c — standalone Linux CLI for n_signer JSON-RPC API.
*
* Connects to a running n_signer process over its abstract UNIX socket
* (or TCP/serial/qrexec) and exposes the full verb surface over stdin/stdout
* so that signed events can be piped directly into `nak publish`.
*
* This client uses the high-level nostr_signer_t API from nostr_core_lib
* for all typed verbs. The per-verb cJSON-building logic lives in the
* library, not here. The CLI is mostly argv parsing + result printing.
*
* Build: make clients
* Usage: n_signer_client [global options] <verb> [verb args...]
*
* See client/n_signer_client_README.md for full documentation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include "nostr_common.h"
#include "nsigner_transport.h"
#include "nsigner_client.h"
#include "nostr_signer.h"
#include "../cjson/cJSON.h"
/* ------------------------------------------------------------------ */
/* Helpers */
/* ------------------------------------------------------------------ */
static void print_usage(FILE *fp, const char *prog) {
fprintf(fp,
"Usage: %s [global options] <verb> [verb args...]\n"
"\n"
"Global options:\n"
" -n, --socket-name <name> Abstract socket name (default: auto-discover)\n"
" --timeout <ms> Transport timeout (default 5000)\n"
" --tcp <host:port> TCP transport (requires --auth-privkey)\n"
" --serial <device> USB CDC-ACM serial transport\n"
" --qrexec <qube:svc> Qubes qrexec transport\n"
" --auth-privkey <hex> Auth envelope privkey (32 bytes hex)\n"
" --auth-label <text> Auth envelope label\n"
"\n"
"Selector options (for nostr_* verbs):\n"
" --role <name> Named path-role\n"
" --path <path> Full BIP-44 derivation path\n"
"\n"
"Algorithm options (for algorithm-based verbs):\n"
" -a, --algorithm <alg> secp256k1/ed25519/x25519/ml-dsa-65/\n"
" slh-dsa-128s/ml-kem-768/otp\n"
" --scheme <schnorr|ecdsa> secp256k1 sign/verify scheme (default schnorr)\n"
" --encoding <ascii|binary> OTP encoding (default ascii)\n"
" --format <plain|structured> get-public-key output (default plain)\n"
" --index <N> Algorithm derivation index\n"
"\n"
"Mine-event options:\n"
" --difficulty <N> Target leading zero bits\n"
" --threads <N> Mining threads (default 1)\n"
" --timeout-sec <N> Mining timeout in seconds\n"
"\n"
"Verbs:\n"
" list List running n_signer sockets\n"
" get-info\n"
" get-public-key\n"
" sign-event\n"
" mine-event\n"
" nip04-encrypt <peer-pubkey>\n"
" nip04-decrypt <peer-pubkey>\n"
" nip44-encrypt <peer-pubkey>\n"
" nip44-decrypt <peer-pubkey>\n"
" sign <msg-hex>\n"
" verify <msg-hex> <sig-hex>\n"
" derive <data>\n"
" encapsulate <peer-pubkey-hex>\n"
" decapsulate <ciphertext-hex>\n"
" derive-shared-secret <peer-pubkey-hex>\n"
" encrypt <plaintext>\n"
" decrypt <ciphertext>\n"
" call <method>\n"
"\n"
"Examples:\n"
" # List running n_signer sockets\n"
" %s list\n"
"\n"
" # Get a Nostr public key by role and path\n"
" %s --role main --path \"m/44'/1237'/0'/0/0\" get-public-key\n"
"\n"
" # Get a key by named path-role\n"
" %s --role role1 --path \"m/44'/1237'/1'/1/0\" get-public-key\n"
"\n"
" # Sign a Nostr event from stdin and pipe to nak for publishing\n"
" echo '{\"kind\":1,\"content\":\"hello world\",\"tags\":[],\"created_at\":1700000000}' \\\n"
" | %s --role main --path \"m/44'/1237'/0'/0/0\" sign-event | nak publish\n"
"\n"
" # Sign an event from argv\n"
" %s --role main --path \"m/44'/1237'/0'/0/0\" sign-event '{\"kind\":1,\"content\":\"hi\",\"tags\":[],\"created_at\":1700000000}'\n"
"\n"
" # Mine an event with proof-of-work (difficulty 20)\n"
" %s --role main --path \"m/44'/1237'/0'/0/0\" --difficulty 20 mine-event '{\"kind\":1,\"content\":\"mined\",\"tags\":[],\"created_at\":1700000000}'\n"
"\n"
" # NIP-44 encrypt then decrypt a round-trip\n"
" %s --role main --path \"m/44'/1237'/0'/0/0\" nip44-encrypt <peer-pubkey> 'secret message'\n"
" %s --role main --path \"m/44'/1237'/0'/0/0\" nip44-decrypt <peer-pubkey> '<ciphertext>'\n"
"\n"
" # Ed25519 sign (SSH-style)\n"
" %s --algorithm ed25519 --index 0 sign 68656c6c6f\n"
"\n"
" # Get signer metadata\n"
" %s get-info\n"
"\n"
" # Qubes qrexec: get the first pubkey from a signer in the nostr_signer qube\n"
" %s --qrexec nostr_signer:qubes.NsignerRpc --role nostr_range --path \"m/44'/1237'/0'/0/0\" get-public-key\n",
prog, prog, prog, prog, prog, prog, prog, prog, prog, prog, prog, prog);
}
/* Read one line from stdin (newline stripped). Returns malloc'd string or NULL on EOF/error. */
static char *read_stdin_line(void) {
size_t cap = 4096;
size_t len = 0;
char *buf = malloc(cap);
if (!buf) return NULL;
int c;
while ((c = fgetc(stdin)) != EOF && c != '\n') {
if (len + 1 >= cap) {
cap *= 2;
char *tmp = realloc(buf, cap);
if (!tmp) { free(buf); return NULL; }
buf = tmp;
}
buf[len++] = (char)c;
}
if (len == 0 && c == EOF) { free(buf); return NULL; }
buf[len] = '\0';
return buf;
}
/* Convert a hex string to raw bytes. Returns number of bytes written, or -1 on error. */
static int hex_to_bytes(const char *hex, unsigned char *out, size_t out_sz) {
size_t len = strlen(hex);
if (len % 2 != 0 || len / 2 > out_sz) return -1;
for (size_t i = 0; i < len / 2; i++) {
unsigned int byte;
if (sscanf(hex + 2 * i, "%2x", &byte) != 1) return -1;
out[i] = (unsigned char)byte;
}
return (int)(len / 2);
}
/* Parse "host:port" string. Returns 0 on success. */
static int parse_host_port(const char *s, char **out_host, int *out_port) {
const char *colon = strrchr(s, ':');
if (!colon || colon == s) return -1;
size_t host_len = (size_t)(colon - s);
*out_host = malloc(host_len + 1);
if (!*out_host) return -1;
memcpy(*out_host, s, host_len);
(*out_host)[host_len] = '\0';
char *end = NULL;
long p = strtol(colon + 1, &end, 10);
if (end == colon + 1 || *end != '\0' || p < 1 || p > 65535) {
free(*out_host);
*out_host = NULL;
return -1;
}
*out_port = (int)p;
return 0;
}
/* Parse "qube:service" string. Returns 0 on success. */
static int parse_qube_service(const char *s, char **out_qube, char **out_service) {
const char *colon = strchr(s, ':');
if (!colon || colon == s) return -1;
size_t qube_len = (size_t)(colon - s);
*out_qube = malloc(qube_len + 1);
if (!*out_qube) return -1;
memcpy(*out_qube, s, qube_len);
(*out_qube)[qube_len] = '\0';
*out_service = strdup(colon + 1);
if (!*out_service) { free(*out_qube); *out_qube = NULL; return -1; }
return 0;
}
/* ------------------------------------------------------------------ */
/* Result printing helper */
/* ------------------------------------------------------------------ */
/* Print a raw string result (from the *_result_json_out wrappers). */
static void print_result_str(const char *s) {
if (s) {
printf("%s\n", s);
} else {
printf("null\n");
}
}
/* ------------------------------------------------------------------ */
/* Transport setup helper */
/* ------------------------------------------------------------------ */
/* Opens a transport based on the CLI args. Returns 0 on success.
* On success, *out_transport is set (caller must not free if handed to signer). */
static int open_transport(const char *socket_name, int timeout_ms,
const char *tcp_arg, const char *serial_arg,
const char *qrexec_arg,
const char *auth_privkey_hex,
nsigner_transport_t **out_transport) {
int transport_count = (tcp_arg ? 1 : 0) + (serial_arg ? 1 : 0) + (qrexec_arg ? 1 : 0) + (socket_name ? 1 : 0);
if (transport_count > 1) {
fprintf(stderr, "error: --tcp, --serial, --qrexec, and --socket-name are mutually exclusive\n");
return -1;
}
*out_transport = NULL;
if (tcp_arg) {
if (!auth_privkey_hex) {
fprintf(stderr, "error: --tcp requires --auth-privkey\n");
return -1;
}
char *host = NULL;
int port = 0;
if (parse_host_port(tcp_arg, &host, &port) != 0) {
fprintf(stderr, "error: invalid --tcp format (expected host:port)\n");
return -1;
}
*out_transport = nsigner_transport_open_tcp(host, port, timeout_ms);
free(host);
if (!*out_transport) {
fprintf(stderr, "error: cannot open TCP transport to %s\n", tcp_arg);
return -1;
}
} else if (serial_arg) {
*out_transport = nsigner_transport_open_serial(serial_arg, timeout_ms);
if (!*out_transport) {
fprintf(stderr, "error: cannot open serial transport on %s\n", serial_arg);
return -1;
}
} else if (qrexec_arg) {
char *qube = NULL, *service = NULL;
if (parse_qube_service(qrexec_arg, &qube, &service) != 0) {
fprintf(stderr, "error: invalid --qrexec format (expected qube:service)\n");
return -1;
}
*out_transport = nsigner_transport_open_qrexec(qube, service, timeout_ms);
free(qube);
free(service);
if (!*out_transport) {
fprintf(stderr, "error: cannot open qrexec transport to %s\n", qrexec_arg);
return -1;
}
} else if (socket_name) {
*out_transport = nsigner_transport_open_unix(socket_name, timeout_ms);
if (!*out_transport) {
fprintf(stderr, "error: cannot open unix transport %s\n", socket_name);
return -1;
}
} else {
/* Auto-discover: enumerate abstract UNIX sockets */
char names[64][64];
int count = nsigner_transport_list_unix(names, 64);
if (count == 0) {
fprintf(stderr, "error: no n_signer sockets found. Is n_signer running?\n");
return -1;
}
if (count > 1) {
fprintf(stderr, "error: multiple n_signer sockets found. Use --socket-name to select one:\n");
for (int j = 0; j < count; j++) {
fprintf(stderr, " %s\n", names[j]);
}
return -1;
}
*out_transport = nsigner_transport_open_unix(names[0], timeout_ms);
if (!*out_transport) {
fprintf(stderr, "error: cannot open unix transport %s\n", names[0]);
return -1;
}
}
return 0;
}
/* ------------------------------------------------------------------ */
/* Main */
/* ------------------------------------------------------------------ */
int main(int argc, char **argv) {
/* ---- globals ---- */
const char *socket_name = NULL;
int timeout_ms = 5000;
const char *tcp_arg = NULL;
const char *serial_arg = NULL;
const char *qrexec_arg = NULL;
const char *auth_privkey_hex = NULL;
const char *auth_label = NULL;
/* ---- selectors (nostr verbs) ---- */
const char *role = NULL;
const char *path = NULL;
int has_index = 0;
int index_val = 0;
/* ---- algorithm options ---- */
const char *algorithm = NULL;
int alg_index = 0;
int has_alg_index = 0;
const char *scheme = NULL;
const char *encoding = NULL;
const char *format = NULL;
/* ---- mine-event options ---- */
int has_difficulty = 0;
int difficulty_val = 0;
int has_threads = 0;
int threads_val = 1;
int has_timeout_sec = 0;
int timeout_sec_val = 0;
const char *prog = argv[0];
/* ---- parse global options ---- */
int i = 1;
while (i < argc && argv[i][0] == '-') {
const char *arg = argv[i];
if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
print_usage(stderr, prog);
return 2;
}
if (strcmp(arg, "--socket-name") == 0 || strcmp(arg, "-n") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --socket-name requires an argument\n"); return 2; }
socket_name = argv[++i];
} else if (strcmp(arg, "--timeout") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --timeout requires an argument\n"); return 2; }
timeout_ms = atoi(argv[++i]);
if (timeout_ms <= 0) { fprintf(stderr, "error: --timeout must be positive\n"); return 2; }
} else if (strcmp(arg, "--tcp") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --tcp requires <host:port>\n"); return 2; }
tcp_arg = argv[++i];
} else if (strcmp(arg, "--serial") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --serial requires a device path\n"); return 2; }
serial_arg = argv[++i];
} else if (strcmp(arg, "--qrexec") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --qrexec requires <qube:service>\n"); return 2; }
qrexec_arg = argv[++i];
} else if (strcmp(arg, "--auth-privkey") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --auth-privkey requires a 32-byte hex key\n"); return 2; }
auth_privkey_hex = argv[++i];
} else if (strcmp(arg, "--auth-label") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --auth-label requires a label\n"); return 2; }
auth_label = argv[++i];
} else if (strcmp(arg, "--role") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --role requires a name\n"); return 2; }
role = argv[++i];
} else if (strcmp(arg, "--path") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --path requires a BIP-44 derivation path\n"); return 2; }
path = argv[++i];
} else if (strcmp(arg, "--index") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --index requires a number\n"); return 2; }
has_index = 1;
index_val = atoi(argv[++i]);
} else if (strcmp(arg, "--algorithm") == 0 || strcmp(arg, "-a") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --algorithm requires a name\n"); return 2; }
algorithm = argv[++i];
} else if (strcmp(arg, "--scheme") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --scheme requires schnorr or edsa\n"); return 2; }
scheme = argv[++i];
} else if (strcmp(arg, "--encoding") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --encoding requires ascii or binary\n"); return 2; }
encoding = argv[++i];
} else if (strcmp(arg, "--format") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --format requires plain or structured\n"); return 2; }
format = argv[++i];
} else if (strcmp(arg, "--difficulty") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --difficulty requires a number\n"); return 2; }
has_difficulty = 1;
difficulty_val = atoi(argv[++i]);
} else if (strcmp(arg, "--threads") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --threads requires a number\n"); return 2; }
has_threads = 1;
threads_val = atoi(argv[++i]);
} else if (strcmp(arg, "--timeout-sec") == 0) {
if (i + 1 >= argc) { fprintf(stderr, "error: --timeout-sec requires a number\n"); return 2; }
has_timeout_sec = 1;
timeout_sec_val = atoi(argv[++i]);
} else {
fprintf(stderr, "error: unknown option: %s\n", arg);
fprintf(stderr, "Try '%s --help' for usage.\n", prog);
return 2;
}
i++;
}
/* ---- verb ---- */
if (i >= argc) {
fprintf(stderr, "error: no verb specified\n");
fprintf(stderr, "Try '%s --help' for usage.\n", prog);
return 2;
}
const char *verb = argv[i++];
/* ---- verb args ---- */
const char *arg1 = (i < argc) ? argv[i++] : NULL;
const char *arg2 = (i < argc) ? argv[i++] : NULL;
/* ---- validate --index usage (algorithm-only now) ---- */
if (has_index && !algorithm) {
fprintf(stderr, "error: --index is only valid with --algorithm (for algorithm verbs)\n");
return 2;
}
/* ---- determine if this is an algorithm verb ---- */
int is_algorithm_verb = (algorithm != NULL);
/* ---- validate --role and --path for nostr verbs ---- */
int is_nostr_verb = (strcmp(verb, "get-public-key") == 0 ||
strcmp(verb, "sign-event") == 0 ||
strcmp(verb, "mine-event") == 0 ||
strcmp(verb, "nip04-encrypt") == 0 ||
strcmp(verb, "nip04-decrypt") == 0 ||
strcmp(verb, "nip44-encrypt") == 0 ||
strcmp(verb, "nip44-decrypt") == 0);
if (is_nostr_verb && !is_algorithm_verb) {
if (!role) {
fprintf(stderr, "error: --role is required for nostr verbs\n");
return 2;
}
if (!path) {
fprintf(stderr, "error: --path is required for nostr verbs\n");
return 2;
}
}
/* ---- nostr_init ---- */
if (nostr_init() != NOSTR_SUCCESS) {
fprintf(stderr, "error: failed to initialize crypto subsystem\n");
return 2;
}
/* ---- list verb (no connection needed) ---- */
if (strcmp(verb, "list") == 0) {
char names[64][64];
int count = nsigner_transport_list_unix(names, 64);
if (count == 0) {
printf("no n_signer sockets found\n");
} else {
for (int j = 0; j < count; j++) {
printf("%s\n", names[j]);
}
}
nostr_cleanup();
return 0;
}
/* ---- open transport ---- */
nsigner_transport_t *transport = NULL;
if (open_transport(socket_name, timeout_ms, tcp_arg, serial_arg, qrexec_arg,
auth_privkey_hex, &transport) != 0) {
nostr_cleanup();
return 2;
}
/* ---- create low-level client (owns transport) ---- */
nsigner_client_t *client = nsigner_client_new(transport);
if (!client) {
fprintf(stderr, "error: cannot create nsigner client\n");
transport->close(transport);
nostr_cleanup();
return 2;
}
transport = NULL; /* owned by client */
/* ---- create high-level signer from client (shares the connection) ---- */
nostr_signer_t *signer = nostr_signer_nsigner_from_client(client, role);
if (!signer) {
fprintf(stderr, "error: cannot create nsigner signer\n");
nsigner_client_free(client);
nostr_cleanup();
return 2;
}
/* signer now owns client; don't free it separately */
/* ---- set role_path selector for nostr verbs ---- */
if (is_nostr_verb && !is_algorithm_verb && path) {
if (nostr_signer_nsigner_set_role_path(signer, path) != NOSTR_SUCCESS) {
fprintf(stderr, "error: failed to set role_path\n");
nostr_signer_free(signer);
nostr_cleanup();
return 2;
}
}
/* ---- auth envelope (TCP) ---- */
if (auth_privkey_hex) {
unsigned char privkey[32];
if (hex_to_bytes(auth_privkey_hex, privkey, 32) != 32) {
fprintf(stderr, "error: --auth-privkey must be 32 bytes (64 hex chars)\n");
nostr_signer_free(signer);
nostr_cleanup();
return 2;
}
if (nostr_signer_nsigner_set_auth(signer, privkey, auth_label ? auth_label : "") != NOSTR_SUCCESS) {
fprintf(stderr, "error: failed to set auth envelope\n");
nostr_signer_free(signer);
nostr_cleanup();
return 2;
}
}
/* ---- resolve algorithm index ---- */
int eff_index = has_alg_index ? alg_index : (has_index ? index_val : 0);
int rc = 2;
char *result_str = NULL;
cJSON *result_obj = NULL;
/* ---- dispatch verbs via high-level library wrappers ---- */
if (strcmp(verb, "get-info") == 0) {
rc = nostr_signer_get_info(signer, &result_obj);
if (rc != NOSTR_SUCCESS) {
fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer));
goto cleanup;
}
char *json = cJSON_PrintUnformatted(result_obj);
if (json) { printf("%s\n", json); free(json); }
rc = 0;
} else if (strcmp(verb, "get-public-key") == 0) {
if (is_algorithm_verb) {
rc = nostr_signer_get_public_key_alg(signer, algorithm, eff_index, &result_str);
if (rc != NOSTR_SUCCESS) {
fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer));
goto cleanup;
}
print_result_str(result_str);
rc = 0;
} else if (format && strcmp(format, "structured") == 0) {
/* Structured format: use low-level client to pass the format option. */
cJSON *params = cJSON_CreateArray();
cJSON *opts = cJSON_CreateObject();
if (role) cJSON_AddStringToObject(opts, "role", role);
if (path) cJSON_AddStringToObject(opts, "role_path", path);
cJSON_AddStringToObject(opts, "format", "structured");
cJSON_AddItemToArray(params, opts);
cJSON *presult = NULL;
rc = nsigner_client_call(client, "nostr_get_public_key", params, &presult);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nsigner_client_last_error(client)); goto cleanup; }
if (cJSON_IsString(presult)) {
print_result_str(presult->valuestring);
} else if (presult) {
char *json = cJSON_PrintUnformatted(presult);
if (json) { printf("%s\n", json); free(json); }
}
cJSON_Delete(presult);
rc = 0;
} else {
char pubkey_hex[65];
rc = nostr_signer_get_public_key(signer, pubkey_hex);
if (rc != NOSTR_SUCCESS) {
fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer));
goto cleanup;
}
printf("%s\n", pubkey_hex);
rc = 0;
}
} else if (strcmp(verb, "sign-event") == 0) {
const char *event_json = arg1;
char *event_buf = NULL;
if (!event_json) {
event_buf = read_stdin_line();
if (!event_buf) {
fprintf(stderr, "error: no event JSON provided (pass as argument or pipe to stdin)\n");
goto cleanup;
}
event_json = event_buf;
}
cJSON *event = cJSON_Parse(event_json);
free(event_buf);
if (!event) {
fprintf(stderr, "error: failed to parse event JSON\n");
goto cleanup;
}
rc = nostr_signer_sign_event(signer, event, &result_obj);
cJSON_Delete(event);
if (rc != NOSTR_SUCCESS) {
fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer));
goto cleanup;
}
char *json = cJSON_PrintUnformatted(result_obj);
if (json) { printf("%s\n", json); free(json); }
rc = 0;
} else if (strcmp(verb, "mine-event") == 0) {
const char *event_json = arg1;
char *event_buf = NULL;
if (!event_json) {
event_buf = read_stdin_line();
if (!event_buf) {
fprintf(stderr, "error: no event JSON provided (pass as argument or pipe to stdin)\n");
goto cleanup;
}
event_json = event_buf;
}
cJSON *event = cJSON_Parse(event_json);
free(event_buf);
if (!event) {
fprintf(stderr, "error: failed to parse event JSON\n");
goto cleanup;
}
rc = nostr_signer_mine_event(signer, event,
has_difficulty ? difficulty_val : 0,
has_timeout_sec ? timeout_sec_val : 0,
has_threads ? threads_val : 1,
&result_obj);
cJSON_Delete(event);
if (rc != NOSTR_SUCCESS) {
fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer));
goto cleanup;
}
char *json = cJSON_PrintUnformatted(result_obj);
if (json) { printf("%s\n", json); free(json); }
rc = 0;
} else if (strcmp(verb, "nip04-encrypt") == 0) {
if (!arg1) { fprintf(stderr, "error: nip04-encrypt requires <peer-pubkey>\n"); goto cleanup; }
const char *plaintext = arg2;
char *pt_buf = NULL;
if (!plaintext) {
pt_buf = read_stdin_line();
if (!pt_buf) { fprintf(stderr, "error: no plaintext provided\n"); goto cleanup; }
plaintext = pt_buf;
}
rc = nostr_signer_nip04_encrypt(signer, arg1, plaintext, &result_str);
free(pt_buf);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
print_result_str(result_str);
rc = 0;
} else if (strcmp(verb, "nip04-decrypt") == 0) {
if (!arg1) { fprintf(stderr, "error: nip04-decrypt requires <peer-pubkey>\n"); goto cleanup; }
const char *ciphertext = arg2;
char *ct_buf = NULL;
if (!ciphertext) {
ct_buf = read_stdin_line();
if (!ct_buf) { fprintf(stderr, "error: no ciphertext provided\n"); goto cleanup; }
ciphertext = ct_buf;
}
rc = nostr_signer_nip04_decrypt(signer, arg1, ciphertext, &result_str);
free(ct_buf);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
print_result_str(result_str);
rc = 0;
} else if (strcmp(verb, "nip44-encrypt") == 0) {
if (!arg1) { fprintf(stderr, "error: nip44-encrypt requires <peer-pubkey>\n"); goto cleanup; }
const char *plaintext = arg2;
char *pt_buf = NULL;
if (!plaintext) {
pt_buf = read_stdin_line();
if (!pt_buf) { fprintf(stderr, "error: no plaintext provided\n"); goto cleanup; }
plaintext = pt_buf;
}
rc = nostr_signer_nip44_encrypt(signer, arg1, plaintext, &result_str);
free(pt_buf);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
print_result_str(result_str);
rc = 0;
} else if (strcmp(verb, "nip44-decrypt") == 0) {
if (!arg1) { fprintf(stderr, "error: nip44-decrypt requires <peer-pubkey>\n"); goto cleanup; }
const char *ciphertext = arg2;
char *ct_buf = NULL;
if (!ciphertext) {
ct_buf = read_stdin_line();
if (!ct_buf) { fprintf(stderr, "error: no ciphertext provided\n"); goto cleanup; }
ciphertext = ct_buf;
}
rc = nostr_signer_nip44_decrypt(signer, arg1, ciphertext, &result_str);
free(ct_buf);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
print_result_str(result_str);
rc = 0;
} else if (strcmp(verb, "sign") == 0) {
if (!arg1) { fprintf(stderr, "error: sign requires <msg-hex>\n"); goto cleanup; }
size_t msg_len = strlen(arg1) / 2;
unsigned char *msg = malloc(msg_len ? msg_len : 1);
if (!msg) { fprintf(stderr, "error: out of memory\n"); goto cleanup; }
int n = hex_to_bytes(arg1, msg, msg_len);
if (n < 0) { free(msg); fprintf(stderr, "error: invalid hex message\n"); goto cleanup; }
rc = nostr_signer_sign(signer, algorithm ? algorithm : "secp256k1",
eff_index, scheme, msg, (size_t)n, &result_str);
free(msg);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
print_result_str(result_str);
rc = 0;
} else if (strcmp(verb, "verify") == 0) {
if (!arg1 || !arg2) { fprintf(stderr, "error: verify requires <msg-hex> <sig-hex>\n"); goto cleanup; }
size_t msg_len = strlen(arg1) / 2;
size_t sig_len = strlen(arg2) / 2;
unsigned char *msg = malloc(msg_len ? msg_len : 1);
unsigned char *sig = malloc(sig_len ? sig_len : 1);
if (!msg || !sig) { free(msg); free(sig); fprintf(stderr, "error: out of memory\n"); goto cleanup; }
int mn = hex_to_bytes(arg1, msg, msg_len);
int sn = hex_to_bytes(arg2, sig, sig_len);
if (mn < 0 || sn < 0) { free(msg); free(sig); fprintf(stderr, "error: invalid hex\n"); goto cleanup; }
int valid = 0;
rc = nostr_signer_verify(signer, algorithm ? algorithm : "secp256k1",
eff_index, scheme, msg, (size_t)mn, sig, (size_t)sn, &valid);
free(msg);
free(sig);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
printf("%s\n", valid ? "valid" : "invalid");
rc = valid ? 0 : 1;
} else if (strcmp(verb, "derive") == 0) {
const char *data = arg1;
char *data_buf = NULL;
if (!data) {
data_buf = read_stdin_line();
if (!data_buf) { fprintf(stderr, "error: no data provided\n"); goto cleanup; }
data = data_buf;
}
if (is_algorithm_verb) {
/* Algorithm-based derive: use low-level client to pass algorithm+index. */
cJSON *params = cJSON_CreateArray();
cJSON_AddItemToArray(params, cJSON_CreateString(data));
cJSON *opts = cJSON_CreateObject();
cJSON_AddStringToObject(opts, "algorithm", algorithm ? algorithm : "secp256k1");
cJSON_AddNumberToObject(opts, "index", eff_index);
cJSON_AddItemToArray(params, opts);
cJSON *dresult = NULL;
rc = nsigner_client_call(client, "derive", params, &dresult);
free(data_buf);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nsigner_client_last_error(client)); goto cleanup; }
if (cJSON_IsString(dresult)) {
/* The derive result is a JSON object string like
* {"algorithm":"secp256k1","key_id":"...","digest":"<64hex>"}.
* Print the raw result string. */
print_result_str(dresult->valuestring);
}
cJSON_Delete(dresult);
rc = 0;
} else {
/* Nostr derive (HMAC): use the high-level wrapper. */
char digest_hex[65];
rc = nostr_signer_derive_hmac(signer, data, digest_hex);
free(data_buf);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
printf("%s\n", digest_hex);
rc = 0;
}
} else if (strcmp(verb, "encapsulate") == 0) {
if (!arg1) { fprintf(stderr, "error: encapsulate requires <peer-pubkey-hex>\n"); goto cleanup; }
rc = nostr_signer_encapsulate(signer, arg1, &result_str);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
print_result_str(result_str);
rc = 0;
} else if (strcmp(verb, "decapsulate") == 0) {
if (!arg1) { fprintf(stderr, "error: decapsulate requires <ciphertext-hex>\n"); goto cleanup; }
rc = nostr_signer_decapsulate(signer, eff_index, arg1, &result_str);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
print_result_str(result_str);
rc = 0;
} else if (strcmp(verb, "derive-shared-secret") == 0) {
if (!arg1) { fprintf(stderr, "error: derive-shared-secret requires <peer-pubkey-hex>\n"); goto cleanup; }
rc = nostr_signer_derive_shared_secret(signer, eff_index, arg1, &result_str);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
print_result_str(result_str);
rc = 0;
} else if (strcmp(verb, "encrypt") == 0) {
const char *plaintext = arg1;
char *pt_buf = NULL;
if (!plaintext) {
pt_buf = read_stdin_line();
if (!pt_buf) { fprintf(stderr, "error: no plaintext provided\n"); goto cleanup; }
plaintext = pt_buf;
}
rc = nostr_signer_otp_encrypt(signer, plaintext, encoding, &result_str);
free(pt_buf);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
print_result_str(result_str);
rc = 0;
} else if (strcmp(verb, "decrypt") == 0) {
const char *ciphertext = arg1;
char *ct_buf = NULL;
if (!ciphertext) {
ct_buf = read_stdin_line();
if (!ct_buf) { fprintf(stderr, "error: no ciphertext provided\n"); goto cleanup; }
ciphertext = ct_buf;
}
rc = nostr_signer_otp_decrypt(signer, ciphertext, encoding, &result_str);
free(ct_buf);
if (rc != NOSTR_SUCCESS) { fprintf(stderr, "error: %s\n", nostr_signer_last_error(signer)); goto cleanup; }
print_result_str(result_str);
rc = 0;
} else if (strcmp(verb, "call") == 0) {
/* Raw passthrough using the low-level client (shared with signer). */
if (!arg1) { fprintf(stderr, "error: call requires <method>\n"); goto cleanup; }
const char *method = arg1;
cJSON *params = NULL;
if (arg2) {
size_t total = 0;
for (int j = i - 1; j < argc; j++) {
total += strlen(argv[j]) + 1;
}
char *json_str = malloc(total + 1);
if (!json_str) { fprintf(stderr, "error: out of memory\n"); goto cleanup; }
json_str[0] = '\0';
for (int j = i - 1; j < argc; j++) {
strcat(json_str, argv[j]);
if (j + 1 < argc) strcat(json_str, " ");
}
params = cJSON_Parse(json_str);
free(json_str);
if (!params) {
fprintf(stderr, "error: failed to parse params JSON from argv\n");
goto cleanup;
}
} else {
char *line = read_stdin_line();
if (!line) {
fprintf(stderr, "error: no params JSON on stdin\n");
goto cleanup;
}
params = cJSON_Parse(line);
free(line);
if (!params) {
fprintf(stderr, "error: failed to parse params JSON from stdin\n");
goto cleanup;
}
}
cJSON *call_result = NULL;
if (nsigner_client_call(client, method, params, &call_result) != NOSTR_SUCCESS) {
fprintf(stderr, "error: %s\n", nsigner_client_last_error(client));
goto cleanup;
}
if (call_result) {
char *json = cJSON_PrintUnformatted(call_result);
if (json) { printf("%s\n", json); free(json); }
cJSON_Delete(call_result);
}
rc = 0;
} else {
fprintf(stderr, "error: unknown verb: %s\n", verb);
fprintf(stderr, "Try '%s --help' for usage.\n", prog);
goto cleanup;
}
cleanup:
if (result_str) free(result_str);
if (result_obj) cJSON_Delete(result_obj);
if (signer) nostr_signer_free(signer);
nostr_cleanup();
return rc;
}
+230
View File
@@ -0,0 +1,230 @@
# Plan: `n_signer_client` — Linux CLI for n_signer
## Goal
A standalone Linux command-line client `n_signer_client` that connects to a
running `n_signer` process over its abstract UNIX socket (and optionally the
other framed transports) and exposes the full verb surface over stdin/stdout so
that signed events can be piped directly into `nak publish`.
## Deliverable & placement
The project lives in [`client/`](.) alongside the existing demo clients
(`demo_c99.c`, `demo_javascript.js`, `demo_python.py`):
- New file: [`client/n_signer_client.c`](n_signer_client.c) — single-file C99 program.
- New file: [`client/n_signer_client_README.md`](n_signer_client_README.md) — dedicated README just for this client (usage, verbs, pipe-to-nak recipes, build instructions). The existing [`client/README.md`](README.md) stays as-is (it documents the nostr_core_lib migration).
- New Makefile target producing `build/n_signer_client`.
The binary links `nostr_core_lib` exactly like the existing examples
[`examples/sign_event_client.c`](../examples/sign_event_client.c) and
[`examples/get_public_key_client.c`](../examples/get_public_key_client.c). It
uses:
- `nsigner_transport_open_unix` (and optionally `_tcp`, `_serial`, `_qrexec`) from `nostr_core_lib/nostr_core/nsigner_transport.h`
- `nsigner_client_new` / `nsigner_client_free` from `nostr_core_lib/nostr_core/nsigner_client.h`
- `nsigner_client_call` (takes ownership of `params`)
- `nsigner_client_set_auth` for TCP mode
## CLI shape
```
n_signer_client [global options] <verb> [verb args...]
```
Global options:
| Flag | Default | Meaning |
|---|---|---|
| `--socket-name`, `-n <name>` | auto-discover | Abstract socket name without `@` |
| `--timeout <ms>` | `5000` | Transport timeout |
| `--tcp <host:port>` | none | Use TCP transport (requires `--auth-privkey`) |
| `--serial <device>` | none | Use USB CDC-ACM serial transport |
| `--qrexec <qube:service>` | none | Use Qubes qrexec transport |
| `--auth-privkey <32-byte hex>` | none | Auth envelope privkey for TCP |
| `--auth-label <text>` | none | Auth envelope label |
Selector options (apply to `nostr_*` verbs; `--role` and `--path` are mutually exclusive):
| Flag | Meaning | JSON emitted |
|---|---|---|
| `--role <name>` | Named path-role registered in the signer's wizard | `{"role":"<name>"}` |
| `--path <full-path>` | Full BIP-44 derivation path | `{"role_path":"<full-path>"}` |
| `--index <N>` | Optional variable-segment index for a named path-role (only valid with `--role`) | adds `"index":N` to the role object |
Algorithm options (apply to algorithm-based verbs):
| Flag | Default | Meaning |
|---|---|---|
| `--algorithm <alg>` | none | `secp256k1`/`ed25519`/`x25519`/`ml-dsa-65`/`slh-dsa-128s`/`ml-kem-768`/`otp` |
| `--index <N>` | `0` | Algorithm derivation index (substituted into the alg's path) |
| `--scheme <schnorr\|ecdsa>` | `schnorr` | secp256k1 `sign`/`verify` only |
| `--encoding <base64\|hex>` | `base64` | OTP `encrypt`/`decrypt` only |
| `--format <plain\|structured>` | `plain` | `nostr_get_public_key` output shape |
Note on `--index` overload: when `--algorithm` is set, `--index` is the
algorithm derivation index. When `--role` is set (and no `--algorithm`),
`--index` is the named path-role's variable-segment index. These two contexts
never overlap because algorithm verbs and `nostr_*` verbs are distinct.
Auto-discovery: when no `--socket-name` and no explicit transport is given,
enumerate via `nsigner_transport_list_unix` and proceed only if exactly one
`nsigner*` socket exists (mirror `discover_single_socket_name` in
[`src/main.c`](../src/main.c)).
## Verb surface (full)
Per [`README.md`](../README.md) §4.3 verb table. The options object is always
the trailing element of the `params` array.
### Metadata
| Verb | RPC method | stdout |
|---|---|---|
| `get-info` | `get_info` | raw `result` JSON (name, version, verbs, algorithms) |
### Nostr verbs (role-based; selector from `--role` / `--path`)
| Verb | RPC method | stdin/argv | stdout |
|---|---|---|---|
| `get-public-key` | `nostr_get_public_key` | none | pubkey hex (or structured JSON with `--format structured`) |
| `sign-event` | `nostr_sign_event` | event JSON from argv or one stdin line | signed event JSON, one line |
| `mine-event` | `nostr_mine_event` | event JSON from argv or stdin; options `--difficulty`, `--threads`, `--timeout-sec` | signed mined event JSON |
| `nip04-encrypt <peer-pubkey>` | `nostr_nip04_encrypt` | plaintext from argv or stdin | ciphertext |
| `nip04-decrypt <peer-pubkey>` | `nostr_nip04_decrypt` | ciphertext from argv or stdin | plaintext |
| `nip44-encrypt <peer-pubkey>` | `nostr_nip44_encrypt` | plaintext from argv or stdin | ciphertext |
| `nip44-decrypt <peer-pubkey>` | `nostr_nip44_decrypt` | ciphertext from argv or stdin | plaintext |
### Algorithm-based verbs (use `--algorithm` and `--index`)
| Verb | RPC method | argv | stdout |
|---|---|---|---|
| `get-public-key` | `get_public_key` | none | structured JSON `{"algorithm":...,"public_key":...,"key_id":...}` |
| `sign <msg-hex>` | `sign` | hex bytes | structured JSON `{"signature":...,"algorithm":...,"key_id":...}` |
| `verify <msg-hex> <sig-hex>` | `verify` | hex bytes | `valid` / `invalid` (exit 0/1) |
| `derive <data>` | `derive` | UTF-8 data (argv or stdin) | structured JSON `{"algorithm":...,"key_id":...,"digest":...}` |
| `encapsulate <peer-pubkey-hex>` | `encapsulate` | hex | structured JSON `{"ciphertext":...,"shared_secret":...}` |
| `decapsulate <ciphertext-hex>` | `decapsulate` | hex | structured JSON `{"shared_secret":...}` |
| `derive-shared-secret <peer-pubkey-hex>` | `derive_shared_secret` | hex | shared secret hex |
| `encrypt <plaintext>` | `encrypt` | plaintext (base64 by default; `--encoding hex`) | ciphertext |
| `decrypt <ciphertext>` | `decrypt` | ciphertext | plaintext |
### Generic escape hatch
| Verb | RPC method | input | stdout |
|---|---|---|---|
| `call <method>` | `<method>` | JSON `params` array from stdin (one line) or argv | raw `result` JSON |
This keeps the client future-proof for any new server verb without a CLI rewrite.
## stdin/stdout contract (pipe-friendly)
- All payload output goes to stdout as a single line, newline-terminated.
- All diagnostics go to stderr.
- Exit code: `0` on success, non-zero on transport/RPC error (use
`nsigner_client_last_error` for the message). For `verify`, exit `0` =
valid, `1` = invalid, `2` = error.
- `sign-event` reads event JSON from argv if present, else reads exactly one
line from stdin. This is the pipe-to-nak path:
```bash
echo '{"kind":1,"content":"hello","tags":[],"created_at":1700000000}' \
| n_signer_client --role main sign-event \
| nak publish
```
- `nip04-encrypt` / `nip44-encrypt` read plaintext from argv or stdin.
- `nip04-decrypt` / `nip44-decrypt` read ciphertext from argv or stdin.
- `sign` / `verify` / `encapsulate` / `decapsulate` / `derive-shared-secret`
take hex from argv (binary payloads, not pipe-friendly text).
- `derive` takes UTF-8 data from argv or stdin.
- `encrypt` / `decrypt` take their payload from argv or stdin (base64 by
default per the server contract).
- `call` reads a JSON `params` array from stdin (one line) or argv.
## Selector handling (per README §4.6)
The `nostr_*` verbs select a secp256k1 NIP-06 key via the options object. The
client builds the options object from the selector flags:
- `--role <name>``{"role":"<name>"}` (named path-role; the derivation path
is hidden from the client by the signer).
- `--role <name> --index <N>``{"role":"<name>","index":N}` (named path-role
with variable-segment index; rejected with `2005 index_out_of_range` if out
of the role's range).
- `--path <full-path>``{"role_path":"<full-path>"}` (raw BIP-44 path; must
match a registered role's path template or be explicitly allowed).
- Default (no selector): server uses the default role `main`.
- Conflicting selectors → client-side error (do not send; the server would
reject with `ambiguous_role_selector` 1001).
Resolution order on the server: `role``role_path` → default `main`. The
client enforces mutual exclusivity of the selector flags before sending.
For algorithm verbs, `--algorithm` and `--index` populate the options object
instead; `--scheme` adds `"scheme"` for secp256k1 sign/verify; `--encoding`
adds `"encoding"` for OTP encrypt/decrypt.
## Transport
- Default: UNIX abstract socket via `nsigner_transport_open_unix(name, timeout_ms)`.
- `--tcp host:port``nsigner_transport_open_tcp` (requires `--auth-privkey`
32-byte hex; calls `nsigner_client_set_auth` with `--auth-label`).
- `--serial /dev/ttyACM0``nsigner_transport_open_serial`.
- `--qrexec qube:service``nsigner_transport_open_qrexec`.
- The vtable is uniform so all four transports share the same call path after
construction.
## Build
Add to [`Makefile`](../Makefile):
```make
N_SIGNER_CLIENT_TARGET := $(BUILD_DIR)/n_signer_client
clients: $(N_SIGNER_CLIENT_TARGET)
$(N_SIGNER_CLIENT_TARGET): $(CLIENT_DIR)/n_signer_client.c
@mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) $(CLIENT_DIR)/n_signer_client.c -o $(N_SIGNER_CLIENT_TARGET) $(LDFLAGS)
```
Add `clients` to the `all` aggregate and to the `test-client` target so it is
built alongside the examples.
## Testing
1. Manual smoke test against a running `nsigner`:
- `n_signer_client get-info` → signer metadata JSON.
- `n_signer_client --role main get-public-key` → 64-hex pubkey.
- `echo '{"kind":1,"content":"hello","tags":[],"created_at":1}' | n_signer_client --role main sign-event` → signed event with `id`, `pubkey`, `sig`.
- Pipe to `nak event` / `nak publish` to verify the signed event is well-formed.
- `n_signer_client --algorithm ed25519 --index 0 sign 68656c6c6f` → structured sig JSON.
- `n_signer_client --role myrole get-public-key` → pubkey for the named path-role.
2. Optional bash script `tests/test_n_signer_client.sh` that:
- Spawns `nsigner --socket-name nsigner_test --listen unix --mnemonic-stdin` with a fixed test mnemonic.
- Runs each verb and asserts on stdout shape.
- Tears down the server.
## Mermaid flow
```mermaid
flowchart LR
A[stdin or argv event JSON] --> B[n_signer_client sign-event]
B --> C[nsigner_transport_open_unix]
C --> D[nsigner_client_call nostr_sign_event]
D --> E[nsigner @nsigner socket]
E --> F[signed event JSON result]
F --> G[stdout one line]
G --> H[nak publish]
```
## Out of scope
- No TUI, no approval UI — the human attendant lives in the running `nsigner`
process; the client is just a thin wire caller.
- No key storage, no mnemonic handling.
- No HTTP listener client (the `http_listener` is server-side; the client uses
the framed transports).
- No NIP-46 bunker mode (covered separately by
[`plans/nip46_bunker_mode.md`](../plans/nip46_bunker_mode.md)).
+171
View File
@@ -0,0 +1,171 @@
# `nsigner_client` — Linux CLI for n_signer
A standalone Linux command-line client that connects to a running [`n_signer`](https://github.com/your-org/n_signer) process and calls its JSON-RPC verbs over stdin/stdout. Designed for pipe-to-`nak` workflows.
## Build
```bash
make clients
```
Produces `build/nsigner_client`. Links `nostr_core_lib` exactly like the existing examples.
## Usage
```
nsigner_client [global options] <verb> [verb args...]
```
### Global options
| Flag | Default | Meaning |
|------|---------|---------|
| `--socket-name`, `-n <name>` | auto-discover | Abstract socket name without `@` |
| `--timeout <ms>` | `5000` | Transport timeout |
| `--tcp <host:port>` | none | TCP transport (requires `--auth-privkey`) |
| `--serial <device>` | none | USB CDC-ACM serial transport |
| `--qrexec <qube:service>` | none | Qubes qrexec transport |
| `--auth-privkey <32-byte hex>` | none | Auth envelope privkey for TCP |
| `--auth-label <text>` | none | Auth envelope label |
### Selector options (for `nostr_*` verbs)
| Flag | Meaning | JSON emitted |
|------|---------|-------------|
| `--role <name>` | Named path-role registered in the signer | `{"role":"<name>"}` |
| `--path <path>` | Full BIP-44 derivation path | `{"role_path":"<path>"}` |
### Algorithm options (for algorithm-based verbs)
| Flag | Default | Meaning |
|------|---------|---------|
| `--algorithm <alg>` | none | `secp256k1`/`ed25519`/`x25519`/`ml-dsa-65`/`slh-dsa-128s`/`ml-kem-768`/`otp` |
| `--index <N>` | `0` | Algorithm derivation index |
| `--scheme <schnork\|ecdsa>` | `schnorr` | secp256k1 `sign`/`verify` only |
| `--encoding <base64\|hex>` | `base64` | OTP `encrypt`/`decrypt` only |
| `--format <plain\|structured>` | `plain` | `nostr_get_public_key` output shape |
### Mine-event options
| Flag | Meaning |
|------|---------|
| `--difficulty <N>` | Target leading zero bits |
| `--threads <N>` | Mining threads (default 1) |
| `--timeout-sec <N>` | Mining timeout in seconds |
## Verb reference
### Utility
| Verb | stdout |
|------|--------|
| `list` | Lists running n_signer abstract sockets (one `@name` per line) |
### Metadata
| Verb | RPC method | stdout |
|------|------------|--------|
| `get-info` | `get_info` | raw result JSON (name, version, verbs, algorithms) |
### Nostr verbs (role-based)
| Verb | RPC method | stdin/argv | stdout |
|------|------------|------------|--------|
| `get-public-key` | `nostr_get_public_key` | none | pubkey hex (or structured JSON with `--format structured`) |
| `sign-event` | `nostr_sign_event` | event JSON from argv or stdin | signed event JSON |
| `mine-event` | `nostr_mine_event` | event JSON from argv or stdin | signed mined event JSON |
| `nip04-encrypt <peer>` | `nostr_nip04_encrypt` | plaintext from argv or stdin | ciphertext |
| `nip04-decrypt <peer>` | `nostr_nip04_decrypt` | ciphertext from argv or stdin | plaintext |
| `nip44-encrypt <peer>` | `nostr_nip44_encrypt` | plaintext from argv or stdin | ciphertext |
| `nip44-decrypt <peer>` | `nostr_nip44_decrypt` | ciphertext from argv or stdin | plaintext |
### Algorithm-based verbs
| Verb | RPC method | argv | stdout |
|------|------------|------|--------|
| `get-public-key` | `get_public_key` | none | structured JSON `{"algorithm":...,"public_key":...,"key_id":...}` |
| `sign <msg-hex>` | `sign` | hex bytes | structured JSON `{"signature":...,"algorithm":...,"key_id":...}` |
| `verify <msg-hex> <sig-hex>` | `verify` | hex bytes | `valid` / `invalid` (exit 0/1) |
| `derive <data>` | `derive` | UTF-8 data (argv or stdin) | structured JSON |
| `encapsulate <peer-pubkey-hex>` | `encapsulate` | hex | structured JSON |
| `decapsulate <ciphertext-hex>` | `decapsulate` | hex | structured JSON |
| `derive-shared-secret <peer-pubkey-hex>` | `derive_shared_secret` | hex | shared secret hex |
| `encrypt <plaintext>` | `encrypt` | plaintext (base64 by default) | ciphertext |
| `decrypt <ciphertext>` | `decrypt` | ciphertext | plaintext |
### Generic escape hatch
| Verb | RPC method | input | stdout |
|------|------------|-------|--------|
| `call <method>` | `<method>` | JSON params array from stdin or argv | raw result JSON |
## Selector explanation
The `nostr_*` verbs select a key via the options object using both `--role` and `--path`:
- **`--role <name> --path <path>`** — Both are required for all `nostr_*` verbs. The role authorizes the request and determines the encryption scheme. The path selects the specific key to derive. Sends `{"role":"<name>","role_path":"<path>"}` to the server.
- **`--role` without `--path`** — Client-side error: `--path is required for nostr verbs`.
- **`--path` without `--role`** — Client-side error: `--role is required for nostr verbs`.
For algorithm verbs, `--algorithm` and `--index` populate the options object instead.
## Pipe-to-nak recipes
```bash
# Get public key
nsigner_client --role main --path "m/44'/1237'/0'/0/0" get-public-key
# Sign an event and publish via nak
echo '{"kind":1,"content":"hello nostr","tags":[],"created_at":1700000000}' \
| nsigner_client --role main --path "m/44'/1237'/0'/0/0" sign-event \
| nak publish
# Mine a proof-of-work event
echo '{"kind":1,"content":"pow","tags":[],"created_at":1700000000}' \
| nsigner_client --role main --path "m/44'/1237'/0'/0/0" mine-event --difficulty 20 --threads 4
# NIP-44 encrypt
nsigner_client --role main --path "m/44'/1237'/0'/0/0" nip44-encrypt <peer-pubkey> "secret message"
# Algorithm-based signing
nsigner_client --algorithm ed25519 --index 0 sign 68656c6c6f
# Verify a signature
nsigner_client --algorithm secp256k1 verify <msg-hex> <sig-hex> && echo "valid"
# Get signer info
nsigner_client get-info
```
## Transport options
| Transport | Flag | Notes |
|-----------|------|-------|
| UNIX abstract socket | `--socket-name <name>` or auto-discover | Default. Auto-discovers if exactly one `@nsigner*` socket exists. |
| TCP | `--tcp <host:port>` | Requires `--auth-privkey` for auth envelope. |
| Serial (USB CDC-ACM) | `--serial <device>` | e.g. `--serial /dev/ttyACM0` |
| Qubes qrexec | `--qrexec <qube:service>` | e.g. `--qrexec sys-signer:qubes.NsignerRpc` |
## Exit codes
| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | Invalid (verify verb only — signature is invalid) |
| 2 | Error (transport, RPC, or usage error) |
For `verify`: exit 0 = valid signature, exit 1 = invalid signature, exit 2 = error.
## stdin/stdout contract
- All payload output goes to stdout as a single line, newline-terminated.
- All diagnostics (errors, warnings) go to stderr.
- `sign-event`, `nip04-*`, `nip44-*`, `derive`, `encrypt`, `decrypt` read their payload from argv if present, otherwise from stdin (one line).
- `sign`, `verify`, `encapsulate`, `decapsulate`, `derive-shared-secret` take hex from argv only (binary payloads).
- `call` reads a JSON params array from stdin (one line) or argv.
## See also
- [`n_signer_client_PLAN.md`](n_signer_client_PLAN.md) — the full implementation plan
- [`README.md`](../README.md) — n_signer main documentation (API §4)
- [`examples/sign_event_client.c`](../examples/sign_event_client.c) — reference example
+140
View File
@@ -0,0 +1,140 @@
#!/bin/bash
#
# deploy_local.sh — Build static nsigner + nsigner_client binaries
# and install them to /usr/local/bin/
#
# Usage:
# ./deploy_local.sh # build + install (uses sudo if needed)
# ./deploy_local.sh --no-build # install existing build/ binaries only
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD_DIR="$SCRIPT_DIR/build"
INSTALL_PREFIX="/usr/local/bin"
HOST_UNAME="$(uname -m)"
case "$HOST_UNAME" in
x86_64) ARCH="x86_64" ;;
aarch64|arm64) ARCH="arm64" ;;
armv7l|armv7) ARCH="armv7" ;;
*)
echo "ERROR: Unsupported host architecture '$HOST_UNAME'"
exit 1
;;
esac
case "$ARCH" in
x86_64)
SIGNER_BIN="$BUILD_DIR/nsigner_static_x86_64"
CLIENT_BIN="$BUILD_DIR/nsigner_client_static_x86_64"
;;
arm64)
SIGNER_BIN="$BUILD_DIR/nsigner_static_arm64"
CLIENT_BIN="$BUILD_DIR/nsigner_client_static_arm64"
;;
armv7)
SIGNER_BIN="$BUILD_DIR/nsigner_static_armv7"
CLIENT_BIN="$BUILD_DIR/nsigner_client_static_armv7"
;;
esac
DO_BUILD=true
while [[ $# -gt 0 ]]; do
case "$1" in
--no-build)
DO_BUILD=false
shift
;;
-h|--help)
echo "deploy_local.sh — Build and install nsigner + nsigner_client to $INSTALL_PREFIX"
echo ""
echo "Usage: $0 [OPTIONS]"
echo ""
echo "OPTIONS:"
echo " --no-build Skip build step; install existing binaries from build/"
echo " -h, --help Show this help message"
exit 0
;;
*)
echo "ERROR: Unknown argument '$1'"
echo "Usage: $0 [--no-build]"
exit 1
;;
esac
done
echo "=========================================="
echo "nsigner local deploy"
echo "=========================================="
echo "Architecture: $ARCH"
echo "Install dir: $INSTALL_PREFIX"
echo "Signer binary: $SIGNER_BIN"
echo "Client binary: $CLIENT_BIN"
echo ""
# --- Build step ---------------------------------------------------------------
if $DO_BUILD; then
echo "[1/3] Building static binaries via build_static.sh"
echo ""
bash "$SCRIPT_DIR/build_static.sh" --arch "$ARCH"
echo ""
else
echo "[1/3] Skipping build (--no-build)"
fi
# --- Verify binaries exist ----------------------------------------------------
echo "[2/3] Verifying binaries"
if [[ ! -f "$SIGNER_BIN" ]]; then
echo "ERROR: Signer binary not found: $SIGNER_BIN"
echo " Run without --no-build, or run build_static.sh first."
exit 1
fi
if [[ ! -x "$SIGNER_BIN" ]]; then
echo "ERROR: Signer binary is not executable: $SIGNER_BIN"
exit 1
fi
if [[ ! -f "$CLIENT_BIN" ]]; then
echo "ERROR: Client binary not found: $CLIENT_BIN"
echo " Run without --no-build, or run build_static.sh first."
exit 1
fi
if [[ ! -x "$CLIENT_BIN" ]]; then
echo "ERROR: Client binary is not executable: $CLIENT_BIN"
exit 1
fi
echo " OK: $SIGNER_BIN ($(du -h "$SIGNER_BIN" | cut -f1))"
echo " OK: $CLIENT_BIN ($(du -h "$CLIENT_BIN" | cut -f1))"
# Quick smoke test
SIGNER_VERSION="$("$SIGNER_BIN" --version 2>&1 || echo "unknown")"
echo " Signer version: $SIGNER_VERSION"
# --- Install ------------------------------------------------------------------
echo ""
echo "[3/3] Installing to $INSTALL_PREFIX"
SUDO=""
if [[ $EUID -ne 0 ]]; then
if ! command -v sudo >/dev/null 2>&1; then
echo "ERROR: Need root privileges to write to $INSTALL_PREFIX but sudo is not available"
exit 1
fi
SUDO="sudo"
fi
$SUDO install -m 0755 "$SIGNER_BIN" "$INSTALL_PREFIX/nsigner"
$SUDO install -m 0755 "$CLIENT_BIN" "$INSTALL_PREFIX/nsigner_client"
echo ""
echo "=========================================="
echo "Deploy complete!"
echo "=========================================="
echo " $INSTALL_PREFIX/nsigner"
echo " $INSTALL_PREFIX/nsigner_client"
echo ""
echo "Verify:"
echo " nsigner --version"
echo " nsigner_client --help"
+736
View File
@@ -0,0 +1,736 @@
# Agent Client Reference — n_signer
This document is the complete reference for **agents, AI tools, and automated processes** that need to call [`n_signer`](../README.md) — a signing oracle that holds BIP-39 keys in locked memory and exposes them over multiple transports.
## Table of Contents
1. [Architecture overview](#1-architecture-overview)
2. [Wire protocol (all transports)](#2-wire-protocol-all-transports)
3. [Transport: Qubes qrexec (recommended for cross-qube)](#3-transport-qubes-qrexec-recommended-for-cross-qube)
4. [Transport: Local Unix abstract socket](#4-transport-local-unix-abstract-socket)
5. [Transport: TCP (FIPS mesh)](#5-transport-tcp-fips-mesh)
6. [Transport: HTTP](#6-transport-http)
7. [Transport: USB/serial (hardware signers)](#7-transport-usbserial-hardware-signers)
8. [Transport: Stdio (one-shot)](#8-transport-stdio-one-shot)
9. [Auth envelope (kind-27235)](#9-auth-envelope-kind-27235)
10. [Complete verb reference](#10-complete-verb-reference)
11. [Algorithm reference](#11-algorithm-reference)
12. [Error codes](#12-error-codes)
13. [End-to-end: publish a Nostr event](#13-end-to-end-publish-a-nostr-event)
14. [End-to-end: sign arbitrary data](#14-end-to-end-sign-arbitrary-data)
15. [End-to-end: PQ KEM encapsulate/decapsulate](#15-end-to-end-pq-kem-encapsulatedecapsulate)
16. [Discovery: finding running signers](#16-discovery-finding-running-signers)
17. [Prerequisites and setup](#17-prerequisites-and-setup)
18. [Reference files in this repo](#18-reference-files-in-this-repo)
---
## 1. Architecture overview
```
┌─────────────────────────────────────────────────────────────┐
│ Caller (agent) │
│ Python / Node / C / Shell / any language │
│ Builds framed JSON-RPC → sends over transport → reads resp │
└──────────┬──────────────────────────────────────┬───────────┘
│ │
┌─────┴──────┐ ┌──────────┴──────────┐
│ qrexec │ │ TCP / HTTP / Unix │
│ (Qubes) │ │ Socket / USB │
└─────┬──────┘ └──────────┬──────────┘
│ │
┌─────┴──────────────────────────────────────┴───────────┐
│ n_signer │
│ BIP-39 mnemonic in mlock'd RAM │
│ Derives keys on demand (secp256k1, ed25519, PQ, etc.) │
│ Enforces policy + approval per caller │
└─────────────────────────────────────────────────────────┘
```
The signer is a **single foreground process** attached to a terminal. It holds the mnemonic in locked memory only — nothing touches disk. When the process exits, all state is destroyed.
---
## 2. Wire protocol (all transports)
Every transport uses the same framing and JSON-RPC contract.
### 2.1 Framing
```
[4 bytes: big-endian payload length N][N bytes: UTF-8 JSON payload]
```
- Length prefix is `uint32_t` in network byte order.
- Payload is exactly `N` bytes of UTF-8 JSON.
- One request frame → one response frame per connection (except HTTP which uses standard HTTP request/response).
### 2.2 Request shape
```json
{
"id": "<caller-supplied string, echoed in response>",
"method": "<verb name>",
"params": [ <arg0>, <arg1>, ..., { <options> } ]
}
```
- `id` — any string. Used to match async responses. Echoed verbatim.
- `method` — one of the verbs in §10.
- `params` — JSON array. Positional args first; last element is conventionally an options object.
### 2.3 Response shape
Success:
```json
{ "id": "<string>", "result": "<value>" }
```
Error:
```json
{ "id": "<string>", "error": { "code": <int>, "message": "<string>" } }
```
`result` is always a JSON string. For structured verbs (like `get_public_key` with algorithm), the string is itself serialized JSON — parse it again.
### 2.4 Auth envelope (required for TCP/HTTP, optional for qrexec)
TCP and HTTP listeners require a kind-27235 auth envelope in the `auth` field. See [§9](#9-auth-envelope-kind-27235).
---
## 3. Transport: Qubes qrexec (recommended for cross-qube)
**Best for**: Agents running in a caller qube, talking to n_signer in a dedicated signer qube.
**Auth**: Not required — caller identity comes from `QREXEC_REMOTE_DOMAIN` as `qubes:<source-vm>`.
### 3.1 Shell one-liner
```bash
# Get public key for nostr_index 0
printf '\x00\x00\x00\x3f'"$(echo '{"id":"1","method":"get_public_key","params":[{"nostr_index":0}]}')" | \
qrexec-client-vm nostr_signer qubes.NsignerRpc | tail -c +5
```
### 3.2 Python (stdlib only)
```python
import json, struct, subprocess
def call_nsigner(target_qube, request):
"""Send one framed JSON-RPC request via qrexec, return parsed response."""
payload = json.dumps(request, separators=(",", ":")).encode("utf-8")
frame = struct.pack(">I", len(payload)) + payload
proc = subprocess.Popen(
["qrexec-client-vm", target_qube, "qubes.NsignerRpc"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
)
out, err = proc.communicate(frame)
if proc.returncode != 0:
raise RuntimeError(f"qrexec failed: {err.decode()}")
length = struct.unpack(">I", out[:4])[0]
return json.loads(out[4:4+length])
```
Full demo: [`client/demo_python.py`](../client/demo_python.py)
### 3.3 Node.js
```javascript
const { spawn } = require("child_process");
function callNsigner(targetQube, request) {
return new Promise((resolve, reject) => {
const payload = Buffer.from(JSON.stringify(request), "utf8");
const header = Buffer.alloc(4);
header.writeUInt32BE(payload.length, 0);
const framed = Buffer.concat([header, payload]);
const proc = spawn("qrexec-client-vm", [targetQube, "qubes.NsignerRpc"], {
stdio: ["pipe", "pipe", "pipe"],
});
const chunks = [];
proc.stdout.on("data", (c) => chunks.push(c));
proc.on("close", (code) => {
if (code !== 0) return reject(new Error(`exit code ${code}`));
const buf = Buffer.concat(chunks);
const len = buf.readUInt32BE(0);
resolve(JSON.parse(buf.subarray(4, 4 + len).toString()));
});
proc.stdin.write(framed);
proc.stdin.end();
});
}
```
Full demo: [`client/demo_javascript.js`](../client/demo_javascript.js)
### 3.4 C (using nostr_core_lib)
```c
#include "nostr_signer.h"
nostr_signer_t *signer = nostr_signer_nsigner_qrexec("nostr_signer", "qubes.NsignerRpc", NULL, 30000);
nostr_signer_nsigner_set_nostr_index(signer, 0);
char pubkey[65];
nostr_signer_get_public_key(signer, pubkey);
```
Full demo: [`client/demo_c99.c`](../client/demo_c99.c)
### 3.5 Prerequisites
1. n_signer running in the signer qube: `nsigner --listen unix --socket-name nsigner --bridge-source-trusted`
2. qrexec service installed at `/etc/qubes-rpc/qubes.NsignerRpc`: `exec nsigner bridge --to nsigner`
3. dom0 policy allowing caller qube → signer qube (see [`packaging/qubes/policy.d/40-nsigner.policy`](../packaging/qubes/policy.d/40-nsigner.policy))
---
## 4. Transport: Local Unix abstract socket
**Best for**: Agents on the same machine as the signer.
**Auth**: Not required — identity from `SO_PEERCRED` (kernel-verified UID/PID).
### 4.1 Discovery
```bash
nsigner list
# Output: @nsigner, @nsigner_hairy_dog, etc.
```
### 4.2 Using the nsigner CLI
```bash
nsigner client '{"id":"1","method":"get_public_key","params":[{"nostr_index":0}]}' --socket-name nsigner
```
### 4.3 C (using nostr_core_lib)
```c
#include "nsigner_transport.h"
#include "nsigner_client.h"
nsigner_transport_t *t = nsigner_transport_open_unix("nsigner", 5000);
nsigner_client_t *c = nsigner_client_new(t);
cJSON *params = cJSON_CreateArray();
cJSON *result = NULL;
nsigner_client_call(c, "nostr_get_public_key", params, &result);
```
See [`examples/get_public_key_client.c`](../examples/get_public_key_client.c).
### 4.4 Python (raw socket)
```python
import json, socket, struct
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect("\0nsigner") # \0 prefix for abstract namespace
payload = json.dumps({"id":"1","method":"get_public_key","params":[{"nostr_index":0}]}).encode()
sock.sendall(struct.pack(">I", len(payload)) + payload)
hdr = sock.recv(4)
length = struct.unpack(">I", hdr)[0]
body = sock.recv(length)
print(json.loads(body))
```
---
## 5. Transport: TCP (FIPS mesh)
**Best for**: Cross-qube or network callers where qrexec is not available.
**Auth**: **Required** — kind-27235 auth envelope (see [§9](#9-auth-envelope-kind-27235)).
### 5.1 Python (with coincurve)
```python
import hashlib, json, socket, struct, time
from coincurve import PrivateKey
HOST, PORT = "192.168.1.100", 11111
CALLER_PRIVKEY = bytes(range(1, 33)) # Replace with your key
params = [{"nostr_index": 0}]
body_hash = hashlib.sha256(json.dumps(params, separators=(",",":")).encode()).hexdigest()
sk = PrivateKey(CALLER_PRIVKEY)
pubkey_x = sk.public_key.format(compressed=False)[1:33].hex()
created_at = int(time.time())
tags = [["nsigner_rpc","1"],["nsigner_method","get_public_key"],["nsigner_body_hash",body_hash]]
serialized = json.dumps([0, pubkey_x, created_at, 27235, tags, "tcp-agent"], separators=(",",":")).encode()
event_id = hashlib.sha256(serialized).hexdigest()
sig = sk.sign_schnorr(bytes.fromhex(event_id), aux_randomness=b"\x00"*32).hex()
request = {
"id": "1", "method": "get_public_key", "params": params,
"auth": {"id": event_id, "pubkey": pubkey_x, "created_at": created_at,
"kind": 27235, "tags": tags, "content": "tcp-agent", "sig": sig},
}
payload = json.dumps(request, separators=(",",":")).encode()
frame = struct.pack(">I", len(payload)) + payload
with socket.create_connection((HOST, PORT), timeout=10) as s:
s.sendall(frame)
hdr = s.recv(4)
ln = struct.unpack(">I", hdr)[0]
body = s.recv(ln)
print(json.loads(body))
```
See [`examples/get_pubkey_fips.py`](../examples/get_pubkey_fips.py) and [`examples/n_signer_qube_example_fips.js`](../examples/n_signer_qube_example_fips.js).
### 5.2 C (using nostr_core_lib)
```c
nsigner_transport_t *t = nsigner_transport_open_tcp("192.168.1.100", 11111, 10000);
nsigner_client_t *c = nsigner_client_new(t);
nsigner_client_set_auth(c, caller_privkey, "tcp-agent");
// ... call as usual
```
See [`examples/get_pubkey_tcp.c`](../examples/get_pubkey_tcp.c).
---
## 6. Transport: HTTP
**Best for**: curl-friendly callers, REST clients.
**Auth**: **Required** — kind-27235 auth envelope in the JSON body.
```bash
curl -X POST http://192.168.1.100:11112/ \
-H "Content-Type: application/json" \
-d '{
"id":"1",
"method":"get_public_key",
"params":[{"nostr_index":0}],
"auth":{...}
}'
```
The HTTP listener uses the same framing internally but presents a standard HTTP interface. One request per connection.
---
## 7. Transport: USB/serial (hardware signers)
**Best for**: Embedded/air-gap signers (Feather S3, Teensy 4.1, CYD ESP32).
**Auth**: Not required — physical possession is the trust anchor.
### 7.1 Python (pyserial)
```python
import json, struct, serial
ser = serial.Serial("/dev/ttyACM0", 115200, timeout=5)
payload = json.dumps({"id":"1","method":"get_public_key","params":[{"nostr_index":0}]}).encode()
ser.write(struct.pack(">I", len(payload)) + payload)
hdr = ser.read(4)
length = struct.unpack(">I", hdr)[0]
body = ser.read(length)
print(json.loads(body))
```
See [`examples/feather_get_public_key.py`](../examples/feather_get_public_key.py) and [`examples/feather_sign_event.py`](../examples/feather_sign_event.py).
---
## 8. Transport: Stdio (one-shot)
**Best for**: Scripted one-off calls via pipe.
The signer can be started with `--listen stdio` to handle exactly one framed request on stdin and write one framed response to stdout.
```bash
echo -n '<framed request>' | nsigner --listen stdio --allow-all
```
Or via the qrexec bridge service (which uses stdio internally to relay to the persistent signer's Unix socket).
---
## 9. Auth envelope (kind-27235)
TCP and HTTP listeners require a **kind-27235 Nostr event** in the `auth` field of every request. This proves the caller controls a keypair.
### 9.1 Auth envelope structure
```json
{
"auth": {
"id": "<sha256 of serialized event>",
"pubkey": "<caller's secp256k1 x-only pubkey hex>",
"created_at": <unix timestamp>,
"kind": 27235,
"tags": [
["nsigner_rpc", "<request id>"],
["nsigner_method", "<method name>"],
["nsigner_body_hash", "<sha256 of canonical params JSON>"]
],
"content": "<arbitrary string>",
"sig": "<schnorr signature hex>"
}
}
```
### 9.2 Building the auth envelope (pseudocode)
```
1. Compute body_hash = SHA256(JSON.stringify(params, separators=(",",":")))
2. Build tags: [["nsigner_rpc", id], ["nsigner_method", method], ["nsigner_body_hash", body_hash]]
3. Serialize event for signing: JSON.stringify([0, pubkey, created_at, 27235, tags, content])
4. Compute event_id = SHA256(serialized)
5. Sign event_id with caller's secp256k1 key (Schnorr/BIP-340)
6. Include full event as the "auth" field in the request
```
### 9.3 Validation rules (server-side)
| Check | Error code |
|-------|-----------|
| Missing `auth` field | 2014 `auth_envelope_required` |
| Malformed auth JSON | 2010 `auth_envelope_malformed` |
| `kind` != 27235 | 2013 `auth_kind_invalid` |
| Signature doesn't verify | 2012 `auth_signature_invalid` |
| `nsigner_rpc` tag != request `id` | 2011 `auth_body_mismatch` |
| `nsigner_method` tag != request `method` | 2011 `auth_body_mismatch` |
| `nsigner_body_hash` != SHA256(params) | 2011 `auth_body_mismatch` |
| Timestamp skew > 300 seconds | 2015 `auth_envelope_mismatch` |
| Replay (same event_id seen before) | 2015 `auth_envelope_mismatch` |
### 9.4 Python example (full)
See [`examples/get_pubkey_fips.py`](../examples/get_pubkey_fips.py) for a complete working example.
### 9.5 JavaScript example (full)
See [`examples/n_signer_qube_example_fips.js`](../examples/n_signer_qube_example_fips.js) for a complete working example.
---
## 10. Complete verb reference
### 10.1 Algorithm-based verbs
These select a key by `algorithm` + `index` (see [§11](#11-algorithm-reference) for derivation paths).
| Verb | Algorithms | Params | Options |
|------|-----------|--------|---------|
| `get_public_key` | All key-deriving | `[]` | `algorithm`, `index` |
| `sign` | secp256k1, ed25519, ml-dsa-65, slh-dsa-128s | `[<message_hex>]` | `algorithm`, `index`, `scheme`* |
| `verify` | secp256k1, ed25519, ml-dsa-65, slh-dsa-128s | `[<message_hex>, <sig_hex>]` | `algorithm`, `index`, `scheme`* |
| `encapsulate` | ml-kem-768 | `[<peer_pubkey_hex>]` | `algorithm` |
| `decapsulate` | ml-kem-768 | `[<ciphertext_hex>]` | `algorithm`, `index` |
| `derive_shared_secret` | x25519 | `[<peer_pubkey_hex>]` | `algorithm`, `index` |
| `derive` | secp256k1 | `[<data>]` | `algorithm`, `index` (required) |
| `encrypt` | otp | `[<plaintext_base64>]` | `algorithm`, `encoding` |
| `decrypt` | otp | `[<ciphertext>]` | `algorithm`, `encoding` |
\* `scheme`: `"schnorr"` (default) or `"ecdsa"` for secp256k1.
### 10.2 Nostr protocol verbs
These select a secp256k1 NIP-06 key via `nostr_index` (or `role`/`role_path`).
| Verb | Params | Options |
|------|--------|---------|
| `nostr_get_public_key` | `[]` | `nostr_index`, `format` |
| `nostr_sign_event` | `[<event_json>]` | `nostr_index` |
| `nostr_mine_event` | `[<event_json>]` | `nostr_index`, `difficulty`, `timeout_sec`, `threads` |
| `nostr_nip04_encrypt` | `[<peer_pubkey_hex>, <plaintext>]` | `nostr_index` |
| `nostr_nip04_decrypt` | `[<peer_pubkey_hex>, <ciphertext>]` | `nostr_index` |
| `nostr_nip44_encrypt` | `[<peer_pubkey_hex>, <plaintext>]` | `nostr_index` |
| `nostr_nip44_decrypt` | `[<peer_pubkey_hex>, <ciphertext>]` | `nostr_index` |
### 10.3 Metadata
| Verb | Params | Description |
|------|--------|-------------|
| `get_info` | `[]` | Returns signer metadata (name, version, supported verbs/algorithms). Safe to call before mnemonic is loaded. |
### 10.4 Example requests
```json
// Get public key for ML-DSA-65 index 0
{"id":"1","method":"get_public_key","params":[{"algorithm":"ml-dsa-65","index":0}]}
// Sign "hello" with ed25519 index 0
{"id":"2","method":"sign","params":["68656c6c6f",{"algorithm":"ed25519","index":0}]}
// Sign a Nostr event with nostr_index 0
{"id":"3","method":"nostr_sign_event","params":["{\"kind\":1,\"content\":\"Hello\",\"tags\":[],\"created_at\":1700000000,\"pubkey\":\"<hex>\"}",{"nostr_index":0}]}
// NIP-44 encrypt
{"id":"4","method":"nostr_nip44_encrypt","params":["<peer_pubkey_hex>","secret message",{"nostr_index":0}]}
// ML-KEM-768 encapsulate
{"id":"5","method":"encapsulate","params":["<peer_pubkey_hex>",{"algorithm":"ml-kem-768"}]}
// Derive HMAC-SHA256(privkey, data) for opaque identifiers
{"id":"6","method":"derive","params":["<data_hex>",{"algorithm":"secp256k1","index":0}]}
```
---
## 11. Algorithm reference
| Algorithm | Key type | FIPS | Derivation path | Pubkey | Privkey | Signature |
|-----------|----------|------|-----------------|--------|---------|-----------|
| `secp256k1` | Signature (Nostr) | — | `m/44'/1237'/<n>'/0/0` | 32 B | 32 B | 64 B |
| `ed25519` | Signature (SSH) | — | `m/44'/102001'/<n>'/0/0'` | 32 B | 32 B | 64 B |
| `x25519` | Key agreement (age) | — | `m/44'/102002'/<n>'/0/0'` | 32 B | 32 B | — |
| `ml-dsa-65` | PQ signature | FIPS 204 | DRBG from seed | 1952 B | 4032 B | 3309 B |
| `slh-dsa-128s` | PQ hash-based sig | FIPS 205 | DRBG from seed | 32 B | 64 B | 7856 B |
| `ml-kem-768` | PQ KEM | FIPS 203 | DRBG from seed | 1184 B | 2400 B | — |
| `otp` | One-time pad | — | USB pad (no derivation) | — | — | — |
### 11.1 `get_public_key` response format
Algorithm-based `get_public_key` returns structured JSON:
```json
{"algorithm":"ml-dsa-65","public_key":"<hex>","key_id":"<first 16 hex chars of pubkey>"}
```
Nostr `nostr_get_public_key` returns a plain 64-hex-char string by default, or structured JSON with `{"format":"structured"}`.
---
## 12. Error codes
| Code | Message | Meaning |
|------|---------|---------|
| -32700 | `parse_error` | Request is not valid JSON |
| -32600 | `invalid_request` | Missing `id`, `method`, or `params` |
| -32601 | `method_not_found` | Unknown verb |
| -32602 | `invalid_params` | Malformed arguments |
| 1001 | `ambiguous_role_selector` | Multiple role selectors given |
| 1002 | `unknown_role` | No role matched selector |
| 1003 | `no_default_role` | No selector and no `main` role |
| 1004 | `purpose_mismatch` | Role purpose not valid for verb |
| 1005 | `curve_mismatch` | Role curve not valid for verb |
| 1006 | `mnemonic_not_loaded` | No mnemonic loaded |
| 1007 | `no_termination_condition` | `nostr_mine_event` without difficulty/timeout |
| 1008 | `mining_failed` | Internal PoW error |
| 1009 | `not_yet_implemented` | Verb+algorithm not yet implemented |
| 1010 | `algorithm_not_supported_for_verb` | Algorithm not valid for verb |
| 2010 | `auth_envelope_malformed` | Auth JSON is malformed |
| 2011 | `auth_body_mismatch` | Auth tags don't match request |
| 2012 | `auth_signature_invalid` | Auth signature doesn't verify |
| 2013 | `auth_kind_invalid` | Auth kind != 27235 |
| 2014 | `auth_envelope_required` | Auth missing (TCP/HTTP) |
| 2015 | `auth_envelope_mismatch` | Timestamp skew or replay |
---
## 13. End-to-end: publish a Nostr event
This is the most common agent task. Here's the complete flow using qrexec (simplest cross-qube transport):
```python
#!/usr/bin/env python3
"""Publish a Nostr event via n_signer over qrexec."""
import json, struct, subprocess, sys, time
def call_nsigner(target_qube, request):
payload = json.dumps(request, separators=(",", ":")).encode()
frame = struct.pack(">I", len(payload)) + payload
proc = subprocess.Popen(
["qrexec-client-vm", target_qube, "qubes.NsignerRpc"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
)
out, _ = proc.communicate(frame)
length = struct.unpack(">I", out[:4])[0]
return json.loads(out[4:4+length])
target = sys.argv[1] if len(sys.argv) > 1 else "nostr_signer"
idx = int(sys.argv[2]) if len(sys.argv) > 2 else 0
# Step 1: Get public key
pub = call_nsigner(target, {"id":"1","method":"get_public_key","params":[{"nostr_index":idx}]})["result"]
print(f"Pubkey: {pub}")
# Step 2: Build and sign event
event = {
"kind": 1,
"content": "Hello from my agent!",
"created_at": int(time.time()),
"tags": [],
"pubkey": pub,
}
result = call_nsigner(target, {
"id": "2",
"method": "nostr_sign_event",
"params": [json.dumps(event, separators=(",",":")), {"nostr_index": idx}],
})
signed = json.loads(result["result"])
print(f"Event ID: {signed['id']}")
print(f"Signature: {signed['sig']}")
# Step 3: Broadcast to relay(s)
# signed is a complete Nostr event with id and sig — send to any relay
```
---
## 14. End-to-end: sign arbitrary data
Using algorithm-based verbs (any algorithm, any index):
```python
# Sign "hello" with ed25519 index 0
result = call_nsigner(target, {
"id": "1",
"method": "sign",
"params": ["68656c6c6f", {"algorithm": "ed25519", "index": 0}],
})
signature = result["result"] # hex string
# Verify
result = call_nsigner(target, {
"id": "2",
"method": "verify",
"params": ["68656c6c6f", signature, {"algorithm": "ed25519", "index": 0}],
})
print(f"Verified: {result['result']}") # "true" or "false"
```
---
## 15. End-to-end: PQ KEM encapsulate/decapsulate
```python
# Get ML-KEM-768 public key for index 0
pub_result = call_nsigner(target, {
"id": "1",
"method": "get_public_key",
"params": [{"algorithm": "ml-kem-768", "index": 0}],
})
pub_info = json.loads(pub_result["result"])
print(f"ML-KEM-768 pubkey: {pub_info['public_key'][:32]}...")
# Encapsulate (generate a shared secret + ciphertext for that pubkey)
enc_result = call_nsigner(target, {
"id": "2",
"method": "encapsulate",
"params": [pub_info["public_key"], {"algorithm": "ml-kem-768"}],
})
enc_data = json.loads(enc_result["result"])
print(f"Ciphertext: {enc_data['ciphertext'][:32]}...")
print(f"Shared secret: {enc_data['shared_secret'][:32]}...")
# Decapsulate (recover shared secret from ciphertext using private key)
dec_result = call_nsigner(target, {
"id": "3",
"method": "decapsulate",
"params": [enc_data["ciphertext"], {"algorithm": "ml-kem-768", "index": 0}],
})
dec_data = json.loads(dec_result["result"])
print(f"Decapsulated secret: {dec_data['shared_secret'][:32]}...")
assert dec_data["shared_secret"] == enc_data["shared_secret"]
print("✓ KEM round-trip verified")
```
---
## 16. Discovery: finding running signers
### 16.1 List running signers
```bash
nsigner list
```
Output (one per line):
```
@nsigner
@nsigner_hairy_dog
@nsigner_brave_canyon
```
### 16.2 Check if a specific signer is running
```bash
nsigner list | grep -q @nsigner && echo "running" || echo "not running"
```
### 16.3 Programmatic discovery (Python)
```python
import subprocess
result = subprocess.run(["nsigner", "list"], capture_output=True, text=True)
signers = [s.strip() for s in result.stdout.split("\n") if s.strip()]
print(f"Found {len(signers)} signer(s): {signers}")
```
---
## 17. Prerequisites and setup
### 17.1 On the signer qube
```bash
# Install nsigner
# Start the persistent signer
nsigner --listen unix --socket-name nsigner --bridge-source-trusted
# Install qrexec service
sudo cp packaging/qubes/rpc/qubes.NsignerRpc /etc/qubes-rpc/qubes.NsignerRpc
sudo chmod 0755 /etc/qubes-rpc/qubes.NsignerRpc
```
### 17.2 In dom0
```bash
# Install policy
sudo cp packaging/qubes/policy.d/40-nsigner.policy /etc/qubes/policy.d/40-nsigner.policy
# Tag the signer qube
qvm-tags nostr_signer add nsigner-signer
```
### 17.3 On the caller qube
No special setup needed — just `qrexec-client-vm` (pre-installed in all Qubes templates).
---
## 18. Reference files in this repo
| File | What it shows |
|------|---------------|
| [`client/demo_python.py`](../client/demo_python.py) | Full Python demo (qrexec, stdlib only) — get_public_key, sign_event, nip44, mine_event |
| [`client/demo_javascript.js`](../client/demo_javascript.js) | Full Node.js demo (qrexec) — same operations |
| [`client/demo_c99.c`](../client/demo_c99.c) | Full C99 demo (qrexec, nostr_core_lib) — same operations |
| [`examples/get_pubkey_fips.py`](../examples/get_pubkey_fips.py) | Minimal TCP/FIPS with auth envelope (Python) |
| [`examples/get_pubkey_qrexec.c`](../examples/get_pubkey_qrexec.c) | Minimal qrexec in C |
| [`examples/get_pubkey_tcp.c`](../examples/get_pubkey_tcp.c) | Minimal TCP in C with auth envelope |
| [`examples/n_signer_qube_example_fips.js`](../examples/n_signer_qube_example_fips.js) | TCP/FIPS in Node.js with auth envelope |
| [`examples/n_signer_qube_example_qrexec.js`](../examples/n_signer_qube_example_qrexec.js) | qrexec in Node.js |
| [`examples/get_public_key_client.c`](../examples/get_public_key_client.c) | Unix socket in C |
| [`examples/sign_event_client.c`](../examples/sign_event_client.c) | Unix socket sign event in C |
| [`examples/feather_get_public_key.py`](../examples/feather_get_public_key.py) | USB/serial hardware signer (Python) |
| [`examples/feather_sign_event.py`](../examples/feather_sign_event.py) | USB/serial sign event (Python) |
| [`examples/pq_sign_example.c`](../examples/pq_sign_example.c) | ML-DSA-65 sign in C |
| [`examples/pq_kem_example.c`](../examples/pq_kem_example.c) | ML-KEM-768 encaps/decaps in C |
| [`examples/ssh_sign_example.c`](../examples/ssh_sign_example.c) | ed25519 SSH sign in C |
| [`documents/CLIENT_IMPLEMENTATION.md`](CLIENT_IMPLEMENTATION.md) | Full wire contract spec (733 lines) |
| [`README.md`](../README.md) | Full n_signer documentation (741 lines) |
| [`packaging/qubes/setup_signer_qube.sh`](../packaging/qubes/setup_signer_qube.sh) | Automated signer qube setup |
| [`.roo/n_signer_client.md`](../.roo/n_signer_client.md) | Roo skill file (agent-invocable) |
+5 -7
View File
@@ -151,16 +151,14 @@ See [README.md §4c](../README.md) for full details.
The last param may include selector options:
- `role`
- `nostr_index`
- `role_path`
- `role` — name of a pre-registered role entry
- `role_path` — full BIP-44 derivation path
Resolution order:
1. `role`
2. `nostr_index`
3. `role_path`
4. default role `main`
2. `role_path`
3. default role `main`
Conflicting selector fields must be rejected as `ambiguous_role_selector`.
@@ -457,7 +455,7 @@ Request:
"method": "sign_event",
"params": [
"<event_json>",
{ "role": "main", "nostr_index": 0 }
{ "role": "main", "role_path": "m/44'/1237'/0'/0/0" }
]
}
```
+227
View File
@@ -0,0 +1,227 @@
# Derivation Paths — A Simple Explanation
## The seed
When you create a mnemonic (seed phrase), it generates a single master key. Think of it as the root of a tree — one key that controls everything below it.
## The tree
From that master key, you can derive **child keys**. Each child key can have its own children, and so on. This creates a tree of keys, all derived from the same seed.
## The path
A **derivation path** is just a set of directions for walking down the tree. It tells you which branches to take, starting from the master key (`m`).
```
m / 44' / 1237' / 0' / 0 / 0
```
Read it left to right:
| Segment | Meaning |
|---------|---------|
| `m` | The master key (your seed) |
| `44'` | Purpose: "this is a BIP-44 wallet" |
| `1237'` | Coin type: "this is Nostr" (1237 is Nostr's registered coin type) |
| `0'` | Account: "account #0" |
| `0` | Change: "external/receive" (0) vs "internal/change" (1) |
| `0` | Address index: "address #0" |
Each segment derives a child key from the parent. Change any segment and you get a completely different key.
## The apostrophe (hardened vs unhardened)
The `'` after a number means **hardened**. It's the most important detail in the path.
### Without the apostrophe (unhardened)
```
m / 44' / 1237' / 0' / 0 / 0
^
no apostrophe = unhardened
```
Unhardened means: you can derive this child's **public key** from just the parent's **public key** — you don't need the private key.
This is useful for **watch-only wallets**: you can share the parent's extended public key with someone, and they can derive all the child public keys (addresses) without ever seeing your private key.
**The risk:** if a child **private key** leaks, and someone has the parent's extended public key, they can work backwards and derive **all sibling private keys**. So if address #5's private key leaks, addresses #0-4 and #6-99 are also compromised.
### With the apostrophe (hardened)
```
m / 44' / 1237' / 0' / 0' / 0'
^
apostrophe = hardened
```
Hardened means: you **need the parent's private key** to derive this child. You cannot derive it from the public key alone.
**The benefit:** if a child private key leaks, the attacker **cannot** derive sibling keys. Each hardened child is isolated. Compromising one doesn't compromise the others.
### Simple analogy
Imagine a building with floors and rooms:
- **Unhardened** = a glass door. Anyone with the floor key can see into all rooms on that floor. If someone picks the lock on room #5, they can figure out how to open rooms #0-4 and #6-99 too.
- **Hardened** = a steel door. You need the master floor key to open any room. Picking the lock on room #5 tells you nothing about the other rooms.
### Visual: what happens when one key leaks
**Unhardened** (no apostrophe) — one leak compromises ALL siblings:
```
m/44'/1237'/0'/0/0 ✓ safe
m/44'/1237'/0'/0/1 ✓ safe
m/44'/1237'/0'/0/2 ✓ safe
m/44'/1237'/0'/0/3 ✓ safe
m/44'/1237'/0'/0/4 ✓ safe
m/44'/1237'/0'/0/5 ✗ COMPROMISED (leaked)
m/44'/1237'/0'/0/6 ✗ COMPROMISED (derived from leak + parent pubkey)
m/44'/1237'/0'/0/7 ✗ COMPROMISED (derived from leak + parent pubkey)
...
m/44'/1237'/0'/0/99 ✗ COMPROMISED (derived from leak + parent pubkey)
Parent extended public key (m/44'/1237'/0'/0) is public
+ one child private key (address #5) leaks
= ALL 100 sibling private keys are compromised
```
**Hardened** (with apostrophe) — one leak only affects that one key:
```
m/44'/1237'/0'/0'/0' ✓ safe
m/44'/1237'/0'/0'/1' ✓ safe
m/44'/1237'/0'/0'/2' ✓ safe
m/44'/1237'/0'/0'/3' ✓ safe
m/44'/1237'/0'/0'/4' ✓ safe
m/44'/1237'/0'/0'/5' ✗ COMPROMISED (leaked)
m/44'/1237'/0'/0'/6' ✓ safe (cannot be derived without parent PRIVATE key)
m/44'/1237'/0'/0'/7' ✓ safe (cannot be derived without parent PRIVATE key)
...
m/44'/1237'/0'/0'/99' ✓ safe (cannot be derived without parent PRIVATE key)
One child private key (address #5) leaks
= ONLY address #5 is compromised
= siblings are safe because hardened derivation requires the parent PRIVATE key
```
## Why NIP-06 uses unhardened last segments
NIP-06 (Nostr's key derivation standard) uses `m/44'/1237'/<account>'/0/0` — the first three segments are hardened, the last two are unhardened.
This is because NIP-06 copied the BIP-44 pattern from Bitcoin, where:
- The **account** segment is hardened (so different accounts are isolated)
- The **change** and **address** segments are unhardened (so watch-only wallets can derive addresses without the private key)
For Bitcoin, this makes sense: you want to share your extended public key with a payment processor so they can generate receive addresses for you.
For Nostr, it's less useful — but it means Nostr tools can derive your public keys from your extended public key, which some key management software uses.
## What this means for n_signer
n_signer always holds your private key and derives everything itself. You never share extended public keys with anyone. So:
- **Unhardened segments give you no benefit** — you don't need watch-only derivation
- **Unhardened segments add risk** — the child key compromise vulnerability
### Recommendation
**Harden everything** if you don't need NIP-06 compatibility:
```
m/44'/1237'/0'/0'/0' ← all hardened, maximum isolation
m/44'/1237'/0-99'/0'/0' ← all hardened, 100 isolated agent keys
```
**Use NIP-06 paths** if you want compatibility with standard Nostr tools:
```
m/44'/1237'/0'/0/0 ← NIP-06 standard (last two unhardened)
m/44'/1237'/0-99'/0/0 ← NIP-06 compatible, 100 agent keys
```
## Common path patterns
### Standard Nostr (NIP-06)
```
m/44'/1237'/0'/0/0
```
One key. The default Nostr key that tools like `nak keygen` produce.
### Multiple Nostr accounts (NIP-06)
```
m/44'/1237'/0'/0/0 ← account 0
m/44'/1237'/1'/0/0 ← account 1
m/44'/1237'/2'/0/0 ← account 2
```
Change the account segment (hardened) to get different Nostr identities.
### Multiple Nostr agents (hardened, maximum isolation)
```
m/44'/1237'/0'/0'/0' ← agent 0
m/44'/1237'/1'/0'/0' ← agent 1
m/44'/1237'/2'/0'/0' ← agent 2
```
Same as above but with the last two segments hardened. Each agent is fully isolated — compromising one doesn't compromise the others.
### Range and wildcard syntax (n_signer wizard)
In n_signer's role wizard, you can use range syntax or wildcard for the variable segment:
```
m/44'/1237'/0-99'/0/0 ← agents 0-99, NIP-06 compatible
m/44'/1237'/0-99'/0'/0' ← agents 0-99, all hardened
m/44'/1237'/*'/0'/0' ← any agent index, all hardened (wildcard)
```
- `0-99'` means "this segment can be any value from 0 to 99, hardened"
- `*'` means "this segment can be any non-negative integer, hardened" (wildcard — no range limit)
- `*` (without `'`) means "any non-negative integer, unhardened"
The client specifies the exact path (e.g. `m/44'/1237'/5'/0/0` for agent #5), and the server verifies it's within the role's allowed range (or accepts any value for `*`).
### SSH keys (ed25519)
```
m/44'/102001'/0'/0'/0'
```
SLIP-0010 derivation for ed25519. All segments are hardened (SLIP-0010 requires this for ed25519).
### Age / x25519 keys
```
m/44'/102002'/0'/0'/0'
```
Key agreement keys for Age encryption or X25519 ECDH.
### Post-quantum keys
```
m/44'/102003'/0'/0'/0' ← ML-DSA-65 (signatures, FIPS 204)
m/44'/102004'/0'/0'/0' ← SLH-DSA-128s (signatures, FIPS 205)
m/44'/102005'/0'/0'/0' ← ML-KEM-768 (KEM, FIPS 203)
```
All hardened. The mnemonic-derived seed feeds a SHAKE-256 DRBG that replaces PQClean's `randombytes()` during keygen.
## Summary
| Concept | Simple explanation |
|---------|-------------------|
| `m` | The master key (your seed) |
| Numbers | Which branch to take at each level |
| `'` (apostrophe) | "Hardened" — need private key to derive, isolates siblings |
| No `'` | "Unhardened" — can derive from public key, but siblings can be compromised |
| Path | A set of directions from the master key to a specific key |
| Different path | Different key (always, no exceptions) |
**Golden rule:** If you don't need watch-only derivation (and n_signer doesn't), harden everything.
+333
View File
@@ -0,0 +1,333 @@
# nsigner Menu Reference
This document describes every interactive menu and screen in the `nsigner` TUI, in the order they appear during a session. Use this as the authoritative reference when discussing changes to the user experience.
## Startup sequence
The menus appear in this order during interactive (TUI) startup:
1. **Unlock — Mnemonic source**
2. **Define a role — Role preset menu** (loops)
3. **Transport — Transport selection**
4. **Running phase — Main status display**
Non-interactive startup (`--mnemonic-stdin`, `--mnemonic-fd`, or piped input) skips menus 14 and creates a default `main` role automatically.
---
## 1. Unlock — Mnemonic source
**When:** First screen, before anything else.
**Title:** `> Unlock`
**Prompt:**
```
Mnemonic source: [E]nter existing or [G]enerate new
Default is E; you can also paste full mnemonic here.
>
```
**Options:**
| Input | Action |
|-------|--------|
| `E` (default) | Prompt for an existing mnemonic (echo disabled) |
| `G` | Generate a fresh 12-word BIP-39 mnemonic from `getrandom(2)`, display it numbered with a "WRITE THIS DOWN — IT WILL NOT BE SHOWN AGAIN" warning |
| Paste full mnemonic | If the input contains spaces and doesn't start with `G`, it's treated as a mnemonic and validated directly |
| `q` / `x` | Exit |
**After `E`:** Prompts for the mnemonic phrase with terminal echo disabled. Validates BIP-39 checksum. Up to 10 invalid attempts before exit.
**After `G`:** Displays the generated mnemonic numbered 112, then continues.
---
## 2. Define a role — Role preset menu
**When:** After mnemonic is loaded, in TUI mode only.
**Title:** `Define a role — bind a role name to a derivation path template`
**Prompt:**
```
Define a role:
1. Standard Nostr (NIP-06): secp256k1, m/44'/1237'/0'/0/0
2. Standard Nostr range: secp256k1, m/44'/1237'/*'/0/0
3. Nostr agent range (hardened): secp256k1, m/44'/1237'/*'/1'/0'
4. SSH role: ed25519, m/44'/102001'/0'/0'/0'
5. Age/x25519 role: x25519, m/44'/102002'/0'/0'/0'
6. ML-DSA-65 role: post-quantum signatures, m/44'/102003'/0'/0'/0'
7. SLH-DSA-128s role: post-quantum signatures, m/44'/102004'/0'/0'/0'
8. ML-KEM-768 role: post-quantum KEM, m/44'/102005'/0'/0'/0'
9. OTP role (one-time pad encryption)
10. Custom path
Select [1]:
```
**Preset defaults:**
| Choice | Default name | Default path | Curve | Purpose |
|--------|-------------|-------------|-------|---------|
| 1 | `main` | `m/44'/1237'/0'/0/0` | secp256k1 | nostr |
| 2 | `nostr_range` | `m/44'/1237'/*'/0/0` | secp256k1 | nostr |
| 3 | `nostr_agent` | `m/44'/1237'/*'/1'/0'` | secp256k1 | nostr |
| 4 | `ssh` | `m/44'/102001'/0'/0'/0'` | ed25519 | ssh |
| 5 | `age` | `m/44'/102002'/0'/0'/0'` | x25519 | age |
| 6 | `ml_dsa_65` | `m/44'/102003'/0'/0'/0'` | ml-dsa-65 | pq_sig |
| 7 | `slh_dsa_128s` | `m/44'/102004'/0'/0'/0'` | slh-dsa-128s | pq_sig |
| 8 | `ml_kem_768` | `m/44'/102005'/0'/0'/0'` | ml-kem-768 | pq_kem |
| 9 | `otp` | (pad file) | otp | n/a |
| 10 | `custom` | `m/44'/1237'/0'/0/0` | (prompted) | (auto-detected) |
**After selecting a preset, the user is prompted for:**
### 2a. Role name
```
Role name [main]:
```
Editable line (arrow keys, backspace). Defaults to the preset's default name. If the name already exists, it's skipped.
### 2b. Curve (only for choice 10 — Custom)
```
Curve:
1) secp256k1 (Nostr, Bitcoin)
2) ed25519 (SSH)
3) x25519 (key agreement, Age)
4) ml-dsa-65 (post-quantum signatures)
5) slh-dsa-128s (post-quantum signatures)
6) ml-kem-768 (post-quantum KEM)
Select [1]:
```
For presets 18, the curve is set automatically. For OTP (9), no curve is needed.
### 2c. Path template (only for choice 10 — Custom)
```
Path template [m/44'/1237'/0'/0/0]:
```
Editable line. Pre-filled with the default path (updated to match the selected curve). Supports range syntax (`0-1000'`), set syntax (`1+34+54`), and wildcard (`*'` for any index).
For presets 18, the path is set automatically from the preset — no prompt. For OTP (9), no path is needed.
### 2c-otp. OTP pad file (only for choice 9 — OTP)
```
OTP pad directory (e.g. /media/usb0):
OTP pad name (e.g. mypad):
```
Prompts for the pad directory and pad name. The pad is bound immediately. If binding fails, the role is skipped.
### 2d. Requires interactive approval
```
Require interactive approval for each request? [Y/n]:
```
- `Y` (default) → `requires_approval = 1` — human attendant must approve each request
- `n``requires_approval = 0` — role name is the password, no prompt (role-as-password)
### 2e. Confirmation
```
Role 'main' registered: curve=secp256k1 path=m/44'/1237'/0'/0/0 (fixed, requires_approval=1).
```
Or for templated paths:
```
Role 'nostr_agent' registered: curve=secp256k1 path=m/44'/1237'/%d'/1'/0' (range 0-1000, requires_approval=1).
```
### 2f. Loop
```
Define another role? [y/N]:
```
- `y` → back to the preset menu
- `N` (default) → continue to transport selection
**Mandatory:** At least one role must be created. If the user exits without creating any roles, the signer prints "At least one role must be defined." and exits.
---
## 3. Transport — Transport selection
**When:** After role definition, in TUI mode with no `--listen` flag.
**Title:** `Transport — how should other programs reach this signer?`
**Prompt:**
```
Select one or more (type a number to toggle, 'a' for all, Enter to confirm):
[x] 1. Local Unix socket (same machine/qube)
[ ] 2. Qubes qrexec bridge (other qubes via qrexec, no network)
[ ] 3. FIPS/TCP listener (framed JSON, FIPS mesh or local network)
[ ] 4. HTTP listener (curl-friendly, localhost by default)
[a] select all Enter = confirm
>
```
**Options:**
| Input | Action |
|-------|--------|
| `1` | Toggle Local Unix socket |
| `2` | Toggle Qubes qrexec bridge |
| `3` | Toggle FIPS/TCP listener |
| `4` | Toggle HTTP listener |
| `a` | Select all |
| Enter | Confirm current selection (at least one required) |
Default: Unix socket only.
---
## 4. Running phase — Main status display
**When:** After all startup menus, this is the main screen.
**Title:** `> Main Menu`
**Layout:**
```
┌ n_signer v<version> — Main Menu ─────────────────────────┐
│ │
│ Roles: │
│ Role Purpose Curve Derivation path
│ -------------------- ------------ ------------ ------------------------
│ main nostr secp256k1 m/44'/1237'/0'/0/0
│ role1 nostr secp256k1 m/44'/1237'/1-100'/0/0
│ │
│ Activity (latest first): │
│ 14:51:05 uid:1000 nostr_get_public_key(pathrole_2) ALLOWED:prompt
│ 14:50:54 uid:1000 nostr_get_public_key(pathrole_2) ALLOWED:prompt
│ │
│ session=unlocked (12 words) signer=nsigner derived=2 │
│ │
│ l lock/reunlock r refresh d display connections q/x quit
│ │
└───────────────────────────────────────────────────────────┘
>
```
**Status line:** `session=<locked|unlocked> (<N> words) signer=<name> derived=<count>`
**Menu items:**
| Key | Action |
|-----|--------|
| `l` | Lock / re-unlock (re-prompt for mnemonic) |
| `r` | Refresh display |
| `d` | Display connections (show transport details + example client commands) |
| `q` / `x` | Quit |
**Note:** The `a toggle auto-approve` menu item has been **removed**. Authorization is now per-role via the `requires_approval` flag set during role definition.
---
## 5. Approval prompt
**When:** A client request arrives for a role with `requires_approval = 1`, and the request is not pre-approved by policy.
**Title:** `> Approval`
**Layout:**
```
┌ n_signer v<version> — Approval ──────────────────────────┐
│ │
│ Approval required │
│ caller: uid:1000 │
│ method: nostr_sign_event │
│ role: main │
│ purpose: nostr │
│ ** NEW IDENTITY — will be derived if approved ** │
│ │
│ y: allow once │
│ n: deny │
│ e: allow this caller+role+verb for session │
│ a: allow this caller+role for session (all verbs) │
│ │
└───────────────────────────────────────────────────────────┘
>
```
**Options:**
| Key | Action | Policy result |
|-----|--------|---------------|
| `y` | Allow this one request | `POLICY_ALLOW` |
| `n` | Deny this request | `POLICY_DENY` |
| `e` | Allow this caller+role+verb for the rest of the session | `POLICY_ALLOW_SESSION_VERB` |
| `a` | Allow this caller+role for all verbs for the session | `POLICY_ALLOW_SESSION_ALL` |
The `** NEW IDENTITY — will be derived if approved **` line appears only when the requested key hasn't been derived yet.
**Fields shown:**
- `caller` — the caller identity (e.g. `uid:1000`, `qubes:vm-name`, `pubkey:<hex>`)
- `fips peer` — (TCP/FIPS mode only) the peer's npub and optional name
- `method` — the JSON-RPC verb (e.g. `nostr_sign_event`, `nostr_get_public_key`)
- `role` — the role name from the request
- `purpose` — the role's purpose (nostr, ssh, age, pq_sig, pq_kem)
---
## 6. Display connections
**When:** Pressed `d` from the main status display.
**Shows:** For each active transport, a section with:
- Transport name and description
- Socket address / port / URL
- Example client command
After any keypress, returns to the main status display.
---
## Non-interactive mode
When started with `--mnemonic-stdin` or `--mnemonic-fd`, or when stdin is not a TTY:
- Menus 14 are skipped
- A default `main` role is created automatically: `secp256k1`, `m/44'/1237'/0'/0/0`, `requires_approval=1`
- The `--allow-all` flag sets `server_set_prompt_always_allow(1)` which bypasses approval prompts (used by tests and automated setups)
- The `NSIGNER_TEST_NONINTERACTIVE_PROMPT` env var can be set to `allow` or `deny` to control the non-interactive prompt fallback
---
## CLI flags that affect menus
| Flag | Effect |
|------|--------|
| `--listen <mode>` | Skips transport selection menu (menu 3) |
| `--mnemonic-stdin` | Skips mnemonic menu (menu 1), reads from stdin |
| `--mnemonic-fd <N>` | Skips mnemonic menu (menu 1), reads from fd N |
| `--allow-all` | Skips approval prompts (sets `prompt_always_allow`) |
| `--socket-name <name>` | Sets the socket name (skips random name generation) |
| `--preapprove <SPEC>` | Pre-approves specific caller+role+verb combinations |
---
## Summary flow
```mermaid
flowchart TD
A[Start] --> B{stdin is TTY?}
B -- No --> C[Non-interactive: create default main role]
B -- Yes --> D[Menu 1: Unlock — mnemonic source]
D --> E[Menu 2: Define a role — preset menu]
E --> F{Another role?}
F -- Yes --> E
F -- No --> G{At least one role?}
G -- No --> H[Error: at least one role required]
G -- Yes --> I{--listen flag?}
I -- No --> J[Menu 3: Transport selection]
I -- Yes --> K[Use --listen mode]
J --> N[Menu 4: Main status display]
K --> N
C --> N
N --> O{Request arrives}
O --> P{requires_approval?}
P -- No --> Q[Authorize immediately]
P -- Yes --> R{Pre-approved?}
R -- Yes --> Q
R -- No --> S[Menu 6: Approval prompt]
S -- y/e/a --> Q
S -- n --> T[Deny]
```
-535
View File
@@ -1,535 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>n_signer CYD Web Serial Demo</title>
<style>
:root {
--bg: #0b0f14;
--panel: #121821;
--panel-2: #182231;
--text: #e6edf3;
--muted: #9fb0c3;
--accent: #58a6ff;
--good: #3fb950;
--bad: #f85149;
--border: #263448;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: Inter, system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.35;
}
.wrap { max-width: 980px; margin: 20px auto; padding: 0 14px 24px; }
h1 { margin: 0 0 8px; font-size: 1.45rem; }
p.note { margin: 0 0 14px; color: var(--muted); }
.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 12px; margin-top: 12px; }
.card { background: linear-gradient(180deg, var(--panel), var(--panel-2)); border: 1px solid var(--border); border-radius: 12px; padding: 12px; }
.card h2 { font-size: 1rem; margin: 0 0 10px; }
label { font-size: 0.86rem; color: var(--muted); display: block; margin: 6px 0 4px; }
input, textarea, select, button { font: inherit; border-radius: 8px; border: 1px solid var(--border); }
input, textarea, select { width: 100%; background: #0c131d; color: var(--text); padding: 8px 10px; }
textarea { min-height: 64px; resize: vertical; }
input[type="number"] { max-width: 130px; }
button { background: #1f6feb; color: white; padding: 8px 12px; cursor: pointer; border: 0; }
button[disabled] { opacity: 0.55; cursor: not-allowed; }
.secondary { background: #334155; }
.status { padding: 6px 10px; border-radius: 999px; background: #2a3648; color: var(--muted); font-size: 0.85rem; border: 1px solid var(--border); }
.status.ok { color: var(--good); border-color: #2f5a3a; }
.status.err { color: var(--bad); border-color: #6a3131; }
pre { margin: 8px 0 0; background: #0a1018; border: 1px solid #1b2636; color: #d7e2ee; padding: 10px; border-radius: 8px; overflow: auto; max-height: 200px; font-size: 12px; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.warn { color: #d29922; font-size: 0.8rem; }
</style>
</head>
<body>
<div class="wrap">
<h1>n_signer CYD Web Serial Demo</h1>
<p class="note">Connect to the CYD (CH340 serial) via Web Serial, then exercise every algorithm and verb in the n_signer API. Chrome/Edge/Brave/Opera only.</p>
<div class="card">
<div class="row">
<button id="connectBtn">Connect Web Serial</button>
<button id="disconnectBtn" class="secondary" disabled>Disconnect</button>
<span id="connStatus" class="status">Disconnected</span>
</div>
<pre id="log" class="mono"></pre>
</div>
<div class="grid">
<!-- Get Public Key (algorithm-based) -->
<section class="card">
<h2>Get Public Key (algorithm)</h2>
<label for="gpkAlg">Algorithm</label>
<select id="gpkAlg">
<option>secp256k1</option><option>ed25519</option><option>x25519</option>
<option>ml-dsa-65</option><option>slh-dsa-128s</option><option>ml-kem-768</option>
</select>
<label for="gpkIdx">Index</label>
<input id="gpkIdx" type="number" value="0" min="0" />
<div class="row" style="margin-top:10px">
<button id="gpkBtn" disabled>get_public_key</button>
</div>
<pre id="gpkOut" class="mono"></pre>
</section>
<!-- Nostr Get Public Key -->
<section class="card">
<h2>nostr_get_public_key</h2>
<label for="ngpkIdx">nostr_index</label>
<input id="ngpkIdx" type="number" value="0" min="0" />
<label for="ngpkFmt">format</label>
<select id="ngpkFmt"><option>bare</option><option>structured</option></select>
<div class="row" style="margin-top:10px">
<button id="ngpkBtn" disabled>nostr_get_public_key</button>
</div>
<pre id="ngpkOut" class="mono"></pre>
</section>
<!-- Sign / Verify -->
<section class="card">
<h2>sign / verify</h2>
<label for="signAlg">Algorithm</label>
<select id="signAlg">
<option>secp256k1</option><option>ed25519</option><option>ml-dsa-65</option><option>slh-dsa-128s</option>
</select>
<label for="signIdx">Index</label>
<input id="signIdx" type="number" value="0" min="0" />
<label for="signScheme">scheme (secp256k1 only)</label>
<select id="signScheme"><option>schnorr</option><option>ecdsa</option></select>
<label for="signMsg">message (hex)</label>
<input id="signMsg" value="68656c6c6f" />
<div class="row" style="margin-top:10px">
<button id="signBtn" disabled>sign</button>
<button id="verifyBtn" disabled>verify</button>
</div>
<pre id="signOut" class="mono"></pre>
</section>
<!-- KEM encapsulate / decapsulate -->
<section class="card">
<h2>encapsulate / decapsulate (ml-kem-768)</h2>
<label for="kemPeer">peer pubkey hex (1184 bytes / 2368 hex) — leave empty to use self pubkey</label>
<textarea id="kemPeer" placeholder="auto: uses ml-kem-768 get_public_key"></textarea>
<label for="kemIdx">index (for decapsulate)</label>
<input id="kemIdx" type="number" value="0" min="0" />
<label for="kemCt">ciphertext hex (for decapsulate)</label>
<textarea id="kemCt" placeholder="filled by encapsulate"></textarea>
<div class="row" style="margin-top:10px">
<button id="encapBtn" disabled>encapsulate</button>
<button id="decapBtn" disabled>decapsulate</button>
</div>
<pre id="kemOut" class="mono"></pre>
</section>
<!-- derive_shared_secret (x25519) -->
<section class="card">
<h2>derive_shared_secret (x25519)</h2>
<label for="x25519Peer">peer pubkey hex (32 bytes / 64 hex)</label>
<input id="x25519Peer" placeholder="64 hex chars" />
<label for="x25519Idx">index</label>
<input id="x25519Idx" type="number" value="0" min="0" />
<div class="row" style="margin-top:10px">
<button id="x25519Btn" disabled>derive_shared_secret</button>
</div>
<pre id="x25519Out" class="mono"></pre>
</section>
<!-- derive (HMAC) -->
<section class="card">
<h2>derive (secp256k1 HMAC-SHA256)</h2>
<label for="deriveData">data (UTF-8 string)</label>
<input id="deriveData" value="hello-derive" />
<label for="deriveIdx">index (required)</label>
<input id="deriveIdx" type="number" value="0" min="0" />
<div class="row" style="margin-top:10px">
<button id="deriveBtn" disabled>derive</button>
</div>
<pre id="deriveOut" class="mono"></pre>
</section>
<!-- Nostr Sign Event -->
<section class="card">
<h2>nostr_sign_event</h2>
<label for="nseContent">content</label>
<textarea id="nseContent">hello from cyd webserial demo</textarea>
<label for="nseIdx">nostr_index</label>
<input id="nseIdx" type="number" value="0" min="0" />
<div class="row" style="margin-top:10px">
<button id="nseBtn" disabled>nostr_sign_event</button>
</div>
<pre id="nseOut" class="mono"></pre>
</section>
<!-- Nostr Mine Event -->
<section class="card">
<h2>nostr_mine_event</h2>
<p class="warn">Slow on ESP32 — uses single-threaded PoW. Keep difficulty low.</p>
<label for="nmeContent">content</label>
<textarea id="nmeContent">mined by cyd</textarea>
<label for="nmeIdx">nostr_index</label>
<input id="nmeIdx" type="number" value="0" min="0" />
<label for="nmeDiff">difficulty (leading zero bits)</label>
<input id="nmeDiff" type="number" value="4" min="1" max="16" />
<label for="nmeTimeout">timeout (sec)</label>
<input id="nmeTimeout" type="number" value="30" min="1" max="60" />
<div class="row" style="margin-top:10px">
<button id="nmeBtn" disabled>nostr_mine_event</button>
</div>
<pre id="nmeOut" class="mono"></pre>
</section>
<!-- NIP-04 -->
<section class="card">
<h2>nostr_nip04_encrypt / decrypt</h2>
<label for="nip04Peer">peer pubkey hex (32-byte x-only)</label>
<input id="nip04Peer" placeholder="64 hex chars" />
<label for="nip04Msg">plaintext</label>
<textarea id="nip04Msg">hello via nip04</textarea>
<label for="nip04Cipher">ciphertext (for decrypt)</label>
<textarea id="nip04Cipher" placeholder="ciphertext?iv=..."></textarea>
<label for="nip04Idx">nostr_index</label>
<input id="nip04Idx" type="number" value="0" min="0" />
<div class="row" style="margin-top:10px">
<button id="nip04EncBtn" disabled>encrypt</button>
<button id="nip04DecBtn" disabled>decrypt</button>
</div>
<pre id="nip04Out" class="mono"></pre>
</section>
<!-- NIP-44 -->
<section class="card">
<h2>nostr_nip44_encrypt / decrypt</h2>
<label for="nip44Peer">peer pubkey hex (32-byte x-only)</label>
<input id="nip44Peer" placeholder="64 hex chars" />
<label for="nip44Msg">plaintext</label>
<textarea id="nip44Msg">hello via nip44</textarea>
<label for="nip44Cipher">ciphertext (for decrypt)</label>
<textarea id="nip44Cipher" placeholder="base64 payload"></textarea>
<label for="nip44Idx">nostr_index</label>
<input id="nip44Idx" type="number" value="0" min="0" />
<div class="row" style="margin-top:10px">
<button id="nip44EncBtn" disabled>encrypt</button>
<button id="nip44DecBtn" disabled>decrypt</button>
</div>
<pre id="nip44Out" class="mono"></pre>
</section>
<!-- OTP encrypt / decrypt -->
<section class="card">
<h2>encrypt / decrypt (otp)</h2>
<p class="note">OTP pad is derived from the mnemonic on the CYD. Offset advances monotonically.</p>
<label for="otpPlain">plaintext (base64)</label>
<textarea id="otpPlain">SGVsbG8sIE9UUCB3b3JsZCE=</textarea>
<label for="otpCipher">ciphertext (for decrypt, base64)</label>
<textarea id="otpCipher" placeholder="filled by encrypt"></textarea>
<label for="otpEnc">encoding</label>
<select id="otpEnc"><option>ascii</option><option>binary</option></select>
<div class="row" style="margin-top:10px">
<button id="otpEncBtn" disabled>encrypt</button>
<button id="otpDecBtn" disabled>decrypt</button>
</div>
<pre id="otpOut" class="mono"></pre>
</section>
</div>
</div>
<script type="module">
import { schnorr } from "https://esm.sh/@noble/curves@1.5.0/secp256k1?bundle";
const logEl = document.getElementById("log");
const connStatusEl = document.getElementById("connStatus");
const connectBtn = document.getElementById("connectBtn");
const disconnectBtn = document.getElementById("disconnectBtn");
let port = null;
let reader = null;
let writer = null;
let readLoopRunning = false;
let rxBuffer = new Uint8Array(0);
let pendingResolve = null;
function log(...args) {
logEl.textContent += args.join(" ") + "\n";
logEl.scrollTop = logEl.scrollHeight;
}
function setStatus(text, mode = "") {
connStatusEl.textContent = text;
connStatusEl.className = `status ${mode}`.trim();
}
function hex(bytes) {
return Array.from(bytes).map(b => b.toString(16).padStart(2, "0")).join("");
}
function utf8(s) { return new TextEncoder().encode(s); }
function be32(n) {
return new Uint8Array([(n >>> 24) & 0xff, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff]);
}
async function sha256Hex(dataBytes) {
const h = await crypto.subtle.digest("SHA-256", dataBytes);
return hex(new Uint8Array(h));
}
function pretty(value) {
try { return JSON.stringify(value, null, 2); } catch { return String(value); }
}
async function buildAuth(method, params) {
const callerPriv = Uint8Array.from({ length: 32 }, (_, i) => i + 1);
const callerPubX = hex(schnorr.getPublicKey(callerPriv));
const createdAt = Math.floor(Date.now() / 1000);
const paramsJson = JSON.stringify(params);
const bodyHash = await sha256Hex(utf8(paramsJson));
const tags = [
["nsigner_rpc", "1"],
["nsigner_method", method],
["nsigner_body_hash", bodyHash],
];
const content = "cyd-webserial-demo";
const ser = JSON.stringify([0, callerPubX, createdAt, 27235, tags, content]);
const id = await sha256Hex(utf8(ser));
const sigBytes = await schnorr.sign(id, callerPriv, new Uint8Array(32));
const sigHex = typeof sigBytes === "string" ? sigBytes : hex(sigBytes);
return { id, pubkey: callerPubX, created_at: createdAt, kind: 27235, tags, content, sig: sigHex };
}
/* ---- Web Serial transport ---- */
async function readLoop() {
readLoopRunning = true;
while (readLoopRunning && reader) {
try {
const { value, done } = await reader.read();
if (done) break;
if (value) {
const next = new Uint8Array(rxBuffer.length + value.length);
next.set(rxBuffer, 0);
next.set(value, rxBuffer.length);
rxBuffer = next;
tryDeliver();
}
} catch (e) {
log("read error:", e.message);
break;
}
}
readLoopRunning = false;
}
function tryDeliver() {
if (pendingResolve === null) return;
while (rxBuffer.length >= 4) {
const len = (rxBuffer[0] << 24) | (rxBuffer[1] << 16) | (rxBuffer[2] << 8) | rxBuffer[3];
if (len <= 0 || len > 16384) {
/* resync: drop one byte */
rxBuffer = rxBuffer.slice(1);
continue;
}
if (rxBuffer.length < 4 + len) return;
const payload = rxBuffer.slice(4, 4 + len);
rxBuffer = rxBuffer.slice(4 + len);
const text = new TextDecoder().decode(payload);
let parsed;
try { parsed = JSON.parse(text); } catch { parsed = text; }
const r = pendingResolve;
pendingResolve = null;
r(parsed);
if (pendingResolve === null) return;
}
}
async function sendRpc(reqObj) {
if (!writer) throw new Error("not connected");
const body = utf8(JSON.stringify(reqObj));
const frame = new Uint8Array(4 + body.length);
frame.set(be32(body.length), 0);
frame.set(body, 4);
await writer.write(frame);
const resp = await new Promise((resolve, reject) => {
pendingResolve = resolve;
setTimeout(() => {
if (pendingResolve === resolve) {
pendingResolve = null;
reject(new Error("timeout (30s) — check the CYD screen for an approval prompt"));
}
}, 65000);
});
return resp;
}
async function callVerb(method, params, outEl) {
outEl.textContent = "→ " + method + " " + JSON.stringify(params);
try {
const auth = await buildAuth(method, params);
const req = { id: String(Math.floor(Math.random() * 1e9)), method, params, auth };
const resp = await sendRpc(req);
outEl.textContent += "\n← " + pretty(resp);
} catch (e) {
outEl.textContent += "\n✗ " + e.message;
}
}
/* ---- Connect / Disconnect ---- */
connectBtn.addEventListener("click", async () => {
try {
port = await navigator.serial.requestPort();
await port.open({ baudRate: 115200 });
reader = port.readable.getReader();
writer = port.writable.getWriter();
rxBuffer = new Uint8Array(0);
readLoop();
setStatus("Connected", "ok");
log("Connected to CYD via Web Serial @ 115200 baud");
document.querySelectorAll("button[id$='Btn']").forEach(b => {
if (b !== connectBtn && b !== disconnectBtn) b.disabled = false;
});
disconnectBtn.disabled = false;
connectBtn.disabled = true;
} catch (e) {
setStatus("Error", "err");
log("connect failed:", e.message);
}
});
disconnectBtn.addEventListener("click", async () => {
readLoopRunning = false;
try { if (reader) await reader.cancel(); } catch {}
try { if (writer) await writer.releaseLock(); } catch {}
try { if (port) await port.close(); } catch {}
reader = null; writer = null; port = null;
setStatus("Disconnected");
document.querySelectorAll("button[id$='Btn']").forEach(b => {
if (b !== connectBtn) b.disabled = true;
});
connectBtn.disabled = false;
disconnectBtn.disabled = true;
log("Disconnected");
});
/* ---- Verb wiring ---- */
const $ = id => document.getElementById(id);
$("gpkBtn").addEventListener("click", () => {
const alg = $("gpkAlg").value, idx = Number($("gpkIdx").value || 0);
callVerb("get_public_key", [{ algorithm: alg, index: idx }], $("gpkOut"));
});
$("ngpkBtn").addEventListener("click", () => {
const idx = Number($("ngpkIdx").value || 0), fmt = $("ngpkFmt").value;
const opts = { nostr_index: idx };
if (fmt === "structured") opts.format = "structured";
callVerb("nostr_get_public_key", [opts], $("ngpkOut"));
});
$("signBtn").addEventListener("click", () => {
const alg = $("signAlg").value, idx = Number($("signIdx").value || 0);
const scheme = $("signScheme").value, msg = $("signMsg").value;
const opts = { algorithm: alg, index: idx };
if (alg === "secp256k1") opts.scheme = scheme;
callVerb("sign", [msg, opts], $("signOut"));
});
$("verifyBtn").addEventListener("click", async () => {
const alg = $("signAlg").value, idx = Number($("signIdx").value || 0);
const scheme = $("signScheme").value, msg = $("signMsg").value;
const opts = { algorithm: alg, index: idx };
if (alg === "secp256k1") opts.scheme = scheme;
/* parse the last sign result to get the signature */
const outText = $("signOut").textContent;
const m = outText.match(/"signature"\s*:\s*"([0-9a-f]+)"/);
if (!m) { $("signOut").textContent += "\n✗ no signature found — run sign first"; return; }
callVerb("verify", [msg, m[1], opts], $("signOut"));
});
$("encapBtn").addEventListener("click", async () => {
let peer = $("kemPeer").value.trim();
if (!peer) {
/* fetch self ml-kem-768 pubkey first */
const opts = [{ algorithm: "ml-kem-768", index: Number($("kemIdx").value || 0) }];
const auth = await buildAuth("get_public_key", opts);
const resp = await sendRpc({ id: String(Math.floor(Math.random()*1e9)), method: "get_public_key", params: opts, auth });
peer = resp.result && JSON.parse(resp.result).public_key;
if (!peer) { $("kemOut").textContent = "✗ could not fetch self pubkey"; return; }
$("kemPeer").value = peer;
}
callVerb("encapsulate", [peer, { algorithm: "ml-kem-768" }], $("kemOut"));
});
$("decapBtn").addEventListener("click", () => {
const ct = $("kemCt").value.trim();
const idx = Number($("kemIdx").value || 0);
if (!ct) { $("kemOut").textContent = "✗ paste a ciphertext first (from encapsulate)"; return; }
callVerb("decapsulate", [ct, { algorithm: "ml-kem-768", index: idx }], $("kemOut"));
});
$("x25519Btn").addEventListener("click", () => {
const peer = $("x25519Peer").value.trim();
const idx = Number($("x25519Idx").value || 0);
if (!peer) { $("x25519Out").textContent = "✗ enter peer pubkey"; return; }
callVerb("derive_shared_secret", [peer, { algorithm: "x25519", index: idx }], $("x25519Out"));
});
$("deriveBtn").addEventListener("click", () => {
const data = $("deriveData").value;
const idx = Number($("deriveIdx").value || 0);
callVerb("derive", [data, { algorithm: "secp256k1", index: idx }], $("deriveOut"));
});
$("nseBtn").addEventListener("click", () => {
const content = $("nseContent").value;
const idx = Number($("nseIdx").value || 0);
const event = { kind: 1, created_at: Math.floor(Date.now()/1000), tags: [], content };
callVerb("nostr_sign_event", [event, { nostr_index: idx }], $("nseOut"));
});
$("nmeBtn").addEventListener("click", () => {
const content = $("nmeContent").value;
const idx = Number($("nmeIdx").value || 0);
const diff = Number($("nmeDiff").value || 4);
const timeout = Number($("nmeTimeout").value || 30);
const event = { kind: 1, created_at: Math.floor(Date.now()/1000), tags: [], content };
callVerb("nostr_mine_event", [event, { nostr_index: idx, difficulty: diff, timeout_sec: timeout }], $("nmeOut"));
});
const nip04Enc = () => {
const peer = $("nip04Peer").value.trim(), msg = $("nip04Msg").value, idx = Number($("nip04Idx").value || 0);
if (!peer) { $("nip04Out").textContent = "✗ enter peer pubkey"; return; }
callVerb("nostr_nip04_encrypt", [peer, msg, { nostr_index: idx }], $("nip04Out"));
};
const nip04Dec = () => {
const peer = $("nip04Peer").value.trim(), ct = $("nip04Cipher").value, idx = Number($("nip04Idx").value || 0);
if (!peer || !ct) { $("nip04Out").textContent = "✗ enter peer pubkey + ciphertext"; return; }
callVerb("nostr_nip04_decrypt", [peer, ct, { nostr_index: idx }], $("nip04Out"));
};
$("nip04EncBtn").addEventListener("click", nip04Enc);
$("nip04DecBtn").addEventListener("click", nip04Dec);
const nip44Enc = () => {
const peer = $("nip44Peer").value.trim(), msg = $("nip44Msg").value, idx = Number($("nip44Idx").value || 0);
if (!peer) { $("nip44Out").textContent = "✗ enter peer pubkey"; return; }
callVerb("nostr_nip44_encrypt", [peer, msg, { nostr_index: idx }], $("nip44Out"));
};
const nip44Dec = () => {
const peer = $("nip44Peer").value.trim(), ct = $("nip44Cipher").value, idx = Number($("nip44Idx").value || 0);
if (!peer || !ct) { $("nip44Out").textContent = "✗ enter peer pubkey + ciphertext"; return; }
callVerb("nostr_nip44_decrypt", [peer, ct, { nostr_index: idx }], $("nip44Out"));
};
$("nip44EncBtn").addEventListener("click", nip44Enc);
$("nip44DecBtn").addEventListener("click", nip44Dec);
$("otpEncBtn").addEventListener("click", () => {
const pt = $("otpPlain").value, enc = $("otpEnc").value;
callVerb("encrypt", [pt, { algorithm: "otp", encoding: enc }], $("otpOut"));
});
$("otpDecBtn").addEventListener("click", () => {
const ct = $("otpCipher").value, enc = $("otpEnc").value;
if (!ct) { $("otpOut").textContent = "✗ paste ciphertext first (from encrypt)"; return; }
callVerb("decrypt", [ct, { algorithm: "otp", encoding: enc }], $("otpOut"));
});
if (!("serial" in navigator)) {
log("Web Serial not supported in this browser. Use Chrome/Edge/Brave/Opera.");
connectBtn.disabled = true;
}
</script>
</body>
</html>
-527
View File
@@ -1,527 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>n_signer Feather WebUSB Demo</title>
<style>
:root {
--bg: #0b0f14;
--panel: #121821;
--panel-2: #182231;
--text: #e6edf3;
--muted: #9fb0c3;
--accent: #58a6ff;
--good: #3fb950;
--bad: #f85149;
--border: #263448;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: Inter, system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.35;
}
.wrap {
max-width: 980px;
margin: 20px auto;
padding: 0 14px 24px;
}
h1 { margin: 0 0 8px; font-size: 1.45rem; }
p.note { margin: 0 0 14px; color: var(--muted); }
.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 12px;
margin-top: 12px;
}
.card {
background: linear-gradient(180deg, var(--panel), var(--panel-2));
border: 1px solid var(--border);
border-radius: 12px;
padding: 12px;
}
.card h2 {
font-size: 1rem;
margin: 0 0 10px;
}
label {
font-size: 0.86rem;
color: var(--muted);
display: block;
margin: 6px 0 4px;
}
input, textarea, button {
font: inherit;
border-radius: 8px;
border: 1px solid var(--border);
}
input, textarea {
width: 100%;
background: #0c131d;
color: var(--text);
padding: 8px 10px;
}
textarea { min-height: 84px; resize: vertical; }
input[type="number"] { max-width: 130px; }
button {
background: #1f6feb;
color: white;
padding: 8px 12px;
cursor: pointer;
border: 0;
}
button[disabled] {
opacity: 0.55;
cursor: not-allowed;
}
.secondary { background: #334155; }
.status {
padding: 6px 10px;
border-radius: 999px;
background: #2a3648;
color: var(--muted);
font-size: 0.85rem;
border: 1px solid var(--border);
}
.status.ok { color: var(--good); border-color: #2f5a3a; }
.status.err { color: var(--bad); border-color: #6a3131; }
pre {
margin: 8px 0 0;
background: #0a1018;
border: 1px solid #1b2636;
color: #d7e2ee;
padding: 10px;
border-radius: 8px;
overflow: auto;
max-height: 220px;
font-size: 12px;
}
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
</style>
</head>
<body>
<div class="wrap">
<h1>n_signer Feather WebUSB Demo</h1>
<p class="note">Connect to the board, choose a key index, fetch a pubkey, sign a kind 1 event, and test NIP-04 / NIP-44 encrypt + decrypt RPCs.</p>
<div class="card">
<div class="row">
<button id="connectBtn">Connect WebUSB</button>
<span id="connStatus" class="status">Disconnected</span>
</div>
<pre id="log" class="mono"></pre>
</div>
<div class="grid">
<section class="card">
<h2>Public Key</h2>
<label for="keyIndex">Key index (nostr_index)</label>
<input id="keyIndex" type="text" inputmode="numeric" pattern="[0-9]*" value="0" />
<div class="row" style="margin-top:10px">
<button id="pubkeyBtn" disabled>Get Public Key</button>
</div>
<pre id="pubkeyOut" class="mono"></pre>
</section>
<section class="card">
<h2>Sign Kind 1 Event</h2>
<label for="kind1Content">Content</label>
<textarea id="kind1Content">hello from feather webusb demo</textarea>
<label for="kind1Tags">Tags JSON (array)</label>
<input id="kind1Tags" value="[]" />
<div class="row" style="margin-top:10px">
<button id="signKind1Btn" disabled>Create + Sign kind 1</button>
</div>
<pre id="signOut" class="mono"></pre>
</section>
<section class="card">
<h2>NIP-04 Encrypt</h2>
<label for="nip04Peer">Peer pubkey (hex, 32-byte x-only)</label>
<input id="nip04Peer" placeholder="e.g. 64 hex chars" />
<label for="nip04Msg">Plaintext</label>
<textarea id="nip04Msg">hello via nip04</textarea>
<div class="row" style="margin-top:10px">
<button id="nip04EncBtn" disabled>Encrypt (nip04_encrypt)</button>
</div>
<pre id="nip04Out" class="mono"></pre>
</section>
<section class="card">
<h2>NIP-04 Decrypt</h2>
<label for="nip04DecPeer">Peer pubkey (hex, 32-byte x-only)</label>
<input id="nip04DecPeer" placeholder="e.g. 64 hex chars" />
<label for="nip04Cipher">Ciphertext</label>
<textarea id="nip04Cipher" placeholder="ciphertext?iv=..."></textarea>
<div class="row" style="margin-top:10px">
<button id="nip04DecBtn" disabled>Decrypt (nip04_decrypt)</button>
</div>
<pre id="nip04DecOut" class="mono"></pre>
</section>
<section class="card">
<h2>NIP-44 Encrypt</h2>
<label for="nip44Peer">Peer pubkey (hex, 32-byte x-only)</label>
<input id="nip44Peer" placeholder="e.g. 64 hex chars" />
<label for="nip44Msg">Plaintext</label>
<textarea id="nip44Msg">hello via nip44</textarea>
<div class="row" style="margin-top:10px">
<button id="nip44EncBtn" disabled>Encrypt (nip44_encrypt)</button>
</div>
<pre id="nip44Out" class="mono"></pre>
</section>
<section class="card">
<h2>NIP-44 Decrypt</h2>
<label for="nip44DecPeer">Peer pubkey (hex, 32-byte x-only)</label>
<input id="nip44DecPeer" placeholder="e.g. 64 hex chars" />
<label for="nip44Cipher">Ciphertext</label>
<textarea id="nip44Cipher" placeholder="base64 payload"></textarea>
<div class="row" style="margin-top:10px">
<button id="nip44DecBtn" disabled>Decrypt (nip44_decrypt)</button>
</div>
<pre id="nip44DecOut" class="mono"></pre>
</section>
</div>
</div>
<script type="module">
import { schnorr } from "https://esm.sh/@noble/curves@1.5.0/secp256k1?bundle";
const logEl = document.getElementById("log");
const connStatusEl = document.getElementById("connStatus");
const connectBtn = document.getElementById("connectBtn");
const pubkeyBtn = document.getElementById("pubkeyBtn");
const signKind1Btn = document.getElementById("signKind1Btn");
const nip04EncBtn = document.getElementById("nip04EncBtn");
const nip04DecBtn = document.getElementById("nip04DecBtn");
const nip44EncBtn = document.getElementById("nip44EncBtn");
const nip44DecBtn = document.getElementById("nip44DecBtn");
const keyIndexEl = document.getElementById("keyIndex");
const pubkeyOutEl = document.getElementById("pubkeyOut");
const kind1ContentEl = document.getElementById("kind1Content");
const kind1TagsEl = document.getElementById("kind1Tags");
const signOutEl = document.getElementById("signOut");
const nip04PeerEl = document.getElementById("nip04Peer");
const nip04MsgEl = document.getElementById("nip04Msg");
const nip04OutEl = document.getElementById("nip04Out");
const nip04DecPeerEl = document.getElementById("nip04DecPeer");
const nip04CipherEl = document.getElementById("nip04Cipher");
const nip04DecOutEl = document.getElementById("nip04DecOut");
const nip44PeerEl = document.getElementById("nip44Peer");
const nip44MsgEl = document.getElementById("nip44Msg");
const nip44OutEl = document.getElementById("nip44Out");
const nip44DecPeerEl = document.getElementById("nip44DecPeer");
const nip44CipherEl = document.getElementById("nip44Cipher");
const nip44DecOutEl = document.getElementById("nip44DecOut");
let dev = null;
let iface = null;
let ownPubkey = "";
const EP_OUT = 1;
const EP_IN = 1;
function log(...args) {
logEl.textContent += args.join(" ") + "\n";
logEl.scrollTop = logEl.scrollHeight;
}
function setStatus(text, mode = "") {
connStatusEl.textContent = text;
connStatusEl.className = `status ${mode}`.trim();
}
function hex(bytes) {
return Array.from(bytes).map(b => b.toString(16).padStart(2, "0")).join("");
}
function utf8(s) {
return new TextEncoder().encode(s);
}
function be32(n) {
return new Uint8Array([(n >>> 24) & 0xff, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff]);
}
async function sha256Hex(dataBytes) {
const h = await crypto.subtle.digest("SHA-256", dataBytes);
return hex(new Uint8Array(h));
}
function getIndexOptions() {
const raw = Number.parseInt(String(keyIndexEl.value ?? "0"), 10);
const index = Number.isFinite(raw) && raw >= 0 ? raw : 0;
return { nostr_index: index };
}
function pretty(value) {
try {
return JSON.stringify(value, null, 2);
} catch {
return String(value);
}
}
async function buildAuth(method, params) {
// Demo caller key only (not secret in browser demo).
const callerPriv = Uint8Array.from({ length: 32 }, (_, i) => i + 1);
const callerPubX = hex(schnorr.getPublicKey(callerPriv));
const createdAt = Math.floor(Date.now() / 1000);
const paramsJson = JSON.stringify(params);
const bodyHash = await sha256Hex(utf8(paramsJson));
const tags = [
["nsigner_rpc", "1"],
["nsigner_method", method],
["nsigner_body_hash", bodyHash],
];
const content = "webusb-demo";
const ser = JSON.stringify([0, callerPubX, createdAt, 27235, tags, content]);
const id = await sha256Hex(utf8(ser));
const sigBytes = await schnorr.sign(id, callerPriv, new Uint8Array(32));
const sigHex = typeof sigBytes === "string" ? sigBytes : hex(sigBytes);
return {
id,
pubkey: callerPubX,
created_at: createdAt,
kind: 27235,
tags,
content,
sig: sigHex,
};
}
async function sendRpc(reqObj) {
const body = utf8(JSON.stringify(reqObj));
const frame = new Uint8Array(4 + body.length);
frame.set(be32(body.length), 0);
frame.set(body, 4);
await dev.transferOut(EP_OUT, frame);
const deadline = Date.now() + 10000;
let ring = new Uint8Array(0);
while (Date.now() < deadline) {
const r = await dev.transferIn(EP_IN, 512);
if (!r.data || r.data.byteLength === 0) continue;
const chunk = new Uint8Array(r.data.buffer, r.data.byteOffset, r.data.byteLength);
const next = new Uint8Array(ring.length + chunk.length);
next.set(ring, 0);
next.set(chunk, ring.length);
ring = next;
while (ring.length >= 4) {
const n = (ring[0] << 24) | (ring[1] << 16) | (ring[2] << 8) | ring[3];
if (n <= 0 || n > 1_000_000) {
ring = ring.slice(1);
continue;
}
if (ring.length < 4 + n) break;
const payload = ring.slice(4, 4 + n);
ring = ring.slice(4 + n);
const txt = new TextDecoder().decode(payload);
return JSON.parse(txt);
}
}
throw new Error("Timed out waiting for framed response");
}
async function rpcCall(method, params, id = "web-1") {
const auth = await buildAuth(method, params);
const req = { jsonrpc: "2.0", id, method, params, auth };
log("→", method, JSON.stringify(params));
const resp = await sendRpc(req);
log("←", method, JSON.stringify(resp));
return resp;
}
function requirePeerHex(peer) {
const v = String(peer || "").trim().toLowerCase();
if (!/^[0-9a-f]{64}$/.test(v)) {
throw new Error("Peer pubkey must be exactly 64 hex chars (x-only pubkey)");
}
return v;
}
function requireStringResult(resp, what) {
if (resp && typeof resp.result === "string") {
return resp.result;
}
throw new Error(`${what} failed: ${pretty(resp)}`);
}
async function fetchOwnPubkeyAndFillPeers() {
const params = [getIndexOptions()];
const resp = await rpcCall("get_public_key", params, "web-own-pubkey");
if (resp && typeof resp.result === "string") {
ownPubkey = resp.result.trim().toLowerCase();
pubkeyOutEl.textContent = pretty(resp);
if (/^[0-9a-f]{64}$/.test(ownPubkey)) {
nip04PeerEl.value = ownPubkey;
nip04DecPeerEl.value = ownPubkey;
nip44PeerEl.value = ownPubkey;
nip44DecPeerEl.value = ownPubkey;
}
}
}
async function connect() {
dev = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x303a }] });
await dev.open();
if (dev.configuration === null) {
await dev.selectConfiguration(1);
}
const intf = dev.configuration.interfaces.find(i =>
i.alternates.some(a => a.interfaceClass === 0xff)
);
if (!intf) throw new Error("No vendor WebUSB interface found");
iface = intf.interfaceNumber;
await dev.claimInterface(iface);
const alt = intf.alternates.find(a => a.interfaceClass === 0xff);
await dev.selectAlternateInterface(iface, alt.alternateSetting);
await dev.controlTransferOut({
requestType: "class",
recipient: "interface",
request: 0x22,
value: 1,
index: iface,
});
pubkeyBtn.disabled = false;
signKind1Btn.disabled = false;
nip04EncBtn.disabled = false;
nip04DecBtn.disabled = false;
nip44EncBtn.disabled = false;
nip44DecBtn.disabled = false;
setStatus(`Connected (iface ${iface})`, "ok");
log("Connected. Interface", String(iface));
try {
await fetchOwnPubkeyAndFillPeers();
log("Default peer pubkeys set to selected signer pubkey");
} catch (e) {
log("Auto pubkey fetch failed:", String(e));
}
}
connectBtn.addEventListener("click", async () => {
try {
await connect();
} catch (e) {
setStatus("Connect failed", "err");
log("Connect failed:", String(e));
}
});
pubkeyBtn.addEventListener("click", async () => {
try {
await fetchOwnPubkeyAndFillPeers();
} catch (e) {
pubkeyOutEl.textContent = String(e);
}
});
signKind1Btn.addEventListener("click", async () => {
try {
let tags = [];
try {
tags = JSON.parse(kind1TagsEl.value || "[]");
if (!Array.isArray(tags)) throw new Error("tags must be an array");
} catch (e) {
throw new Error(`Invalid tags JSON: ${String(e)}`);
}
const unsignedEvent = {
kind: 1,
created_at: Math.floor(Date.now() / 1000),
tags,
content: String(kind1ContentEl.value || ""),
};
const params = [unsignedEvent, getIndexOptions()];
const resp = await rpcCall("nostr_sign_event", params, "web-sign-kind1");
signOutEl.textContent = pretty(resp?.result ?? resp);
} catch (e) {
signOutEl.textContent = String(e);
}
});
nip04EncBtn.addEventListener("click", async () => {
try {
const peer = requirePeerHex(nip04PeerEl.value);
const msg = String(nip04MsgEl.value || "");
const params = [peer, msg, getIndexOptions()];
const resp = await rpcCall("nostr_nip04_encrypt", params, "web-nip04-enc");
nip04OutEl.textContent = pretty(resp?.result ?? resp);
if (resp && typeof resp.result === "string") {
nip04DecPeerEl.value = peer;
nip04CipherEl.value = resp.result;
}
} catch (e) {
nip04OutEl.textContent = String(e);
}
});
nip04DecBtn.addEventListener("click", async () => {
try {
const peer = requirePeerHex(nip04DecPeerEl.value);
const ciphertext = String(nip04CipherEl.value || "");
const params = [peer, ciphertext, getIndexOptions()];
const resp = await rpcCall("nostr_nip04_decrypt", params, "web-nip04-dec");
nip04DecOutEl.textContent = requireStringResult(resp, "NIP-04 decrypt");
} catch (e) {
nip04DecOutEl.textContent = String(e);
}
});
nip44EncBtn.addEventListener("click", async () => {
try {
const peer = requirePeerHex(nip44PeerEl.value);
const msg = String(nip44MsgEl.value || "");
const params = [peer, msg, getIndexOptions()];
const resp = await rpcCall("nostr_nip44_encrypt", params, "web-nip44-enc");
nip44OutEl.textContent = pretty(resp?.result ?? resp);
if (resp && typeof resp.result === "string") {
nip44DecPeerEl.value = peer;
nip44CipherEl.value = resp.result;
}
} catch (e) {
nip44OutEl.textContent = String(e);
}
});
nip44DecBtn.addEventListener("click", async () => {
try {
const peer = requirePeerHex(nip44DecPeerEl.value);
const ciphertext = String(nip44CipherEl.value || "");
const params = [peer, ciphertext, getIndexOptions()];
const resp = await rpcCall("nostr_nip44_decrypt", params, "web-nip44-dec");
nip44DecOutEl.textContent = requireStringResult(resp, "NIP-44 decrypt");
} catch (e) {
nip44DecOutEl.textContent = String(e);
}
});
</script>
</body>
</html>
+5 -5
View File
@@ -46,10 +46,10 @@ CDC path:
./.venv/bin/python ./examples/feather_sign_event.py /dev/ttyACM0
```
WebUSB path:
WebUSB / Web Serial path (unified):
- Open [`examples/feather_webusb_demo.html`](../examples/feather_webusb_demo.html)
- Connect in Chrome/Edge
- Open [`usb-test.html`](../usb-test.html) in Chrome/Edge
- Connect via Web Serial (works for Teensy 4.1 USB CDC, CYD CH340, Feather, etc.)
- Run `get_public_key`
- Confirm pubkey matches CDC result
@@ -58,9 +58,9 @@ WebUSB path:
The CYD has no native USB; its CH340 bridge exposes a serial port. The browser
transport is **Web Serial** (`navigator.serial`), Chromium-only. A full test
page covering every algorithm and verb lives at
[`examples/cyd_webserial_demo.html`](../examples/cyd_webserial_demo.html):
[`usb-test.html`](../usb-test.html):
- Open [`examples/cyd_webserial_demo.html`](../examples/cyd_webserial_demo.html) in Chrome/Edge
- Open [`usb-test.html`](../usb-test.html) in Chrome/Edge
- Click **Connect Web Serial**, select the CH340 port (`1a86:7523`)
- Exercise each card: `get_public_key` (all 6 algorithms), `sign`/`verify`,
`encapsulate`/`decapsulate`, `derive_shared_secret`, `derive`,
+2 -2
View File
@@ -95,9 +95,9 @@ hardware note below.
The CYD has no native USB; the CH340 bridge exposes a serial port. The browser
transport is **Web Serial** (`navigator.serial`), Chromium-only. A full test
page covering every algorithm and verb lives at
[`examples/cyd_webserial_demo.html`](../../examples/cyd_webserial_demo.html):
[`usb-test.html`](../../usb-test.html):
1. Open [`examples/cyd_webserial_demo.html`](../../examples/cyd_webserial_demo.html) in Chrome/Edge.
1. Open [`usb-test.html`](../../usb-test.html) in Chrome/Edge.
2. Click **Connect Web Serial**, select the CH340 port (`1a86:7523`).
3. On the CYD touchscreen, enter or generate a mnemonic to reach the "ready" state.
4. Exercise each card: `get_public_key` (all 6 algorithms), `sign`/`verify`,
+71 -1
View File
@@ -30,7 +30,7 @@
#include "nostr_common.h"
#include "utils.h"
#define FIRMWARE_VERSION "0.0.2"
#define FIRMWARE_VERSION "0.0.3"
#ifndef GIT_HASH
#define GIT_HASH "dev"
#endif
@@ -115,6 +115,7 @@ typedef enum {
#define VERB_GET_PUBLIC_KEY "get_public_key"
#define VERB_ENCRYPT "encrypt"
#define VERB_DECRYPT "decrypt"
#define VERB_GET_INFO "get_info"
/* Nostr protocol verbs (secp256k1 NIP-06, nostr_index selector). */
#define VERB_NOSTR_GET_PUBLIC_KEY "nostr_get_public_key"
@@ -1299,6 +1300,75 @@ static void handle_request(cJSON *req, const char *method, const char *id_token,
cJSON *params = cJSON_GetObjectItemCaseSensitive(req, "params");
char key_id[17];
/* ===================== get_info (no key material, no approval) ============ */
if (strcmp(method, VERB_GET_INFO) == 0) {
(void)params;
(void)caller_hex;
{
cJSON *obj = cJSON_CreateObject();
char *out = NULL;
if (obj == NULL) {
snprintf(s_response_buf, sizeof(s_response_buf),
"{\"jsonrpc\":\"2.0\",\"id\":%s,\"error\":{\"code\":%d,\"message\":\"internal error\"}}",
id_token, ERR_INTERNAL);
return;
}
cJSON_AddStringToObject(obj, "name", "n_signer");
cJSON_AddStringToObject(obj, "implementation", "cyd_esp32_2432s028");
cJSON_AddStringToObject(obj, "version", FIRMWARE_VERSION);
cJSON_AddStringToObject(obj, "git_hash", GIT_HASH);
cJSON_AddStringToObject(obj, "api", "json-rpc-2.0");
{
cJSON *verbs = cJSON_CreateArray();
if (verbs != NULL) {
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_GET_INFO));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_GET_PUBLIC_KEY));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_SIGN));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_VERIFY));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_ENCAPSULATE));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_DECAPSULATE));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_DERIVE_SHARED));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_DERIVE));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_ENCRYPT));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_DECRYPT));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_NOSTR_GET_PUBLIC_KEY));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_NOSTR_SIGN_EVENT));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_NOSTR_MINE_EVENT));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_NOSTR_NIP04_ENCRYPT));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_NOSTR_NIP04_DECRYPT));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_NOSTR_NIP44_ENCRYPT));
cJSON_AddItemToArray(verbs, cJSON_CreateString(VERB_NOSTR_NIP44_DECRYPT));
cJSON_AddItemToObject(obj, "verbs", verbs);
}
}
{
cJSON *algs = cJSON_CreateArray();
if (algs != NULL) {
cJSON_AddItemToArray(algs, cJSON_CreateString("secp256k1"));
cJSON_AddItemToArray(algs, cJSON_CreateString("ed25519"));
cJSON_AddItemToArray(algs, cJSON_CreateString("x25519"));
cJSON_AddItemToArray(algs, cJSON_CreateString("ml-dsa-65"));
cJSON_AddItemToArray(algs, cJSON_CreateString("slh-dsa-128s"));
cJSON_AddItemToArray(algs, cJSON_CreateString("ml-kem-768"));
cJSON_AddItemToArray(algs, cJSON_CreateString("otp"));
cJSON_AddItemToObject(obj, "algorithms", algs);
}
}
out = cJSON_PrintUnformatted(obj);
cJSON_Delete(obj);
if (out == NULL) {
snprintf(s_response_buf, sizeof(s_response_buf),
"{\"jsonrpc\":\"2.0\",\"id\":%s,\"error\":{\"code\":%d,\"message\":\"internal error\"}}",
id_token, ERR_INTERNAL);
} else {
snprintf(s_response_buf, sizeof(s_response_buf),
"{\"jsonrpc\":\"2.0\",\"id\":%s,\"result\":%s}", id_token, out);
cJSON_free(out);
}
}
return;
}
/* ===================== Nostr verbs (secp256k1 NIP-06) ===================== */
if (strcmp(method, VERB_NOSTR_GET_PUBLIC_KEY) == 0) {
@@ -13,21 +13,8 @@
# include "pico/rand.h"
# define NOSTR_HAVE_PICO_RAND 1
# endif
# if __has_include("hardware/adc.h")
# include "hardware/adc.h"
# define NOSTR_HAVE_PICO_ADC 1
# endif
#endif
static uint32_t xorshift32(uint32_t *state) {
uint32_t x = *state ? *state : 0xA5A5A5A5u;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
*state = x;
return x;
}
int nostr_platform_random(unsigned char *buf, size_t len) {
if (!buf) {
return -1;
@@ -47,33 +34,14 @@ int nostr_platform_random(unsigned char *buf, size_t len) {
}
return 0;
#else
uint32_t seed = 0x13579BDFu;
#if defined(ARDUINO)
seed ^= (uint32_t)micros();
seed ^= ((uint32_t)millis() << 16);
seed ^= (uint32_t)(uintptr_t)&seed;
#endif
#if defined(NOSTR_HAVE_PICO_ADC)
adc_init();
adc_set_temp_sensor_enabled(true);
adc_select_input(4);
for (int k = 0; k < 16; ++k) {
seed ^= ((uint32_t)adc_read() << ((k & 3) * 8));
}
#endif
while (i < len) {
uint32_t r = xorshift32(&seed);
#if defined(ARDUINO)
r ^= (uint32_t)micros();
#endif
size_t take = (len - i >= 4) ? 4 : (len - i);
memcpy(buf + i, &r, take);
i += take;
}
return 0;
/* No hardware RNG available — fail closed.
* The Pico SDK's get_rand_32() (ring-oscillator-based TRNG) is available
* on all official RP2040 boards. Without it, we cannot provide secure
* randomness for key generation. The previous xorshift32 fallback was
* removed because it was cryptographically weak (32-bit state, predictable
* from boot timing). See audit/F-006-rp2040-xorshift-fallback-rng.md. */
(void)i;
(void)len;
return -1;
#endif
}
+192 -11
View File
@@ -1,7 +1,13 @@
# n_signer Teensy 4.1 Firmware
**Status:** Planned — not yet implemented. See
[`plans/teensy41_signer_port.md`](../../plans/teensy41_signer_port.md).
**Status:** In progress — Phase 0 + SD + TFT + touch all verified on hardware
(toolchain, blink, USB CDC serial, 4-bit SDMMC card read, ST7796S 480×320 TFT
landscape fill + text, XPT2046 touch calibrated + live dot-draw verified). See
[`plans/teensy41_bringup.md`](../../plans/teensy41_bringup.md) for the bring-up
log, [`firmware/teensy41/WIRING.md`](WIRING.md) for the display wiring, and
[`plans/teensy41_signer_port.md`](../../plans/teensy41_signer_port.md) for the
full port plan. Next: exFAT re-test on the 1 TB SDXC card, then port the CYD
display/touch/UI code.
The **Teensy 4.1** (NXP i.MX RT1062, Cortex-M7 @ 600 MHz) is the high-capacity
OTP pad target. Its built-in SD slot supports **1 TB SDXC cards (exFAT)** via
@@ -44,17 +50,192 @@ the CYD's [`touch.c`](../cyd_esp32_2432s028/main/touch.c) with 480×320
resolution constants. The ST7796S display driver is new code (different init
sequence than the CYD's ILI9341).
Wiring: TFT SPI on pins 11/12/13, CS=10, DC=9, RESET=8, BL=22; touch shares
the SPI bus with T_CS=7, T_IRQ=6. See
[`plans/teensy41_signer_port.md`](../../plans/teensy41_signer_port.md) for the
full pin table.
Wiring: TFT SPI on pins 11/12/13 (hardware SPI0), CS=5, DC=7, RESET=6, BL=8;
touch shares the SPI bus with T_CS=9, T_IRQ=2. See
[`WIRING.md`](WIRING.md) for the full pin table and wire-by-wire chart.
## Build (planned)
## Calibrated values & settings (verified on hardware)
```bash
# Arduino CLI / Teensyduino
arduino-cli compile --fqbn teensy:avr:teensy41 firmware/teensy41
arduino-cli upload -p /dev/ttyACM0 --fqbn teensy:avr:teensy41 firmware/teensy41
These are the values to use when porting the CYD display/touch/UI code to the
Teensy 4.1. They were measured on the actual Elecrow 4.0" ST7796S + XPT2046
module during bring-up (see [`plans/teensy41_bringup.md`](../../plans/teensy41_bringup.md)).
### Display
| Setting | Value | Notes |
|---|---|---|
| Orientation | **Landscape 480×320** | Wider than tall. |
| `tft.init()` | `tft.init(320, 480)` | Pass the *native* (portrait) dims so the library takes its zero-offset branch. Do NOT use `init(480, 320)` — that computes a negative `_colstart` and offsets the image. |
| `tft.setRotation()` | `setRotation(1)` | Produces landscape 480×320 from the `init(320, 480)` base. |
| `SCREEN_W` / `SCREEN_H` | `480` / `320` | Use these constants for all drawing coordinates. **Do not use `tft.width()` / `tft.height()`** — the `ST7796_t3` accessors are broken and always return 480×320 regardless of rotation. |
| Library | `ST7796_t3` (in Teensy's `ST7735_t3` library) | Hardware SPI0. |
| `drawPixel()` | **Avoid near edges** | Use `fillRect(x, y, 1, n, c)` / `fillRect(x, y, n, 1, c)` for crosshairs and thin lines — `drawPixel` mispositions near the right/bottom edges. |
### Touch (XPT2046)
| Setting | Value | Notes |
|---|---|---|
| `T_CS` | pin 9 | Touch chip select (active low). |
| `T_IRQ` | **pin 2** | Touch interrupt. **Must not be pin 10** — pin 10 is SPI0 CS0, and `pinMode(10, INPUT)` corrupts the SPI engine and reverts the display to the wrong orientation. |
| SPI clock | 2 MHz | XPT2046 max is ~2.5 MHz; drop the clock before every touch read (`SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0))`). |
| Axis swap | **Yes** | In landscape rotation 1, raw Y → screen X, raw X → screen Y. The calibration struct + `raw_to_screen()` handle this (see below). |
| Control bytes | `0xD0` = X, `0x90` = Y, `0xB0`/`0xC0` = Z1/Z2 | Same as the CYD's [`touch.c`](../cyd_esp32_2432s028/main/touch.c). |
| Pressure threshold | 80 | Reject readings with `pressure < 80` (stylus not pressing hard enough). Same as CYD. |
### Touch calibration constants (measured 2026-07-26)
```c
static TouchCal s_cal = {
/* x_min = */ 207,
/* x_max = */ 1909,
/* y_min = */ 168,
/* y_max = */ 1798,
/* invert_x = */ 1,
/* invert_y = */ 1,
};
```
With the axis swap, `x_min/x_max` is the range of **raw Y** that maps to screen
X, and `y_min/y_max` is the range of **raw X** that maps to screen Y. The
`raw_to_screen()` function swaps accordingly:
```c
*sx = map_clamped((int)raw_y, s_cal.x_min, s_cal.x_max,
s_cal.invert_x ? (SCREEN_W - 1) : 0,
s_cal.invert_x ? 0 : (SCREEN_W - 1));
*sy = map_clamped((int)raw_x, s_cal.y_min, s_cal.y_max,
s_cal.invert_y ? (SCREEN_H - 1) : 0,
s_cal.invert_y ? 0 : (SCREEN_H - 1));
```
These constants are for the specific panel we calibrated. If you swap a
display module, re-run [`firmware/teensy41/touch_cal/touch_cal.ino`](touch_cal/touch_cal.ino)
and paste the new constants.
## Build
```bash
# Arduino CLI / Teensyduino — uses the custom linker script
bash firmware/teensy41/build_signer.sh # compile only
bash firmware/teensy41/build_signer.sh --flash # compile + upload
bash firmware/teensy41/build_signer.sh --test # compile + upload + run tests
```
The build uses a custom linker script
([`signer/imxrt1062_t41_flashmem.ld`](signer/imxrt1062_t41_flashmem.ld)) that
routes crypto and SdFat code to FLASH (off-chip QSPI) instead of ITCM
(tightly-coupled RAM), freeing the limited FlexRAM for stack. See the memory
management section below for details.
See the port plan: [`plans/teensy41_signer_port.md`](../../plans/teensy41_signer_port.md).
## Memory management
The Teensy 4.1's NXP i.MX RT1062 has a unique FlexRAM architecture that makes
memory budgeting the central engineering challenge of this firmware. This
section documents the layout, the custom linker script, and the build-time
stack gauge that catches overflows before they become mystery crashes.
### The FlexRAM problem
The i.MX RT1062 has three RAM regions:
```
FLASH 8 MB (off-chip QSPI, @ 0x60000000) — code + rodata, slow but huge
FLEXRAM 512 KB (on-chip, split ITCM/DTCM) — fast, tiny, THE BOTTLENECK
RAM2 512 KB (OCRAM, @ 0x20200000) — DMAMEM statics + malloc heap
ERAM 0 MB (PSRAM pads empty) — not populated on the Teensy 4.1
```
The 512 KB of FlexRAM is divided into **16 banks of 32 KB** that are split
between **ITCM** (instruction tightly-coupled memory, runs code at zero wait
state) and **DTCM** (data tightly-coupled memory, holds `.data` + `.bss` +
**the stack**). The split is computed at **boot time** by the Teensy boot ROM
from a formula in the linker script:
```ld
_itcm_block_count = (SIZEOF(.text.itcm) + SIZEOF(.ARM.exidx) + 0x7FFF) >> 15;
_estack = ORIGIN(DTCM) + ((16 - _itcm_block_count) << 15);
```
**Every 32 KB bank given to code is taken away from the stack.** If ITCM code
grows past a 32 KB boundary, a whole bank is stolen from DTCM, and the stack
shrinks by 32 KB. The linker cannot detect this because the split happens at
reset, not link time — an over-committed DTCM links cleanly and then hard-faults
on boot.
### The custom linker script
[`signer/imxrt1062_t41_flashmem.ld`](signer/imxrt1062_t41_flashmem.ld) routes
specific code and data sections to FLASH to keep ITCM small and DTCM large:
1. **Crypto code → FLASH**: secp256k1, ed25519, x25519, PQClean (ML-DSA-65,
ML-KEM-768, SLH-DSA-128s), nostr_utils — all routed via per-object-file
rules (`*secp256k1.c.o(.text*)`, etc.). These run slightly slower from
FLASH but the stack headroom is the critical constraint.
2. **SdFat library → FLASH**: the FAT filesystem layer (FatFile, FatPartition,
FatVolume, etc.) is routed to FLASH. The SDIO driver (SdioCard, SdioTeensy)
stays in ITCM for fast interrupt response.
3. **`.rodata` → FLASH** (v0.1.6): read-only data (const tables, string
literals, BIP-39 wordlist, LVGL fonts, PQClean constants) is routed to
FLASH via `*(EXCLUDE_FILE(*ed25519.c.o) .rodata*)`. This reclaimed **124 KB
of DTCM** (`.data` went from 131 KB to 6.8 KB), increasing free stack from
5,984 bytes to **130,912 bytes**.
The `EXCLUDE_FILE(*ed25519.c.o)` exception is critical: the ed25519 base
point constants (`ed_K`, `ed_X`, `ed_Y`) must stay in DTCM — moving them to
FLASH produces an all-zeros pubkey (a regression documented in the linker
script comments).
### Build-time stack gauge
[`check_stack.sh`](check_stack.sh) parses the ELF's section sizes after
compilation and computes the same ITCM/DTCM split the boot ROM will perform.
It **fails the build** if free stack would be below 16 KB:
```
=== Teensy 4.1 FlexRAM stack gauge ===
.text.itcm : 355056 bytes -> 11 banks (360448 bytes)
.data (DTCM) : 6848 bytes
.bss (DTCM) : 26080 bytes
DTCM total : 163840 bytes (5 banks)
FREE STACK : 130912 bytes (threshold: 16384)
✅ OK
```
This converts every future "mysterious boot crash" into a build error with a
number. The gauge is wired into [`build_signer.sh`](build_signer.sh) and runs
automatically after every compile.
### Current memory layout (v0.1.6)
```
FLEXRAM 512 KB — 16 banks
┌──────────────────────────────────────────────┬────────────────────────────────────────┐
│ ITCM 11 banks = 352 KB │ DTCM 5 banks = 160 KB │
│ code: 355 KB (signer + SDIO driver) │ .data: 6.8 KB (writable globals) │
│ │ .bss: 25.4 KB (zero-init globals) │
│ │ FREE STACK: 130.9 KB ✅ │
└──────────────────────────────────────────────┴────────────────────────────────────────┘
RAM2 / OCRAM 512 KB
┌──────────────────────────────────────────────────────────────────────────────────────────┐
│ .bss.dma: 413.6 KB (LVGL draw buffers, crypto DMAMEM workspaces) heap: 110.7 KB free │
└──────────────────────────────────────────────────────────────────────────────────────────┘
FLASH 7936 KB
┌──────────────────────────────────────────────────────────────────────────────────────────┐
│ Used: ~1.6 MB (crypto code + SdFat + .rodata + ITCM/DTCM load images) Free: ~6.3 MB │
└──────────────────────────────────────────────────────────────────────────────────────────┘
```
### History
The memory budget was the direct cause of six versions of crash-fixing
(v0.1.1v0.1.6). The v0.1.6 `.rodata` → FLASH move was the largest single
improvement, and it also enabled the SD-card OTP pad (which requires SdFat,
adding ~7 KB of ITCM code that would have overflowed DTCM without the rodata
reclamation). See [`plans/teensy41_memory_evaluation.md`](../../plans/teensy41_memory_evaluation.md)
for the full analysis.
+306
View File
@@ -0,0 +1,306 @@
# Wiring: 4.0" ST7796S 480×320 SPI TFT + XPT2046 Touch → Teensy 4.1
This document describes how to wire the **Elecrow/Hosyond 4.0" 480×320 SPI TFT
module with ST7796S driver and XPT2046 resistive touch** to the **Teensy 4.1**.
It is the reference for Phase 1 of [`plans/teensy41_signer_port.md`](../../plans/teensy41_signer_port.md)
(display + touch bring-up). Source documents for the pinout live in
[`firmware/teensy41/documents/`](documents/):
- [`ST7796S_Datasheet.pdf`](documents/ST7796S_Datasheet.pdf) — display controller
- [`4.0inch_SPI_Module_User_Manual.pdf`](documents/4.0inch_SPI_Module_User_Manual.pdf) — module manual
- [`4.0 Inch 480_320 SPI TFT LCD Module with ST7796 Driver_With Touch Function - Elecrow Wiki.html`](documents/4.0%20Inch%20480_320%20SPI%20TFT%20LCD%20Module%20with%20ST7796%20Driver_With%20Touch%20Function%20-%20Elecrow%20Wiki.html)
- [`Teensy® 4.1.html`](documents/Teensy%C2%AE%204.1.html) — PJRC pinout reference
## Module pinout
The module breaks out 14 pins along one long edge. The labels below are the
**silk-screen names on the actual Elecrow/Hosyond board** (read in order from
one end of the header to the other). Alternate names in parentheses are the
ones used in some other vendors' docs.
| # | Silkscreen | Alt name | Function |
|----|------------|-------------|-----------------------------------|
| 1 | t_irq | | Touch interrupt (active low) |
| 2 | t_do | T_MISO | Touch SPI MISO (shared bus) |
| 3 | t_din | T_MOSI | Touch SPI MOSI (shared bus) |
| 4 | t_cs | | Touch chip select (active low) |
| 5 | t_clk | T_SCK | Touch SPI clock (shared bus) |
| 6 | sdo (miso) | SDO / MISO | TFT SPI MISO (shared with touch) |
| 7 | led | BL / BKL | Backlight (high = on; PWM-able) |
| 8 | sck | CLK / SCL | TFT SPI clock (shared with touch) |
| 9 | sdi (mosi) | SDI / SDA | TFT SPI MOSI (shared with touch) |
| 10 | dc/rs | DC / A0 | TFT data/command select |
| 11 | reset | RST | TFT reset (active low) |
| 12 | cs | LCD_CS | TFT chip select (active low) |
| 13 | gnd | | Ground |
| 14 | vcc | | Power (3.3V5V) |
> The module has a **second SD card slot** on the PCB (separate from the
> Teensy's built-in slot). Its pins are not broken out on the 14-pin header —
> they go to the SD contacts on the back of the module. We **do not use** the
> module's SD slot; the 1 TB OTP pad lives in the Teensy's built-in SDMMC slot
> (4-bit bus, ~2040 MB/s, exFAT). See [`README.md`](README.md) §SD card size support.
## Connection chart (wire-by-wire)
This is the simple "connect this Teensy pin to that module pin" list. **Power
first, then signals.**
### By display header position (use this when the silkscreen is hidden)
When the display is plugged into a breadboard, you can't read the silkscreen.
This table is indexed by **physical position on the display header**, counting
from the end with `t_irq` (pin 1) to the end with `vcc` (pin 14). Hold the
display with the header at the bottom and the screen facing you; pin 1 is the
leftmost pin (the `t_irq` end), pin 14 is the rightmost (the `vcc` end).
| Display header pos | Silkscreen | → | Teensy 4.1 pin | Function |
|---|---|---|---|---|
| 1 | t_irq | → | 2 | Touch interrupt (active low) — see note below on why not pin 10 |
| 2 | t_do | → | 12 | SPI0 MISO (shared) |
| 3 | t_din | → | 11 | SPI0 MOSI (shared) |
| 4 | t_cs | → | 9 | Touch chip select (active low) |
| 5 | t_clk | → | 13 | SPI0 SCK (shared) — opposite edge |
| 6 | sdo (miso) | → | 12 | SPI0 MISO (same wire as pos 2) |
| 7 | led | → | 8 | Backlight (PWM-able) |
| 8 | sck | → | 13 | SPI0 SCK (same wire as pos 5) |
| 9 | sdi (mosi) | → | 11 | SPI0 MOSI (same wire as pos 3) |
| 10 | dc/rs | → | 7 | TFT data/command |
| 11 | reset | → | 6 | TFT reset (active low) |
| 12 | cs | → | 5 | TFT chip select (software CS) |
| 13 | gnd | → | GND | Ground (opposite edge, next to pin 13) |
| 14 | vcc | → | 3V3 | 3.3V power (long edge, past pin 12) — **NOT 5V** |
**Shared pins (pos 2↔6, 3↔9, 5↔8):** these pairs are tied together on the
display PCB, so you only need to wire **one of each pair** to the Teensy. The
table shows both for completeness, but in practice you can wire pos 2, 3, 5
and leave pos 6, 8, 9 floating (or wire them to the same Teensy pin —
harmless). That brings it to **11 wires** total (8 unique signals + 3V3 + GND
+ the 3 shared-pair duplicates you choose to wire).
### By Teensy pin number (for lookup at the Teensy)
Sorted by Teensy pin number for easy lookup at the Teensy end of the wires.
| Teensy 4.1 pin | → | Module silkscreen | What it does |
|----------------|---|-------------------|--------------|
| GND | → | gnd | Ground (GND is on the opposite edge, next to pin 13) |
| 3V3 | → | vcc | 3.3V power (**not 5V**) — the 3V3 pin is on the long edge, just past pin 12 |
| 2 | → | t_irq | Touch interrupt (active low) — **not pin 10** (see note below) |
| 5 | → | cs | TFT chip select (software CS — see note below) |
| 6 | → | reset | TFT reset (active low) |
| 7 | → | dc/rs | TFT data/command |
| 8 | → | led | Backlight (HIGH = on; PWM-able) |
| 9 | → | t_cs | Touch chip select (active low) |
| 11 | → | sdi (mosi) | SPI0 MOSI (also wires to `t_din`) |
| 12 | → | sdo (miso) | SPI0 MISO (also wires to `t_do`) |
| 13 | → | sck | SPI0 SCK (also wires to `t_clk`) — **pin 13 is on the opposite edge**, route via a short jumper |
That's **11 wires** total, all in the pins 5-13 range plus 3V3 and GND. The
three shared SPI lines (`sdi (mosi)`, `sdo (miso)`, `sck`) each fan out to two
module pins — see the next section for why and how.
> **Why `cs` is on pin 5 (software CS) and `t_irq` is on pin 2 (not pin 10):**
> Pin 10 is the hardware CS0 for SPI0. **Do not use pin 10 for anything else**
> calling `pinMode(10, ...)` (e.g. for `t_irq` as an input) corrupts the SPI0
> engine state and reverts the ST7796S display to landscape mode after
> `setRotation()`. This is a hard-won lesson documented in
> [`plans/teensy41_bringup.md`](../../plans/teensy41_bringup.md). So:
> - `cs` is on pin 5 (software CS via `SPI.beginTransaction()`) — the speed
> difference vs hardware CS0 is negligible for a signer UI.
> - `t_irq` is on pin 2 (long edge, before pin 5) — keeps it off pin 10 and
> out of the SPI0 CS0 conflict.
> If you want hardware CS0 for the TFT, you can put `cs` on pin 10, but then
> `t_irq` must stay on pin 2 (or be dropped entirely in favor of polling).
> **Shared-bus shortcut:** `sdi (mosi)` and `t_din` are the same net on the
> module PCB, `sdo (miso)` and `t_do` are the same net, and `sck` and `t_clk`
> are the same net. So for each shared pair you can either (a) wire the Teensy
> pin to **both** module pins (harmless, just a Y-jumper), or (b) wire the
> Teensy pin to **one** module pin and leave the other floating (it's tied
> internally on the PCB). The connection chart above wires each Teensy SPI pin
> to the TFT-side silkscreen; the touch-side silkscreen of each pair is tied to
> the same net on the board.
## Teensy 4.1 pin assignments
The Teensy 4.1 has 3 hardware SPI ports. We use **SPI0** (the primary port with
the FIFO) on pins 11/12/13. The TFT and the XPT2046 share this bus; each has its
own CS. All pins are 3.3V — the module is 3.3V-logic compatible, so no level
shifting is needed.
| Silkscreen | Teensy 4.1 pin | Teensy function | Notes |
|------------|----------------|--------------------------|-------|
| gnd | GND | Ground | GND is on the opposite edge, next to pin 13. |
| vcc | 3V3 | 3.3V output | **Use 3.3V, not 5V/VIN.** The 3V3 pin is on the long edge, just past pin 12. The Teensy's 3.3V regulator can supply up to ~250 mA; the display + backlight draw ~80120 mA, well within budget. |
| cs | 5 | GPIO (software CS) | TFT chip select (active low). Software CS via `SPI.beginTransaction()` — see the note in the connection chart about why we didn't use hardware CS0 on pin 10. |
| reset | 6 | GPIO | TFT reset. Drive low for >10 µs to reset; pull high (or set as OUTPUT HIGH) for normal operation. Can also be tied to a 10 kΩ pull-up and left floating if you don't need software reset. |
| dc/rs | 7 | GPIO | TFT data/command. High = data (pixel/command param), Low = command. |
| led | 8 | GPIO / PWM | Backlight. Drive HIGH for full brightness, or use `analogWrite(8, 0..255)` for dimming. Can also be tied to 3.3V through a ~100 Ω resistor for always-on. |
| t_cs | 9 | GPIO | Touch chip select. Active low. Must be HIGH when talking to the TFT, LOW when reading the touch. |
| t_irq | 2 | GPIO (input + interrupt) | Touch interrupt. Pulled high by the XPT2046 internally; goes low when touch pressure is detected. Optional — can be left unconnected and polled, but wiring it lets us sleep until a touch happens. **Must not be pin 10** (SPI0 CS0 — `pinMode(10, INPUT)` corrupts the SPI engine and reverts the display to landscape). |
| sdi (mosi) | 11 | SPI0 MOSI | Shared with touch `t_din`. |
| sdo (miso) | 12 | SPI0 MISO | Shared with touch `t_do`. The TFT rarely drives MISO (most ST7796S commands are write-only), but the XPT2046 reads return on this line. |
| sck | 13 | SPI0 SCK | Shared with touch `t_clk`. **Pin 13 is on the opposite edge** of the Teensy (next to GND), so route it via a short jumper across the board. Pin 13 also drives the onboard orange LED — that's fine, the LED just blinks during SPI activity. |
| t_clk | 13 | SPI0 SCK (shared) | Same wire as `sck`. |
| t_do | 12 | SPI0 MISO (shared) | Same wire as `sdo (miso)`. |
| t_din | 11 | SPI0 MOSI (shared) | Same wire as `sdi (mosi)`. |
### Pin map summary (Teensy side)
Wires, listed in the same order as the module's silkscreen header (pin 1 → 14):
```
Teensy 4.1 Silkscreen Function
----------- ----------- ------------------------------------------
pin 2 t_irq Touch interrupt (active low — NOT pin 10, see note)
pin 12 t_do Touch MISO (shared SPI0 MISO)
pin 11 t_din Touch MOSI (shared SPI0 MOSI)
pin 9 t_cs Touch chip select (active low)
pin 13 t_clk Touch SCK (shared SPI0 SCK — opposite edge)
pin 12 sdo (miso) TFT MISO (shared SPI0 MISO — same wire as t_do)
pin 8 led Backlight (HIGH = on; analogWrite for dimming)
pin 13 sck TFT SCK (shared SPI0 SCK — same wire as t_clk)
pin 11 sdi (mosi) TFT MOSI (shared SPI0 MOSI — same wire as t_din)
pin 7 dc/rs TFT data/command
pin 6 reset TFT reset (active low)
pin 5 cs TFT chip select (software CS)
GND gnd Ground (opposite edge, next to pin 13)
3V3 vcc Power (3.3V — NOT 5V; long edge, past pin 12)
```
Shared-bus note: `t_do` and `sdo (miso)` are the **same electrical net** on the
module (both connect to the SPI MISO line), and `t_din`/`sdi (mosi)` and
`t_clk`/`sck` are likewise the same nets. You only need to wire one of each
shared pair to the Teensy — but on this module the header brings both out, so
you can either wire both to the same Teensy pin (harmless) or wire one and leave
the other floating (also fine, since they're tied together on the PCB). The
table above wires both to the same Teensy pin for clarity.
## SPI bus sharing
The TFT and the XPT2046 share MOSI / SCK / MISO. The rule for sharing:
1. **Only one CS is low at a time.** Before talking to the TFT, set `t_cs` HIGH
and `cs` LOW. Before reading the touch, set `cs` HIGH and `t_cs` LOW.
2. **Use `SPI.beginTransaction(SPISettings(spi_speed, MSBFIRST, SPI_MODE0))` /
`SPI.endTransaction()`** around each device's access. The TFT and the XPT2046
both use SPI mode 0, but they may want different clock speeds:
- TFT: up to 40 MHz (the ST7796S supports 1-line SPI up to ~62 MHz; 40 MHz is
a safe conservative choice on the Teensy's SPI0).
- XPT2046: 22.5 MHz max (the XPT2046 datasheet specifies a max serial clock
of ~2.5 MHz). **Always drop the clock before reading the touch.**
3. **The XPT2046 control byte** is `0x90` for X read (channel 5) and `0xD0` for
Y read (channel 1), 8-bit, MSB first, with the start bit set. See
[`firmware/cyd_esp32_2432s028/main/touch.c`](../cyd_esp32_2432s028/main/touch.c)
`xpt2046_transfer_12b()` for the bit-banged reference; on the Teensy we can
use the hardware SPI engine instead of bit-banging.
## Routing notes (trace-crossing analysis)
This assignment uses **hardware SPI0** (MOSI=11, MISO=12, SCK=13) for maximum
display throughput (FIFO + DMA, up to 40 MHz), with all display pins in a
contiguous block on the Teensy's long edge (pins 5-12) plus SCK=13 on the
opposite edge. The display module's silkscreen pin order doesn't match the
Teensy's SPI0 pin order, so a small number of trace crossings are unavoidable.
This is fine for jumper wires and trivial on a 2-layer PCB.
**Teensy 4.1 physical layout (relevant part):**
- **Long edge:** 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 3V3, 24, 25, ...
- **Opposite edge:** 0, 13, 14, ... with GND in the middle
So pins 5-12 are contiguous on the long edge, 3V3 is right past pin 12, and
pin 13 (SCK) + GND are on the opposite edge. All display signals fit in the
pins 5-13 range plus 3V3 and GND — no need to reach up to pins 24+.
**Crossings (2 on the long edge + 1 SCK via):**
1. **MOSI/MISO swap.** Display order is MISO(`t_do`/`sdo`, pos 2/6) then
MOSI(`t_din`/`sdi`, pos 3/9); Teensy SPI0 is MOSI(11) then MISO(12). One
crossing — unavoidable given the fixed SPI0 pin assignments.
2. **`t_cs` jumps over the SPI pins.** Display pos 3-4-5 is
MOSI-`t_cs`-SCK; Teensy pins 11-12-13 are MOSI-MISO-SCK with no free pin
between MOSI(11) and SCK(13). `t_cs` (Teensy pin 9) routes below the SPI
block, crossing the MOSI/MISO pair. One crossing.
3. **SCK via to the opposite edge.** SCK is on pin 13, which is on the
opposite edge of the Teensy from pins 5-12. This is a via (a short jumper
across the board), not a trace crossing on the long edge.
The remaining GPIOs (`led`=8, `dc/rs`=7, `reset`=6, `cs`=5) run monotonically
down the long edge below `t_cs`=9 — zero crossings among them.
**Why not zero crossings?** A zero-crossing assignment is possible by
bit-banging SPI on Teensy pins in exact display order, but it loses the
hardware SPI engine — display refresh drops to ~0.2-0.5 s per full 480×320
frame. We chose hardware SPI0 for a snappy UI and accepted 2 crossings + 1
via, which is trivial for jumper wires or a 2-layer PCB.
**Why `cs`=5 (software CS) and `t_irq`=2?** Pin 10 is the hardware CS0 for
SPI0, but **pin 10 cannot be used for `t_irq`** — calling `pinMode(10, INPUT)`
corrupts the SPI0 engine and reverts the display to landscape after
`setRotation()` (verified during bring-up, see
[`plans/teensy41_bringup.md`](../../plans/teensy41_bringup.md)). So `t_irq` is
on pin 2 (long edge, before pin 5), and `cs` is on pin 5 (software CS via
`SPI.beginTransaction()`). The speed difference vs hardware CS0 is negligible
for a signer UI. If you want hardware CS0 for the TFT, put `cs` on pin 10 and
leave `t_irq` on pin 2 (or drop `t_irq` and poll).
## Power notes
- **3.3V only.** The Teensy 4.1's pins are **not 5V tolerant**. The display
module is rated 3.3V5V and works at 3.3V logic — power it from the Teensy's
`3V3` pin, **not** `VIN`/`VUSB` (5V). Driving VCC with 5V while the signal
pins are at 3.3V can back-power the ST7796S level shifters and is unnecessary.
- **Backlight current.** The LED pin on these modules is typically driven
through a transistor on the module; a direct 3.3V GPIO high is enough to turn
it on. If the backlight flickers or the GPIO can't hold high, drive `LED` from
3.3V through a ~100 Ω resistor instead and skip PWM dimming.
- **Total draw.** Display + backlight + touch ≈ 80120 mA at 3.3V. The Teensy's
onboard regulator is rated for ~250 mA external use, so this is within budget.
If you add other peripherals (Ethernet PHY, etc.), re-check the budget.
## Wiring checklist (do this before powering on)
- [ ] VCC → **3V3** (not 5V/VIN).
- [ ] GND → GND.
- [ ] All SPI signal pins (`cs`, `dc/rs`, `reset`, `sdi (mosi)`, `sck`,
`sdo (miso)`, `t_cs`, `t_irq`) go to the Teensy pins listed above —
confirm none are swapped. The easy one to get backwards is
`sdi (mosi)``sdo (miso)`: on this module **`sdi (mosi)` = Teensy pin 11
(MOSI)** and **`sdo (miso)` = Teensy pin 12 (MISO)**.
- [ ] The shared-bus pairs (`t_do`/`sdo (miso)`, `t_din`/`sdi (mosi)`,
`t_clk`/`sck`) are tied together on the module PCB — wire one of each
pair to the Teensy pin and the other can go to the same pin or float.
Don't wire them to *different* Teensy pins.
- [ ] No 5V signal reaches any Teensy pin.
- [ ] The Teensy's built-in SD slot is **not** wired to the display — the
module's SD slot is unused. The 1 TB pad goes in the Teensy's built-in
slot only.
## Bring-up order (Phase 1)
1. **TFT only first.** Wire `vcc`, `gnd`, `cs`, `reset`, `dc/rs`, `sdi (mosi)`,
`sck`, `led`, `sdo (miso)`. Leave `t_cs`, `t_irq` floating for now. Run a
fill-screen + draw-text sketch. Exit criterion: solid color fill + readable
text.
2. **Touch second.** Add `t_cs`, `t_clk` (shared with `sck`), `t_din` (shared
with `sdi (mosi)`), `t_do` (shared with `sdo (miso)`), `t_irq`. Run a
touch-read sketch that prints raw X/Y + mapped pixel coords. Exit criterion:
stylus press prints coordinates that track the stylus position across the
full 480×320 area.
3. **Calibration.** The XPT2046 raw readings need a 2-point calibration per
axis (min/max raw → 0/480 and 0/320). Port the calibration struct from
[`firmware/cyd_esp32_2432s028/main/touch.c`](../cyd_esp32_2432s028/main/touch.c)
`s_cal` and re-calibrate on the Teensy (the CYD's numbers won't match —
different panel, different controller).
## References
- Port plan: [`plans/teensy41_signer_port.md`](../../plans/teensy41_signer_port.md)
- Bring-up log: [`plans/teensy41_bringup.md`](../../plans/teensy41_bringup.md)
- CYD display driver to port: [`firmware/cyd_esp32_2432s028/main/ili9341.c`](../cyd_esp32_2432s028/main/ili9341.c)
- CYD touch driver to port: [`firmware/cyd_esp32_2432s028/main/touch.c`](../cyd_esp32_2432s028/main/touch.c)
- ST7796S datasheet: [`firmware/teensy41/documents/ST7796S_Datasheet.pdf`](documents/ST7796S_Datasheet.pdf)
- Module user manual: [`firmware/teensy41/documents/4.0inch_SPI_Module_User_Manual.pdf`](documents/4.0inch_SPI_Module_User_Manual.pdf)
- Teensy 4.1 pinout: [`firmware/teensy41/documents/Teensy® 4.1.html`](documents/Teensy%C2%AE%204.1.html)
+24
View File
@@ -0,0 +1,24 @@
// Teensy 4.1 bring-up: blink the onboard red LED on pin 13 at 1 Hz.
//
// Phase 0 of plans/teensy41_signer_port.md. First sketch to load after the
// board's application flash was erased (board enumerates as Halfkay bootloader
// 16c0:0478 with no /dev/ttyACMx and no LED activity). A successful upload +
// visible 1 Hz blink confirms the toolchain, the FQBN, and the USB upload path.
//
// Build / upload:
// arduino-cli compile --fqbn teensy:avr:teensy41 firmware/teensy41/blink
// arduino-cli upload -p /dev/ttyACM0 --fqbn teensy:avr:teensy41 firmware/teensy41/blink
//
// Exit criterion: the red LED near the USB connector toggles at exactly 1 Hz
// (slower than the PJRC factory blink, which is ~5 Hz, so the change is obvious).
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // LED_BUILTIN == 13 on Teensy 4.1
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
+99
View File
@@ -0,0 +1,99 @@
#!/bin/bash
# build_signer.sh — reproducible build + optional flash for the Teensy 4.1 n_signer.
#
# Usage:
# ./firmware/teensy41/build_signer.sh # compile only
# ./firmware/teensy41/build_signer.sh --flash # compile + upload
# ./firmware/teensy41/build_signer.sh --test # compile + upload + run test suite
#
# This script handles:
# - Copying lv_conf.h to the Arduino libraries directory (where LVGL's
# lv_conf_internal.h searches for it via ../../lv_conf.h).
# - Passing the custom linker script (imxrt1062_t41_flashmem.ld) that routes
# crypto code to FLASH instead of ITCM, freeing stack space.
# - Printing the memory usage report.
# - Optionally uploading to the first discovered Teensy port.
# - Optionally running the hardware test suite.
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SIGNER_DIR="$SCRIPT_DIR/signer"
FQBN="teensy:avr:teensy41"
LV_CONF_SRC="$SIGNER_DIR/lv_conf.h"
LV_CONF_DST="$HOME/Arduino/libraries/lv_conf.h"
LINKER_SCRIPT="$SIGNER_DIR/imxrt1062_t41_flashmem.ld"
# --- Step 1: Copy lv_conf.h to the Arduino libraries directory ---
if [ -f "$LV_CONF_SRC" ]; then
mkdir -p "$(dirname "$LV_CONF_DST")"
cp "$LV_CONF_SRC" "$LV_CONF_DST"
echo "[build] Copied lv_conf.h to $LV_CONF_DST"
else
echo "[build] WARNING: $LV_CONF_SRC not found — LVGL may use default config."
fi
# --- Step 2: Compile with the custom linker script ---
echo "[build] Compiling..."
LINKER_FLAG="-Wl,--gc-sections,--relax,--no-warn-rwx-segments -T${LINKER_SCRIPT}"
if [ -f "$LINKER_SCRIPT" ]; then
arduino-cli compile \
--fqbn "$FQBN" \
--build-property "build.flags.ld=${LINKER_FLAG}" \
"$SIGNER_DIR" || true # size-determination step may error with custom .ld
else
echo "[build] WARNING: Linker script not found at $LINKER_SCRIPT — using default."
arduino-cli compile --fqbn "$FQBN" "$SIGNER_DIR"
fi
# --- Step 2b: FlexRAM stack gauge ---
# arduino-cli's "Error while determining sketch size" with a custom linker
# script is non-fatal (the ELF is produced), but it means we lose the built-in
# memory report. Run our own gauge against the ELF to catch DTCM stack
# overflows that the linker cannot detect (the ITCM/DTCM split is computed at
# boot, not link time).
ELF_FILE=$(find "$HOME/.cache/arduino/sketches" -name "signer.ino.elf" -newer "$LINKER_SCRIPT" 2>/dev/null | head -1)
if [ -z "$ELF_FILE" ]; then
ELF_FILE=$(find "$HOME/.cache/arduino/sketches" -name "signer.ino.elf" 2>/dev/null | head -1)
fi
if [ -n "$ELF_FILE" ] && [ -f "$ELF_FILE" ]; then
echo "[build] Running FlexRAM stack gauge..."
bash "$SCRIPT_DIR/check_stack.sh" "$ELF_FILE" 16384 || {
echo "[build] ❌ Stack gauge FAILED — refusing to flash. See check_stack.sh output above."
exit 1
}
else
echo "[build] WARNING: could not find signer.ino.elf for stack gauge — skipping."
fi
echo "[build] Compilation successful."
# --- Step 3: Find the Teensy port ---
find_teensy_port() {
arduino-cli board list 2>/dev/null | grep 'teensy Teensy Ports' | awk '{print $1}' | head -1
}
# --- Step 4: Flash (if --flash or --test) ---
if [ "$1" = "--flash" ] || [ "$1" = "--test" ]; then
PORT=$(find_teensy_port)
if [ -z "$PORT" ]; then
echo "[flash] No Teensy found. Press the PROGRAM button on the Teensy."
exit 1
fi
echo "[flash] Uploading to $PORT..."
arduino-cli upload -p "$PORT" --fqbn "$FQBN" "$SIGNER_DIR"
echo "[flash] Upload complete."
fi
# --- Step 5: Run test suite (if --test) ---
if [ "$1" = "--test" ]; then
echo "[test] Waiting for device to boot..."
sleep 4
PORT_DEV=$(arduino-cli board list 2>/dev/null | grep 'ttyACM' | awk '{print $1}' | head -1)
if [ -z "$PORT_DEV" ]; then
PORT_DEV="/dev/ttyACM0"
fi
echo "[test] Running test suite on $PORT_DEV..."
python3 "$SCRIPT_DIR/test_signer.py" --port "$PORT_DEV" || true
fi
+107
View File
@@ -0,0 +1,107 @@
#!/bin/bash
# check_stack.sh — Teensy 4.1 FlexRAM stack gauge.
#
# Computes the same ITCM/DTCM split the i.MX RT1062 boot ROM will perform, and
# fails if the resulting free stack is below a threshold. The linker cannot
# catch this because the split is computed at reset from _itcm_block_count,
# not at link time.
#
# Usage: check_stack.sh <signer.ino.elf> [min_stack_bytes]
# min_stack_bytes defaults to 16384 (16 KB).
#
# Exits 0 if the stack is above the threshold, 1 if below (with a diagnostic).
#
# The arithmetic (from imxrt1062_t41_flashmem.ld:215-217):
# itcm_banks = ceil((.text.itcm + .ARM.exidx) / 32768)
# dtcm_total = (16 - itcm_banks) * 32768
# free_stack = dtcm_total - .data - .bss
# _estack = ORIGIN(DTCM) + dtcm_total (stack grows down from here)
#
# Note: .bss here is the DTCM .bss (RAM1), NOT .bss.dma (RAM2/OCRAM). The
# .bss.dma section lives in a separate 512 KB region and does not affect the
# stack.
set -euo pipefail
ELF="${1:-}"
MIN_STACK="${2:-16384}"
if [ -z "$ELF" ] || [ ! -f "$ELF" ]; then
echo "check_stack: usage: $0 <signer.ino.elf> [min_stack_bytes]" >&2
exit 2
fi
# Locate the arm-none-eabi-size tool from the Teensy toolchain.
SIZE_BIN=""
for candidate in \
/home/user/.arduino15/packages/teensy/tools/teensy-compile/*/arm/bin/arm-none-eabi-size \
"$(dirname "$0")/../.arduino15/packages/teensy/tools/teensy-compile/*/arm/bin/arm-none-eabi-size"; do
if [ -x "$candidate" ]; then SIZE_BIN="$candidate"; break; fi
done
# Fall back to PATH
if [ -z "$SIZE_BIN" ]; then SIZE_BIN="$(command -v arm-none-eabi-size || true)"; fi
if [ -z "$SIZE_BIN" ]; then
echo "check_stack: cannot find arm-none-eabi-size" >&2
exit 2
fi
# We need per-section sizes, not the aggregate. Use objdump -h.
OBJDUMP_BIN="${SIZE_BIN%size}objdump"
# Extract section sizes (in bytes, decimal) by name.
get_section_size() {
local section="$1"
# objdump -h prints: idx Name Size VMA LMA File-off Al
"$OBJDUMP_BIN" -h "$ELF" 2>/dev/null \
| awk -v sec="$section" '$2 == sec { print strtonum("0x"$3); exit }'
}
TEXT_ITCM=$(get_section_size ".text.itcm")
ARM_EXIDX=$(get_section_size ".ARM.exidx")
DATA_SEC=$(get_section_size ".data")
BSS_SEC=$(get_section_size ".bss")
BSS_DMA=$(get_section_size ".bss.dma")
# Guard against missing sections (e.g. exidx may be 0/absent).
: "${TEXT_ITCM:=0}"
: "${ARM_EXIDX:=0}"
: "${DATA_SEC:=0}"
: "${BSS_SEC:=0}"
: "${BSS_DMA:=0}"
BANK=32768
ITCM_BYTES=$(( TEXT_ITCM + ARM_EXIDX ))
ITCM_BANKS=$(( (ITCM_BYTES + BANK - 1) / BANK ))
DTCM_TOTAL=$(( (16 - ITCM_BANKS) * BANK ))
DATA_BSS=$(( DATA_SEC + BSS_SEC ))
FREE_STACK=$(( DTCM_TOTAL - DATA_BSS ))
# Also report RAM2 (OCRAM) usage for completeness.
RAM2_TOTAL=$(( 512 * 1024 ))
RAM2_FREE=$(( RAM2_TOTAL - BSS_DMA ))
echo "=== Teensy 4.1 FlexRAM stack gauge ==="
echo " .text.itcm : $(printf '%7d' $TEXT_ITCM) bytes"
echo " .ARM.exidx : $(printf '%7d' $ARM_EXIDX) bytes"
echo " ITCM total : $(printf '%7d' $ITCM_BYTES) bytes -> $ITCM_BANKS banks ($(( ITCM_BANKS * BANK )) bytes)"
echo " .data (DTCM) : $(printf '%7d' $DATA_SEC) bytes"
echo " .bss (DTCM) : $(printf '%7d' $BSS_SEC) bytes"
echo " DTCM total : $(printf '%7d' $DTCM_TOTAL) bytes ($(( 16 - ITCM_BANKS )) banks)"
echo " data + bss : $(printf '%7d' $DATA_BSS) bytes"
echo " FREE STACK : $(printf '%7d' $FREE_STACK) bytes (threshold: $MIN_STACK)"
echo " ---"
echo " .bss.dma RAM2: $(printf '%7d' $BSS_DMA) / $RAM2_TOTAL bytes (free: $RAM2_FREE)"
if [ "$FREE_STACK" -lt "$MIN_STACK" ]; then
echo ""
echo " ❌ FAIL: free stack $FREE_STACK < threshold $MIN_STACK"
echo " The boot ROM will allocate $ITCM_BANKS ITCM banks, leaving only"
echo " $DTCM_TOTAL bytes of DTCM. .data+.bss needs $DATA_BSS bytes."
echo " Reduce ITCM (route more code to FLASH) or reduce .data/.bss"
echo " (move .rodata to FLASH)."
exit 1
fi
echo ""
echo " ✅ OK: free stack $FREE_STACK >= threshold $MIN_STACK"
exit 0
@@ -0,0 +1,756 @@
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkC3kaWzU.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkAnkaWzU.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkCnkaWzU.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBXkaWzU.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* math */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkenkaWzU.woff2) format('woff2');
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF;
}
/* symbols */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkaHkaWzU.woff2) format('woff2');
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkCXkaWzU.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkCHkaWzU.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, 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;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBnka.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkC3kaWzU.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkAnkaWzU.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkCnkaWzU.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBXkaWzU.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* math */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkenkaWzU.woff2) format('woff2');
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF;
}
/* symbols */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkaHkaWzU.woff2) format('woff2');
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkCXkaWzU.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkCHkaWzU.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, 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;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBnka.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkC3kaWzU.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkAnkaWzU.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkCnkaWzU.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBXkaWzU.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* math */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkenkaWzU.woff2) format('woff2');
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF;
}
/* symbols */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkaHkaWzU.woff2) format('woff2');
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkCXkaWzU.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkCHkaWzU.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, 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;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBnka.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3GUBGEe.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3iUBGEe.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3CUBGEe.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3-UBGEe.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* math */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMawCUBGEe.woff2) format('woff2');
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF;
}
/* symbols */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMaxKUBGEe.woff2) format('woff2');
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3OUBGEe.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, 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;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3GUBGEe.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3iUBGEe.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3CUBGEe.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3-UBGEe.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* math */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMawCUBGEe.woff2) format('woff2');
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF;
}
/* symbols */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMaxKUBGEe.woff2) format('woff2');
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3OUBGEe.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, 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;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3GUBGEe.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3iUBGEe.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3CUBGEe.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3-UBGEe.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* math */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMawCUBGEe.woff2) format('woff2');
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF;
}
/* symbols */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMaxKUBGEe.woff2) format('woff2');
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3OUBGEe.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, 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;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm3CWWoKC.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm3mWWoKC.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm36WWoKC.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm3KWWoKC.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm3OWWoKC.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, 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;
}
/* latin */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm32WWg.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm3CWWoKC.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm3mWWoKC.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm36WWoKC.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm3KWWoKC.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm3OWWoKC.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, 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;
}
/* latin */
@font-face {
font-family: 'Roboto Mono';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x7DF4xlVMF-BfR8bXMIjhOm32WWg.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhGq3-OXg.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhPq3-OXg.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhIq3-OXg.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhEq3-OXg.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhFq3-OXg.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, 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;
}
/* latin */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhLq38.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhGq3-OXg.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhPq3-OXg.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhIq3-OXg.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhEq3-OXg.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhFq3-OXg.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, 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;
}
/* latin */
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/robotomono/v31/L0x5DF4xlVMF-BfR8bXMIjhLq38.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@@ -0,0 +1,11 @@
.md-header{
background-color:#172360 !important;
}
.md-typeset mark{
background-color:blue;
color: #fff;
}
.md-typeset table:not([class]) td{
vertical-align: middle;
word-break: break-all;
}
@@ -0,0 +1,5 @@
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-KRSVT6V');
@@ -0,0 +1 @@
"use strict";(()=>{function c(s,n){parent.postMessage(s,n||"*")}function d(...s){return s.reduce((n,e)=>n.then(()=>new Promise(r=>{let t=document.createElement("script");t.src=e,t.onload=r,document.body.appendChild(t)})),Promise.resolve())}var o=class extends EventTarget{constructor(e){super();this.url=e;this.m=e=>{e.source===this.w&&(this.dispatchEvent(new MessageEvent("message",{data:e.data})),this.onmessage&&this.onmessage(e))};this.e=(e,r,t,i,m)=>{if(r===`${this.url}`){let a=new ErrorEvent("error",{message:e,filename:r,lineno:t,colno:i,error:m});this.dispatchEvent(a),this.onerror&&this.onerror(a)}};let r=document.createElement("iframe");r.hidden=!0,document.body.appendChild(this.iframe=r),this.w.document.open(),this.w.document.write(`<html><body><script>postMessage=${c};importScripts=${d};addEventListener("error",({error})=>{parent.dispatchEvent(new ErrorEvent("error",{filename:"${e}",error}))})<\/script><script src=${e}?${+Date.now()}><\/script></body></html>`),this.w.document.close(),onmessage=this.m,onerror=this.e,this.r=new Promise((t,i)=>{this.w.onload=t,this.w.onerror=i})}terminate(){this.iframe.remove(),onmessage=onerror=null}postMessage(e){this.r.catch().then(()=>{this.w.dispatchEvent(new MessageEvent("message",structuredClone({data:e})))})}get w(){return this.iframe.contentWindow}};window.IFrameWorker=o;location.protocol==="file:"&&(window.Worker=o);})();
Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

File diff suppressed because one or more lines are too long
@@ -0,0 +1,29 @@
var ezTcfConsent=window.ezTcfConsent?window.ezTcfConsent:{loaded:false,store_info:false,develop_and_improve_services:false,measure_ad_performance:false,measure_content_performance:false,select_basic_ads:false,create_ad_profile:false,select_personalized_ads:false,create_content_profile:false,select_personalized_content:false,understand_audiences:false,use_limited_data_to_select_content:false,};if(typeof _emitEzConsentEvent!=="function"){function _emitEzConsentEvent(){var customEvent=new CustomEvent("ezConsentEvent",{detail:{ezTcfConsent:window.ezTcfConsent},bubbles:true,cancelable:true});document.dispatchEvent(customEvent);}}
(function(window,document){function _setAllEzConsentTrue(){window.ezTcfConsent.loaded=true;window.ezTcfConsent.store_info=true;window.ezTcfConsent.develop_and_improve_services=true;window.ezTcfConsent.measure_ad_performance=true;window.ezTcfConsent.measure_content_performance=true;window.ezTcfConsent.select_basic_ads=true;window.ezTcfConsent.create_ad_profile=true;window.ezTcfConsent.select_personalized_ads=true;window.ezTcfConsent.create_content_profile=true;window.ezTcfConsent.select_personalized_content=true;window.ezTcfConsent.understand_audiences=true;window.ezTcfConsent.use_limited_data_to_select_content=true;window.ezTcfConsent.select_personalized_content=true;}
function _clearEzConsentCookie(){document.cookie="ezCMPCookieConsent=tcf2;Domain=.{domain};Path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT";}
_clearEzConsentCookie();if(typeof window.__tcfapi!=="undefined"){window.ezgconsent=false;var amazonHasRun=false;function _ezAllowed(tcdata,purpose){return(tcdata.purpose.consents[purpose]||tcdata.purpose.legitimateInterests[purpose]);}
function _handleConsentDecision(tcdata){window.ezTcfConsent.loaded=true;if(!tcdata.vendor.consents["{vendor_id}"]&&!tcdata.vendor.legitimateInterests["{vendor_id}"]){window._emitEzConsentEvent();return;}
window.ezTcfConsent.store_info=_ezAllowed(tcdata,"{store_info}");window.ezTcfConsent.develop_and_improve_services=_ezAllowed(tcdata,"{develop_and_improve_services}");window.ezTcfConsent.measure_content_performance=_ezAllowed(tcdata,"{measure_content_performance}");window.ezTcfConsent.select_basic_ads=_ezAllowed(tcdata,"{select_basic_ads}");window.ezTcfConsent.create_ad_profile=_ezAllowed(tcdata,"{create_ad_profile}");window.ezTcfConsent.select_personalized_ads=_ezAllowed(tcdata,"{select_personalized_ads}");window.ezTcfConsent.create_content_profile=_ezAllowed(tcdata,"{create_content_profile}");window.ezTcfConsent.measure_ad_performance=_ezAllowed(tcdata,"{measure_ad_performance}");window.ezTcfConsent.use_limited_data_to_select_content=_ezAllowed(tcdata,"{use_limited_data_to_select_content}");window.ezTcfConsent.select_personalized_content=_ezAllowed(tcdata,"{select_personalized_content}");window.ezTcfConsent.understand_audiences=_ezAllowed(tcdata,"{understand_audiences}");window._emitEzConsentEvent();}
function _handleGoogleConsentV2(tcdata){if(!tcdata||!tcdata.purpose||!tcdata.purpose.consents){return;}
var googConsentV2={};if(tcdata.purpose.consents[1]){googConsentV2.ad_storage='granted';googConsentV2.analytics_storage='granted';}
if(tcdata.purpose.consents[3]&&tcdata.purpose.consents[4]){googConsentV2.ad_personalization='granted';}
if(tcdata.purpose.consents[1]&&tcdata.purpose.consents[7]){googConsentV2.ad_user_data='granted';}
if(googConsentV2.analytics_storage=='denied'){gtag('set','url_passthrough',true);}
gtag('consent','update',googConsentV2);}
__tcfapi("addEventListener",2,function(tcdata,success){if(!success||!tcdata){window._emitEzConsentEvent();return;}
if(!tcdata.gdprApplies){_setAllEzConsentTrue();window._emitEzConsentEvent();return;}
if(tcdata.eventStatus==="useractioncomplete"||tcdata.eventStatus==="tcloaded"){if(typeof gtag!='undefined'){_handleGoogleConsentV2(tcdata);}
_handleConsentDecision(tcdata);if(tcdata.purpose.consents["{store_info}"]===true&&tcdata.vendor.consents["{google_vendor_id}"]!==false){window.ezgconsent=true;(adsbygoogle=window.adsbygoogle||[]).pauseAdRequests=0;}
if(window.__ezconsent){__ezconsent.setEzoicConsentSettings(ezConsentCategories);}
__tcfapi("removeEventListener",2,function(success){return null;},tcdata.listenerId);if(!(tcdata.purpose.consents["{store_info}"]===true&&_ezAllowed(tcdata,"{select_basic_ads}")&&_ezAllowed(tcdata,"{create_ad_profile}")&&_ezAllowed(tcdata,"{select_personalized_ads}"))){if(typeof __ez=="object"&&typeof __ez.bit=="object"&&typeof window["_ezaq"]=="object"&&typeof window["_ezaq"]["page_view_id"]=="string"){__ez.bit.Add(window["_ezaq"]["page_view_id"],[new __ezDotData("non_personalized_ads",true),]);}}}});}else{_setAllEzConsentTrue();window._emitEzConsentEvent();}})(window,document);var ezCMPQueue=ezCMPQueue||{queue:[],gotResponse:false};ezCMPQueue.push=function(f){if(ezCMPQueue.gotResponse){f();}else{ezCMPQueue.queue.push(f);}};(function(){var getUrlParam=function(){var param="?force_regulations";var url=document.location.href;var results=new RegExp("[?&]"+param+"=([^&#]*)").exec(url);if(results==null){return "";}else{return decodeURI(results[0])||"";}};var xhr=new XMLHttpRequest();var consentUrl="https://privacy.gatekeeperconsent.com/consent_modules.json"+getUrlParam();xhr.open("GET",consentUrl);xhr.onload=function(){ezCMPQueue.gotResponse=true;if(xhr.status===200){var json=JSON.parse(xhr.responseText);for(var key in json){if(key.toLowerCase()==="gdpr"){setupEzTcfApi();}
if(json.hasOwnProperty(key)&&json[key]!==null){const ezCmpScript=document.createElement("script");ezCmpScript.src=json[key];var ezHead=document.getElementsByTagName("head")[0];ezHead.insertBefore(ezCmpScript,ezHead.firstChild);}}}else{console.error("Error: "+xhr.status);}
while(ezCMPQueue.queue.length>0){const ezCMPQueueFunc=ezCMPQueue.queue.shift();if(typeof ezCMPQueueFunc==='function'){try{ezCMPQueueFunc();}catch(error){console.error('Error executing function in ezCMPQueue:',error);}}}};xhr.onerror=function(){console.error("Error: consent request failed");};xhr.send();})();function __setCMPv2RequestData(){var browserLang=navigator.language.split("-")[0];window._CMPv2RequestData={"language":browserLang,"stylingLogo":""};}
function __getCMPv2InitialSelectedLanguage(){return navigator.language.split("-")[0];}
__setCMPv2RequestData();var setupEzTcfApi=function(){var gdprApplies,tcfapiLocator="__tcfapiLocator",messageQueue=[],currentWindow=window;while(currentWindow){try{if(currentWindow.frames[tcfapiLocator]){gdprApplies=currentWindow;break;}}catch(err){}
if(currentWindow===window.top){break;}
currentWindow=currentWindow.parent;}
if(!gdprApplies){(function createLocatorIframe(){var doc=window.document;var hasLocator=!!window.frames[tcfapiLocator];if(!hasLocator){if(doc.body){var iframe=doc.createElement("iframe");iframe.style.cssText="display:none";iframe.name=tcfapiLocator;doc.body.appendChild(iframe);}else{setTimeout(createLocatorIframe,5);}}
return!hasLocator;})();window.__tcfapi=function(){var args=Array.prototype.slice.call(arguments);if(!args.length){return messageQueue;}
if(args[0]==="setGdprApplies"&&args.length>3&&parseInt(args[1],10)===2&&typeof args[3]==="boolean"){gdprApplies=args[3];if(typeof args[2]==="function"){args[2]("set",true);}}else if(args[0]==="ping"){var response={gdprApplies:gdprApplies,cmpLoaded:false,cmpStatus:"stub"};if(typeof args[2]==="function"){args[2](response);}}else{messageQueue.push(args);}};window.addEventListener("message",function(event){var isString=typeof event.data==="string";var message={};try{message=isString?JSON.parse(event.data):event.data;}catch(err){}
var tcfapiCall=message.__tcfapiCall;if(tcfapiCall){window.__tcfapi(tcfapiCall.command,tcfapiCall.version,function(returnValue,success){var response={__tcfapiReturn:{returnValue:returnValue,success:success,callId:tcfapiCall.callId}};if(isString){response=JSON.stringify(response);}
event.source.postMessage(response,"*");},tcfapiCall.parameter);}},false);}};
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@@ -0,0 +1,669 @@
// Copyright 2012 Google Inc. All rights reserved.
(function(){
var data = {
"resource": {
"version":"1",
"macros":[{"function":"__u","vtp_component":"URL","vtp_enableMultiQueryKeys":false,"vtp_enableIgnoreEmptyQueryParam":false},{"function":"__u","vtp_component":"HOST","vtp_enableMultiQueryKeys":false,"vtp_enableIgnoreEmptyQueryParam":false},{"function":"__u","vtp_component":"PATH","vtp_enableMultiQueryKeys":false,"vtp_enableIgnoreEmptyQueryParam":false},{"function":"__f","vtp_component":"URL"},{"function":"__e"}],
"tags":[],
"predicates":[],
"rules":[]
},
"runtime":[ [50,"__e",[46,"a"],[36,[13,[41,"$0"],[3,"$0",["require","internal.getEventData"]],["$0","event"]]]]
,[50,"__f",[46,"a"],[52,"b",["require","copyFromDataLayer"]],[52,"c",["require","getReferrerUrl"]],[52,"d",["require","makeString"]],[52,"e",["require","parseUrl"]],[52,"f",[15,"__module_legacyUrls"]],[52,"g",[30,["b","gtm.referrer",1],["c"]]],[22,[28,[15,"g"]],[46,[36,["d",[15,"g"]]]]],[38,[17,[15,"a"],"component"],[46,"PROTOCOL","HOST","PORT","PATH","QUERY","FRAGMENT","URL"],[46,[5,[46,[36,[2,[15,"f"],"B",[7,[15,"g"]]]]]],[5,[46,[36,[2,[15,"f"],"C",[7,[15,"g"],[17,[15,"a"],"stripWww"]]]]]],[5,[46,[36,[2,[15,"f"],"D",[7,[15,"g"]]]]]],[5,[46,[36,[2,[15,"f"],"E",[7,[15,"g"],[17,[15,"a"],"defaultPages"]]]]]],[5,[46,[22,[17,[15,"a"],"queryKey"],[46,[53,[36,[2,[15,"f"],"H",[7,[15,"g"],[17,[15,"a"],"queryKey"]]]]]]],[52,"h",["e",[15,"g"]]],[36,[2,[17,[15,"h"],"search"],"replace",[7,"?",""]]]]],[5,[46,[36,[2,[15,"f"],"G",[7,[15,"g"]]]]]],[5,[46]],[9,[46,[36,[2,[15,"f"],"A",[7,["d",[15,"g"]]]]]]]]]]
,[50,"__u",[46,"a"],[50,"k",[46,"l","m"],[52,"n",[17,[15,"m"],"multiQueryKeys"]],[52,"o",[30,[17,[15,"m"],"queryKey"],""]],[52,"p",[17,[15,"m"],"ignoreEmptyQueryParam"]],[22,[20,[15,"o"],""],[46,[53,[52,"r",[2,[17,["i",[15,"l"]],"search"],"replace",[7,"?",""]]],[36,[39,[1,[28,[15,"r"]],[15,"p"]],[44],[15,"r"]]]]]],[41,"q"],[22,[15,"n"],[46,[53,[22,[20,["e",[15,"o"]],"array"],[46,[53,[3,"q",[15,"o"]]]],[46,[53,[52,"r",["c","\\s+","g"]],[3,"q",[2,[2,["f",[15,"o"]],"replace",[7,[15,"r"],""]],"split",[7,","]]]]]]]],[46,[53,[3,"q",[7,["f",[15,"o"]]]]]]],[65,"r",[15,"q"],[46,[53,[52,"s",[2,[15,"h"],"H",[7,[15,"l"],[15,"r"]]]],[22,[29,[15,"s"],[44]],[46,[53,[22,[1,[15,"p"],[20,[15,"s"],""]],[46,[53,[6]]]],[36,[15,"s"]]]]]]]],[36,[44]]],[52,"b",["require","copyFromDataLayer"]],[52,"c",["require","internal.createRegex"]],[52,"d",["require","getUrl"]],[52,"e",["require","getType"]],[52,"f",["require","makeString"]],[52,"g",["require","parseUrl"]],[52,"h",[15,"__module_legacyUrls"]],[52,"i",["require","internal.legacyParseUrl"]],[41,"j"],[22,[17,[15,"a"],"customUrlSource"],[46,[53,[3,"j",[17,[15,"a"],"customUrlSource"]]]],[46,[53,[3,"j",["b","gtm.url",1]]]]],[3,"j",[30,[15,"j"],["d"]]],[38,[17,[15,"a"],"component"],[46,"PROTOCOL","HOST","PORT","PATH","EXTENSION","QUERY","FRAGMENT","URL"],[46,[5,[46,[36,[2,[15,"h"],"B",[7,[15,"j"]]]]]],[5,[46,[36,[2,[15,"h"],"C",[7,[15,"j"],[17,[15,"a"],"stripWww"]]]]]],[5,[46,[36,[2,[15,"h"],"D",[7,[15,"j"]]]]]],[5,[46,[36,[2,[15,"h"],"E",[7,[15,"j"],[17,[15,"a"],"defaultPages"]]]]]],[5,[46,[36,[2,[15,"h"],"F",[7,[15,"j"]]]]]],[5,[46,[36,["k",[15,"j"],[15,"a"]]]]],[5,[46,[36,[2,[15,"h"],"G",[7,[15,"j"]]]]]],[5,[46]],[9,[46,[36,[2,[15,"h"],"A",[7,["f",[15,"j"]]]]]]]]]]
,[52,"__module_legacyUrls",[13,[41,"$0"],[3,"$0",[51,"",[7],[50,"a",[46],[50,"h",[46,"p"],[52,"q",[2,[15,"p"],"indexOf",[7,"#"]]],[36,[39,[23,[15,"q"],0],[15,"p"],[2,[15,"p"],"substring",[7,0,[15,"q"]]]]]],[50,"i",[46,"p"],[52,"q",[17,["e",[15,"p"]],"protocol"]],[36,[39,[15,"q"],[2,[15,"q"],"replace",[7,":",""]],""]]],[50,"j",[46,"p","q"],[41,"r"],[3,"r",[17,["e",[15,"p"]],"hostname"]],[22,[28,[15,"r"]],[46,[36,""]]],[52,"s",["b",":[0-9]+"]],[3,"r",[2,[15,"r"],"replace",[7,[15,"s"],""]]],[22,[15,"q"],[46,[53,[52,"t",["b","^www\\d*\\."]],[52,"u",[2,[15,"r"],"match",[7,[15,"t"]]]],[22,[1,[15,"u"],[16,[15,"u"],0]],[46,[3,"r",[2,[15,"r"],"substring",[7,[17,[16,[15,"u"],0],"length"]]]]]]]]],[36,[15,"r"]]],[50,"k",[46,"p"],[52,"q",["e",[15,"p"]]],[41,"r"],[3,"r",["f",[17,[15,"q"],"port"]]],[22,[28,[15,"r"]],[46,[53,[22,[20,[17,[15,"q"],"protocol"],"http:"],[46,[53,[3,"r",80]]],[46,[22,[20,[17,[15,"q"],"protocol"],"https:"],[46,[53,[3,"r",443]]],[46,[53,[3,"r",""]]]]]]]]],[36,["g",[15,"r"]]]],[50,"l",[46,"p","q"],[52,"r",["e",[15,"p"]]],[41,"s"],[3,"s",[39,[20,[2,[17,[15,"r"],"pathname"],"indexOf",[7,"/"]],0],[17,[15,"r"],"pathname"],[0,"/",[17,[15,"r"],"pathName"]]]],[22,[20,["d",[15,"q"]],"array"],[46,[53,[52,"t",[2,[15,"s"],"split",[7,"/"]]],[22,[19,[2,[15,"q"],"indexOf",[7,[16,[15,"t"],[37,[17,[15,"t"],"length"],1]]]],0],[46,[53,[43,[15,"t"],[37,[17,[15,"t"],"length"],1],""],[3,"s",[2,[15,"t"],"join",[7,"/"]]]]]]]]],[36,[15,"s"]]],[50,"m",[46,"p"],[52,"q",[17,["e",[15,"p"]],"pathname"]],[52,"r",[2,[15,"q"],"split",[7,"."]]],[41,"s"],[3,"s",[39,[18,[17,[15,"r"],"length"],1],[16,[15,"r"],[37,[17,[15,"r"],"length"],1]],""]],[36,[16,[2,[15,"s"],"split",[7,"/"]],0]]],[50,"n",[46,"p"],[52,"q",[17,["e",[15,"p"]],"hash"]],[36,[2,[15,"q"],"replace",[7,"#",""]]]],[50,"o",[46,"p","q"],[50,"s",[46,"t"],[36,["c",[2,[15,"t"],"replace",[7,["b","\\+","g"]," "]]]]],[52,"r",[2,[17,["e",[15,"p"]],"search"],"replace",[7,"?",""]]],[65,"t",[2,[15,"r"],"split",[7,"&"]],[46,[53,[52,"u",[2,[15,"t"],"split",[7,"="]]],[22,[21,["s",[16,[15,"u"],0]],[15,"q"]],[46,[6]]],[36,["s",[2,[2,[15,"u"],"slice",[7,1]],"join",[7,"="]]]]]]],[36]],[52,"b",["require","internal.createRegex"]],[52,"c",["require","decodeUriComponent"]],[52,"d",["require","getType"]],[52,"e",["require","internal.legacyParseUrl"]],[52,"f",["require","makeNumber"]],[52,"g",["require","makeString"]],[36,[8,"F",[15,"m"],"H",[15,"o"],"G",[15,"n"],"C",[15,"j"],"E",[15,"l"],"D",[15,"k"],"B",[15,"i"],"A",[15,"h"]]]],[36,["a"]]]],["$0"]]]
]
,"entities":{
"__e":{"2":true,"5":true,"6":true}
,
"__f":{"2":true,"5":true,"6":true}
,
"__u":{"2":true,"5":true,"6":true}
}
,"blob":{"1":"1","10":"GTM-P72JJ8GB","14":"67m0","15":"0","16":"ChAI8L2R0wYQjJXKrLXS8vxqEh0AarpFtovtVVBrYkX1C5m1iqvZKf50hYglhzQNAxoCWyI=","19":"dataLayer","2":true,"20":"","21":"www.googletagmanager.com","22":"eyIwIjoiVVMiLCIxIjoiVVMtTkoiLCIyIjpmYWxzZSwiMyI6IiIsIjQiOiIiLCI1Ijp0cnVlLCI2IjpmYWxzZSwiNyI6ImFkX3N0b3JhZ2V8YW5hbHl0aWNzX3N0b3JhZ2V8YWRfdXNlcl9kYXRhfGFkX3BlcnNvbmFsaXphdGlvbiIsIjkiOmZhbHNlfQ","23":"google.tagmanager.debugui2.queue","24":"tagassistant.google.com","27":0.005,"3":"www.googletagmanager.com","30":"US","31":"US-NJ","32":true,"36":"https://adservice.google.com/pagead/regclk","37":"__TAGGY_INSTALLED","38":"cct.google","39":"googTaggyReferrer","40":"https://cct.google/taggy/agent.js","41":"google.tagmanager.ta.prodqueue","42":0.01,"43":"{\"keys\":[{\"hpkePublicKey\":{\"params\":{\"aead\":\"AES_128_GCM\",\"kdf\":\"HKDF_SHA256\",\"kem\":\"DHKEM_P256_HKDF_SHA256\"},\"publicKey\":\"BKzFAUqesyDSoqlJwzyUj2MgjlEY/O0/CQ4mcnvPCi9TRjuOyvYv+80tVmVBDG0+be1NVvZuWgR8d9G51vq90SU=\",\"version\":0},\"id\":\"f9d39023-ea84-4a20-a7c9-b316c1a5e44e\"},{\"hpkePublicKey\":{\"params\":{\"aead\":\"AES_128_GCM\",\"kdf\":\"HKDF_SHA256\",\"kem\":\"DHKEM_P256_HKDF_SHA256\"},\"publicKey\":\"BJICfyLz06w3CEPPnl1Ywxn+LJxdxP4qJMemMf7PoqbAmynF/YtDatTOu1k3VwAi5dUYraauIKrtEMNts/evDxE=\",\"version\":0},\"id\":\"99ece3ee-0f30-44fe-a9f0-36ff2db2592c\"},{\"hpkePublicKey\":{\"params\":{\"aead\":\"AES_128_GCM\",\"kdf\":\"HKDF_SHA256\",\"kem\":\"DHKEM_P256_HKDF_SHA256\"},\"publicKey\":\"BDWc8Gf/CVuAXaRDDHdjFwKG6q2DhoJq2u2NU5FTnR1hXNQTqh0L3KpuiOCm3XWuY4L54JfZAB/0DRsbYjaBF4c=\",\"version\":0},\"id\":\"65dbd8b7-bcaf-4d33-90ff-f587b37f45ad\"},{\"hpkePublicKey\":{\"params\":{\"aead\":\"AES_128_GCM\",\"kdf\":\"HKDF_SHA256\",\"kem\":\"DHKEM_P256_HKDF_SHA256\"},\"publicKey\":\"BEHHlZYAUIk5rrJTLvAsA72CPMmp+vs+uM9C6Dgq3ntA4CyQWlREII+CiqNWNQ+L/AetJ7SmN9LNczNADK/kIwo=\",\"version\":0},\"id\":\"34b5c7b5-a389-4ecf-b68a-b11597997f35\"},{\"hpkePublicKey\":{\"params\":{\"aead\":\"AES_128_GCM\",\"kdf\":\"HKDF_SHA256\",\"kem\":\"DHKEM_P256_HKDF_SHA256\"},\"publicKey\":\"BD36E6jXqE4MRHvF03OKm6jLhKY1XM34t2HEyktBfbyQshIZgFqpZLPDUHuauoEaIv5qOFHkCY7Hbj/iU15olec=\",\"version\":0},\"id\":\"0c7b47ba-058a-4ce4-8b9e-7a29396ff240\"}]}","44":"118897920~118897930","46":{"1":"1000","10":"66u0","11":"66g0","14":"1000","16":"US-CO~US-CT~US-MT~US-NE~US-NH~US-TX~US-MN~US-NJ~US-MD~US-OR~US-DE","17":"US-CO~US-CT~US-MT~US-NE~US-NH~US-TX~US-MN~US-NJ~US-MD~US-OR~US-DE","2":"9","20":"5000","21":"5000","22":"4.4.0","23":"0.0.0","25":"1","26":"4000","27":"100","3":"5","4":"ad_storage|analytics_storage|ad_user_data|ad_personalization","44":"15000","48":"30000","5":"ad_storage|analytics_storage|ad_user_data","6":"1","61":"1000","62":"A6ONHRY7/bvBro+IMZd/a6LNjn7SSv999SkN/hFAE9L6vMr34dNgfdSVdYmv4U+NHZg1sxd38RtciRpRUtIRPgQAAACCeyJvcmlnaW4iOiJodHRwczovL3d3dy5nb29nbGV0YWdtYW5hZ2VyLmNvbTo0NDMiLCJmZWF0dXJlIjoiU2hhcmVkV29ya2VyRXh0ZW5kZWRMaWZldGltZSIsImV4cGlyeSI6MTc3NjcyOTYwMCwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ==","63":"1000","66":"100","7":"10"},"48":true,"5":"GTM-P72JJ8GB","55":["GTM-P72JJ8GB"],"56":[{"1":403,"3":0.5,"4":115938465,"5":115938466,"6":0,"7":2},{"1":404,"3":0.5,"4":115938468,"5":115938469,"6":0,"7":1},{"1":602,"3":0.01,"4":120124455,"5":120124453,"6":120124454,"7":3},{"1":569,"2":true},{"1":475,"2":true},{"1":502,"2":true},{"1":577,"2":true},{"1":568,"3":0.01,"4":119791749,"5":119791748,"6":0,"7":1},{"1":490,"2":true},{"1":491,"3":0.01,"4":118012007,"5":118012008,"6":118012009,"7":1},{"1":480,"2":true},{"1":594,"3":0.01,"4":119793974,"5":119793972,"6":119793973,"7":1},{"1":599,"2":true},{"1":580,"3":0.1,"4":119527020,"5":119527019,"6":0,"7":1},{"1":523,"2":true},{"1":581,"3":0.01,"4":119948854,"5":119948852,"6":119948853,"7":3},{"1":555,"3":0.01,"4":119259606,"5":119259605,"6":0,"7":2},{"1":504,"2":true},{"1":462,"3":0.05,"4":118806524,"5":118806525,"6":118806526,"7":1},{"1":413,"2":true},{"1":593,"2":true},{"1":506,"2":true},{"1":500,"2":true},{"1":561,"3":0.001,"4":119404703,"5":119404702,"6":0,"7":1},{"1":481,"3":0.001,"4":119404701,"5":119404700,"6":0,"7":1},{"1":450,"3":0.01,"4":117227714,"5":117227715,"6":117227716,"7":3},{"1":583,"3":0.5,"4":119896803,"5":119896802,"6":0,"7":1},{"1":458,"2":true},{"1":582,"3":0.01,"4":119381664,"5":119381662,"6":119381663,"7":1},{"1":570,"2":true},{"1":498,"3":0.2,"4":115616985,"5":115616986,"6":0,"7":1},{"1":595,"2":true},{"1":589,"3":0.01,"4":120084215,"5":120084214,"6":0,"7":1},{"1":495,"3":0.05,"4":118131810,"5":118131808,"6":118131809,"7":3},{"1":587,"3":0.1,"4":119732171,"5":119732170,"6":0,"7":3},{"1":584,"2":true},{"1":564,"3":0.0001,"4":119205317,"5":119205315,"6":119205316,"7":1},{"1":557,"2":true},{"1":427,"3":0.1,"4":119724322,"5":119724320,"6":119724321,"7":2},{"1":576,"3":0.01,"4":119317810,"5":119317811,"6":119318177,"7":3},{"1":573,"2":true},{"1":499,"2":true},{"1":516,"3":0.1,"4":118395335,"5":118395333,"6":118395334,"7":1},{"1":524,"2":true}],"59":["GTM-P72JJ8GB"],"6":"196278269","62":false,"63":0.005}
,"permissions":{
"__e":{"read_event_data":{"eventDataAccess":"specific","keyPatterns":["event"]}}
,
"__f":{"read_data_layer":{"keyPatterns":["gtm.referrer"]},"get_referrer":{"urlParts":"any"}}
,
"__u":{"read_data_layer":{"keyPatterns":["gtm.url"]},"get_url":{"urlParts":"any"}}
}
,"security_groups":{
"google":[
"__e"
,
"__f"
,
"__u"
]
}
};
var k,aa=typeof Object.create=="function"?Object.create:function(a){var b=function(){};b.prototype=a;return new b},ba=typeof Object.defineProperties=="function"?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a},ca=function(a){for(var b=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global],c=0;c<b.length;++c){var d=b[c];if(d&&d.Math==Math)return d}throw Error("Cannot find global object");
},ha=ca(this),ia=typeof Symbol==="function"&&typeof Symbol("x")==="symbol",ka={},la={},na=function(a,b,c){if(!c||a!=null){var d=la[b];if(d==null)return a[b];var e=a[d];return e!==void 0?e:a[b]}},oa=function(a,b,c){if(b)a:{var d=a.split("."),e=d.length===1,f=d[0],g;!e&&f in ka?g=ka:g=ha;for(var h=0;h<d.length-1;h++){var l=d[h];if(!(l in g))break a;g=g[l]}var n=d[d.length-1],p=ia&&c==="es6"?g[n]:null,q=b(p);if(q!=null)if(e)ba(ka,n,{configurable:!0,writable:!0,value:q});else if(q!==p){if(la[n]===void 0){var r=
Math.random()*1E9>>>0;la[n]=ia?ha.Symbol(n):"$jscp$"+r+"$"+n}ba(g,la[n],{configurable:!0,writable:!0,value:q})}}},pa;if(ia&&typeof Object.setPrototypeOf=="function")pa=Object.setPrototypeOf;else{var ra;a:{var ta={a:!0},ua={};try{ua.__proto__=ta;ra=ua.a;break a}catch(a){}ra=!1}pa=ra?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null}
var va=pa,wa=function(a,b){a.prototype=aa(b.prototype);a.prototype.constructor=a;if(va)va(a,b);else for(var c in b)if(c!="prototype")if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.Ft=b.prototype},xa=function(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}},m=function(a){var b=typeof Symbol!="undefined"&&Symbol.iterator&&a[Symbol.iterator];if(b)return b.call(a);if(typeof a.length=="number")return{next:xa(a)};
throw Error(String(a)+" is not an iterable or ArrayLike");},ya=function(a){for(var b,c=[];!(b=a.next()).done;)c.push(b.value);return c},w=function(a){return a instanceof Array?a:ya(m(a))},Aa=function(a){return za(a,a)},za=function(a,b){a.raw=b;Object.freeze&&(Object.freeze(a),Object.freeze(b));return a},Ba=ia&&typeof na(Object,"assign")=="function"?na(Object,"assign"):function(a,b){if(a==null)throw new TypeError("No nullish arg");a=Object(a);for(var c=1;c<arguments.length;c++){var d=arguments[c];
if(d)for(var e in d)Object.prototype.hasOwnProperty.call(d,e)&&(a[e]=d[e])}return a};oa("Object.assign",function(a){return a||Ba},"es6");var Ca=function(a){if(!(a instanceof Object))throw new TypeError("Iterator result "+a+" is not an object");},Da=function(){this.fa=!1;this.R=null;this.ja=void 0;this.H=1;this.N=this.Z=0;this.La=this.K=null},Ea=function(a){if(a.fa)throw new TypeError("Generator is already running");a.fa=!0};Da.prototype.ya=function(a){this.ja=a};
var Ga=function(a,b){a.K={ao:b,isException:!0};a.H=a.Z||a.N};Da.prototype.getNextAddressJsc=function(){return this.H};Da.prototype.getYieldResultJsc=function(){return this.ja};Da.prototype.return=function(a){this.K={return:a};this.H=this.N};Da.prototype["return"]=Da.prototype.return;Da.prototype.Aj=function(a){this.K={nd:a};this.H=this.N};Da.prototype.jumpThroughFinallyBlocks=Da.prototype.Aj;Da.prototype.ac=function(a,b){this.H=b;return{value:a}};Da.prototype.yield=Da.prototype.ac;
Da.prototype.xs=function(a,b){var c=m(a),d=c.next();Ca(d);if(d.done)this.ja=d.value,this.H=b;else return this.R=c,this.ac(d.value,b)};Da.prototype.yieldAll=Da.prototype.xs;Da.prototype.nd=function(a){this.H=a};Da.prototype.jumpTo=Da.prototype.nd;Da.prototype.Dj=function(){this.H=0};Da.prototype.jumpToEnd=Da.prototype.Dj;Da.prototype.Nj=function(a,b){this.Z=a;b!=void 0&&(this.N=b)};Da.prototype.setCatchFinallyBlocks=Da.prototype.Nj;Da.prototype.vg=function(a){this.Z=0;this.N=a||0};
Da.prototype.setFinallyBlock=Da.prototype.vg;Da.prototype.Ij=function(a,b){this.H=a;this.Z=b||0};Da.prototype.leaveTryBlock=Da.prototype.Ij;Da.prototype.Ph=function(a){this.Z=a||0;var b=this.K.ao;this.K=null;return b};Da.prototype.enterCatchBlock=Da.prototype.Ph;Da.prototype.kd=function(a,b,c){c?this.La[c]=this.K:this.La=[this.K];this.Z=a||0;this.N=b||0};Da.prototype.enterFinallyBlock=Da.prototype.kd;
Da.prototype.he=function(a,b){var c=this.La.splice(b||0)[0],d=this.K=this.K||c;d?d.isException?this.H=this.Z||this.N:d.nd!=void 0&&this.N<d.nd?(this.H=d.nd,this.K=null):this.H=this.N:this.H=a};Da.prototype.leaveFinallyBlock=Da.prototype.he;Da.prototype.fe=function(a){return new Ha(a)};Da.prototype.forIn=Da.prototype.fe;var Ha=function(a){this.K=a;this.H=[];for(var b in a)this.H.push(b);this.H.reverse()};Ha.prototype.ho=function(){for(;this.H.length>0;){var a=this.H.pop();if(a in this.K)return a}return null};
Ha.prototype.getNext=Ha.prototype.ho;
var Ia=function(a){this.H=new Da;this.K=a},La=function(a,b){Ea(a.H);var c=a.H.R;if(c)return Ja(a,"return"in c?c["return"]:function(d){return{value:d,done:!0}},b,a.H.return);a.H.return(b);return Ka(a)},Ja=function(a,b,c,d){try{var e=b.call(a.H.R,c);Ca(e);if(!e.done)return a.H.fa=!1,e;var f=e.value}catch(g){return a.H.R=null,Ga(a.H,g),Ka(a)}a.H.R=null;d.call(a.H,f);return Ka(a)},Ka=function(a){for(;a.H.H;)try{var b=a.K(a.H);if(b)return a.H.fa=!1,{value:b.value,done:!1}}catch(d){a.H.ja=void 0,Ga(a.H,
d)}a.H.fa=!1;if(a.H.K){var c=a.H.K;a.H.K=null;if(c.isException)throw c.ao;return{value:c.return,done:!0}}return{value:void 0,done:!0}},Ma=function(a){this.next=function(b){var c;Ea(a.H);a.H.R?c=Ja(a,a.H.R.next,b,a.H.ya):(a.H.ya(b),c=Ka(a));return c};this.throw=function(b){var c;Ea(a.H);a.H.R?c=Ja(a,a.H.R["throw"],b,a.H.ya):(Ga(a.H,b),c=Ka(a));return c};this.return=function(b){return La(a,b)};this[Symbol.iterator]=function(){return this}},Na=function(a,b){var c=new Ma(new Ia(b));va&&a.prototype&&va(c,
a.prototype);return c},Oa=function(){for(var a=Number(this),b=[],c=a;c<arguments.length;c++)b[c-a]=arguments[c];return b},Qa=function(a){return a};/*
Copyright The Closure Library Authors.
SPDX-License-Identifier: Apache-2.0
*/
var Ra=this||self,Sa=function(a,b){function c(){}c.prototype=b.prototype;a.Ft=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.nv=function(d,e,f){for(var g=Array(arguments.length-2),h=2;h<arguments.length;h++)g[h-2]=arguments[h];return b.prototype[e].apply(d,g)}};var Ta=function(a,b){this.type=a;this.data=b};var Ua=function(){this.map={};this.H={}};Ua.prototype.get=function(a){return this.map["dust."+a]};Ua.prototype.set=function(a,b){var c="dust."+a;this.H.hasOwnProperty(c)||(this.map[c]=b)};Ua.prototype.has=function(a){return this.map.hasOwnProperty("dust."+a)};Ua.prototype.remove=function(a){var b="dust."+a;this.H.hasOwnProperty(b)||delete this.map[b]};
var Va=function(a,b){var c=[],d;for(d in a.map)if(a.map.hasOwnProperty(d)){var e=d.substring(5);switch(b){case 1:c.push(e);break;case 2:c.push(a.map[d]);break;case 3:c.push([e,a.map[d]])}}return c};Ua.prototype.Fa=function(){return Va(this,1)};Ua.prototype.hc=function(){return Va(this,2)};Ua.prototype.fc=function(){return Va(this,3)};var Wa=function(){};Wa.prototype.reset=function(){};var Xa=function(){this.value={};this.prefix="gtm."};k=Xa.prototype;k.set=function(a,b){this.value[this.prefix+String(a)]=b};k.get=function(a){return this.value[this.prefix+String(a)]};k.has=function(a){return this.value.hasOwnProperty(this.prefix+String(a))};k.delete=function(a){var b=this.prefix+String(a);return this.value.hasOwnProperty(b)?(delete this.value[b],!0):!1};k.clear=function(){this.value={}};
k.values=function(){var a=this;return function c(){var d,e,f;return Na(c,function(g){switch(g.H){case 1:g.vg(2),e=g.fe(a.value);case 4:if((d=e.ho())==null){g.nd(2);break}if(!a.value.hasOwnProperty(d)){g.nd(4);break}f=Qa;return g.ac(a.value[d],8);case 8:f(g.ja);g.nd(4);break;case 2:g.kd(),g.he(0)}})}()};ha.Object.defineProperties(Xa.prototype,{size:{configurable:!0,enumerable:!0,get:function(){return Object.keys(this.value).length}}});
function Ya(){try{if(Map)return new Map}catch(a){}return new Xa};var Za=function(){this.values=[]};Za.prototype.add=function(a){this.values.indexOf(a)===-1&&this.values.push(a)};Za.prototype.has=function(a){return this.values.indexOf(a)>-1};var $a=function(a,b){this.fa=a;this.parent=b;this.R=this.K=void 0;this.Hb=!1;this.N=function(d,e,f){return d.apply(e,f)};this.H=Ya();var c;a:{try{if(Set){c=new Set;break a}}catch(d){}c=new Za}this.Z=c};$a.prototype.add=function(a,b){ab(this,a,b,!1)};$a.prototype.Qh=function(a,b){ab(this,a,b,!0)};var ab=function(a,b,c,d){a.Hb||a.Z.has(b)||(d&&a.Z.add(b),a.H.set(b,c))};k=$a.prototype;
k.set=function(a,b){this.Hb||(!this.H.has(a)&&this.parent&&this.parent.has(a)?this.parent.set(a,b):this.Z.has(a)||this.H.set(a,b))};k.get=function(a){return this.H.has(a)?this.H.get(a):this.parent?this.parent.get(a):void 0};k.has=function(a){return!!this.H.has(a)||!(!this.parent||!this.parent.has(a))};k.wb=function(){var a=new $a(this.fa,this);this.K&&a.Qb(this.K);a.sd(this.N);a.ue(this.R);return a};k.je=function(){return this.fa};k.Qb=function(a){this.K=a};k.fo=function(){return this.K};
k.sd=function(a){this.N=a};k.Pj=function(){return this.N};k.Za=function(){this.Hb=!0};k.ue=function(a){this.R=a};k.xb=function(){return this.R};var bb=function(a,b,c){var d;d=Error.call(this,a.message);this.message=d.message;"stack"in d&&(this.stack=d.stack);this.vo=a;this.Sn=c===void 0?!1:c;this.K=[];this.H=b};wa(bb,Error);var cb=function(a){return a instanceof bb?a:new bb(a,void 0,!0)};var db=Ya();function eb(a,b){for(var c,d=m(b),e=d.next();!e.done&&!(c=fb(a,e.value),c instanceof Ta);e=d.next());return c}function fb(a,b){try{var c=b[0],d=b.slice(1),e=String(c),f=db.has(e)?db.get(e):a.get(e);if(!f||typeof f.invoke!=="function")throw cb(Error("Attempting to execute non-function "+b[0]+"."));return f.apply(a,d)}catch(h){var g=a.fo();g&&g(h,b.context?{id:b[0],line:b.context.line}:null);throw h;}};var gb=function(){this.K=new Wa;this.H=new $a(this.K)};k=gb.prototype;k.je=function(){return this.K};k.Qb=function(a){this.H.Qb(a)};k.sd=function(a){this.H.sd(a)};k.execute=function(a){return this.rk([a].concat(w(Oa.apply(1,arguments))))};k.rk=function(){for(var a,b=m(Oa.apply(0,arguments)),c=b.next();!c.done;c=b.next())a=fb(this.H,c.value);return a};k.Jq=function(a){var b=Oa.apply(1,arguments),c=this.H.wb();c.ue(a);for(var d,e=m(b),f=e.next();!f.done;f=e.next())d=fb(c,f.value);return d};k.Za=function(){this.H.Za()};var hb=function(a,b){this.R=a;this.parent=b;this.N=this.H=void 0;this.Hb=!1;this.K=function(c,d,e){return c.apply(d,e)};this.values=new Ua};hb.prototype.add=function(a,b){jb(this,a,b,!1)};hb.prototype.Qh=function(a,b){jb(this,a,b,!0)};var jb=function(a,b,c,d){if(!a.Hb)if(d){var e=a.values;e.set(b,c);e.H["dust."+b]=!0}else a.values.set(b,c)};k=hb.prototype;k.set=function(a,b){this.Hb||(!this.values.has(a)&&this.parent&&this.parent.has(a)?this.parent.set(a,b):this.values.set(a,b))};
k.get=function(a){return this.values.has(a)?this.values.get(a):this.parent?this.parent.get(a):void 0};k.has=function(a){return!!this.values.has(a)||!(!this.parent||!this.parent.has(a))};k.wb=function(){var a=new hb(this.R,this);this.H&&a.Qb(this.H);a.sd(this.K);a.ue(this.N);return a};k.je=function(){return this.R};k.Qb=function(a){this.H=a};k.fo=function(){return this.H};k.sd=function(a){this.K=a};k.Pj=function(){return this.K};k.Za=function(){this.Hb=!0};k.ue=function(a){this.N=a};k.xb=function(){return this.N};var kb=function(){this.Na=!1;this.la=new Ua};k=kb.prototype;k.get=function(a){return this.la.get(a)};k.set=function(a,b){this.Na||this.la.set(a,b)};k.has=function(a){return this.la.has(a)};k.remove=function(a){this.Na||this.la.remove(a)};k.Fa=function(){return this.la.Fa()};k.hc=function(){return this.la.hc()};k.fc=function(){return this.la.fc()};k.Za=function(){this.Na=!0};k.Hb=function(){return this.Na};function lb(){for(var a=mb,b={},c=0;c<a.length;++c)b[a[c]]=c;return b}function nb(){var a="ABCDEFGHIJKLMNOPQRSTUVWXYZ";a+=a.toLowerCase()+"0123456789-_";return a+"."}var mb,ob;function pb(a){mb=mb||nb();ob=ob||lb();for(var b=[],c=0;c<a.length;c+=3){var d=c+1<a.length,e=c+2<a.length,f=a.charCodeAt(c),g=d?a.charCodeAt(c+1):0,h=e?a.charCodeAt(c+2):0,l=f>>2,n=(f&3)<<4|g>>4,p=(g&15)<<2|h>>6,q=h&63;e||(q=64,d||(p=64));b.push(mb[l],mb[n],mb[p],mb[q])}return b.join("")}
function qb(a){function b(l){for(;d<a.length;){var n=a.charAt(d++),p=ob[n];if(p!=null)return p;if(!/^[\s\xa0]*$/.test(n))throw Error("Unknown base64 encoding at char: "+n);}return l}mb=mb||nb();ob=ob||lb();for(var c="",d=0;;){var e=b(-1),f=b(0),g=b(64),h=b(64);if(h===64&&e===-1)return c;c+=String.fromCharCode(e<<2|f>>4);g!==64&&(c+=String.fromCharCode(f<<4&240|g>>2),h!==64&&(c+=String.fromCharCode(g<<6&192|h)))}};var rb={};function sb(a,b){var c=rb[a];c||(c=rb[a]=[]);c[b]=!0}function tb(){delete rb.GA4_EVENT}function ub(){var a=vb.H.slice();rb.GTAG_EVENT_FEATURE_CHANNEL=a}function wb(a){for(var b=[],c=0,d=0;d<a.length;d++)d%8===0&&d>0&&(b.push(String.fromCharCode(c)),c=0),a[d]&&(c|=1<<d%8);c>0&&b.push(String.fromCharCode(c));return pb(b.join("")).replace(/\.+$/,"")};function xb(){}function yb(a){return typeof a==="function"}function zb(a){return typeof a==="string"}function Ab(a){return typeof a==="number"&&!isNaN(a)}function Bb(a){return Array.isArray(a)?a:[a]}function Cb(a,b){if(a&&Array.isArray(a))for(var c=0;c<a.length;c++)if(a[c]&&b(a[c]))return a[c]}function Db(a,b){if(!Ab(a)||!Ab(b)||a>b)a=0,b=2147483647;return Math.floor(Math.random()*(b-a+1)+a)}
function Eb(a,b){for(var c=new Fb,d=0;d<a.length;d++)c.set(a[d],!0);for(var e=0;e<b.length;e++)if(c.get(b[e]))return!0;return!1}function Gb(a,b){for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&b(c,a[c])}function Hb(a){return!!a&&(Object.prototype.toString.call(a)==="[object Arguments]"||Object.prototype.hasOwnProperty.call(a,"callee"))}function Ib(a){return Math.round(Number(a))||0}function Jb(a){return"false"===String(a).toLowerCase()?!1:!!a}
function Kb(a){var b=[];if(Array.isArray(a))for(var c=0;c<a.length;c++)b.push(String(a[c]));return b}function Lb(a){return a?a.replace(/^\s+|\s+$/g,""):""}function Mb(){return new Date(Date.now())}function Nb(){return Mb().getTime()}var Fb=function(){this.prefix="gtm.";this.values={}};Fb.prototype.set=function(a,b){this.values[this.prefix+a]=b};Fb.prototype.get=function(a){return this.values[this.prefix+a]};Fb.prototype.contains=function(a){return this.get(a)!==void 0};
function Ob(a,b,c){return a&&a.hasOwnProperty(b)?a[b]:c}function Pb(a){var b=a;return function(){if(b){var c=b;b=void 0;try{c()}catch(d){}}}}function Qb(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}function Rb(a,b){for(var c=[],d=0;d<a.length;d++)c.push(a[d]),c.push.apply(c,b[a[d]]||[]);return c}function Sb(a,b){return a.length>=b.length&&a.substring(0,b.length)===b}function Tb(a,b){return a.length>=b.length&&a.substring(a.length-b.length,a.length)===b}
function Ub(a,b,c){c=c||[];for(var d=a,e=0;e<b.length-1;e++){if(!d.hasOwnProperty(b[e]))return;d=d[b[e]];if(c.indexOf(d)>=0)return}return d}function Vb(a,b){for(var c={},d=c,e=a.split("."),f=0;f<e.length-1;f++)d=d[e[f]]={};d[e[e.length-1]]=b;return c}var Wb=/^\w{1,9}$/;function Yb(a,b){a=a||{};b=b||",";var c=[];Gb(a,function(d,e){Wb.test(d)&&e&&c.push(d)});return c.join(b)}
function Zb(a){for(var b=[],c=0;c<a.length;c++){var d=a.charCodeAt(c);d<128?b.push(d):d<2048?b.push(192|d>>6,128|d&63):d<55296||d>=57344?b.push(224|d>>12,128|d>>6&63,128|d&63):(d=65536+((d&1023)<<10|a.charCodeAt(++c)&1023),b.push(240|d>>18,128|d>>12&63,128|d>>6&63,128|d&63))}return new Uint8Array(b)}function $b(a){if(!a)return a;var b=a;try{b=decodeURIComponent(a)}catch(d){}var c=b.split(",");return c.length===2&&c[0]===c[1]?c[0]:a}
function ac(a,b,c){function d(n){var p=n.split("=")[0];if(a.indexOf(p)<0)return n;if(c!==void 0)return p+"="+c}function e(n){return n.split("&").map(d).filter(function(p){return p!==void 0}).join("&")}var f=b.href.split(/[?#]/)[0],g=b.search,h=b.hash;g[0]==="?"&&(g=g.substring(1));h[0]==="#"&&(h=h.substring(1));g=e(g);h=e(h);g!==""&&(g="?"+g);h!==""&&(h="#"+h);var l=""+f+g+h;l[l.length-1]==="/"&&(l=l.substring(0,l.length-1));return l}
function bc(a){for(var b=0;b<3;++b)try{var c=decodeURIComponent(a).replace(/\+/g," ");if(c===a)break;a=c}catch(d){return""}return a}function cc(){var a=A,b;a:{var c=a.crypto||a.msCrypto;if(c&&c.getRandomValues)try{var d=new Uint8Array(25);c.getRandomValues(d);b=btoa(String.fromCharCode.apply(String,w(d))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"");break a}catch(e){}b=void 0}return b};/*
Copyright Google LLC
SPDX-License-Identifier: Apache-2.0
*/
var dc=globalThis.trustedTypes,ec;function fc(){var a=null;if(!dc)return a;try{var b=function(c){return c};a=dc.createPolicy("goog#html",{createHTML:b,createScript:b,createScriptURL:b})}catch(c){}return a}function hc(){ec===void 0&&(ec=fc());return ec};var ic=function(a){this.H=a};ic.prototype.toString=function(){return this.H+""};function jc(a){var b=a,c=hc(),d=c?c.createScriptURL(b):b;return new ic(d)}function kc(a){if(a instanceof ic)return a.H;throw Error("");};var lc=Aa([""]),mc=za(["\x00"],["\\0"]),nc=za(["\n"],["\\n"]),oc=za(["\x00"],["\\u0000"]);function pc(a){return a.toString().indexOf("`")===-1}pc(function(a){return a(lc)})||pc(function(a){return a(mc)})||pc(function(a){return a(nc)})||pc(function(a){return a(oc)});var qc=function(a){this.H=a};qc.prototype.toString=function(){return this.H};var rc=function(a){this.Js=a};function sc(a){return new rc(function(b){return b.substr(0,a.length+1).toLowerCase()===a+":"})}var tc=[sc("data"),sc("http"),sc("https"),sc("mailto"),sc("ftp"),new rc(function(a){return/^[^:]*([/?#]|$)/.test(a)})];function uc(a){var b;b=b===void 0?tc:b;if(a instanceof qc)return a;for(var c=0;c<b.length;++c){var d=b[c];if(d instanceof rc&&d.Js(a))return new qc(a)}}var vc=/^\s*(?!javascript:)(?:[\w+.-]+:|[^:/?#]*(?:[/?#]|$))/i;
function wc(a){var b;if(a instanceof qc)if(a instanceof qc)b=a.H;else throw Error("");else b=vc.test(a)?a:void 0;return b};function xc(a,b){var c=wc(b);c!==void 0&&(a.action=c)};function yc(a,b){throw Error(b===void 0?"unexpected value "+a+"!":b);};var zc=function(a){this.H=a};zc.prototype.toString=function(){return this.H+""};var Bc=function(){this.H=Ac[0].toLowerCase()};Bc.prototype.toString=function(){return this.H};function Cc(a,b){var c=[new Bc];if(c.length===0)throw Error("");var d=c.map(function(f){var g;if(f instanceof Bc)g=f.H;else throw Error("");return g}),e=b.toLowerCase();if(d.every(function(f){return e.indexOf(f)!==0}))throw Error('Attribute "'+b+'" does not match any of the allowed prefixes.');a.setAttribute(b,"true")};var Dc=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if(typeof a==="string")return typeof b!=="string"||b.length!=1?-1:a.indexOf(b,0);for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1};"ARTICLE SECTION NAV ASIDE H1 H2 H3 H4 H5 H6 HEADER FOOTER ADDRESS P HR PRE BLOCKQUOTE OL UL LH LI DL DT DD FIGURE FIGCAPTION MAIN DIV EM STRONG SMALL S CITE Q DFN ABBR RUBY RB RT RTC RP DATA TIME CODE VAR SAMP KBD SUB SUP I B U MARK BDI BDO SPAN BR WBR NOBR INS DEL PICTURE PARAM TRACK MAP TABLE CAPTION COLGROUP COL TBODY THEAD TFOOT TR TD TH SELECT DATALIST OPTGROUP OPTION OUTPUT PROGRESS METER FIELDSET LEGEND DETAILS SUMMARY MENU DIALOG SLOT CANVAS FONT CENTER ACRONYM BASEFONT BIG DIR HGROUP STRIKE TT".split(" ").concat(["BUTTON",
"INPUT"]);function Ec(a){return a===null?"null":a===void 0?"undefined":a};var A=window,Fc=[],Gc=window.history,B=document,Hc=navigator;function Ic(){var a;try{a=Hc.serviceWorker}catch(b){return}return a}var Jc=B.currentScript,Kc=Jc&&Jc.src;function Mc(a,b){var c=A,d=c[a];c[a]=d===void 0?b:d;return c[a]}function Nc(a){return(Hc.userAgent||"").indexOf(a)!==-1}function Oc(){return Nc("Firefox")||Nc("FxiOS")}function Pc(){return(Nc("GSA")||Nc("GoogleApp"))&&(Nc("iPhone")||Nc("iPad"))}function Qc(){return Nc("Edg/")||Nc("EdgA/")||Nc("EdgiOS/")}
var Rc={async:1,nonce:1,onerror:1,onload:1,src:1,type:1},Sc={height:1,onload:1,src:1,style:1,width:1};function Tc(a,b,c){b&&Gb(b,function(d,e){d=d.toLowerCase();c.hasOwnProperty(d)||a.setAttribute(d,e)})}
function Uc(a,b,c,d,e){var f=B.createElement("script");Tc(f,d,Rc);f.type="text/javascript";f.async=d&&d.async===!1?!1:!0;var g;g=jc(Ec(a));f.src=kc(g);var h,l=f.ownerDocument;l=l===void 0?document:l;var n,p,q=(p=(n=l).querySelector)==null?void 0:p.call(n,"script[nonce]");(h=q==null?"":q.nonce||q.getAttribute("nonce")||"")&&f.setAttribute("nonce",h);b&&(f.onload=b);c&&(f.onerror=c);e?e.appendChild(f):Vc.Bs(f);return f}
function Wc(){if(Kc){var a=Kc.toLowerCase();if(a.indexOf("https://")===0)return 2;if(a.indexOf("http://")===0)return 3}return 1}function Xc(a,b,c,d,e,f){f=f===void 0?!0:f;var g=e,h=!1;g||(g=B.createElement("iframe"),h=!0);Tc(g,c,Sc);d&&Gb(d,function(n,p){g.dataset[n]=p});f&&(g.height="0",g.width="0",g.style.display="none",g.style.visibility="hidden");a!==void 0&&(g.src=a);if(h){var l=B.body&&B.body.lastChild||B.body||B.head;l.parentNode.insertBefore(g,l)}b&&(g.onload=b);return g}
function Zc(){return Vc.Er.apply(Vc,w(Oa.apply(0,arguments)))}function $c(a,b,c,d){a.addEventListener&&a.addEventListener(b,c,!!d)}function ad(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}function bd(a){A.setTimeout(a,0)}function cd(a,b){var c=Oa.apply(2,arguments),d,e=(d=A).setInterval.apply(d,[a,b].concat(w(c)));Fc.push(e);return e}
function dd(a){var b=A;yb(b.queueMicrotask)?b.queueMicrotask(a):yb(b.Promise)&&b.Promise.resolve?b.Promise.resolve().then(function(){a()}).catch(function(){}):bd(a)}function ed(a,b){return a&&b&&a.attributes&&a.attributes[b]?a.attributes[b].value:null}function fd(a){var b=a.innerText||a.textContent||"";b&&b!==" "&&(b=b.replace(/^[\s\xa0]+/g,""),b=b.replace(/[\s\xa0]+$/g,""));b&&(b=b.replace(/(\xa0+|\s{2,}|\n|\r\t)/g," "));return b}
function gd(a){var b=B.createElement("div"),c=b,d,e=Ec("A<div>"+a+"</div>"),f=hc(),g=f?f.createHTML(e):e;d=new zc(g);if(c.nodeType===1&&/^(script|style)$/i.test(c.tagName))throw Error("");var h;if(d instanceof zc)h=d.H;else throw Error("");c.innerHTML=h;b=b.lastChild;for(var l=[];b&&b.firstChild;)l.push(b.removeChild(b.firstChild));return l}
function hd(a,b,c){c=c||100;for(var d={},e=0;e<b.length;e++)d[b[e]]=!0;for(var f=a,g=0;f&&g<=c;g++){if(d[String(f.tagName).toLowerCase()])return f;f=f.parentElement}return null}function id(a,b,c){var d;try{d=Hc.sendBeacon&&Hc.sendBeacon(a)}catch(e){sb("TAGGING",15)}d?b==null||b():Zc(a,b,c)}function jd(a,b){try{if(Hc.sendBeacon!==void 0)return Hc.sendBeacon(a,b)}catch(c){sb("TAGGING",15)}return!1}function kd(){return Hc.sendBeacon!==void 0}
var ld={cache:"no-store",credentials:"include",keepalive:!0,method:"POST",mode:"no-cors",redirect:"follow"};
function md(a,b,c,d,e){if(nd()){var f=na(Object,"assign").call(Object,{},ld);b&&(f.body=b);c&&(c.attributionReporting&&(f.attributionReporting=c.attributionReporting),c.browsingTopics!==void 0&&(f.browsingTopics=c.browsingTopics),c.credentials&&(f.credentials=c.credentials),c.keepalive!==void 0&&(f.keepalive=c.keepalive),c.method&&(f.method=c.method),c.mode&&(f.mode=c.mode));try{var g=A.fetch(a,f);if(g)return g.then(function(l){l&&(l.ok||l.status===0)?d==null||d():e==null||e()}).catch(function(){e==
null||e()}),!0}catch(l){}}if((c==null?0:c.Qg)||(c==null?0:c.credentials)&&c.credentials!=="include")return e==null||e(),!1;if(b){var h=jd(a,b);h?d==null||d():e==null||e();return h}Vc.wt(a,d,e);return!0}function nd(){return yb(A.fetch)}function od(a,b){var c=a[b];c&&typeof c.animVal==="string"&&(c=c.animVal);return c}function pd(){var a=A.performance;if(a&&yb(a.now))return a.now()}
function qd(){var a,b=A.performance;if(b&&b.getEntriesByType)try{var c=b.getEntriesByType("navigation");c&&c.length>0&&(a=c[0].type)}catch(d){return"e"}if(!a)return"u";switch(a){case "navigate":return"n";case "back_forward":return"h";case "reload":return"r";case "prerender":return"p";default:return"x"}}function rd(){return A.performance||void 0}function sd(){var a=A.webPixelsManager;return a?a.createShopifyExtend!==void 0:!1}
var Vc={Er:function(a,b,c,d){var e=new Image(1,1);Tc(e,d,{});e.onload=function(){e.onload=null;b&&b()};e.onerror=function(){e.onerror=null;c&&c()};e.src=a;return e},Bs:function(a){var b=B.getElementsByTagName("script")[0]||B.body||B.head;b.parentNode.insertBefore(a,b)},wt:id};function td(a,b){return this.evaluate(a)&&this.evaluate(b)}function ud(a,b){return this.evaluate(a)===this.evaluate(b)}function vd(a,b){return this.evaluate(a)||this.evaluate(b)}function wd(a,b){var c=this.evaluate(a),d=this.evaluate(b);return String(c).indexOf(String(d))>-1}function xd(a,b){var c=String(this.evaluate(a)),d=String(this.evaluate(b));return c.substring(0,d.length)===d}
function yd(a,b){var c=this.evaluate(a),d=this.evaluate(b);switch(c){case "pageLocation":var e=A.location.href;d instanceof kb&&d.get("stripProtocol")&&(e=e.replace(/^https?:\/\//,""));return e}};/*
jQuery (c) 2005, 2012 jQuery Foundation, Inc. jquery.org/license.
*/
var zd=/\[object (Boolean|Number|String|Function|Array|Date|RegExp)\]/,Ad=function(a){if(a==null)return String(a);var b=zd.exec(Object.prototype.toString.call(Object(a)));return b?b[1].toLowerCase():"object"},Bd=function(a,b){return Object.prototype.hasOwnProperty.call(Object(a),b)},Cd=function(a){if(!a||Ad(a)!="object"||a.nodeType||a==a.window)return!1;try{if(a.constructor&&!Bd(a,"constructor")&&!Bd(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}for(var b in a);return b===void 0||
Bd(a,b)},Ed=function(a,b){var c=b||(Ad(a)=="array"?[]:{}),d;for(d in a)if(Bd(a,d)){var e=a[d];Ad(e)=="array"?(Ad(c[d])!="array"&&(c[d]=[]),c[d]=Ed(e,c[d])):Cd(e)?(Cd(c[d])||(c[d]={}),c[d]=Ed(e,c[d])):c[d]=e}return c};function Fd(a){return typeof a==="number"&&a>=0&&isFinite(a)&&a%1===0||typeof a==="string"&&a[0]!=="-"&&a===""+parseInt(a)};var Gd=function(a){a=a===void 0?[]:a;this.la=new Ua;this.values=[];this.Na=!1;for(var b in a)a.hasOwnProperty(b)&&(Fd(b)?this.values[Number(b)]=a[Number(b)]:this.la.set(b,a[b]))};k=Gd.prototype;k.toString=function(a){if(a&&a.indexOf(this)>=0)return"";for(var b=[],c=0;c<this.values.length;c++){var d=this.values[c];d===null||d===void 0?b.push(""):d instanceof Gd?(a=a||[],a.push(this),b.push(d.toString(a)),a.pop()):b.push(String(d))}return b.join(",")};
k.set=function(a,b){if(!this.Na)if(a==="length"){if(!Fd(b))throw cb(Error("RangeError: Length property must be a valid integer."));this.values.length=Number(b)}else Fd(a)?this.values[Number(a)]=b:this.la.set(a,b)};k.get=function(a){return a==="length"?this.length():Fd(a)?this.values[Number(a)]:this.la.get(a)};k.length=function(){return this.values.length};k.Fa=function(){for(var a=this.la.Fa(),b=0;b<this.values.length;b++)this.values.hasOwnProperty(b)&&a.push(String(b));return a};
k.hc=function(){for(var a=this.la.hc(),b=0;b<this.values.length;b++)this.values.hasOwnProperty(b)&&a.push(this.values[b]);return a};k.fc=function(){for(var a=this.la.fc(),b=0;b<this.values.length;b++)this.values.hasOwnProperty(b)&&a.push([String(b),this.values[b]]);return a};k.remove=function(a){Fd(a)?delete this.values[Number(a)]:this.Na||this.la.remove(a)};k.pop=function(){return this.values.pop()};k.push=function(){return this.values.push.apply(this.values,w(Oa.apply(0,arguments)))};k.shift=function(){return this.values.shift()};
k.splice=function(a,b){var c=Oa.apply(2,arguments);return b===void 0&&c.length===0?new Gd(this.values.splice(a)):new Gd(this.values.splice.apply(this.values,[a,b||0].concat(w(c))))};k.unshift=function(){return this.values.unshift.apply(this.values,w(Oa.apply(0,arguments)))};k.has=function(a){return Fd(a)&&this.values.hasOwnProperty(a)||this.la.has(a)};k.Za=function(){this.Na=!0;Object.freeze(this.values)};k.Hb=function(){return this.Na};
function Hd(a){for(var b=[],c=0;c<a.length();c++)a.has(c)&&(b[c]=a.get(c));return b};var Id=function(a,b){this.functionName=a;this.ie=b;this.la=new Ua;this.Na=!1};k=Id.prototype;k.toString=function(){return this.functionName};k.getName=function(){return this.functionName};k.getKeys=function(){return new Gd(this.Fa())};k.invoke=function(a){return this.ie.call.apply(this.ie,[new Jd(this,a)].concat(w(Oa.apply(1,arguments))))};k.apply=function(a,b){return this.ie.apply(new Jd(this,a),b)};k.Nc=function(a){var b=Oa.apply(1,arguments);try{return this.invoke.apply(this,[a].concat(w(b)))}catch(c){}};
k.get=function(a){return this.la.get(a)};k.set=function(a,b){this.Na||this.la.set(a,b)};k.has=function(a){return this.la.has(a)};k.remove=function(a){this.Na||this.la.remove(a)};k.Fa=function(){return this.la.Fa()};k.hc=function(){return this.la.hc()};k.fc=function(){return this.la.fc()};k.Za=function(){this.Na=!0};k.Hb=function(){return this.Na};var Kd=function(a,b){Id.call(this,a,b)};wa(Kd,Id);var Ld=function(a,b){Id.call(this,a,b)};wa(Ld,Id);var Jd=function(a,b){this.ie=a;this.T=b};
Jd.prototype.evaluate=function(a){var b=this.T;return Array.isArray(a)?fb(b,a):a};Jd.prototype.getName=function(){return this.ie.getName()};Jd.prototype.je=function(){return this.T.je()};var Md=function(){this.map=new Map};Md.prototype.set=function(a,b){this.map.set(a,b)};Md.prototype.get=function(a){return this.map.get(a)};var Nd=function(){this.keys=[];this.values=[]};Nd.prototype.set=function(a,b){this.keys.push(a);this.values.push(b)};Nd.prototype.get=function(a){var b=this.keys.indexOf(a);if(b>-1)return this.values[b]};function Od(){try{return Map?new Md:new Nd}catch(a){return new Nd}};var Pd=function(a){if(a instanceof Pd)return a;var b;a:if(a==void 0||Array.isArray(a)||Cd(a))b=!0;else{switch(typeof a){case "boolean":case "number":case "string":case "function":b=!0;break a}b=!1}if(b)throw Error("Type of given value has an equivalent Pixie type.");this.value=a};Pd.prototype.getValue=function(){return this.value};Pd.prototype.toString=function(){return String(this.value)};var Sd=function(a){this.promise=a;this.Na=!1;this.la=new Ua;this.la.set("then",Rd(this));this.la.set("catch",Rd(this,!0));this.la.set("finally",Rd(this,!1,!0))};k=Sd.prototype;k.get=function(a){return this.la.get(a)};k.set=function(a,b){this.Na||this.la.set(a,b)};k.has=function(a){return this.la.has(a)};k.remove=function(a){this.Na||this.la.remove(a)};k.Fa=function(){return this.la.Fa()};k.hc=function(){return this.la.hc()};k.fc=function(){return this.la.fc()};
var Rd=function(a,b,c){b=b===void 0?!1:b;c=c===void 0?!1:c;return new Kd("",function(d,e){b&&(e=d,d=void 0);c&&(e=d);d instanceof Kd||(d=void 0);e instanceof Kd||(e=void 0);var f=this.T.wb(),g=function(l){return function(n){try{return c?(l.invoke(f),a.promise):l.invoke(f,n)}catch(p){return Promise.reject(p instanceof Error?new Pd(p):String(p))}}},h=a.promise.then(d&&g(d),e&&g(e));return new Sd(h)})};Sd.prototype.Za=function(){this.Na=!0};Sd.prototype.Hb=function(){return this.Na};function Td(a,b,c){var d=Od(),e=function(g,h){for(var l=g.Fa(),n=0;n<l.length;n++)h[l[n]]=f(g.get(l[n]))},f=function(g){if(g===null||g===void 0)return g;var h=d.get(g);if(h)return h;if(g instanceof Gd){var l=[];d.set(g,l);for(var n=g.Fa(),p=0;p<n.length;p++)l[n[p]]=f(g.get(n[p]));return l}if(g instanceof Sd)return g.promise.then(function(u){return Td(u,b,1)},function(u){return Promise.reject(Td(u,b,1))});if(g instanceof kb){var q={};d.set(g,q);e(g,q);return q}if(g instanceof Kd){var r=function(){for(var u=
[],v=0;v<arguments.length;v++)u[v]=Ud(arguments[v],b,c);var x=new hb(b?b.je():new Wa);b&&x.ue(b.xb());return f(g.apply(x,u))};d.set(g,r);e(g,r);return r}var t=!1;switch(c){case 1:t=!0;break;case 2:t=!1;break;case 3:t=!1;break;default:}if(g instanceof Pd&&t)return g.getValue();switch(typeof g){case "boolean":case "number":case "string":case "undefined":return g;case "object":if(g===
null)return null}};return f(a)}
function Ud(a,b,c){var d=Od(),e=function(g,h){for(var l in g)g.hasOwnProperty(l)&&h.set(l,f(g[l]))},f=function(g){var h=d.get(g);if(h)return h;if(Array.isArray(g)||Hb(g)){var l=new Gd;d.set(g,l);for(var n in g)g.hasOwnProperty(n)&&l.set(n,f(g[n]));return l}if(Cd(g)){var p=new kb;d.set(g,p);e(g,p);return p}if(typeof g==="function"){var q=new Kd("",function(){for(var u=Oa.apply(0,arguments),v=[],x=0;x<u.length;x++)v[x]=Td(this.evaluate(u[x]),b,c);return f(this.T.Pj()(g,g,v))});d.set(g,q);e(g,q);return q}var r=typeof g;if(g===null||r==="string"||r==="number"||r==="boolean")return g;var t=!1;switch(c){case 1:t=!0;break;case 2:t=!1;break;default:}if(g!==void 0&&t)return new Pd(g)};return f(a)};var Vd={supportedMethods:"concat every filter forEach hasOwnProperty indexOf join lastIndexOf map pop push reduce reduceRight reverse shift slice some sort splice unshift toString".split(" "),concat:function(a){for(var b=[],c=0;c<this.length();c++)b.push(this.get(c));for(var d=1;d<arguments.length;d++)if(arguments[d]instanceof Gd)for(var e=arguments[d],f=0;f<e.length();f++)b.push(e.get(f));else b.push(arguments[d]);return new Gd(b)},every:function(a,b){for(var c=this.length(),d=0;d<this.length()&&
d<c;d++)if(this.has(d)&&!b.invoke(a,this.get(d),d,this))return!1;return!0},filter:function(a,b){for(var c=this.length(),d=[],e=0;e<this.length()&&e<c;e++)this.has(e)&&b.invoke(a,this.get(e),e,this)&&d.push(this.get(e));return new Gd(d)},forEach:function(a,b){for(var c=this.length(),d=0;d<this.length()&&d<c;d++)this.has(d)&&b.invoke(a,this.get(d),d,this)},hasOwnProperty:function(a,b){return this.has(b)},indexOf:function(a,b,c){var d=this.length(),e=c===void 0?0:Number(c);e<0&&(e=Math.max(d+e,0));for(var f=
e;f<d;f++)if(this.has(f)&&this.get(f)===b)return f;return-1},join:function(a,b){for(var c=[],d=0;d<this.length();d++)c.push(this.get(d));return c.join(b)},lastIndexOf:function(a,b,c){var d=this.length(),e=d-1;c!==void 0&&(e=c<0?d+c:Math.min(c,e));for(var f=e;f>=0;f--)if(this.has(f)&&this.get(f)===b)return f;return-1},map:function(a,b){for(var c=this.length(),d=[],e=0;e<this.length()&&e<c;e++)this.has(e)&&(d[e]=b.invoke(a,this.get(e),e,this));return new Gd(d)},pop:function(){return this.pop()},push:function(a){return this.push.apply(this,
w(Oa.apply(1,arguments)))},reduce:function(a,b,c){var d=this.length(),e,f=0;if(c!==void 0)e=c;else{if(d===0)throw cb(Error("TypeError: Reduce on List with no elements."));for(var g=0;g<d;g++)if(this.has(g)){e=this.get(g);f=g+1;break}if(g===d)throw cb(Error("TypeError: Reduce on List with no elements."));}for(var h=f;h<d;h++)this.has(h)&&(e=b.invoke(a,e,this.get(h),h,this));return e},reduceRight:function(a,b,c){var d=this.length(),e,f=d-1;if(c!==void 0)e=c;else{if(d===0)throw cb(Error("TypeError: ReduceRight on List with no elements."));
for(var g=1;g<=d;g++)if(this.has(d-g)){e=this.get(d-g);f=d-(g+1);break}if(g>d)throw cb(Error("TypeError: ReduceRight on List with no elements."));}for(var h=f;h>=0;h--)this.has(h)&&(e=b.invoke(a,e,this.get(h),h,this));return e},reverse:function(){for(var a=Hd(this),b=a.length-1,c=0;b>=0;b--,c++)a.hasOwnProperty(b)?this.set(c,a[b]):this.remove(c);return this},shift:function(){return this.shift()},slice:function(a,b,c){var d=this.length();b===void 0&&(b=0);b=b<0?Math.max(d+b,0):Math.min(b,d);c=c===
void 0?d:c<0?Math.max(d+c,0):Math.min(c,d);c=Math.max(b,c);for(var e=[],f=b;f<c;f++)e.push(this.get(f));return new Gd(e)},some:function(a,b){for(var c=this.length(),d=0;d<this.length()&&d<c;d++)if(this.has(d)&&b.invoke(a,this.get(d),d,this))return!0;return!1},sort:function(a,b){var c=Hd(this);b===void 0?c.sort():c.sort(function(e,f){return Number(b.invoke(a,e,f))});for(var d=0;d<c.length;d++)c.hasOwnProperty(d)?this.set(d,c[d]):this.remove(d);return this},splice:function(a,b,c){return this.splice.apply(this,
[b,c].concat(w(Oa.apply(3,arguments))))},toString:function(){return this.toString()},unshift:function(a){return this.unshift.apply(this,w(Oa.apply(1,arguments)))}};var Wd={charAt:1,concat:1,indexOf:1,lastIndexOf:1,match:1,replace:1,search:1,slice:1,split:1,substring:1,toLowerCase:1,toLocaleLowerCase:1,toString:1,toUpperCase:1,toLocaleUpperCase:1,trim:1},Xd=new Ta("break"),Yd=new Ta("continue");function Zd(a,b){return this.evaluate(a)+this.evaluate(b)}function $d(a,b){return this.evaluate(a)&&this.evaluate(b)}
function ae(a,b,c){var d=this.evaluate(a),e=this.evaluate(b),f=this.evaluate(c);if(!(f instanceof Gd))throw Error("Error: Non-List argument given to Apply instruction.");if(d===null||d===void 0)throw cb(Error("TypeError: Can't read property "+e+" of "+d+"."));var g=typeof d==="number";if(typeof d==="boolean"||g){if(e==="toString"){if(g&&f.length()){var h=Td(f.get(0));try{return d.toString(h)}catch(u){}}return d.toString()}throw cb(Error("TypeError: "+d+"."+e+" is not a function."));}if(typeof d===
"string"){if(Wd.hasOwnProperty(e)){var l=Td(f,void 0,1);return Ud(d[e].apply(d,l),this.T)}throw cb(Error("TypeError: "+e+" is not a function"));}if(d instanceof Gd){if(d.has(e)){var n=d.get(String(e));if(n instanceof Kd){var p=Hd(f);return n.apply(this.T,p)}throw cb(Error("TypeError: "+e+" is not a function"));}if(Vd.supportedMethods.indexOf(e)>=0){var q=Hd(f);return Vd[e].call.apply(Vd[e],[d,this.T].concat(w(q)))}}if(d instanceof Kd||d instanceof kb||d instanceof Sd){if(d.has(e)){var r=d.get(e);
if(r instanceof Kd){var t=Hd(f);return r.apply(this.T,t)}throw cb(Error("TypeError: "+e+" is not a function"));}if(e==="toString")return d instanceof Kd?d.getName():d.toString();if(e==="hasOwnProperty")return d.has(f.get(0))}if(d instanceof Pd&&e==="toString")return d.toString();throw cb(Error("TypeError: Object has no '"+e+"' property."));}
function be(a,b){a=this.evaluate(a);if(typeof a!=="string")throw Error("Invalid key name given for assignment.");var c=this.T;if(!c.has(a))throw Error("Attempting to assign to undefined value "+b);var d=this.evaluate(b);c.set(a,d);return d}function ce(){var a=Oa.apply(0,arguments),b=this.T.wb(),c=eb(b,a);if(c instanceof Ta)return c}function de(){return Xd}function ee(a){for(var b=this.evaluate(a),c=0;c<b.length;c++){var d=this.evaluate(b[c]);if(d instanceof Ta)return d}}
function fe(){for(var a=this.T,b=0;b<arguments.length-1;b+=2){var c=arguments[b];if(typeof c==="string"){var d=this.evaluate(arguments[b+1]);a.Qh(c,d)}}}function ge(){return Yd}function he(a,b){return new Ta(a,this.evaluate(b))}function ie(a,b){var c=Oa.apply(2,arguments),d;d=new Gd;for(var e=this.evaluate(b),f=0;f<e.length;f++)d.push(e[f]);var g=[51,a,d].concat(w(c));this.T.add(a,this.evaluate(g))}function je(a,b){return this.evaluate(a)/this.evaluate(b)}
function ke(a,b){var c=this.evaluate(a),d=this.evaluate(b),e=c instanceof Pd,f=d instanceof Pd;return e||f?e&&f?c.getValue()===d.getValue():!1:c==d}function le(){for(var a,b=0;b<arguments.length;b++)a=this.evaluate(arguments[b]);return a}function me(a,b,c,d){for(var e=0;e<b();e++){var f=a(c(e)),g=eb(f,d);if(g instanceof Ta){if(g.type==="break")break;if(g.type==="return")return g}}}
function ne(a,b,c){if(typeof b==="string")return me(a,function(){return b.length},function(f){return f},c);if(b instanceof kb||b instanceof Sd||b instanceof Gd||b instanceof Kd){var d=b.Fa(),e=d.length;return me(a,function(){return e},function(f){return d[f]},c)}}function oe(a,b,c){var d=this.evaluate(a),e=this.evaluate(b),f=this.evaluate(c),g=this.T;return ne(function(h){g.set(d,h);return g},e,f)}
function pe(a,b,c){var d=this.evaluate(a),e=this.evaluate(b),f=this.evaluate(c),g=this.T;return ne(function(h){var l=g.wb();l.Qh(d,h);return l},e,f)}function qe(a,b,c){var d=this.evaluate(a),e=this.evaluate(b),f=this.evaluate(c),g=this.T;return ne(function(h){var l=g.wb();l.add(d,h);return l},e,f)}function re(a,b,c){var d=this.evaluate(a),e=this.evaluate(b),f=this.evaluate(c),g=this.T;return se(function(h){g.set(d,h);return g},e,f)}
function te(a,b,c){var d=this.evaluate(a),e=this.evaluate(b),f=this.evaluate(c),g=this.T;return se(function(h){var l=g.wb();l.Qh(d,h);return l},e,f)}function ue(a,b,c){var d=this.evaluate(a),e=this.evaluate(b),f=this.evaluate(c),g=this.T;return se(function(h){var l=g.wb();l.add(d,h);return l},e,f)}
function se(a,b,c){if(typeof b==="string")return me(a,function(){return b.length},function(d){return b[d]},c);if(b instanceof Gd)return me(a,function(){return b.length()},function(d){return b.get(d)},c);throw cb(Error("The value is not iterable."));}
function ve(a,b,c,d){function e(q,r){for(var t=0;t<f.length();t++){var u=f.get(t);r.add(u,q.get(u))}}var f=this.evaluate(a);if(!(f instanceof Gd))throw Error("TypeError: Non-List argument given to ForLet instruction.");var g=this.T,h=this.evaluate(d),l=g.wb();for(e(g,l);fb(l,b);){var n=eb(l,h);if(n instanceof Ta){if(n.type==="break")break;if(n.type==="return")return n}var p=g.wb();e(l,p);fb(p,c);l=p}}
function we(a,b){var c=Oa.apply(2,arguments),d=this.T,e=this.evaluate(b);if(!(e instanceof Gd))throw Error("Error: non-List value given for Fn argument names.");return new Kd(a,function(){return function(){var f=Oa.apply(0,arguments),g=d.wb();g.xb()===void 0&&g.ue(this.T.xb());for(var h=[],l=0;l<f.length;l++){var n=this.evaluate(f[l]);h[l]=n}for(var p=e.get("length"),q=0;q<p;q++)q<h.length?g.add(e.get(q),h[q]):g.add(e.get(q),void 0);g.add("arguments",new Gd(h));var r=eb(g,c);if(r instanceof Ta)return r.type===
"return"?r.data:r}}())}function xe(a){var b=this.evaluate(a),c=this.T;if(ye&&!c.has(b))throw new ReferenceError(b+" is not defined.");return c.get(b)}
function ze(a,b){var c,d=this.evaluate(a),e=this.evaluate(b);if(d===void 0||d===null)throw cb(Error("TypeError: Cannot read properties of "+d+" (reading '"+e+"')"));if(d instanceof kb||d instanceof Sd||d instanceof Gd||d instanceof Kd)c=d.get(e);else if(typeof d==="string")e==="length"?c=d.length:Fd(e)&&(c=d[e]);else if(d instanceof Pd)return;return c}function Ae(a,b){return this.evaluate(a)>this.evaluate(b)}function Be(a,b){return this.evaluate(a)>=this.evaluate(b)}
function Ce(a,b){var c=this.evaluate(a),d=this.evaluate(b);c instanceof Pd&&(c=c.getValue());d instanceof Pd&&(d=d.getValue());return c===d}function De(a,b){return!Ce.call(this,a,b)}function Ee(a,b,c){var d=[];this.evaluate(a)?d=this.evaluate(b):c&&(d=this.evaluate(c));var e=eb(this.T,d);if(e instanceof Ta)return e}var ye=!1;
function Fe(a,b){return this.evaluate(a)<this.evaluate(b)}function Ge(a,b){return this.evaluate(a)<=this.evaluate(b)}function He(){for(var a=new Gd,b=0;b<arguments.length;b++){var c=this.evaluate(arguments[b]);a.push(c)}return a}function Ie(){for(var a=new kb,b=0;b<arguments.length-1;b+=2){var c=String(this.evaluate(arguments[b])),d=this.evaluate(arguments[b+1]);a.set(c,d)}return a}function Je(a,b){return this.evaluate(a)%this.evaluate(b)}
function Ke(a,b){return this.evaluate(a)*this.evaluate(b)}function Le(a){return-this.evaluate(a)}function Me(a){return!this.evaluate(a)}function Ne(a,b){return!ke.call(this,a,b)}function Oe(){return null}function Pe(a,b){return this.evaluate(a)||this.evaluate(b)}function Qe(a,b){var c=this.evaluate(a);this.evaluate(b);return c}function Re(a){return this.evaluate(a)}function Se(){return Oa.apply(0,arguments)}function Te(a){return new Ta("return",this.evaluate(a))}
function Ue(a,b,c){var d=this.evaluate(a),e=this.evaluate(b),f=this.evaluate(c);if(d===null||d===void 0)throw cb(Error("TypeError: Can't set property "+e+" of "+d+"."));(d instanceof Kd||d instanceof Gd||d instanceof kb)&&d.set(String(e),f);return f}function Ve(a,b){return this.evaluate(a)-this.evaluate(b)}
function We(a,b,c){var d=this.evaluate(a),e=this.evaluate(b),f=this.evaluate(c);if(!Array.isArray(e)||!Array.isArray(f))throw Error("Error: Malformed switch instruction.");for(var g,h=!1,l=0;l<e.length;l++)if(h||d===this.evaluate(e[l]))if(g=this.evaluate(f[l]),g instanceof Ta){var n=g.type;if(n==="break")return;if(n==="return"||n==="continue")return g}else h=!0;if(f.length===e.length+1&&(g=this.evaluate(f[f.length-1]),g instanceof Ta&&(g.type==="return"||g.type==="continue")))return g}
function Xe(a,b,c){return this.evaluate(a)?this.evaluate(b):this.evaluate(c)}function Ye(a){var b=this.evaluate(a);return b instanceof Kd?"function":typeof b}function Ze(){for(var a=this.T,b=0;b<arguments.length;b++){var c=arguments[b];typeof c!=="string"||a.add(c,void 0)}}
function $e(a,b,c,d){var e=this.evaluate(d);if(this.evaluate(c)){var f=eb(this.T,e);if(f instanceof Ta){if(f.type==="break")return;if(f.type==="return")return f}}for(;this.evaluate(a);){var g=eb(this.T,e);if(g instanceof Ta){if(g.type==="break")break;if(g.type==="return")return g}this.evaluate(b)}}function af(a){return~Number(this.evaluate(a))}function bf(a,b){return Number(this.evaluate(a))<<Number(this.evaluate(b))}function cf(a,b){return Number(this.evaluate(a))>>Number(this.evaluate(b))}
function df(a,b){return Number(this.evaluate(a))>>>Number(this.evaluate(b))}function ef(a,b){return Number(this.evaluate(a))&Number(this.evaluate(b))}function ff(a,b){return Number(this.evaluate(a))^Number(this.evaluate(b))}function gf(a,b){return Number(this.evaluate(a))|Number(this.evaluate(b))}function hf(){}
function kf(a,b,c){try{var d=this.evaluate(b);if(d instanceof Ta)return d}catch(h){if(!(h instanceof bb&&h.Sn))throw h;var e=this.T.wb();a!==""&&(h instanceof bb&&(h=h.vo),e.add(a,new Pd(h)));var f=this.evaluate(c),g=eb(e,f);if(g instanceof Ta)return g}}function lf(a,b){var c,d;try{d=this.evaluate(a)}catch(f){if(!(f instanceof bb&&f.Sn))throw f;c=f}var e=this.evaluate(b);if(e instanceof Ta)return e;if(c)throw c;if(d instanceof Ta)return d};var nf=function(){this.H=new gb;mf(this)};nf.prototype.execute=function(a){return this.H.rk(a)};var mf=function(a){var b=function(c,d){var e=new Ld(String(c),d);e.Za();var f=String(c);a.H.H.set(f,e);db.set(f,e)};b("map",Ie);b("and",td);b("contains",wd);b("equals",ud);b("or",vd);b("startsWith",xd);b("variable",yd)};nf.prototype.Qb=function(a){this.H.Qb(a)};var pf=function(){this.K=!1;this.H=new gb;of(this);this.K=!0};pf.prototype.execute=function(a){return qf(this.H.rk(a))};var rf=function(a,b,c){return qf(a.H.Jq(b,c))};pf.prototype.Za=function(){this.H.Za()};
var of=function(a){var b=function(c,d){var e=String(c),f=new Ld(e,d);f.Za();a.H.H.set(e,f);db.set(e,f)};b(0,Zd);b(1,$d);b(2,ae);b(3,be);b(56,ef);b(57,bf);b(58,af);b(59,gf);b(60,cf);b(61,df);b(62,ff);b(53,ce);b(4,de);b(5,ee);b(68,kf);b(52,fe);b(6,ge);b(49,he);b(7,He);b(8,Ie);b(9,ee);b(50,ie);b(10,je);b(12,ke);b(13,le);b(67,lf);b(51,we);b(47,oe);b(54,pe);b(55,qe);b(63,ve);b(64,re);b(65,te);b(66,ue);b(15,xe);b(16,ze);b(17,ze);b(18,Ae);b(19,Be);b(20,Ce);b(21,De);b(22,Ee);b(23,Fe);b(24,Ge);b(25,Je);b(26,
Ke);b(27,Le);b(28,Me);b(29,Ne);b(45,Oe);b(30,Pe);b(32,Qe);b(33,Qe);b(34,Re);b(35,Re);b(46,Se);b(36,Te);b(43,Ue);b(37,Ve);b(38,We);b(39,Xe);b(40,Ye);b(44,hf);b(41,Ze);b(42,$e)};pf.prototype.je=function(){return this.H.je()};pf.prototype.Qb=function(a){this.H.Qb(a)};pf.prototype.sd=function(a){this.H.sd(a)};
function qf(a){if(a instanceof Ta||a instanceof Kd||a instanceof Gd||a instanceof kb||a instanceof Sd||a instanceof Pd||a===null||a===void 0||typeof a==="string"||typeof a==="number"||typeof a==="boolean")return a};var sf=function(a){this.message=a};function tf(a){a.qv=!0;return a};var uf=tf(function(a){return typeof a==="number"}),vf=tf(function(a){return typeof a==="string"}),wf=tf(function(a){return typeof a==="boolean"});function xf(a){var b="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[a];return b===void 0?new sf("Value "+a+" can not be encoded in web-safe base64 dictionary."):b};function yf(a){switch(a){case 1:return"1";case 2:case 4:return"0";default:return"-"}};var zf=/^[1-9a-zA-Z_-][1-9a-c][1-9a-v]\d$/;function Af(a,b){for(var c="",d=!0;a>7;){var e=a&31;a>>=5;d?d=!1:e|=32;c=""+xf(e)+c}a<<=2;d||(a|=32);return c=""+xf(a|b)+c}function Bf(a,b){return b===void 0||b===0?"":""+Af(a,1)+xf(b)}
function Cf(a,b){var c;var d=a.hi,e=a.bk;d===void 0?c="":(e||(e=0),c=""+Af(1,1)+xf(d<<2|e));var f="4"+c+Bf(2,a.qr),g,h=a.Io;g=h&&zf.test(h)?""+Af(3,2)+h:"";var l;var n=a.ctid;if(n&&b){var p=Af(5,3),q=n.split("-"),r=q[0].toUpperCase();if(r!=="GTM"&&r!=="OPT")l="";else{var t=q[1];l=""+p+xf(1+t.length)+(a.Ls||0)+t}}else l="";var u=a.canonicalId,v=a.mc,x=a.zv,y=f+g+Bf(4,a.Do)+l+Bf(6,a.Dt)+(u?""+Af(7,3)+xf(u.length)+u:"")+(v?""+Af(8,3)+xf(v.length)+v:"")+(x?""+Af(9,3)+xf(x.length)+x:""),z;var C=a.zr;C=
C===void 0?{}:C;for(var D=[],I=m(Object.keys(C)),G=I.next();!G.done;G=I.next()){var N=G.value;D[Number(N)]=C[N]}if(D.length){var S=Af(10,3),W;if(D.length===0)W=xf(0);else{for(var ea=[],ja=0,fa=!1,sa=0;sa<D.length;sa++){fa=!0;var da=sa%6;D[sa]&&(ja|=1<<da);da===5&&(ea.push(xf(ja)),ja=0,fa=!1)}fa&&ea.push(xf(ja));W=ea.join("")}var ma=W;z=""+S+xf(ma.length)+ma}else z="";var Pa=a.Us,Fa=a.nt;return y+z+(Pa?""+Af(11,3)+xf(Pa.length)+Pa:"")+(Fa?""+Af(13,3)+xf(Fa.length)+Fa:"")+Bf(14,a.Et)+Bf(15,a.rv)+Bf(16,
a.Av)};function Df(a){for(var b=[],c=0,d=0;d<a.length;d++){var e=a.charCodeAt(d);e<128?b[c++]=e:(e<2048?b[c++]=e>>6|192:((e&64512)==55296&&d+1<a.length&&(a.charCodeAt(d+1)&64512)==56320?(e=65536+((e&1023)<<10)+(a.charCodeAt(++d)&1023),b[c++]=e>>18|240,b[c++]=e>>12&63|128):b[c++]=e>>12|224,b[c++]=e>>6&63|128),b[c++]=e&63|128)}return b};function Ef(a,b){for(var c=qb(b),d=new Uint8Array(c.length),e=0;e<c.length;e++)d[e]=c.charCodeAt(e);if(d.length!==32)throw Error("Key is not 32 bytes.");return Ff(a,d)}function Ff(a,b){if(a==="")return"";var c=Zb(a),d=b.slice(-2),e=[].concat(w(d),w(c)).map(function(g,h){return g^b[h%b.length]}),f=new Uint8Array([].concat(w(e),w(d)));return pb(String.fromCharCode.apply(String,w(f))).replace(/\.+$/,"")};var Gf=function(){function a(b){return{toString:function(){return b}}}return{cp:a("consent"),Zk:a("convert_case_to"),al:a("convert_false_to"),bl:a("convert_null_to"),ep:a("convert_to_boolean"),ah:a("convert_to_number"),fl:a("convert_true_to"),il:a("convert_undefined_to"),Yt:a("debug_mode_metadata"),Yb:a("function"),Rm:a("instance_name"),Nq:a("live_only"),Oq:a("malware_disabled"),METADATA:a("metadata"),Rq:a("original_activity_id"),Tu:a("original_vendor_template_id"),Su:a("once_on_load"),Qq:a("once_per_event"),
kn:a("once_per_load"),Vu:a("priority_override"),Yu:a("respected_consent_types"),tn:a("setup_tags"),yj:a("tag_id"),Dn:a("teardown_tags"),pl:a("disabled_in_google_mode"),Fq:a("generated_tagging_metadata")}}();function Hf(a,b){var c={};c[Gf.Yb]="__"+a;for(var d in b)b.hasOwnProperty(d)&&(c["vtp_"+d]=b[d]);return c};function If(a,b){b=b===void 0?!1:b;var c,d;return((c=data)==null?0:(d=c.blob)==null?0:d.hasOwnProperty(a))?!!data.blob[a]:b}function E(a){var b;b=b===void 0?"":b;var c,d;return((c=data)==null?0:(d=c.blob)==null?0:d.hasOwnProperty(a))?String(data.blob[a]):b}function Jf(a){var b,c;return((b=data)==null?0:(c=b.blob)==null?0:c.hasOwnProperty(a))?Number(data.blob[a]):0}function Kf(a){var b;b=b===void 0?[]:b;var c,d,e=(c=data)==null?void 0:(d=c.blob)==null?void 0:d[a];return Array.isArray(e)?e:b}
function Lf(a){var b;b=b===void 0?"":b;var c=Mf(46);return c&&(c==null?0:c.hasOwnProperty(a))?String(c[a]):b}function Nf(a,b){var c=Mf(46);return c&&(c==null?0:c.hasOwnProperty(a))?Number(c[a]):b}function Mf(a){var b,c;return(b=data)==null?void 0:(c=b.blob)==null?void 0:c[a]};var Of=function(a,b,c){var d;d=Error.call(this,c);this.message=d.message;"stack"in d&&(this.stack=d.stack);this.permissionId=a;this.parameters=b;this.name="PermissionError"};wa(Of,Error);Of.prototype.getMessage=function(){return this.message};function Pf(a,b){if(Array.isArray(a)){Object.defineProperty(a,"context",{value:{line:b[0]}});for(var c=1;c<a.length;c++)Pf(a[c],b[c])}};function Qf(){return function(a,b){var c;var d=Rf;a instanceof bb?(a.H=d,c=a):c=new bb(a,d);var e=c;b&&e.K.push(b);throw e;}}function Rf(a){if(!a.length)return a;a.push({id:"main",line:0});for(var b=a.length-1;b>0;b--)Ab(a[b].id)&&a.splice(b++,1);for(var c=a.length-1;c>0;c--)a[c].line=a[c-1].line;a.splice(0,1);return a};var Sf=RegExp("[^0-9\\.+-]","g"),Tf=RegExp("[^0-9\\,+-]","g"),Uf=RegExp("[^0-9+-]","g");
function Vf(a,b){if(typeof a==="number")return a;var c=String(a),d;if(b==="AUTOMATIC"){var e=(c.match(/\./g)||[]).length,f=(c.match(/,/g)||[]).length,g="NONE";if(e>0&&f>0){var h=c.lastIndexOf(".")>c.lastIndexOf(",");h&&e===1?g="PERIOD":h||f!==1||(g="COMMA")}else e===1?g=(c.split(".")[1].match(/[0-9]/g)||[]).length!==3?"PERIOD":"NONE":f===1&&(g=(c.split(",")[1].match(/[0-9]/g)||[]).length!==3?"COMMA":"NONE");d=g}else d=b==="COMMA"?"COMMA":"PERIOD";var l,n;d==="PERIOD"?(l=".",n=Sf):d==="COMMA"?(l=",",
n=Tf):(l="",n=Uf);var p=c.replace(n,"");if(l!==""&&p.split(l).length>2)return a;var q=p.replace(/,/g,".");if(q==="")return a;var r=Number(q);return isNaN(r)?a:r};var Wf=[],Xf={};function Yf(a){return Wf[a]===void 0?!1:Wf[a]};var Zf=function(){this.H={}},$f=function(a,b,c){var d;(d=a.H)[b]!=null||(d[b]=[]);a.H[b].push(function(){return c.apply(null,w(Oa.apply(0,arguments)))})};function ag(a,b,c,d){if(a)for(var e=0;e<a.length;e++){var f=void 0,g="A policy function denied the permission request";try{f=a[e](b,c,d),g+="."}catch(h){g=typeof h==="string"?g+(": "+h):h instanceof Error?g+(": "+h.message):g+"."}if(!f)throw new Of(c,d,g);}}
function bg(a,b){var c=cg(dg.H,b,function(){return{}});try{return c(a),!0}catch(d){return!1}}function cg(a,b,c){return function(d){if(d){var e=a.H[d],f=a.H.all;if(e||f){var g=c.apply(void 0,[d].concat(w(Oa.apply(1,arguments))));ag(e,b,d,g);ag(f,b,d,g)}}}};var gg=function(a,b,c){var d=this;this.K={};this.H=new Zf;var e={},f={},g=cg(this.H,a,function(h){return h&&e[h]?e[h].apply(void 0,[h].concat(w(Oa.apply(1,arguments)))):{}});Gb(b,function(h,l){function n(q){var r=Oa.apply(1,arguments);if(!p[q])throw eg(q,{},"The requested additional permission "+q+" is not configured.");g.apply(null,[q].concat(w(r)))}var p={};Gb(l,function(q,r){var t=fg(q,r,c);p[q]=t.assert;e[q]||(e[q]=t.aa);t.On&&!f[q]&&(f[q]=t.On)});d.K[h]=function(q,r){var t=p[q];if(!t)throw eg(q,
{},"The requested permission "+q+" is not configured.");var u=Array.prototype.slice.call(arguments,0);t.apply(void 0,u);g.apply(void 0,u);var v=f[q];v&&v.apply(null,[n].concat(w(u.slice(1))))}})},hg=function(a){return dg.K[a]||function(){}};
function fg(a,b,c){try{var d=c["__"+a];if(!d)throw Error("No function found for permission: "+a+".");var e=Hf(a,b);e.vtp_permissionName=a;e.vtp_createPermissionError=eg;delete e[Gf.Yb];return d(e)}catch(f){return{assert:function(g){throw new Of(g,{},"Permission "+g+" is unknown.");},aa:function(){throw new Of(a,{},"Permission "+a+" is unknown.");}}}}function eg(a,b,c){return new Of(a,b,c)};var ig=E(5),jg=E(20),kg=E(1),lg=!1;var mg={};mg.Po=If(29);mg.Kr=If(28);function ng(a){var b=1,c,d,e;if(a)for(b=0,d=a.length-1;d>=0;d--)e=a.charCodeAt(d),b=(b<<6&268435455)+e+(e<<14),c=b&266338304,b=c!==0?b^c>>21:b;return b};var og=function(a){this.cache=a};og.prototype.get=function(a){var b=ng(a),c=this.cache.get(b);if(!c)return{promise:void 0,Kj:0};if(Date.now()>=c.timestamp+9E5)return this.cache.delete(b),{promise:void 0,Kj:3};var d=c.resolvedValue?2:1;return{promise:c.resolvedValue?Promise.resolve(c.resolvedValue):c.promise,Kj:d}};og.prototype.set=function(a,b){var c={promise:b,resolvedValue:void 0,timestamp:Date.now()};this.cache.set(ng(a),c);b.then(function(d){c.resolvedValue=d})};function pg(a){switch(a){case 0:break;case 9:return"e4";case 6:return"e5";case 14:return"e6";default:return"e7"}};var F={D:{Xa:"ad_personalization",ka:"ad_storage",ma:"ad_user_data",ra:"analytics_storage",nc:"region",sa:"consent_updated",Yg:"wait_for_update",eh:"endpoint_type",qp:"app_remove",rp:"app_store_refund",tp:"app_store_subscription_cancel",up:"app_store_subscription_convert",vp:"app_store_subscription_renew",wp:"consent_update",xp:"conversion",vl:"add_payment_info",wl:"add_shipping_info",xe:"add_to_cart",ye:"remove_from_cart",xl:"view_cart",Ad:"begin_checkout",eu:"generate_lead",ze:"select_item",oc:"view_item_list",
Qc:"select_promotion",qc:"view_promotion",Ib:"purchase",Ae:"refund",rc:"view_item",yl:"add_to_wishlist",yp:"exception",zp:"first_open",Ap:"first_visit",wa:"gtag.config",Jb:"gtag.get",Bp:"in_app_purchase",sc:"page_view",Cp:"screen_view",Dp:"session_start",Ep:"source_update",Fp:"timing_complete",Gp:"track_social",yf:"user_engagement",Hp:"user_id_update",fh:"braid_link_decoration_source",gh:"braid_storage_source",Bd:"gclid_link_decoration_source",Cd:"gclid_storage_source",Sb:"gclgb",lb:"gclid",zl:"gclid_len",
Be:"gclgs",Ce:"gcllp",De:"gclst",mb:"ads_data_redaction",zf:"gad_source",Af:"gad_source_src",Dd:"gclid_url",Al:"gclsrc",Bf:"gbraid",Ee:"wbraid",Rc:"allow_ad_personalization_signals",ri:"allow_custom_scripts",hh:"allow_display_features",si:"allow_enhanced_conversions",Sc:"allow_google_signals",ui:"allow_interest_groups",Ip:"app_id",Jp:"app_installer_id",Kp:"app_name",Lp:"app_version",Ed:"auid",fu:"auto_detection_enabled",Bl:"auto_event",Cl:"aw_remarketing",ih:"aw_remarketing_only",Cf:"discount",Df:"aw_feed_country",
Ef:"aw_feed_language",Ha:"items",Ff:"aw_merchant_id",wi:"aw_basket_type",Gf:"campaign_content",Hf:"campaign_id",If:"campaign_medium",Jf:"campaign_name",Kf:"campaign",Lf:"campaign_source",Mf:"campaign_term",Kb:"client_id",Dl:"rnd",xi:"consent_update_type",Mp:"content_group",Np:"content_type",Fd:"conversion_cookie_prefix",yi:"conversion_id",uc:"conversion_linker",Hd:"conversion_linker_disabled",Fe:"conversion_api",zi:"_&rcb",jh:"cookie_deprecation",Lb:"cookie_domain",Cb:"cookie_expires",Tb:"cookie_flags",
Id:"cookie_name",vc:"cookie_path",nb:"cookie_prefix",Jd:"cookie_update",Tc:"country",eb:"currency",Ge:"customer_lifetime_value",kh:"customer_type",He:"custom_map",Ai:"gcldc_link_decoration_source",Bi:"gcldc_storage_source",Nf:"gcldc",Kd:"dclid",El:"debug_mode",Oa:"developer_id",Op:"disable_merchant_reported_purchases",Uc:"dc_custom_params",Pp:"dc_natural_search",Qp:"dynamic_event_settings",Fl:"affiliation",mh:"checkout_option",Ci:"checkout_step",Gl:"coupon",Of:"item_list_name",Di:"list_name",Rp:"promotions",
Ld:"shipping",Hl:"tax",nh:"engagement_time_msec",oh:"enhanced_client_id",Sp:"enhanced_conversions",gu:"enhanced_conversions_automatic_settings",Ie:"estimated_delivery_date",Pf:"event_callback",Tp:"event_category",Vc:"event_developer_id_string",Md:"event_id",Ei:"_event_join_id",Up:"event_label",Ub:"event",Il:"_&ae",Fi:"event_settings",ph:"event_timeout",Vp:"description",Wp:"fatal",Xp:"experiments",Nd:"ext_client_id",Gi:"firebase_id",Qf:"first_party_collection",Rf:"_x_20",Vb:"_x_19",Yp:"flight_error_code",
Zp:"flight_error_message",Hi:"fl_activity_category",Ii:"fl_activity_group",qh:"fl_advertiser_id",Ji:"match_id",Jl:"fl_random_number",Kl:"tran",Ll:"u",rh:"gac_gclid",Je:"gac_wbraid",Ml:"gac_wbraid_multiple_conversions",aq:"ga_restrict_domain",Nl:"ga_temp_client_id",bq:"ga_temp_ecid",Ke:"gdpr_applies",sh:"_gt_metadata",Ol:"geo_granularity",Sf:"value_callback",Tf:"value_key",Ta:"google_analysis_params",Le:"_google_ng",cq:"_ono",Uf:"google_signals",fq:"google_tld",th:"gpp_sid",uh:"gpp_string",Od:"groups",
Pl:"gsa_experiment_id",Vf:"gtag_event_feature_usage",Ql:"gtm_up",Me:"iframe_state",Wf:"ignore_referrer",Rl:"internal_traffic_results",Sl:"_is_fpm",Yc:"is_legacy_converted",Zc:"is_legacy_loaded",Ki:"is_passthrough",Pd:"_lps",tb:"language",Li:"legacy_developer_id_string",Db:"linker",Xf:"accept_incoming",wc:"decorate_forms",Aa:"domains",ad:"url_position",Qd:"merchant_feed_label",Rd:"merchant_feed_language",Sd:"merchant_id",Tl:"method",gq:"name",Ul:"navigation_type",Ne:"new_customer",Mi:"non_interaction",
hq:"optimize_id",Vl:"page_hostname",Yf:"page_path",Ua:"page_referrer",Mb:"page_title",iq:"passengers",Wl:"phone_conversion_callback",jq:"phone_conversion_country_code",Xl:"phone_conversion_css_class",kq:"phone_conversion_ids",Yl:"phone_conversion_number",Zl:"phone_conversion_options",lq:"_platinum_request_status",mq:"_protected_audience_enabled",wh:"quantity",xh:"redact_device_info",am:"referral_exclusion_definition",hu:"_request_start_time",Wb:"restricted_data_processing",nq:"retoken",oq:"sample_rate",
Ni:"screen_name",bd:"screen_resolution",bm:"_script_source",pq:"search_term",Td:"send_page_view",Xb:"send_to",Oi:"server_container_3p_enrichment",dd:"server_container_url",qq:"session_attributes_encoded",yh:"session_duration",zh:"session_engaged",Pi:"session_engaged_time",xc:"session_id",Ah:"session_number",Zf:"_shared_user_id",Ud:"delivery_postal_code",iu:"_tag_firing_delay",ju:"_tag_firing_time",ku:"temporary_client_id",Qi:"testonly",rq:"_timezone",Pe:"topmost_url",Qe:"tracking_id",Ri:"traffic_type",
Pa:"transaction_id",dm:"transaction_id_source",yc:"transport_url",sq:"trip_type",Vd:"update",zc:"url_passthrough",fm:"uptgs",cg:"_user_agent_architecture",dg:"_user_agent_bitness",eg:"_user_agent_full_version_list",fg:"_user_agent_mobile",gg:"_user_agent_model",hg:"_user_agent_platform",ig:"_user_agent_platform_version",jg:"_user_agent_wow64",Ac:"user_data",gm:"user_data_auto_latency",hm:"user_data_auto_meta",im:"user_data_auto_multi",jm:"user_data_auto_selectors",km:"user_data_auto_status",Bc:"user_data_mode",
lm:"user_data_settings",fb:"user_id",Wd:"user_properties",om:"_user_region",kg:"us_privacy_string",Qa:"value",qm:"wbraid_multiple_conversions",ed:"_fpm_parameters",Wi:"_host_name",Vm:"_in_page_command",Yi:"_ip_override",Zm:"_is_passthrough_cid",Jh:"_measurement_type",de:"non_personalized_ads",oj:"_sst_parameters",Yq:"sgtm_geo_user_country",Gd:"conversion_label",za:"page_location",Wc:"_extracted_data",Xc:"global_developer_id_string",Oe:"tc_privacy_string"}};var H={J:{So:"abort_without_fail",ki:"accept_by_default",Bk:"add_tag_timing",Dk:"ads_consent_granted",vd:"ads_event_page_view",wd:"allow_ad_personalization",Qt:"auto_event",Kk:"batch_on_navigation",Xg:"biscotti_join_id",Pk:"client_id_source",uf:"consent_event_id",vf:"consent_priority_id",St:"consent_state",sa:"consent_updated",wf:"conversion_linker_enabled",Tt:"conversion_marking_called",Ga:"cookie_options",ol:"dc_random",Zt:"dedupe_id",Pc:"em_event",bu:"endpoint_for_debug",tl:"enhanced_client_id_source",
pp:"enhanced_match_result",rm:"euid_logged_in_state",lg:"euid_mode_enabled",tq:"event_provenance",mu:"event_source",Eb:"event_start_timestamp_ms",wm:"event_usage",Ch:"extra_tag_experiment_ids",pu:"add_parameter",Ui:"counting_method",Dh:"send_as_iframe",qu:"parameter_order",Eh:"parsed_target",su:"form_event_canceled",Aq:"ga4_collection_subdomain",Vi:"ga4_request_flags",Nm:"gbraid_cookie_marked",Qm:"gtm_extracted_data",Cc:"handle_internally",uu:"has_ga_conversion_consents",da:"hit_type",Dc:"hit_type_override",
Hq:"ignore_dupe_config",Ou:"is_config_command",Gh:"is_consent_update",mg:"is_conversion",Wm:"is_ecommerce",Xm:"is_ec_cm_split",ae:"is_external_event",ng:"is_first_visit",Ym:"is_first_visit_conversion",Zi:"is_fl_fallback_conversion_flow_allowed",fd:"is_fpm_encryption",aj:"is_fpm_split",ob:"is_gcp_browser",bj:"is_google_measurement_allowed",cj:"is_google_signals_enabled",be:"is_merchant_center",Hh:"is_new_to_site",Ec:"is_personalization",dj:"is_server_side_destination",Te:"is_session_start",bn:"is_session_start_conversion",
Pu:"is_sgtm_ga_ads_conversion_study_control_group",Qu:"is_sgtm_prehit",dn:"is_sgtm_service_worker",Ih:"is_split_conversion",Iq:"is_syn",Fc:"is_test_event",og:"join_id",ej:"join_elapsed",pg:"join_timer_sec",gn:"local_storage_aw_conversion_counters",We:"tunnel_updated",Uu:"prehit_for_retry",Wu:"promises",Xu:"record_aw_latency",Xe:"redact_ads_data",Ye:"redact_click_ids",pn:"remarketing_only",lj:"send_ccm_parallel_ping",hd:"send_doubleclick_join",Mh:"send_fpm_geo_join",Nh:"send_fpm_google_join",Zu:"send_ccm_parallel_test_ping",
rn:"send_google_measurement",rg:"send_tld_join",sg:"send_to_destinations",mj:"send_to_targets",sn:"send_user_data_hit",pj:"service_worker_context",Nb:"source_canonical_id",Ja:"speculative",yn:"speculative_in_message",An:"suppress_script_load",Bn:"syn_or_mod",zj:"transient_ecsid",tg:"transmission_type",Ya:"user_data",gv:"user_data_from_automatic",hv:"user_data_from_automatic_getter",Gn:"user_data_from_code",ir:"user_data_from_manual",jv:"user_data_mode",ug:"user_id_updated"}};var J={U:{kp:1,mp:2,En:3,nn:4,ql:5,rl:6,Eq:7,np:8,Dq:9,jp:10,hp:11,xn:12,vn:13,Nk:14,Uo:15,Wo:16,hn:17,sl:18,fn:19,lp:20,Pq:21,ap:22,Vo:23,Xo:24,nl:25,Lk:26,er:27,Jm:28,Um:29,Tm:30,Sm:31,Mm:32,Km:33,Lm:34,Gm:35,Fm:36,Hm:37,Im:38,Bq:39,Cq:40,Uq:41}};J.U[J.U.kp]="CREATE_EVENT_SOURCE";J.U[J.U.mp]="EDIT_EVENT";J.U[J.U.En]="TRAFFIC_TYPE";J.U[J.U.nn]="REFERRAL_EXCLUSION";J.U[J.U.ql]="ECOMMERCE_FROM_GTM_TAG";J.U[J.U.rl]="ECOMMERCE_FROM_GTM_UA_SCHEMA";J.U[J.U.Eq]="GA_SEND";J.U[J.U.np]="EM_FORM";
J.U[J.U.Dq]="GA_GAM_LINK";J.U[J.U.jp]="CREATE_EVENT_AUTO_PAGE_PATH";J.U[J.U.hp]="CREATED_EVENT";J.U[J.U.xn]="SIDELOADED";J.U[J.U.vn]="SGTM_LEGACY_CONFIGURATION";J.U[J.U.Nk]="CCD_EM_EVENT";J.U[J.U.Uo]="AUTO_REDACT_EMAIL";J.U[J.U.Wo]="AUTO_REDACT_QUERY_PARAM";J.U[J.U.hn]="MULTIPLE_PAGEVIEW_FROM_CONFIG";J.U[J.U.sl]="EM_EVENT_SENT_BEFORE_CONFIG";J.U[J.U.fn]="LOADED_VIA_CST_OR_SIDELOADING";J.U[J.U.lp]="DECODED_PARAM_MATCH";J.U[J.U.Pq]="NON_DECODED_PARAM_MATCH";J.U[J.U.ap]="CCD_EVENT_SGTM";
J.U[J.U.Vo]="AUTO_REDACT_EMAIL_SGTM";J.U[J.U.Xo]="AUTO_REDACT_QUERY_PARAM_SGTM";J.U[J.U.nl]="DAILY_LIMIT_REACHED";J.U[J.U.Lk]="BURST_LIMIT_REACHED";J.U[J.U.er]="SHARED_USER_ID_SET_AFTER_REQUEST";J.U[J.U.Jm]="GA4_MULTIPLE_SESSION_COOKIES";J.U[J.U.Um]="INVALID_GA4_SESSION_COUNT";J.U[J.U.Tm]="INVALID_GA4_LAST_EVENT_TIMESTAMP";J.U[J.U.Sm]="INVALID_GA4_JOIN_TIMER";J.U[J.U.Mm]="GA4_STALE_SESSION_COOKIE_SELECTED";J.U[J.U.Km]="GA4_SESSION_COOKIE_GS1_READ";J.U[J.U.Lm]="GA4_SESSION_COOKIE_GS2_READ";
J.U[J.U.Gm]="GA4_DL_PARAM_RECOVERY_AVAILABLE";J.U[J.U.Fm]="GA4_DL_PARAM_RECOVERY_APPLIED";J.U[J.U.Hm]="GA4_GOOGLE_MEASUREMENT_ALLOWED";J.U[J.U.Im]="GA4_GOOGLE_SIGNALS_ENABLED";J.U[J.U.Bq]="GA4_FALLBACK_REQUEST";J.U[J.U.Cq]="GA_ADS_LINK_BEFORE_CONVERSION_MARKING";J.U[J.U.Uq]="PLATINUM_ELIGIBLE";var xg={},yg=(xg.uaa=!0,xg.uab=!0,xg.uafvl=!0,xg.uamb=!0,xg.uam=!0,xg.uap=!0,xg.uapv=!0,xg.uaw=!0,xg);
var Eg=function(a,b){for(var c=0;c<b.length;c++){var d=a,e=b[c];if(!Cg.exec(e))throw Error("Invalid key wildcard");var f=e.indexOf(".*"),g=f!==-1&&f===e.length-2,h=g?e.slice(0,e.length-2):e,l;a:if(d.length===0)l=!1;else{for(var n=d.split("."),p=0;p<n.length;p++)if(!Dg.exec(n[p])){l=!1;break a}l=!0}if(!l||h.length>d.length||!g&&d.length!==e.length?0:g?Sb(d,h)&&(d===h||d.charAt(h.length)==="."):d===h)return!0}return!1},Dg=/^[a-z$_][\w-$]*$/i,Cg=/^(?:[a-z_$][a-z-_$0-9]*\.)*[a-z_$][a-z-_$0-9]*(?:\.\*)?$/i;
var Fg=["matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector"];function Gg(a,b){if(!a)return!1;try{for(var c=0;c<Fg.length;c++){var d=Fg[c];if(a[d]!=null)return a[d](b)}}catch(e){}return!1}function Hg(a,b){var c=String(a),d=String(b),e=c.length-d.length;return e>=0&&c.indexOf(d,e)===e}function Ig(a,b){return String(a).split(",").indexOf(String(b))>=0}
function Jg(a,b,c,d){var e=c?"i":void 0;try{var f=String(b)+String(e),g=d==null?void 0:d.get(f);g||(g=new RegExp(b,e),d==null||d.set(f,g));return g.test(a)}catch(h){return!1}}function Kg(a,b){return String(a).indexOf(String(b))>=0}function Lg(a,b){return String(a)===String(b)}function Mg(a,b){return Number(a)>=Number(b)}function Ng(a,b){return Number(a)<=Number(b)}function Og(a,b){return Number(a)>Number(b)}function Pg(a,b){return Number(a)<Number(b)}
function Qg(a,b){return Sb(String(a),String(b))};function Xg(a){var b=a.search;return a.protocol+"//"+a.hostname+a.pathname+(b?b+"&richsstsse":"?richsstsse")};var Yg=function(){this.R=""},$g=function(a,b){return function(){var c=b.fallback_url,d=b.fallback_url_method;if(c&&d){var e={};Zg(a,(e[d]=[c],e.options={},e))}}},ah=function(a,b,c){if(Array.isArray(a))for(var d=m(a),e=d.next();!e.done;e=d.next()){var f=e.value;typeof f==="string"&&c(f,b)}},Zg=function(a,b){if(b)for(var c=Cd(b.options)?b.options:{},d=m(Object.keys(b)),e=d.next();!e.done;e=d.next()){var f=e.value,g=b[f];switch(f){case "send_pixel":ah(g,c,function(h,l){return void a.K(h,l)});break;case "fetch":ah(g,
c,function(h,l){return void a.H(h,l)})}}};var bh=/^([a-z][a-z0-9]*):(!|\?)(\*|string|boolean|number|Fn|PixieMap|List|OpaqueValue)$/i,ch={Fn:"function",PixieMap:"Object",List:"Array"};
function dh(a,b){for(var c=["input:!*"],d=0;d<c.length;d++){var e=bh.exec(c[d]);if(!e)throw Error("Internal Error in "+a);var f=e[1],g=e[2]==="!",h=e[3],l=b[d];if(l==null){if(g)throw Error("Error in "+a+". Required argument "+f+" not supplied.");}else if(h!=="*"){var n=typeof l;l instanceof Kd?n="Fn":l instanceof Gd?n="List":l instanceof kb?n="PixieMap":l instanceof Sd?n="PixiePromise":l instanceof Pd&&(n="OpaqueValue");if(n!==h)throw Error("Error in "+a+". Argument "+f+" has type "+((ch[n]||n)+", which does not match required type ")+
((ch[h]||h)+"."));}}}function K(a,b,c){for(var d=[],e=m(c),f=e.next();!f.done;f=e.next()){var g=f.value;g instanceof Kd?d.push("function"):g instanceof Gd?d.push("Array"):g instanceof kb?d.push("Object"):g instanceof Sd?d.push("Promise"):g instanceof Pd?d.push("OpaqueValue"):d.push(typeof g)}return Error("Argument error in "+a+". Expected argument types ["+(b.join(",")+"], but received [")+(d.join(",")+"]."))}function eh(a){return a instanceof kb}function fh(a){return eh(a)||a===null||gh(a)}
function hh(a){return a instanceof Kd}function ih(a){return hh(a)||a===null||gh(a)}function jh(a){return a instanceof Gd}function kh(a){return a instanceof Pd}function lh(a){return typeof a==="string"}function mh(a){return lh(a)||a===null||gh(a)}function nh(a){return typeof a==="boolean"}function oh(a){return nh(a)||gh(a)}function ph(a){return nh(a)||a===null||gh(a)}function qh(a){return typeof a==="number"}function gh(a){return a===void 0};function rh(a){return""+a}
function sh(a,b){var c=[];return c};function th(a,b){var c=new Kd(a,function(){for(var d=Array.prototype.slice.call(arguments,0),e=0;e<d.length;e++)d[e]=this.evaluate(d[e]);try{return b.apply(this,d)}catch(g){throw cb(g);}});c.Za();return c}
function uh(a,b){var c=new kb,d;for(d in b)if(b.hasOwnProperty(d)){var e=b[d];yb(e)?c.set(d,th(a+"_"+d,e)):Cd(e)?c.set(d,uh(a+"_"+d,e)):(Ab(e)||zb(e)||typeof e==="boolean")&&c.set(d,e)}c.Za();return c};function wh(a,b){if(!lh(a))throw K(this.getName(),["string"],arguments);if(!mh(b))throw K(this.getName(),["string","undefined"],arguments);var c={},d=new kb;return d=uh("AssertApiSubject",
c)};function xh(a,b){if(!mh(b))throw K(this.getName(),["string","undefined"],arguments);if(a instanceof Sd)throw Error("Argument actual cannot have type Promise. Assertions on asynchronous code aren't supported.");var c={},d=new kb;return d=uh("AssertThatSubject",c)};function yh(a){return function(){for(var b=Oa.apply(0,arguments),c=[],d=this.T,e=0;e<b.length;++e)c.push(Td(b[e],d));return Ud(a.apply(null,c))}}function zh(){for(var a=Math,b=Ah,c={},d=0;d<b.length;d++){var e=b[d];a.hasOwnProperty(e)&&(c[e]=yh(a[e].bind(a)))}return c};function Bh(a){return a!=null&&Sb(a,"__cvt_")};function Ch(a){var b;return b};function Dh(a){var b;if(!lh(a))throw K(this.getName(),["string"],arguments);try{b=decodeURIComponent(a)}catch(c){}return b};function Eh(a){try{return encodeURI(a)}catch(b){}};function Fh(a){try{return encodeURIComponent(String(a))}catch(b){}};function Gh(a,b){var c=!1;return c}function Lh(a){if(!mh(a))throw K(this.getName(),["string|undefined"],arguments);};function Mh(a){var b=Td(a);return ng(b?""+b:"")};function Nh(a,b){if(!qh(a)||!qh(b))throw K(this.getName(),["number","number"],arguments);return Db(a,b)};function Oh(){return(new Date).getTime()};function Ph(a){if(a===null)return"null";if(a instanceof Gd)return"array";if(a instanceof Kd)return"function";if(a instanceof Pd){var b=a.getValue();if((b==null?void 0:b.constructor)===void 0||b.constructor.name===void 0){var c=String(b);return c.substring(8,c.length-1)}return String(b.constructor.name)}return typeof a};function Qh(a){function b(c){return function(d){try{return c(d)}catch(e){(lg||mg.Po)&&a.call(this,e.message)}}}return{parse:b(function(c){return Ud(JSON.parse(c))}),stringify:b(function(c){return JSON.stringify(Td(c))}),publicName:"JSON"}};function Rh(a){return Ib(Td(a,this.T))};function Sh(a){return Number(Td(a,this.T))};function Th(a){return a===null?"null":a===void 0?"undefined":a.toString()};function Uh(a,b,c){var d=null,e=!1;return e?d:null};var Ah="floor ceil round max min abs pow sqrt".split(" ");function Vh(){var a={};return{Wr:function(b){return a.hasOwnProperty(b)?a[b]:void 0},Ko:function(b,c){a[b]=c},reset:function(){a={}}}}function Wh(a,b){return function(){return Kd.prototype.invoke.apply(a,[b].concat(w(Oa.apply(0,arguments))))}}
function Xh(a,b){if(!lh(a))throw K(this.getName(),["string","any"],arguments);}
function Yh(a,b){if(!lh(a)||!eh(b))throw K(this.getName(),["string","PixieMap"],arguments);};var Zh={};
Zh.keys=function(a){return new Gd};
Zh.values=function(a){return new Gd};
Zh.entries=function(a){return new Gd};
Zh.freeze=function(a){return a};Zh.delete=function(a,b){return!1};function L(a,b){var c=Oa.apply(2,arguments),d=a.T.xb();if(!d)throw Error("Missing program state.");if(d.it){try{d.Rn.apply(null,[b].concat(w(c)))}catch(e){throw sb("TAGGING",21),e;}return}d.Rn.apply(null,[b].concat(w(c)))};var ai=function(){this.K={};this.H={};this.N=!0;};ai.prototype.get=function(a,b){var c=this.contains(a)?this.K[a]:void 0;return c};ai.prototype.contains=function(a){return this.K.hasOwnProperty(a)};
ai.prototype.add=function(a,b,c){if(this.contains(a))throw Error("Attempting to add a function which already exists: "+a+".");if(this.H.hasOwnProperty(a))throw Error("Attempting to add an API with an existing private API name: "+a+".");this.K[a]=c?void 0:yb(b)?th(a,b):uh(a,b)};function bi(a,b){var c=void 0;return c};function ci(){var a={};
return a};var di={},ei=(di[F.D.sa]="gcu",di[F.D.eh]="ept",di[F.D.Sb]="gclgb",di[F.D.lb]="gclaw",di[F.D.zl]="gclid_len",di[F.D.Be]="gclgs",di[F.D.Ce]="gcllp",di[F.D.De]="gclst",di[F.D.Ed]="auid",di[F.D.Bl]="ae",di[F.D.Cf]="dscnt",di[F.D.Df]="fcntr",di[F.D.Ef]="flng",di[F.D.Ff]="mid",di[F.D.wi]="bttype",di[F.D.Kb]="gacid",di[F.D.Gd]="label",di[F.D.Fe]="capi",di[F.D.jh]="pscdl",di[F.D.eb]="currency_code",di[F.D.Ge]="vdltv",di[F.D.kh]="cloct",di[F.D.El]="_dbg",di[F.D.Ie]="oedeld",di[F.D.Vc]="edid",di[F.D.Md]="evnid",
di[F.D.Ei]="evjid",di[F.D.Nd]="excid",di[F.D.rh]="gac",di[F.D.Je]="gacgb",di[F.D.Ml]="gacmcov",di[F.D.Ke]="gdpr",di[F.D.Xc]="gdid",di[F.D.Le]="_ng",di[F.D.cq]="_ono",di[F.D.th]="gpp_sid",di[F.D.uh]="gpp",di[F.D.Pl]="gsaexp",di[F.D.Vf]="_tu",di[F.D.Me]="frm",di[F.D.Ki]="gtm_up",di[F.D.Pd]="lps",di[F.D.Li]="did",di[F.D.Qd]="fcntr",di[F.D.Rd]="flng",di[F.D.Sd]="mid",di[F.D.Ne]=void 0,di[F.D.Mb]="tiba",di[F.D.Wb]="rdp",di[F.D.xc]="ecsid",di[F.D.Zf]="ga_uid",di[F.D.Ud]="delopc",di[F.D.Oe]="gdpr_consent",
di[F.D.Pa]="oid",di[F.D.dm]="oidsrc",di[F.D.fm]="uptgs",di[F.D.cg]="uaa",di[F.D.dg]="uab",di[F.D.eg]="uafvl",di[F.D.fg]="uamb",di[F.D.gg]="uam",di[F.D.hg]="uap",di[F.D.ig]="uapv",di[F.D.jg]="uaw",di[F.D.gm]="ec_lat",di[F.D.hm]="ec_meta",di[F.D.im]="ec_m",di[F.D.jm]="ec_sel",di[F.D.km]="ec_s",di[F.D.Bc]="ec_mode",di[F.D.fb]="userId",di[F.D.kg]="us_privacy",di[F.D.Qa]="value",di[F.D.qm]="mcov",di[F.D.Wi]="hn",di[F.D.Vm]="gtm_ee",di[F.D.Yi]="uip",di[F.D.Jh]="mt",di[F.D.de]="npa",di[F.D.Yq]="sg_uc",di[F.D.yi]=
null,di[F.D.bd]=null,di[F.D.tb]=null,di[F.D.Ha]=null,di[F.D.za]=null,di[F.D.Ua]=null,di[F.D.Pe]=null,di[F.D.ed]=null,di[F.D.sh]=null,di[F.D.Bd]=null,di[F.D.Cd]=null,di[F.D.fh]=null,di[F.D.gh]=null,di[F.D.Ta]=null,di[F.D.Wc]=null,di);function fi(a,b){if(a){var c=a.split("x");c.length===2&&(gi(b,"u_w",c[0]),gi(b,"u_h",c[1]))}}function hi(a){var b=ii;b=b===void 0?ji:b;return ki(li(a,b))}function ki(a){return(a||[]).filter(function(b){return!!b}).map(function(b){return"("+[mi(b.value),mi(b.quantity),mi(b.item_id),mi(b.start_date),mi(b.end_date)].join("*")+")"}).join("")}
function li(a,b){return(a||[]).filter(function(c){return!!c}).map(function(c){return{item_id:b(c),quantity:c.quantity,value:c.price,start_date:c.start_date,end_date:c.end_date}})}function ji(a){return[a.item_id,a.id,a.item_name].find(function(b){return b!=null})}function ni(a){if(a&&a.length)return a.map(function(b){return b&&b.estimated_delivery_date?b.estimated_delivery_date:""}).join(",")}function gi(a,b,c){c===void 0||c===null||c===""&&!yg[b]||(a[b]=c)}
function mi(a){return typeof a!=="number"&&typeof a!=="string"?"":a.toString()};function oi(){this.blockSize=-1};function pi(a,b){this.blockSize=-1;this.blockSize=64;this.N=Ra.Uint8Array?new Uint8Array(this.blockSize):Array(this.blockSize);this.R=this.K=0;this.H=[];this.fa=a;this.Z=b;this.ja=Ra.Int32Array?new Int32Array(64):Array(64);qi===void 0&&(Ra.Int32Array?qi=new Int32Array(ri):qi=ri);this.reset()}Sa(pi,oi);for(var si=[],ti=0;ti<63;ti++)si[ti]=0;var ui=[].concat(128,si);
pi.prototype.reset=function(){this.R=this.K=0;var a;if(Ra.Int32Array)a=new Int32Array(this.Z);else{var b=this.Z,c=b.length;if(c>0){for(var d=Array(c),e=0;e<c;e++)d[e]=b[e];a=d}else a=[]}this.H=a};
var vi=function(a){for(var b=a.N,c=a.ja,d=0,e=0;e<b.length;)c[d++]=b[e]<<24|b[e+1]<<16|b[e+2]<<8|b[e+3],e=d*4;for(var f=16;f<64;f++){var g=c[f-15]|0,h=c[f-2]|0;c[f]=((c[f-16]|0)+((g>>>7|g<<25)^(g>>>18|g<<14)^g>>>3)|0)+((c[f-7]|0)+((h>>>17|h<<15)^(h>>>19|h<<13)^h>>>10)|0)|0}for(var l=a.H[0]|0,n=a.H[1]|0,p=a.H[2]|0,q=a.H[3]|0,r=a.H[4]|0,t=a.H[5]|0,u=a.H[6]|0,v=a.H[7]|0,x=0;x<64;x++){var y=((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+(l&n^l&p^n&p)|0,z=(v+((r>>>6|r<<26)^(r>>>11|r<<21)^(r>>>25|r<<7))|
0)+(((r&t^~r&u)+(qi[x]|0)|0)+(c[x]|0)|0)|0;v=u;u=t;t=r;r=q+z|0;q=p;p=n;n=l;l=z+y|0}a.H[0]=a.H[0]+l|0;a.H[1]=a.H[1]+n|0;a.H[2]=a.H[2]+p|0;a.H[3]=a.H[3]+q|0;a.H[4]=a.H[4]+r|0;a.H[5]=a.H[5]+t|0;a.H[6]=a.H[6]+u|0;a.H[7]=a.H[7]+v|0};
pi.prototype.update=function(a,b){b===void 0&&(b=a.length);var c=0,d=this.K;if(typeof a==="string")for(;c<b;)this.N[d++]=a.charCodeAt(c++),d==this.blockSize&&(vi(this),d=0);else{var e,f=typeof a;e=f!="object"?f:a?Array.isArray(a)?"array":f:"null";if(e=="array"||e=="object"&&typeof a.length=="number")for(;c<b;){var g=a[c++];if(!("number"==typeof g&&0<=g&&255>=g&&g==(g|0)))throw Error("message must be a byte array");this.N[d++]=g;d==this.blockSize&&(vi(this),d=0)}else throw Error("message must be string or array");
}this.K=d;this.R+=b};pi.prototype.digest=function(){var a=[],b=this.R*8;this.K<56?this.update(ui,56-this.K):this.update(ui,this.blockSize-(this.K-56));for(var c=63;c>=56;c--)this.N[c]=b&255,b/=256;vi(this);for(var d=0,e=0;e<this.fa;e++)for(var f=24;f>=0;f-=8)a[d++]=this.H[e]>>f&255;return a};
var ri=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,
4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],qi;function wi(){pi.call(this,8,xi)}Sa(wi,pi);var xi=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225];var yi=/^[0-9A-Fa-f]{64}$/;function zi(a){try{return(new TextEncoder).encode(a)}catch(b){return Zb(a)}}function Ai(a){var b=A;if(a===""||a==="e0")return Promise.resolve(a);var c;if((c=b.crypto)==null?0:c.subtle){if(yi.test(a))return Promise.resolve(a);try{var d=zi(a);return b.crypto.subtle.digest("SHA-256",d).then(function(e){return Bi(e,b)}).catch(function(){return"e2"})}catch(e){return Promise.resolve("e2")}}else return Promise.resolve("e1")}
function Ci(a){try{var b=new wi;b.update(zi(a));return b.digest()}catch(c){return"e2"}}function Di(a){var b=A;if(a===""||a==="e0"||yi.test(a))return a;var c=Ci(a);if(c==="e2")return"e2";try{return Bi(c,b)}catch(d){return"e2"}}function Bi(a,b){var c=Array.from(new Uint8Array(a)).map(function(d){return String.fromCharCode(d)}).join("");return b.btoa(c).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")};function Ei(){for(var a=!1,b=!1,c=0;a===b;)if(a=Db(0,1)===0,b=Db(0,1)===0,c++,c>30)return;return a}var Gi={sk:function(a,b,c){return Fi.sk(a,b,c)}},Hi=function(){this.studies={};this.H=Ei};
Hi.prototype.sk=function(a,b,c){var d=this.studies[b];if(!((c===void 0?Db(0,9999):c%1E4)<d.probability*(d.controlId2?4:2)*1E4))return a;a:{var e=d.studyId,f=d.experimentId,g=d.controlId,h=d.controlId2;if(!((a.exp||{})[f]||(a.exp||{})[g]||h&&(a.exp||{})[h])){var l=c!==void 0?c%2===0:this.H();if(l!==void 0){var n=l?0:1;if(h){var p=c!==void 0?(c>>1)%2===0:this.H();if(p===void 0)break a;n|=(p?0:1)<<1}n===0?Ii(a,f,e):n===1?Ii(a,g,e):n===2&&Ii(a,h,e)}}}return a};
var Ki=function(a,b){var c=Fi;return c.studies[b]?Ji(c,b)||!!(a.exp||{})[c.studies[b].experimentId]:!1},Li=function(a,b){var c=Fi;return c.studies[b]&&c.studies[b].controlId&&!Ji(c,b)?!!(a.exp||{})[c.studies[b].controlId]:!1},Mi=function(a,b){var c=Fi;return c.studies[b]&&c.studies[b].controlId2&&!Ji(c,b)?!!(a.exp||{})[c.studies[b].controlId2]:!1},Ni=function(a,b){for(var c=a.exp||{},d=m(Object.keys(c).map(Number)),e=d.next();!e.done;e=d.next()){var f=e.value;if(c[f]===b)return f}},Ji=function(a,
b){return!!a.studies[b].active||a.studies[b].probability>.5},Ii=function(a,b,c){var d=a.exp||{};d[b]=c;a.exp=d},Fi=new Hi;var ij=function(){this.H=A.google_tag_manager=A.google_tag_manager||{}},jj;function kj(a,b){lj();var c=jj;return c.H[a]=c.H[a]||b()}function mj(a){lj();return jj.H[a]}function nj(a,b){lj();jj.H[a]=b}function oj(a){var b=E(5);lj();var c=jj;c.H[b]=c.H[b]||a}function pj(){var a=E(19);lj();var b=jj;return b.H[a]=b.H[a]||{}}function qj(){var a=E(19);lj();return jj.H[a]}function rj(){lj();var a=jj,b=a.H.sequence||1;a.H.sequence=b+1;return b}function lj(){jj||(jj=new ij)};var sj=function(a){switch(a){case 1:return 0;case 491:return 12;case 480:return 11;case 499:return 10;case 500:return 6;case 421:return 9;case 561:return 17;case 482:return 15;case 570:return 19;case 495:return 13;case 514:return 16;case 573:return 18;case 235:return 8;case 53:return 1;case 54:return 2;case 52:return 4;case 75:return 3}},tj=function(a,b){a.N[b]=!0;var c=sj(b);c!==void 0&&(Wf[c]=!0)},M=function(a){return!!uj.N[a]},uj=new function(){this.N=[];this.K=[];this.H=[];
tj(this,132);var a=Nf(6,6E4);Xf[1]=a;var b=Nf(7,1);Xf[3]=b;var c=Nf(35,50);Xf[2]=c;var d=Nf(69,1776448920);Xf[4]=d;
tj(this,435);tj(this,141);
};var vj=function(){this.H=new Set;this.K=new Set},xj=function(a){var b=wj.H;a=a===void 0?[]:a;var c=[].concat(w(b.H)).concat([].concat(w(b.K))).concat(a);c.sort(function(d,e){return d-e});return c},yj=function(){var a=[].concat(w(wj.H.H));a.sort(function(b,c){return b-c});return a},zj=function(){var a=wj.H,b=E(44);a.H=new Set;if(b!=="")for(var c=m(b.split("~")),d=c.next();!d.done;d=c.next()){var e=Number(d.value);isNaN(e)||a.H.add(e)}};var Aj={},Bj={__cl:1,__ecl:1,__ehl:1,__evl:1,__fal:1,__fil:1,__fsl:1,__hl:1,__jel:1,__lcl:1,__sdl:1,__tl:1,__ytl:1},Cj=na(Object,"assign").call(Object,{},{__paused:1,__tg:1},Bj),Dj,Ej=!1;Dj=Ej;var Fj="";Aj.qj=Fj;var wj=new function(){this.H=new vj};var Gj=/:[0-9]+$/,Hj=/^\d+\.fls\.doubleclick\.net$/;function Ij(a,b,c,d){var e=Jj(a,!!d,b),f,g;return c?(g=e[b])!=null?g:[]:(f=e[b])==null?void 0:f[0]}function Jj(a,b,c){for(var d={},e=m(a.split("&")),f=e.next();!f.done;f=e.next()){var g=m(f.value.split("=")),h=g.next().value,l=ya(g),n=decodeURIComponent(h.replace(/\+/g," "));if(c===void 0||n===c){var p=l.join("=");d[n]||(d[n]=[]);d[n].push(b?p:decodeURIComponent(p.replace(/\+/g," ")))}}return d}
function Kj(a){try{return decodeURIComponent(a)}catch(b){}}function Lj(a,b,c,d,e){b&&(b=String(b).toLowerCase());if(b==="protocol"||b==="port")a.protocol=Mj(a.protocol)||Mj(A.location.protocol);b==="port"?a.port=String(Number(a.hostname?a.port:A.location.port)||(a.protocol==="http"?80:a.protocol==="https"?443:"")):b==="host"&&(a.hostname=(a.hostname||A.location.hostname).replace(Gj,"").toLowerCase());return Nj(a,b,c,d,e)}
function Nj(a,b,c,d,e){var f,g=Mj(a.protocol);b&&(b=String(b).toLowerCase());switch(b){case "url_no_fragment":f=Oj(a);break;case "protocol":f=g;break;case "host":f=a.hostname.replace(Gj,"").toLowerCase();if(c){var h=/^www\d*\./.exec(f);h&&h[0]&&(f=f.substring(h[0].length))}break;case "port":f=String(Number(a.port)||(g==="http"?80:g==="https"?443:""));break;case "path":a.pathname||a.hostname||sb("TAGGING",1);f=a.pathname.substring(0,1)==="/"?a.pathname:"/"+a.pathname;var l=f.split("/");(d||[]).indexOf(l[l.length-
1])>=0&&(l[l.length-1]="");f=l.join("/");break;case "query":f=a.search.replace("?","");e&&(f=Ij(f,e,!1));break;case "extension":var n=a.pathname.split(".");f=n.length>1?n[n.length-1]:"";f=f.split("/")[0];break;case "fragment":f=a.hash.replace("#","");break;default:f=a&&a.href}return f}function Mj(a){return a?a.replace(":","").toLowerCase():""}function Oj(a){var b="";if(a&&a.href){var c=a.href.indexOf("#");b=c<0?a.href:a.href.substring(0,c)}return b}var Pj={},Qj=0;
function Rj(a){var b=Pj[a];if(!b){var c=B.createElement("a");a&&(c.href=a);var d=c.pathname;d[0]!=="/"&&(a||sb("TAGGING",1),d="/"+d);var e=c.hostname.replace(Gj,"");b={href:c.href,protocol:c.protocol,host:c.host,hostname:e,pathname:d,search:c.search,hash:c.hash,port:c.port};Qj<5&&(Pj[a]=b,Qj++)}return b}function Sj(a,b,c){var d=Rj(a);return ac(b,d,c)}
function Tj(a){var b=Rj(A.location.href),c=Lj(b,"host",!1);if(c&&c.match(Hj)){var d=Lj(b,"path");if(d){var e=d.split(a+"=");if(e.length>1)return e[1].split(";")[0].split("?")[0]}}};var Uj={"https://www.google.com":"/g","https://www.googleadservices.com":"/as","https://pagead2.googlesyndication.com":"/gs"},Vj=["/as/d/ccm/conversion","/g/d/ccm/conversion","/gs/ccm/conversion","/d/ccm/form-data"];function Wj(){return If(47)?Jf(54)!==1:!1}function Xj(){var a=E(18),b=a.length;return a[b-1]==="/"?a.substring(0,b-1):a}
function Yj(a,b){if(a){var c=""+a;c.indexOf("http://")!==0&&c.indexOf("https://")!==0&&(c="https://"+c);c[c.length-1]==="/"&&(c=c.substring(0,c.length-1));return Rj(""+c+b).href}}function Zj(a){if(ak())return Yj(a,"/analytics.js")}function bk(a){return a===2||a===3}function ck(a){return M(588)&&a===3}function ak(){return Wj()||If(50)}function dk(){return!!Aj.qj&&Aj.qj.split("@@").join("")!=="SGTM_TOKEN"}
function ek(a){for(var b=m([F.D.dd,F.D.yc]),c=b.next();!c.done;c=b.next()){var d=O(a,c.value);if(d)return d}}function fk(a,b,c){c=c===void 0?"":c;if(!Wj())return a;var d=b?Uj[a]||"":"";d==="/gs"&&(c="");return""+Xj()+d+c}function gk(a){if(Wj())for(var b=m(Vj),c=b.next();!c.done;c=b.next()){var d=c.value;if(Sb(a,""+Xj()+d))return"::"}}
function hk(){var a=A;if(!a)return!1;try{if(a===a.top)return!1;var b=a.location.pathname;return b.indexOf("/_/service_worker/")!==-1&&Tb(b,"/sw_iframe.html")}catch(c){return!1}};var ik=/gtag[.\/]js/,jk=/gtm[.\/]js/,lk=function(a){var b=kk;if((a.scriptContainerId||"").indexOf("GTM-")>=0){var c;a:{var d,e=(d=a.scriptElement)==null?void 0:d.src;if(e){for(var f=If(47),g=Rj(e),h=f?g.pathname:""+g.hostname+g.pathname,l=B.scripts,n="",p=0;p<l.length;++p){var q=l[p];if(!(q.innerHTML.length===0||!f&&q.innerHTML.indexOf(a.scriptContainerId||"SHOULD_NOT_BE_SET")<0||q.innerHTML.indexOf(h)<0)){if(q.innerHTML.indexOf("(function(w,d,s,l,i)")>=0){c=String(p);break a}n=String(p)}}if(n){c=
n;break a}}c=void 0}var r=c;if(r)return b.H=!0,r}var t=[].slice.call(B.scripts);return a.scriptElement?String(t.indexOf(a.scriptElement)):"-1"},mk=function(a){if(kk.H)return"1";var b,c=(b=a.scriptElement)==null?void 0:b.src;if(c){if(ik.test(c))return"3";if(jk.test(c))return"2"}return"0"},kk=new function(){this.H=!1};function P(a){sb("GTM",a)};function nk(a){var b=ok().destinationArray[a],c=ok().destination[a];return b&&b.length>0?b[0]:c}function pk(a,b){var c=ok();c.pending||(c.pending=[]);Cb(c.pending,function(d){return d.target.ctid===a.ctid&&d.target.isDestination===a.isDestination})||c.pending.push({target:a,onLoad:b})}function qk(){var a=A.google_tags_first_party;Array.isArray(a)||(a=[]);for(var b={},c=m(a),d=c.next();!d.done;d=c.next())b[d.value]=!0;return Object.freeze(b)}
var rk=function(){this.container={};this.destination={};this.destinationArray={};this.canonical={};this.pending=[];this.injectedFirstPartyContainers={};this.injectedFirstPartyContainers=qk()};
function ok(){var a=Mc("google_tag_data",{}),b=a.tidr;b&&typeof b==="object"||(b=new rk,a.tidr=b);var c=b;c.container||(c.container={});c.destination||(c.destination={});c.destinationArray||(c.destinationArray={});c.canonical||(c.canonical={});c.pending||(c.pending=[]);c.injectedFirstPartyContainers||(c.injectedFirstPartyContainers=qk());return c};function sk(){return If(7)&&tk().some(function(a){return a===E(5)})}function uk(){var a;return(a=Kf(55))!=null?a:[]}function vk(){return E(6)||"_"+E(5)}function wk(){var a=E(10);return a?a.split("|"):[E(5)]}function tk(){var a=Kf(59);return Array.isArray(a)?a.filter(function(b){return typeof b==="string"}).filter(function(b){return b.indexOf("GTM-")!==0}):[]}function xk(){var a=yk(zk()),b=a&&a.parent;if(b)return yk(b)}
function Ak(){var a=yk(zk());if(a){for(;a.parent;){var b=yk(a.parent);if(!b)break;a=b}return a}}function yk(a){var b=ok();return a.isDestination?nk(a.ctid):b.container[a.ctid]}function Bk(){var a=ok();if(a.pending){for(var b,c=[],d=!1,e=wk(),f=tk(),g={},h=0;h<a.pending.length;g={Rg:void 0},h++)g.Rg=a.pending[h],Cb(g.Rg.target.isDestination?f:e,function(l){return function(n){return n===l.Rg.target.ctid}}(g))?d||(b=g.Rg.onLoad,d=!0):c.push(g.Rg);a.pending=c;if(b)try{b(vk())}catch(l){}}}
function Ck(){for(var a=E(5),b=wk(),c=tk(),d=uk(),e=function(q,r){var t={canonicalContainerId:E(6),scriptContainerId:a,state:2,containers:b.slice(),destinations:c.slice()};Jc&&(t.scriptElement=Jc);Kc&&(t.scriptSource=Kc);xk()===void 0&&(t.htmlLoadOrder=lk(t),t.loadScriptType=mk(t));var u,v;switch(r){case 0:u=function(z){f.container[q]=z};v=f.container[q];break;case 1:u=function(z){f.destinationArray[q]=f.destinationArray[q]||[];f.destinationArray[q].unshift(z)};var x,y=((x=f.destinationArray[q])==
null?void 0:x[0])||f.destination[q];!y||y.state!==0&&y.state!==1||(v=y);break;case 2:u=function(z){f.destinationArray[q]=f.destinationArray[q]||[];f.destinationArray[q].push(z)},v=void 0}u&&(v?(v.state===0&&P(93),na(Object,"assign").call(Object,v,t)):u(t))},f=ok(),g=m(b),h=g.next();!h.done;h=g.next())e(h.value,0);for(var l=m(c),n=l.next();!n.done;n=l.next()){var p=n.value;d.includes(p)?e(p,1):e(p,2)}f.canonical[vk()]={};Bk()}function Dk(){var a=vk();return!!ok().canonical[a]}
function Ek(a){return!!ok().container[a]}function Fk(){var a=zk(),b=yk(a);return b&&b.context}function Gk(a){var b=nk(a);return b?b.state!==0:!1}function zk(){return{ctid:E(5),isDestination:If(7)}}function Hk(a,b,c){var d=zk(),e=ok().container[a];e&&e.state!==3||(ok().container[a]={state:1,context:b,parent:d},pk({ctid:a,isDestination:!1},c))}function Ik(a,b,c){var d=ok(),e=nk(a);e?e.state=1:(e={context:b,state:1,parent:zk()},d.destinationArray[a]=[e]);pk({ctid:a,isDestination:!0},c)}
function Jk(a,b,c,d){var e=ok(),f=nk(a);f?f.state=0:(f={state:0,transportUrl:b,context:c,parent:zk()},e.destinationArray[a]=[f]);pk({ctid:a,isDestination:!0},d);P(91)}function Kk(){var a=ok().container,b;for(b in a)if(a.hasOwnProperty(b)&&a[b].state===1)return!0;return!1}function Lk(){var a={};Gb(ok().destination,function(b,c){(c==null?void 0:c.state)===0&&(a[b]=c)});Gb(ok().destinationArray,function(b,c){var d=c[0];(d==null?void 0:d.state)===0&&(a[b]=d)});return a}
function Mk(a){return!!(a&&a.parent&&a.context&&a.context.source===1&&a.parent.ctid.indexOf("GTM-")!==0)}function Nk(){for(var a=ok(),b=m(wk()),c=b.next();!c.done;c=b.next())if(a.injectedFirstPartyContainers[c.value])return!0;return!1};var Ok=function(){};Ok.prototype.toString=function(){return"undefined"};var Pk=new Ok;var Xk=function(){this.storage=Ya()};Xk.prototype.set=function(a,b){this.storage.set(String(a),b)};Xk.prototype.get=function(a){return this.storage.get(String(a))};var Yk;function Zk(a,b){Yk||(Yk=new Xk);Yk.set(a,b)}function $k(a){Yk||(Yk=new Xk);return Yk.get(a)}function al(a,b){Yk||(Yk=new Xk);var c=Yk;c.storage.has(String(a))||c.storage.set(String(a),b());return c.storage.get(String(a))};function bl(a,b){function c(g){var h=Rj(g),l=Lj(h,"protocol"),n=Lj(h,"host",!0),p=Lj(h,"port"),q=Lj(h,"path").toLowerCase().replace(/\/$/,"");if(l===void 0||l==="http"&&p==="80"||l==="https"&&p==="443")l="web",p="default";return[l,n,p,q]}for(var d=c(String(a)),e=c(String(b)),f=0;f<d.length;f++)if(d[f]!==e[f])return!1;return!0}function cl(a){return dl(a)?1:0}
function dl(a){var b=a.arg0,c=a.arg1;if(a.any_of&&Array.isArray(c)){for(var d=0;d<c.length;d++){var e=Ed(a,{});Ed({arg1:c[d],any_of:void 0},e);if(cl(e))return!0}return!1}switch(a["function"]){case "_cn":return Kg(b,c);case "_css":return Gg(b,c);case "_ew":return Hg(b,c);case "_eq":return Lg(b,c);case "_ge":return Mg(b,c);case "_gt":return Og(b,c);case "_lc":return Ig(b,c);case "_le":return Ng(b,c);case "_lt":return Pg(b,c);case "_re":return Jg(b,c,a.ignore_case,al(3,function(){return new Map}));case "_sw":return Qg(b,
c);case "_um":return bl(b,c)}return!1};function el(a,b,c,d,e){if(Array.isArray(a)){var f;switch(a[0]){case "function_id":return a[1];case "list":f=[];for(var g=1;g<a.length;g++)f.push(el(a[g],b,c,d,e));return f;case "macro":var h=d[a[1]];return h?h.evaluate(b,e):void 0;case "map":f={};for(var l=1;l<a.length;l+=2)f[el(a[l],b,c,d,e)]=el(a[l+1],b,c,d,e);return f;case "template":f=[];for(var n=!1,p=1;p<a.length;p++){var q=el(a[p],b,c,d,e);f.push(q)}return f.join("");case "escape":f=el(a[1],b,c,d,e);f=String(f);for(var y=2;y<a.length;y++)Ui[a[y]]&&(f=Ui[a[y]](f));return f;case "tag":var z=a[1];if(!c[z])throw Error("Unable to resolve tag reference "+
z+".");return{bo:a[2],index:z};case "zb":var C={},D=(C[Gf.Yb]=a[1],C.arg0=el(a[2],b,c,d,e),C.arg1=el(a[3],b,c,d,e),C.ignore_case=el(a[5],b,c,d,e),C),I=cl(D),G=!!a[4];return G||I!==2?G!==(I===1):null;default:throw Error("Attempting to expand unknown Value type: "+a[0]+".");}}return a};function fl(a){return a&&a.indexOf("pending:")===0?gl(a.substr(8)):!1}function gl(a){if(a==null||a.length===0)return!1;var b=Number(a),c=Nb();return b<c+3E5&&b>c-9E5};var hl=!1,il=!1,jl=!1,kl=0,ll=!1,ml=void 0,nl=[];function ol(a){if(kl===0)ll&&nl&&(nl.length>=100&&nl.shift(),nl.push(a));else if(pl()){var b=E(41),c=Mc(b,[]);c.length>=50&&c.shift();c.push(a)}}function ql(){il||(rl(),sl(kl))}function sl(a){if(!il||kl===2&&a===1)if(il=!0,jl&&(ad(B,"TAProdDebugSignal",ql),jl=!1),ml!==void 0&&(A.clearTimeout(ml),ml=void 0),kl=a,a===1){var b=nl;nl=void 0;b==null||b.forEach(function(c){ol(c)})}}
function rl(){var a=B.documentElement.getAttribute("data-tag-assistant-prod-present");gl(a)?kl=1:!fl(a)||hl||jl?kl=2:(jl=!0,$c(B,"TAProdDebugSignal",ql,!1),ml=A.setTimeout(function(){il||(rl(),sl(kl));hl=!0},200))}function pl(){if(!ll)return!1;switch(kl){case 1:case 0:return!0;case 2:return!1;default:return!1}};function tl(){var a=Mc("google_tag_data",{});return a.ics=a.ics||new ul}var ul=function(){this.entries={};this.waitPeriodTimedOut=this.wasSetLate=this.accessedAny=this.accessedDefault=this.usedImplicit=this.usedUpdate=this.usedDefault=this.usedDeclare=this.active=!1;this.H=[]};
ul.prototype.default=function(a,b,c,d,e,f,g){this.usedDefault||this.usedDeclare||!this.accessedDefault&&!this.accessedAny||(this.wasSetLate=!0);this.usedDefault=this.active=!0;sb("TAGGING",19);b==null?sb("TAGGING",18):vl(this,a,b==="granted",c,d,e,f,g)};ul.prototype.waitForUpdate=function(a,b,c){for(var d=0;d<a.length;d++)vl(this,a[d],void 0,void 0,"","",b,c)};
var vl=function(a,b,c,d,e,f,g,h){var l=a.entries,n=l[b]||{},p=n.region,q=d&&zb(d)?d.toUpperCase():void 0;e=e.toUpperCase();f=f.toUpperCase();if(e===""||q===f||(q===e?p!==f:!q&&!p)){var r=!!(g&&g>0&&n.update===void 0),t={region:q,declare_region:n.declare_region,implicit:n.implicit,default:c!==void 0?c:n.default,declare:n.declare,update:n.update,quiet:r};if(e!==""||n.default!==!1)l[b]=t;r&&A.setTimeout(function(){l[b]===t&&t.quiet&&(sb("TAGGING",2),a.waitPeriodTimedOut=!0,a.clearTimeout(b,void 0,h),
a.notifyListeners())},g)}};k=ul.prototype;k.clearTimeout=function(a,b,c){var d=[a],e=c.delegatedConsentTypes,f;for(f in e)e.hasOwnProperty(f)&&e[f]===a&&d.push(f);var g=this.entries[a]||{},h=this.getConsentState(a,c);if(g.quiet){g.quiet=!1;for(var l=m(d),n=l.next();!n.done;n=l.next())wl(this,n.value)}else if(b!==void 0&&h!==b)for(var p=m(d),q=p.next();!q.done;q=p.next())wl(this,q.value)};
k.update=function(a,b,c){this.usedDefault||this.usedDeclare||this.usedUpdate||!this.accessedAny||(this.wasSetLate=!0);this.usedUpdate=this.active=!0;if(b!=null){var d=this.getConsentState(a,c),e=this.entries;(e[a]=e[a]||{}).update=b==="granted";this.clearTimeout(a,d,c)}};
k.declare=function(a,b,c,d,e){this.usedDeclare=this.active=!0;var f=this.entries,g=f[a]||{},h=g.declare_region,l=c&&zb(c)?c.toUpperCase():void 0;d=d.toUpperCase();e=e.toUpperCase();if(d===""||l===e||(l===d?h!==e:!l&&!h)){var n={region:g.region,declare_region:l,declare:b==="granted",implicit:g.implicit,default:g.default,update:g.update,quiet:g.quiet};if(d!==""||g.declare!==!1)f[a]=n}};
k.implicit=function(a,b){this.usedImplicit=!0;var c=this.entries,d=c[a]=c[a]||{};d.implicit!==!1&&(d.implicit=b==="granted")};
k.getConsentState=function(a,b){var c=this.entries,d=c[a]||{},e=d.update;if(e!==void 0)return e?1:2;if(b.usedContainerScopedDefaults){var f=b.containerScopedDefaults[a];if(f===3)return 1;if(f===2)return 2}else if(e=d.default,e!==void 0)return e?1:2;if(b==null?0:b.delegatedConsentTypes.hasOwnProperty(a)){var g=b.delegatedConsentTypes[a],h=c[g]||{};e=h.update;if(e!==void 0)return e?1:2;if(b.usedContainerScopedDefaults){var l=b.containerScopedDefaults[g];if(l===3)return 1;if(l===2)return 2}else if(e=
h.default,e!==void 0)return e?1:2}e=d.declare;if(e!==void 0)return e?1:2;e=d.implicit;return e!==void 0?e?3:4:0};k.addListener=function(a,b){this.H.push({consentTypes:a,ie:b})};var wl=function(a,b){for(var c=0;c<a.H.length;++c){var d=a.H[c];Array.isArray(d.consentTypes)&&d.consentTypes.indexOf(b)!==-1&&(d.xo=!0)}};ul.prototype.notifyListeners=function(a,b){for(var c=0;c<this.H.length;++c){var d=this.H[c];if(d.xo){d.xo=!1;try{d.ie({consentEventId:a,consentPriorityId:b})}catch(e){}}}};var xl=!1,yl=!1,zl={},Al={delegatedConsentTypes:{},corePlatformServices:{},usedCorePlatformServices:!1,selectedAllCorePlatformServices:!1,containerScopedDefaults:(zl.ad_storage=1,zl.analytics_storage=1,zl.ad_user_data=1,zl.ad_personalization=1,zl),usedContainerScopedDefaults:!1};function Bl(a){var b=tl();b.accessedAny=!0;return(zb(a)?[a]:a).every(function(c){switch(b.getConsentState(c,Al)){case 1:case 3:return!0;case 2:case 4:return!1;default:return!0}})}
function Cl(a){var b=tl();b.accessedAny=!0;return b.getConsentState(a,Al)}function Dl(a){var b=tl();b.accessedAny=!0;return!(b.entries[a]||{}).quiet}function El(){if(!Yf(5))return!1;var a=tl();a.accessedAny=!0;if(a.active)return!0;if(!Al.usedContainerScopedDefaults)return!1;for(var b=m(Object.keys(Al.containerScopedDefaults)),c=b.next();!c.done;c=b.next())if(Al.containerScopedDefaults[c.value]!==1)return!0;return!1}function Fl(a,b){tl().addListener(a,b)}
function Gl(a,b){tl().notifyListeners(a,b)}function Hl(a,b){if(b.every(Dl))a({});else{var c=!1;Fl(b,function(d){!c&&b.every(Dl)&&(c=!0,a(d))})}}
function Il(a,b){var c=zb(b)?[b]:b,d={},e=function(){return c.filter(function(h){return Bl(h)&&!d[h]})},f=e();if(f.length!==c.length){var g=function(h){for(var l=m(h),n=l.next();!n.done;n=l.next())d[n.value]=!0};g(f);Fl(c,function(h){function l(q){q.length!==0&&(g(q),h.consentTypes=q,a(h))}var n=e();if(n.length!==0){var p=Object.keys(d).length;n.length+p>=c.length?l(n):A.setTimeout(function(){l(e())},500)}})}};var Jl=!1;function Kl(a,b){var c=wk(),d=tk();E(26);var e=If(47)?0:If(50)?1:3,f=Xj();if(pl()){var g=Ll("INIT");g.containerLoadSource=a!=null?a:0;b&&(g.parentTargetReference=b);g.aliases=c;g.destinations=d;e!==void 0&&(g.gtg={source:e,mPath:f!=null?f:""});ol(g)}}
function Ml(a){var b,c,d,e;b=a.targetId;c=a.request;d=a.qb;e=a.isBatched;var f;if(f=pl()){var g;a:switch(c.endpoint){case 68:case 69:case 19:case 62:case 47:g=!0;break a;default:g=!1}f=!g}if(f){var h=Ll("GTAG_HIT",{eventId:d.eventId,priorityId:d.priorityId});h.target=b;h.url=c.url;c.postBody&&(h.postBody=c.postBody);h.parameterEncoding=c.parameterEncoding;h.endpoint=c.endpoint;e!==void 0&&(h.isBatched=e);ol(h)}}function Nl(a){pl()&&Ml(a())}
function Ll(a,b){b=b===void 0?{}:b;b.groupId=Ol;var c,d=b,e=Pl,f={publicId:Ql};d.eventId!=null&&(f.eventId=d.eventId);d.priorityId!=null&&(f.priorityId=d.priorityId);d.eventName&&(f.eventName=d.eventName);d.groupId&&(f.groupId=d.groupId);d.tagName&&(f.tagName=d.tagName);c={containerProduct:"GTM",key:f,version:e,messageType:a};c.containerProduct=Jl?"OGT":"GTM";c.key.targetRef=Rl;return c}var Ql="",Pl="",Rl={ctid:"",isDestination:!1},Ol;
function Sl(a){var b=E(5),c=If(45),d=sk(),e=E(6),f=E(1);E(23);kl=0;ll=!0;rl();Ol=a;Ql=b;Pl=f;Jl=c;Rl={ctid:b,isDestination:d,canonicalId:e}};function Tl(a,b,c,d){if(pl()){var e=b.M;Ml({targetId:d||[b.target.destinationId],request:{url:a,parameterEncoding:2,endpoint:c},qb:{eventId:e.eventId,priorityId:e.priorityId},Fj:{eventId:Q(b,H.J.uf),priorityId:Q(b,H.J.vf)}})}};function Ul(a,b,c){var d="https://"+a+b;return c?function(){return Wj()?Xj()+c+b:d}:function(){return d}};var Vl={},Wl=(Vl[22]=Ul("www.googleadservices.com","/ccm/conversion","/as/d"),Vl[60]=Ul("pagead2.googlesyndication.com","/ccm/conversion","/gs"),Vl[23]=Ul("www.google.com","/ccm/conversion","/g/d"),Vl);var Xl={},Yl=(Xl[5]=Ul("www.googleadservices.com","/pagead/conversion"),Xl[6]=Ul("pagead2.googlesyndication.com","/pagead/conversion","/gs"),Xl[8]=Ul("www.google.com","/pagead/1p-conversion"),Xl[66]=Ul("www.google.com","/pagead/uconversion"),Xl[63]=Ul("www.googleadservices.com","/pagead/conversion"),Xl[64]=Ul("pagead2.googlesyndication.com","/pagead/conversion","/gs"),Xl[65]=Ul("www.google.com","/pagead/1p-conversion"),Xl[74]=function(){return Xj()+"/as/p/c"},Xl);var Zl={},$l=(Zl[45]=Ul("www.google.com","/ccm/collect"),Zl[46]=Ul("pagead2.googlesyndication.com","/ccm/collect","/gs"),Zl[69]=Ul("ad.doubleclick.net","/ccm/s/collect"),Zl[58]=Ul("www.google.com","/pagead/set_partitioned_cookie"),Zl[57]=Ul("www.googleadservices.com","/pagead/set_partitioned_cookie"),Zl);var am={},bm=(am[9]=Ul("googleads.g.doubleclick.net","/pagead/viewthroughconversion"),am[68]=Ul("www.google.com","/rmkt/collect"),am);var cm={},dm=(cm[11]=Ul("www.google.com","/pagead/form-data","/d"),cm[21]=Ul("www.google.com","/ccm/form-data","/d"),cm[72]=Ul("google.com","/pagead/form-data","/d"),cm[73]=Ul("google.com","/ccm/form-data","/d"),cm);var em={},fm=(em[51]=Ul("www.google.com","/travel/flights/click/conversion"),em);var gm={},hm=(gm[1]=function(){return"https://ad.doubleclick.net/activity;"},gm[2]=function(){return(Wj()?Xj():"https://ade.googlesyndication.com")+"/ddm/activity"+(M(467)?";":"/")},gm[3]=function(a){return"https://"+a.lr+".fls.doubleclick.net/activityi;"},gm);function im(a){sb("HEALTH",a)};var jm={ba:{Pt:"aw_user_data_cache",oi:"cookie_deprecation_label",bh:"diagnostics_page_id",op:"ememo",du:"em_registry",Si:"eab",ru:"fl_user_data_cache",tu:"ga4_user_data_cache",Lu:"idc_pv_claim",Se:"ip_geo_data_cache",Xi:"ip_geo_fetch_in_progress",jn:"nb_data",Tq:"page_experiment_ids",ln:"pld",Ve:"pt_data",mn:"pt_listener_set",kj:"retry_containers",Oh:"service_worker_endpoint",Zq:"shared_user_id",ar:"shared_user_id_requested",sj:"shared_user_id_source",bv:"awh",hr:"universal_claim_registry"}};var km=function(a){return tf(function(b){for(var c in a)if(b===a[c]&&!/^[0-9]+$/.test(c))return!0;return!1})}(jm.ba);
function lm(a,b){b=b===void 0?!1:b;if(km(a)){var c,d,e=(d=(c=Mc("google_tag_data",{})).xcd)!=null?d:c.xcd={};if(e[a])return e[a];if(b){var f=void 0,g=1,h={},l={set:function(n){f=n;l.notify()},get:function(){return f},subscribe:function(n){h[String(g)]=n;return g++},unsubscribe:function(n){var p=String(n);return h.hasOwnProperty(p)?(delete h[p],!0):!1},notify:function(){for(var n=m(Object.keys(h)),p=n.next();!p.done;p=n.next()){var q=p.value;try{h[q](a,f)}catch(r){}}}};return e[a]=l}}}
function mm(a,b){var c=lm(a,!0);c&&c.set(b)}function nm(a){var b;return(b=lm(a))==null?void 0:b.get()}function om(a,b){var c=lm(a);if(!c){c=lm(a,!0);if(!c)return;c.set(b)}return c.get()}function pm(a,b){if(typeof b==="function"){var c;return(c=lm(a,!0))==null?void 0:c.subscribe(b)}}function qm(a,b){var c=lm(a);return c?c.unsubscribe(b):!1};var sm=function(){this.H={};this.K=!1};sm.prototype.bind=function(){this.K||(this.H=tm(),this.H["0"]&&om(jm.ba.Se,JSON.stringify(this.H)))};
var xm=function(){var a=um,b=vm,c=void 0,d=function(){c!==void 0&&qm(jm.ba.Se,c);try{var f=nm(jm.ba.Se);b.H=JSON.parse(f)}catch(g){P(123),im(2),b.H={}}b.K=!0;a()},e=nm(jm.ba.Se);e?d(e):(c=pm(jm.ba.Se,d),wm())},wm=function(){if(!nm(jm.ba.Xi)){mm(jm.ba.Xi,!0);var a=function(b){mm(jm.ba.Se,b||"{}");mm(jm.ba.Xi,!1)};try{A.fetch("https://www.google.com/ccm/geo",{method:"GET",cache:"no-store",mode:"cors",credentials:"omit"}).then(function(b){b.ok?b.text().then(function(c){a(c)},function(){a()}):a()},function(){a()})}catch(b){a()}}},
tm=function(){var a=E(22);try{return JSON.parse(qb(a))}catch(b){return P(123),im(2),{}}},ym=function(){return vm.H["0"]||""},zm=function(){return vm.H["1"]||""},Am=function(){var a=vm,b=!1;return b},Bm=function(){return vm.H["6"]!==!1},Cm=function(){var a=vm,b=!1;return b},Dm=function(){var a=vm,b="";
return b},Em=function(){var a=vm,b="";return b},vm=new sm;function Fm(a){a=a===void 0?"g/collect":a;return"https://"+(Dm()||"www")+".google-analytics.com/"+a}function Gm(a){a=a===void 0?"g/collect":a;var b=Dm();return"https://"+(b?b+".":"")+"analytics.google.com/"+a}var Hm={},Im=(Hm[17]=function(){return Wj()&&!Dm()?Xj()+"/ag/g/c":Gm()},Hm[16]=function(){return Wj()&&!Dm()?Xj()+"/ga/g/c":Fm()},Hm[67]=function(){var a;a=a===void 0?"g/collect":a;return Dm()?"":"https://www.google.com/"+a},Hm);function Jm(a,b,c){var d=Ul(b,"/measurement/conversion",c);return function(){return Dm()?a("measurement/conversion"):d()}}var Km={},Lm=(Km[55]=Jm(Fm,"pagead2.googlesyndication.com","/gs"),Km[54]=Jm(Gm,"www.google.com","/g"),Km);var Mm=na(Object,"assign").call(Object,{},Wl,Yl,$l,bm,dm,fm,hm,Lm,Im);function Nm(a,b){var c=Object.keys(b).filter(function(d){return b[d]!=null}).map(function(d){return d+"="+b[d]}).join("&");return Mm[a](void 0)+"?"+c};var Om={},Pm=(Om.tdp=1,Om.exp=1,Om.gtm=1,Om.pid=1,Om.dl=1,Om.seq=1,Om.t=1,Om.v=1,Om),Rm=function(){var a=Qm;return Object.keys(a.H).filter(function(b){return a.H[b]})},Sm=function(a,b,c){if(a.H[b]===void 0||(c===void 0?0:c))a.H[b]=!0},Tm=function(a){a.forEach(function(b){Pm[b]||(Qm.H[b]=!1)})},Qm=new function(){this.H={};this.K={}};function Um(a,b,c){var d=c===void 0?!0:c,e=Qm;e.K[a]=b;(d===void 0||d)&&Sm(e,a)}function Vm(a,b){Sm(Qm,a,b===void 0?!1:b)};function Wm(a){var b=0;a.Gc.forEach(function(c){b|=1<<c});return b}function Xm(){return{total:0,jb:0,Gc:new Set,lf:{}}}function Ym(a,b,c,d){var e=Object.keys(a.nf).sort(function(f,g){return Number(f)-Number(g)}).map(function(f){return[f,b(a.nf[f])]}).filter(function(f){return f[1]!==void 0}).map(function(f){return f.join(c)}).join(d);return e?e:void 0}
function Zm(a,b){var c,d,e;c=c===void 0?"_":c;d=d===void 0?";":d;e=e===void 0?"~":e;for(var f=[],g=m(Object.keys(a.lf).sort()),h=g.next();!h.done;h=g.next()){var l=h.value,n=Ym(a.lf[l],b,c,d);if(n){var p=void 0;f.push(""+((p=l)!=null?p:"")+d+n)}}return f.length?f.join(e):void 0}
function $m(a){a.jb=0;a.Gc.clear();for(var b=m(Object.keys(a.lf)),c=b.next();!c.done;c=b.next()){var d=a.lf[c.value];d.jb=0;d.Gc.clear();for(var e=m(Object.keys(d.nf)),f=e.next();!f.done;f=e.next()){var g=d.nf[f.value];g.jb=0;g.Gc.clear()}}}
function an(a,b,c,d,e){d=d===void 0?1:d;a.total+=d;a.jb+=d;var f,g=b===void 0?"":b;f=a.lf[g]||(a.lf[g]={total:0,jb:0,Gc:new Set,nf:{}});f.total+=d;f.jb+=d;var h,l=String(c);h=f.nf[l]||(f.nf[l]={total:0,jb:0,Gc:new Set});h.total+=d;h.jb+=d;e!==void 0&&(a.Gc.add(e),f.Gc.add(e),h.Gc.add(e))};var bn=function(){this.H=Xm()};bn.prototype.increment=function(a,b){an(this.H,a,b)};var cn=new bn;function dn(a){var b=String(a[Gf.Yb]||"").replace(/_/g,"");return Sb(b,"cvt")?"cvt":b}var en=A.location.search.indexOf("?gtm_latency=")>=0||A.location.search.indexOf("&gtm_latency=")>=0;var gn=function(){var a=fn;return M(603)&&If(65,!1)&&!a.Z},fn=new function(a){this.R=a();var b=Jf(27);this.N=en||this.R<b;var c=Jf(42);this.Z=en||this.R>=1-c;var d=M(603)&&If(65,!1);this.K=this.Z||d;var e=Jf(27),f=Jf(63);this.H=en||f===1||this.R>=e&&this.R<e+f}(function(){return Math.random()});var hn=function(){this.H={}};hn.prototype.register=function(a,b,c){if(fn.K){var d=jn(b,c);if(d){var e,f=b;f===4&&(f=5);var g=this.H[f];g||(g=this.H[f]={});e=g;var h=e[d];h||(h=e[d]=[]);h.push(na(Object,"assign").call(Object,{},a));cn.increment(a.destinationId,a.endpoint);a.endpoint!==56&&a.endpoint!==61&&Vm("mde",!0)}}};
var mn=function(a,b){var c=kn,d=jn(a,b);if(d){var e=ln(c,a);if(e){var f=e[d];f&&(e[d]=f.filter(function(g){return!g.Eo}))}}},ln=function(a,b){b===4&&(b=5);return a.H[b]},jn=function(a,b){var c=b;if(b[0]==="/"){var d;c=((d=A.location)==null?void 0:d.origin)+b}try{var e=new URL(c);return a===2?e.origin:e.origin+e.pathname}catch(f){}},kn=new hn;
function nn(a){switch(a){case "script-src":return 4;case "script-src-elem":return 5;case "frame-src":return 2;case "connect-src":return 1;case "img-src":return 3}};function on(a,b,c){var d,e=a.GooglebQhCsO;e||(e={},a.GooglebQhCsO=e);d=e;if(d[b])return!1;d[b]=[];d[b][0]=c;return!0};var pn,qn;a:{for(var rn=["CLOSURE_FLAGS"],sn=Ra,tn=0;tn<rn.length;tn++)if(sn=sn[rn[tn]],sn==null){qn=null;break a}qn=sn}var un=qn&&qn[610401301];pn=un!=null?un:!1;function vn(){var a=Ra.navigator;if(a){var b=a.userAgent;if(b)return b}return""}var wn,xn=Ra.navigator;wn=xn?xn.userAgentData||null:null;function yn(a){if(!pn||!wn)return!1;for(var b=0;b<wn.brands.length;b++){var c=wn.brands[b].brand;if(c&&c.indexOf(a)!=-1)return!0}return!1}function zn(a){return vn().indexOf(a)!=-1};function An(){return pn?!!wn&&wn.brands.length>0:!1}function Bn(){return An()?!1:zn("Opera")}function Cn(){return zn("Firefox")||zn("FxiOS")}function Dn(){return An()?yn("Chromium"):(zn("Chrome")||zn("CriOS"))&&!(An()?0:zn("Edge"))||zn("Silk")};function En(){return pn?!!wn&&!!wn.platform:!1}function Fn(){return zn("iPhone")&&!zn("iPod")&&!zn("iPad")}function Gn(){Fn()||zn("iPad")||zn("iPod")};var Hn=function(a){Hn[" "](a);return a};Hn[" "]=function(){};Bn();An()||zn("Trident")||zn("MSIE");zn("Edge");!zn("Gecko")||vn().toLowerCase().indexOf("webkit")!=-1&&!zn("Edge")||zn("Trident")||zn("MSIE")||zn("Edge");vn().toLowerCase().indexOf("webkit")!=-1&&!zn("Edge")&&zn("Mobile");En()||zn("Macintosh");En()||zn("Windows");(En()?wn.platform==="Linux":zn("Linux"))||En()||zn("CrOS");En()||zn("Android");Fn();zn("iPad");zn("iPod");Gn();vn().toLowerCase().indexOf("kaios");Cn();Fn()||zn("iPod");zn("iPad");!zn("Android")||Dn()||Cn()||Bn()||zn("Silk");Dn();!zn("Safari")||Dn()||(An()?0:zn("Coast"))||Bn()||(An()?0:zn("Edge"))||(An()?yn("Microsoft Edge"):zn("Edg/"))||(An()?yn("Opera"):zn("OPR"))||Cn()||zn("Silk")||zn("Android")||Gn();var In={},Jn=null;
function Kn(a){for(var b=[],c=0,d=0;d<a.length;d++){var e=a.charCodeAt(d);e>255&&(b[c++]=e&255,e>>=8);b[c++]=e}var f=4;f===void 0&&(f=0);if(!Jn){Jn={};for(var g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),h=["+/=","+/","-_=","-_.","-_"],l=0;l<5;l++){var n=g.concat(h[l].split(""));In[l]=n;for(var p=0;p<n.length;p++){var q=n[p];Jn[q]===void 0&&(Jn[q]=p)}}}for(var r=In[f],t=Array(Math.floor(b.length/3)),u=r[64]||"",v=0,x=0;v<b.length-2;v+=3){var y=b[v],z=b[v+1],C=b[v+2],
D=r[y>>2],I=r[(y&3)<<4|z>>4],G=r[(z&15)<<2|C>>6],N=r[C&63];t[x++]=""+D+I+G+N}var S=0,W=u;switch(b.length-v){case 2:S=b[v+1],W=r[(S&15)<<2]||u;case 1:var ea=b[v];t[x]=""+r[ea>>2]+r[(ea&3)<<4|S>>4]+W+u}return t.join("")};var Ln=function(a){return decodeURIComponent(a.replace(/\+/g," "))};var Mn=RegExp("^(?:([^:/?#.]+):)?(?://(?:([^\\\\/?#]*)@)?([^\\\\/?#]*?)(?::([0-9]+))?(?=[\\\\/?#]|$))?([^?#]+)?(?:\\?([^#]*))?(?:#([\\s\\S]*))?$");function Nn(a,b,c,d){for(var e=b,f=c.length;(e=a.indexOf(c,e))>=0&&e<d;){var g=a.charCodeAt(e-1);if(g==38||g==63){var h=a.charCodeAt(e+f);if(!h||h==61||h==38||h==35)return e}e+=f+1}return-1}var On=/#|$/;
function Pn(a,b){var c=a.search(On),d=Nn(a,0,b,c);if(d<0)return null;var e=a.indexOf("&",d);if(e<0||e>c)e=c;d+=b.length+1;return Ln(a.slice(d,e!==-1?e:0))}var Qn=/[?&]($|#)/;
function Rn(a,b,c){for(var d,e=a.search(On),f=0,g,h=[];(g=Nn(a,f,b,e))>=0;)h.push(a.substring(f,g)),f=Math.min(a.indexOf("&",g)+1||e,e);h.push(a.slice(f));d=h.join("").replace(Qn,"$1");var l,n=c!=null?"="+encodeURIComponent(String(c)):"";var p=b+n;if(p){var q,r=d.indexOf("#");r<0&&(r=d.length);var t=d.indexOf("?"),u;t<0||t>r?(t=r,u=""):u=d.substring(t+1,r);q=[d.slice(0,t),u,d.slice(r)];var v=q[1];q[1]=p?v?v+"&"+p:p:v;l=q[0]+(q[1]?"?"+q[1]:"")+q[2]}else l=d;return l};function Sn(a,b,c,d,e,f,g,h){var l=Pn(c,"fmt");if(d){var n=Pn(c,"random"),p=Pn(c,"label")||"";if(!n)return;var q=Kn(Ln(p)+":"+Ln(n));if(!on(a,q,d))return}l&&Number(l)!==4?(c=Rn(c,"rfmt",l),c=Rn(c,"fmt",4)):l||(c=Rn(c,"fmt",4));Uc(c,function(){g==null||Tn(g);h==null||Un(h,c);a.google_noFurtherRedirects&&d&&(a.google_noFurtherRedirects=null,d())},function(){g==null||Tn(g);h==null||Un(h,c);e==null||e()},f,b.getElementsByTagName("script")[0].parentElement||void 0);return c};function Vn(a){var b=Oa.apply(1,arguments);kn.register(a,1,b[0]);id.apply(null,w(b))}function Wn(a){var b=Oa.apply(1,arguments);kn.register(a,1,b[0]);return jd.apply(null,w(b))}function Xn(a){var b=Oa.apply(1,arguments);kn.register(a,3,b[0]);Zc.apply(null,w(b))}function Yn(a){var b=Oa.apply(1,arguments);kn.register(a,1,b[0]);return md.apply(null,w(b))}function Zn(a){var b=Oa.apply(1,arguments);kn.register(a,5,b[0]);Uc.apply(null,w(b))}
function $n(a){var b=Oa.apply(1,arguments);b[0]&&kn.register(a,2,b[0]);Xc.apply(null,w(b))}function ao(a){var b=Sn.apply(null,w(Oa.apply(1,arguments)));b&&kn.register(a,4,b);return b};var bo={Ma:{Re:0,Ue:1,Lh:2}};bo.Ma[bo.Ma.Re]="FULL_TRANSMISSION";bo.Ma[bo.Ma.Ue]="LIMITED_TRANSMISSION";bo.Ma[bo.Ma.Lh]="NO_TRANSMISSION";var co={ia:{gd:0,cb:1,xd:2,Zb:3}};co.ia[co.ia.gd]="NO_QUEUE";co.ia[co.ia.cb]="ADS";co.ia[co.ia.xd]="ANALYTICS";co.ia[co.ia.Zb]="MONITORING";var eo=function(a,b){this.H=a;this.consentTypes=b};eo.prototype.isConsentGranted=function(){switch(this.H){case 0:return this.consentTypes.every(function(a){return Bl(a)});case 1:return this.consentTypes.some(function(a){return Bl(a)});default:yc(this.H,"consentsRequired had an unknown type")}};
var fo=new function(){var a={};this.H=(a[co.ia.gd]=bo.Ma.Re,a[co.ia.cb]=bo.Ma.Re,a[co.ia.xd]=bo.Ma.Re,a[co.ia.Zb]=bo.Ma.Re,a);var b={};this.K=(b[co.ia.gd]=new eo(0,[]),b[co.ia.cb]=new eo(0,["ad_storage"]),b[co.ia.xd]=new eo(0,["analytics_storage"]),b[co.ia.Zb]=new eo(1,["ad_storage","analytics_storage"]),b)};var ho=function(a){var b=this;this.type=a;this.H=[];Fl(fo.K[a].consentTypes,function(){go(b)||b.flush()})};ho.prototype.flush=function(){for(var a=m(this.H),b=a.next();!b.done;b=a.next()){var c=b.value;c()}this.H=[]};var go=function(a){return fo.H[a.type]===bo.Ma.Lh&&!fo.K[a.type].isConsentGranted()},io=function(a,b){go(a)?a.H.push(b):b()},jo=function(){this.H=new Map},lo=function(a){var b=ko;b.H.has(a)||b.H.set(a,new ho(a));return b.H.get(a)};jo.prototype.reset=function(){this.H.clear()};
var ko=new jo;var mo=["fin","fs","mcc","ncc"],no=function(a){a=a===void 0?!1:a;var b=Rm(),c=Qm.K,d=b.filter(function(e){return c[e]!==void 0&&(a||!mo.includes(e))});Tm(d);return d.map(function(e){var f=c[e];typeof f==="function"&&(f=f());return f?"&"+e+"="+f:""}).join("")+"&z=0"},oo=function(a){var b="https://"+E(21),c="/td?id="+E(5);return""+fk(b)+c+a},po=function(a,b,c){b=b===void 0?!1:b;c=c===void 0?!1:c;if($k(26)&&fn.K&&E(5)&&(c||!gn())){var d=lo(co.ia.Zb);if(go(d))a.H||(a.H=!0,io(d,function(){return po(a)}));
else{b&&Um("fin","1");var e=no(b),f=oo(e),g={destinationId:E(5),endpoint:61};b?Yn(g,f,void 0,{Qg:!0},void 0,function(){Zc(f+"&img=1")}):Xn(g,f);a.H=!1;qo(e)}}},qo=function(a){if(Kc&&(Sb(Kc,"https://www.googletagmanager.com/")||If(47))&&!(a.indexOf("&csp=")<0&&a.indexOf("&mde=")<0)){var b;a:{try{if(Kc){b=new URL(Kc);break a}}catch(c){}b=void 0}b&&Uc(""+Kc+(Kc.indexOf("?")>=0?"&":"?")+"is_td=1"+a)}},ro=function(a){Rm().some(function(b){return!Pm[b]})&&po(a,!0)},so=new function(){var a=this;this.H=!1;
$c(A,"pagehide",function(){ro(a)})};function to(a,b){po(so,a===void 0?!1:a,b===void 0?!1:b)};var uo=["ad_storage","analytics_storage","ad_user_data","ad_personalization"],vo=[F.D.dd,F.D.yc,F.D.Qf,F.D.Kb,F.D.xc,F.D.fb,F.D.Db,F.D.nb,F.D.Lb,F.D.vc],yo=function(){var a=wo;!a.R&&a.H&&(uo.some(function(b){return Al.containerScopedDefaults[b]!==1})||xo("mbc"));a.R=!0},xo=function(a){fn.K&&(Um(a,"1"),to())},zo=function(a,b){var c=wo;if(!c.N[b]&&(c.N[b]=!0,c.K[b]))for(var d=m(vo),e=d.next();!e.done;e=d.next())if(O(a,e.value)){xo("erc");break}},wo=new function(){this.R=this.H=!1;this.N={};this.K={}};var Ao={},Bo=Object.freeze((Ao[F.D.Rc]=1,Ao[F.D.hh]=1,Ao[F.D.si]=1,Ao[F.D.Sc]=1,Ao[F.D.Ha]=1,Ao[F.D.Lb]=1,Ao[F.D.Cb]=1,Ao[F.D.Tb]=1,Ao[F.D.Id]=1,Ao[F.D.vc]=1,Ao[F.D.nb]=1,Ao[F.D.Jd]=1,Ao[F.D.He]=1,Ao[F.D.Oa]=1,Ao[F.D.Qp]=1,Ao[F.D.Pf]=1,Ao[F.D.Fi]=1,Ao[F.D.ph]=1,Ao[F.D.Wc]=1,Ao[F.D.Qf]=1,Ao[F.D.aq]=1,Ao[F.D.Ta]=1,Ao[F.D.Uf]=1,Ao[F.D.fq]=1,Ao[F.D.Od]=1,Ao[F.D.Rl]=1,Ao[F.D.Yc]=1,Ao[F.D.Zc]=1,Ao[F.D.Db]=1,Ao[F.D.am]=1,Ao[F.D.Wb]=1,Ao[F.D.Td]=1,Ao[F.D.Xb]=1,Ao[F.D.Oi]=1,Ao[F.D.dd]=1,Ao[F.D.yh]=1,Ao[F.D.Pi]=
1,Ao[F.D.Ud]=1,Ao[F.D.yc]=1,Ao[F.D.Vd]=1,Ao[F.D.lm]=1,Ao[F.D.Wd]=1,Ao[F.D.ed]=1,Ao[F.D.oj]=1,Ao));Object.freeze([F.D.za,F.D.Ua,F.D.Mb,F.D.tb,F.D.Ni,F.D.fb,F.D.Gi,F.D.Mp]);
var Co={},Do=Object.freeze((Co[F.D.qp]=1,Co[F.D.rp]=1,Co[F.D.tp]=1,Co[F.D.up]=1,Co[F.D.vp]=1,Co[F.D.zp]=1,Co[F.D.Ap]=1,Co[F.D.Bp]=1,Co[F.D.Dp]=1,Co[F.D.yf]=1,Co)),Eo={},Fo=Object.freeze((Eo[F.D.vl]=1,Eo[F.D.wl]=1,Eo[F.D.xe]=1,Eo[F.D.ye]=1,Eo[F.D.xl]=1,Eo[F.D.Ad]=1,Eo[F.D.ze]=1,Eo[F.D.oc]=1,Eo[F.D.Qc]=1,Eo[F.D.qc]=1,Eo[F.D.Ib]=1,Eo[F.D.Ae]=1,Eo[F.D.rc]=1,Eo[F.D.yl]=1,Eo)),Go=Object.freeze([F.D.Rc,F.D.Sc,F.D.Jd,F.D.Qf,F.D.Wf,F.D.Td,F.D.Oi,F.D.Vd]),Ho=Object.freeze([].concat(w(Go))),Io=Object.freeze([F.D.Cb,
F.D.ph,F.D.yh,F.D.Pi,F.D.nh]),Jo=Object.freeze([].concat(w(Io))),Ko={},Lo=(Ko[F.D.ka]="1",Ko[F.D.ra]="2",Ko[F.D.ma]="3",Ko[F.D.Xa]="4",Ko),Mo={},No=Object.freeze((Mo.search="s",Mo.youtube="y",Mo.playstore="p",Mo.shopping="h",Mo.ads="a",Mo.maps="m",Mo));function Oo(a){return typeof a!=="object"||a===null?{}:a}function Po(a){return a===void 0||a===null?"":typeof a==="object"?a.toString():String(a)}function Qo(a){if(a!==void 0&&a!==null)return Po(a)};var Ro=[F.D.ka,F.D.ra,F.D.ma,F.D.Xa];function So(a){for(var b=m(a[F.D.nc]||[""]),c=b.next(),d={};!c.done;d={region:void 0},c=b.next())d.region=c.value,Gb(a,function(e){return function(f,g){if(f!==F.D.nc){var h=Po(g),l=e.region,n=ym(),p=zm();yl=!0;xl&&sb("TAGGING",20);tl().declare(f,h,l,n,p)}}}(d))}
function To(a){yo();var b=al(17,function(){return!1}),c=al(16,function(){return!1});!b&&c&&xo("crc");Zk(17,!0);var d=a[F.D.Yg];d&&P(41);var e=a[F.D.nc];e?P(40):e=[""];for(var f=m(e),g=f.next(),h={};!g.done;h={Bo:void 0},g=f.next())h.Bo=g.value,Gb(a,function(l){return function(n,p){if(n!==F.D.nc&&n!==F.D.Yg){var q=Qo(p),r=l.Bo,t=Number(d),u=ym(),v=zm();t=t===void 0?0:t;xl=!0;yl&&sb("TAGGING",20);tl().default(n,q,r,u,v,t,Al)}}}(h))}
function Uo(a){Al.usedContainerScopedDefaults=!0;var b=a[F.D.nc];if(b){var c=Array.isArray(b)?b:[b];if(!c.includes(zm())&&!c.includes(ym()))return}Gb(a,function(d,e){switch(d){case "ad_storage":case "analytics_storage":case "ad_user_data":case "ad_personalization":break;default:return}Al.usedContainerScopedDefaults=!0;Al.containerScopedDefaults[d]=e==="granted"?3:2})}
function Vo(a,b){yo();Zk(16,!0);Gb(a,function(c,d){var e=Po(d);xl=!0;yl&&sb("TAGGING",20);tl().update(c,e,Al)});Gl(b.eventId,b.priorityId)}function Wo(a){a.hasOwnProperty("all")&&(Al.selectedAllCorePlatformServices=!0,Gb(No,function(b){Al.corePlatformServices[b]=a.all==="granted";Al.usedCorePlatformServices=!0}));Gb(a,function(b,c){b!=="all"&&(Al.corePlatformServices[b]=c==="granted",Al.usedCorePlatformServices=!0)})}
function Xo(a){Array.isArray(a)||(a=[a]);return a.every(function(b){return Bl(b)})}function Yo(){var a=Zo;Array.isArray(a)||(a=[a]);return a.some(function(b){return Bl(b)})}function $o(a,b){Fl(a,b)}function ap(a,b){Il(a,b)}function bp(a,b){Hl(a,b)}function cp(){var a=[F.D.ka,F.D.Xa,F.D.ma];tl().waitForUpdate(a,500,Al)}function dp(a){for(var b=m(a),c=b.next();!c.done;c=b.next()){var d=c.value;tl().clearTimeout(d,void 0,Al)}Gl()}
function ep(a){for(var b={},c=m(a.split("|")),d=c.next();!d.done;d=c.next())b[d.value]=!0;return b};var fp=Object.freeze([F.D.ka,F.D.ma]);function op(a,b){if(b!=null&&b!==""){var c=b===!0?"1":b===!1?"0":encodeURIComponent(String(b));if(Sb(a,"_&"))return{key:a.substring(2),value:c};var d=np[a];if(d!==null)return d?{key:d,value:c}:{key:Ab(b)?"epn."+a:"ep."+a,value:c}}};function pp(a){a=a===void 0?[]:a;return xj(a).join("~")};function qp(){var a=[],b=Number('')||0,c=Number('')||0;c||(c=b/100);var d=function(){var t=!1;return t}();a.push({uk:228,studyId:228,experimentId:105177154,controlId:105177155,controlId2:105255245,probability:c,active:d,Ze:0});var e=Number('')||
0,f=Number('')||0;f||(f=e/100);var g=function(){var t=!1;return t}();a.push({uk:235,studyId:235,experimentId:105357150,controlId:105357151,controlId2:0,probability:f,active:g,Ze:1});var h=Number('')||0,l=Number('')||
0;l||(l=h/100);var n=function(){var t=!1;return t}();a.push({uk:266,studyId:266,experimentId:115718529,controlId:115718530,controlId2:115718531,probability:l,active:n,Ze:0});var p=Number('')||0,q=Number('')||
0;q||(q=p/100);var r=function(){var t=!1;return t}();a.push({uk:267,studyId:267,experimentId:115718526,controlId:115718527,controlId2:115718528,probability:q,active:r,Ze:0});return a};var rp=function(){this.K={};this.H={};this.N={};this.R=new Set},xp=function(a,b){var c=b,d=b=a.N[c.studyId]?na(Object,"assign").call(Object,{},c,{active:!0}):c,e=Fi;d.controlId2&&d.probability<=.25||(d=na(Object,"assign").call(Object,{},d,{controlId2:0}));e.studies[d.studyId]=d;b.focused&&(a.K[b.studyId]=!0);if(b.Ze===1){var f=b.studyId;sp(a,tp(),f);up(a,f)?tj(uj,f):vp(a,f)?uj.K[f]=!0:wp(a,f)&&(uj.H[f]=!0)}else if(b.Ze===0){var g=b.studyId;sp(a,a.H,g);up(a,g)?tj(uj,g):vp(a,g)?uj.K[g]=!0:wp(a,g)&&
(uj.H[g]=!0)}},sp=function(a,b,c,d){var e=Fi;if(e.studies[c]){var f=e.studies[c],g=f.experimentId,h=f.probability;if(!(b.studies||{})[c]){var l=b.studies||{};l[c]=!0;b.studies=l;if(!e.studies[c].active)if(e.studies[c].probability>.5)Ii(b,g,c);else if(!(h<=0||h>1)){var n=void 0;if(d){var p=Ci(d+"~"+c);if(p==="e2")n=-1;else{for(var q=new Uint8Array(p),r=BigInt(0),t=m(q),u=t.next();!u.done;u=t.next())r=r<<BigInt(8)|BigInt(u.value);n=Number(r%BigInt(Number.MAX_SAFE_INTEGER))}}Gi.sk(b,c,n)}}}if(!a.K[c]){var v=
Ni(b,c);v&&wj.H.K.add(v)}},tp=function(){return om(jm.ba.Tq,{})},up=function(a,b){var c=tp();return Ki(c,b)||Ki(a.H,b)},vp=function(a,b){var c=tp();return Li(c,b)||Li(a.H,b)},wp=function(a,b){var c=tp();return Mi(c,b)||Mi(a.H,b)},yp;
function zp(){if(!yp){var a=yp=new rp,b,c,d=((b=A)==null?void 0:(c=b.location)==null?void 0:c.hash)||"";if(d[0]==="#"&&d[1]==="_"&&d[2]==="t"&&d[3]==="e"&&d[4]==="="){var e=d.substring(5);if(e)for(var f=m(e.split("~")),g=f.next();!g.done;g=f.next()){var h=Number(g.value);h&&(a.N[h]=!0,tj(uj,h))}}for(var l=m(qp()),n=l.next();!n.done;n=l.next())xp(a,n.value);for(var p=[],q=m(Mf(56)||[]),r=q.next();!r.done;r=q.next()){var t=r.value,u={studyId:t[1],active:!!t[2],probability:t[3]||0,experimentId:t[4]||
0,controlId:t[5]||0,controlId2:t[6]||0},v=0;switch(t[7]){case 2:v=1;break;case 3:v=2;break;case 1:case 4:case 5:case 0:v=0}var x;a:switch(u.studyId){case 567:case 462:x=!0;break a;default:x=!1}var y=na(Object,"assign").call(Object,{},u,{Ze:v,focused:x});(y.active||y.probability>.5&&y.experimentId||y.experimentId&&y.controlId)&&p.push(y)}for(var z=m(p),C=z.next();!C.done;C=z.next())xp(a,C.value)}}
function Ap(a,b){zp();var c=yp;sp(c,tp(),a,b);up(c,a)?tj(uj,a):vp(c,a)?uj.K[a]=!0:wp(c,a)&&(uj.H[a]=!0)}function Bp(){zp();var a=yp,b=up(a,567);if(a.K[567]){var c,d=tp();(c=Ni(d,567)||Ni(a.H,567))&&a.R.add(c)}return b}function Cp(a){zp();var b=new Set(yp.R);if(a)for(var c=Q(a,H.J.Ch)||[],d=m(c),e=d.next();!e.done;e=d.next())b.add(e.value);return pp([].concat(w(b)))};function Dp(a){var b=a.location.href;if(a===a.top)return{url:b,Is:!0};var c=!1,d=a.document;d&&d.referrer&&(b=d.referrer,a.parent===a.top&&(c=!0));var e=a.location.ancestorOrigins;if(e){var f=e[e.length-1],g;f&&((g=b)==null?void 0:g.indexOf(f))===-1&&(c=!1,b=f)}return{url:b,Is:c}}function Ep(a){try{var b;if(b=!!a&&a.location.href!=null)a:{try{Hn(a.foo);b=!0;break a}catch(c){}b=!1}return b}catch(c){return!1}}function Fp(){for(var a=A,b=a;a&&a!==a.parent;)a=a.parent,Ep(a)&&(b=a);return b};var Gp=function(a,b){var c=function(){};c.prototype=a.prototype;var d=new c;a.apply(d,Array.prototype.slice.call(arguments,1));return d},Hp=function(a){var b=a;return function(){if(b){var c=b;b=null;c()}}};function Ip(a,b){if(a)for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&b(a[c],c,a)};function Jp(a){var b=a.split(/[?#]/),c=/[?]/.test(a)?"?"+b[1]:"";return{zk:b[0],params:c,fragment:/[#]/.test(a)?"#"+(c?b[2]:b[1]):""}}function Kp(a){var b=Oa.apply(1,arguments);if(b.length===0)return jc(a[0]);for(var c=a[0],d=0;d<b.length;d++)c+=encodeURIComponent(b[d])+a[d+1];return jc(c)}
function Lp(a,b,c,d){function e(g,h){g!=null&&(Array.isArray(g)?g.forEach(function(l){return e(l,h)}):(b+=f+encodeURIComponent(h)+"="+encodeURIComponent(g),f="&"))}var f=b.length?"&":"?";d.constructor===Object&&(d=Object.entries(d));Array.isArray(d)?d.forEach(function(g){return e(g[1],g[0])}):d.forEach(e);return jc(a+b+c)}function Mp(a,b){var c=Jp(kc(a).toString()),d=c.zk.slice(-1)==="/"?"":"/",e=c.zk+d+encodeURIComponent(b);return jc(e+c.params+c.fragment)};var Np=function(a,b){for(var c=a,d=0;d<50;++d){var e;try{e=!(!c.frames||!c.frames[b])}catch(h){e=!1}if(e)return c;var f;a:{try{var g=c.parent;if(g&&g!==c){f=g;break a}}catch(h){}f=null}if(!(c=f))break}return null},Op=function(a){var b=A;if(b.top==b)return 0;if(a===void 0?0:a){var c=b.location.ancestorOrigins;if(c)return c[c.length-1]==b.location.origin?1:2}return Ep(b.top)?1:2},Pp=function(a){a=a===void 0?document:a;return a.createElement("img")};function Qp(a){for(var b=[],c=B.cookie.split(";"),d=new RegExp("^\\s*"+(a||"_gac")+"_(UA-\\d+-\\d+)=\\s*(.+?)\\s*$"),e=0;e<c.length;e++){var f=c[e].match(d);f&&b.push({ud:f[1],value:f[2],timestamp:Number(f[2].split(".")[1])||0})}b.sort(function(g,h){return h.timestamp-g.timestamp});return b}
function Rp(a,b){var c=Qp(a),d={};if(!c||!c.length)return d;for(var e=0;e<c.length;e++){var f=c[e].value.split(".");if(!(f[0]!=="1"||b&&f.length<3||!b&&f.length!==3)&&Number(f[1])){d[c[e].ud]||(d[c[e].ud]=[]);var g={version:f[0],timestamp:Number(f[1])*1E3,gclid:f[2]};b&&f.length>3&&(g.labels=f.slice(3));d[c[e].ud].push(g)}}return d};function Sp(a){return a.origin!=="null"};var Tp={},Up=(Tp.k={na:/^[\w-]+$/},Tp.b={na:/^[\w-]+$/,nk:!0},Tp.i={na:/^[1-9]\d*$/},Tp.h={na:/^\d+$/},Tp.t={na:/^[1-9]\d*$/},Tp.d={na:/^[A-Za-z0-9_-]+$/},Tp.j={na:/^\d+$/},Tp.u={na:/^[1-9]\d*$/},Tp.l={na:/^[01]$/},Tp.o={na:/^[1-9]\d*$/},Tp.g={na:/^[01]$/},Tp.s={na:/^.+$/},Tp.m={na:/^[01]$/},Tp);var Vp={},Zp=(Vp[5]={ji:{2:Wp},Zj:"2",Rh:["k","i","b","u"]},Vp[4]={ji:{2:Wp,GCL:Xp},Zj:"2",Rh:["k","i","b","m"]},Vp[2]={ji:{GS2:Wp,GS1:Yp},Zj:"GS2",Rh:"sogtjlhd".split("")},Vp);function $p(a,b,c){var d=Zp[b];if(d){var e=a.split(".")[0];c==null||c(e);if(e){var f=d.ji[e];if(f)return f(a,b)}}}
function Wp(a,b){var c=a.split(".");if(c.length===3){var d=c[2];if(d.indexOf("$")===-1&&d.indexOf("%24")!==-1)try{d=decodeURIComponent(d)}catch(t){}var e={},f=Zp[b];if(f){for(var g=f.Rh,h=m(d.split("$")),l=h.next();!l.done;l=h.next()){var n=l.value,p=n[0];if(g.indexOf(p)!==-1)try{var q=decodeURIComponent(n.substring(1)),r=Up[p];r&&(r.nk?(e[p]=e[p]||[],e[p].push(q)):e[p]=q)}catch(t){}}return e}}}function aq(a,b,c){var d=Zp[b];if(d)return[d.Zj,c||"1",bq(a,b)].join(".")}
function bq(a,b){var c=Zp[b];if(c){for(var d=[],e=m(c.Rh),f=e.next();!f.done;f=e.next()){var g=f.value,h=Up[g];if(h){var l=a[g];if(l!==void 0)if(h.nk&&Array.isArray(l))for(var n=m(l),p=n.next();!p.done;p=n.next())d.push(encodeURIComponent(""+g+p.value));else d.push(encodeURIComponent(""+g+l))}}return d.join("$")}}function Xp(a){var b=a.split(".");b.shift();var c=b.shift(),d=b.shift(),e={};return e.k=d,e.i=c,e.b=b,e}
function Yp(a){var b=a.split(".").slice(2);if(!(b.length<5||b.length>7)){var c={};return c.s=b[0],c.o=b[1],c.g=b[2],c.t=b[3],c.j=b[4],c.l=b[5],c.h=b[6],c}};function cq(a,b,c,d){var e;return(e=dq(function(f){return f===a},b,c,d)[a])!=null?e:[]}function dq(a,b,c,d){var e;if(eq(d)){for(var f={},g=String(b||fq()).split(";"),h=0;h<g.length;h++){var l=g[h].split("="),n=l[0].trim();if(n&&a(n)){var p=l.slice(1).join("=").trim();p&&c&&(p=decodeURIComponent(p));var q=void 0,r=void 0;((q=f)[r=n]||(q[r]=[])).push(p)}}e=f}else e={};return e}
function gq(a,b,c,d,e){if(eq(e)){var f=hq(a,d,e);if(f.length===1)return f[0];if(f.length!==0){f=iq(f,function(g){return g.Jr},b);if(f.length===1)return f[0];f=iq(f,function(g){return g.Ws},c);return f[0]}}}function jq(a,b,c,d){var e=fq(),f=A;Sp(f)&&(f.document.cookie=a);var g=fq();return e!==g||c!==void 0&&cq(b,g,!1,d).indexOf(c)>=0}
function kq(a,b,c,d){function e(x,y,z){if(z==null)return delete h[y],x;h[y]=z;return x+"; "+y+"="+z}function f(x,y){if(y==null)return x;h[y]=!0;return x+"; "+y}if(!eq(c.Mc))return 2;var g;b==null?g=a+"=deleted; expires="+(new Date(0)).toUTCString():(c.encode&&(b=encodeURIComponent(b)),b=lq(b),g=a+"="+b);var h={};g=e(g,"path",c.path);var l;c.expires instanceof Date?l=c.expires.toUTCString():c.expires!=null&&(l=""+c.expires);g=e(g,"expires",l);g=e(g,"max-age",c.Os);g=e(g,"samesite",c.rt);c.secure&&
(g=f(g,"secure"));var n=c.domain;if(n&&n.toLowerCase()==="auto"){for(var p=mq(),q=void 0,r=!1,t=0;t<p.length;++t){var u=p[t]!=="none"?p[t]:void 0,v=e(g,"domain",u);v=f(v,c.flags);try{d&&d(a,h)}catch(x){q=x;continue}r=!0;if(!nq(u,c.path)&&jq(v,a,b,c.Mc))return 0}if(q&&!r)throw q;return 1}n&&n.toLowerCase()!=="none"&&(g=e(g,"domain",n));g=f(g,c.flags);d&&d(a,h);return nq(n,c.path)?1:jq(g,a,b,c.Mc)?0:1}function oq(a,b,c){c.path==null&&(c.path="/");c.domain||(c.domain="auto");return kq(a,b,c)}
function iq(a,b,c){for(var d=[],e=[],f,g=0;g<a.length;g++){var h=a[g],l=b(h);l===c?d.push(h):f===void 0||l<f?(e=[h],f=l):l===f&&e.push(h)}return d.length>0?d:e}function hq(a,b,c){for(var d=[],e=cq(a,void 0,void 0,c),f=0;f<e.length;f++){var g=e[f].split("."),h=g.shift();if(!b||!h||b.indexOf(h)!==-1){var l=g.shift();if(l){var n=l.split("-");d.push({Br:e[f],Cr:g.join("."),Jr:Number(n[0])||1,Ws:Number(n[1])||1})}}}return d}function lq(a){a&&a.length>1200&&(a=a.substring(0,1200));return a}
var pq=/^(www\.)?google(\.com?)?(\.[a-z]{2})?$/,qq=/(^|\.)doubleclick\.net$/i;function nq(a,b){return a!==void 0&&(qq.test(A.document.location.hostname)||b==="/"&&pq.test(a))}function rq(a){if(!a)return 1;var b=a;Yf(4)&&a==="none"&&(b=A.document.location.hostname);b=b.indexOf(".")===0?b.substring(1):b;return b.split(".").length}function sq(a){if(!a||a==="/")return 1;a[0]!=="/"&&(a="/"+a);a[a.length-1]!=="/"&&(a+="/");return a.split("/").length-1}
function tq(a,b){var c=""+rq(a),d=sq(b);d>1&&(c+="-"+d);return c}
var fq=function(){var a=A;return Sp(a)?a.document.cookie:""},eq=function(a){return a&&Yf(5)?(Array.isArray(a)?a:[a]).every(function(b){return Dl(b)&&Bl(b)}):!0},mq=function(){var a=[],b=A.document.location.hostname.split(".");if(b.length===4){var c=b[b.length-1];if(Number(c).toString()===c)return["none"]}for(var d=b.length-2;d>=0;d--)a.push(b.slice(d).join("."));var e=A.document.location.hostname;qq.test(e)||pq.test(e)||a.push("none");return a};function uq(a,b,c,d){var e,f=Number(a.pd!=null?a.pd:void 0);f!==0&&(e=new Date((b||Nb())+1E3*(f||7776E3)));return{path:a.path,domain:a.domain,flags:a.flags,encode:!!c,expires:e,Mc:d}};var vq=new Map([[5,"ad_storage"],[4,["ad_storage","ad_user_data"]],[2,"analytics_storage"]]);function wq(a,b,c){if(Zp[b]){for(var d=[],e=cq(a,void 0,void 0,vq.get(b)),f=m(e),g=f.next();!g.done;g=f.next()){var h=$p(g.value,b,c);h&&d.push(xq(h))}return d}}
function yq(a){var b=zq;if(Zp[2]){for(var c={},d=dq(a,void 0,void 0,vq.get(2)),e=Object.keys(d).sort(),f=m(e),g=f.next();!g.done;g=f.next())for(var h=g.value,l=m(d[h]),n=l.next();!n.done;n=l.next()){var p=$p(n.value,2,b);p&&(c[h]||(c[h]=[]),c[h].push(xq(p)))}return c}}function Aq(a,b,c,d,e){d=d||{};var f=tq(d.domain,d.path),g=aq(b,c,f);if(!g)return 1;var h=uq(d,e,void 0,vq.get(c));return oq(a,g,h)}function Bq(a,b){var c=b.na;return typeof c==="function"?c(a):c.test(a)}
function xq(a){for(var b=m(Object.keys(a)),c=b.next(),d={};!c.done;d={Ag:void 0},c=b.next()){var e=c.value,f=a[e];d.Ag=Up[e];d.Ag?d.Ag.nk?a[e]=Array.isArray(f)?f.filter(function(g){return function(h){return Bq(h,g.Ag)}}(d)):void 0:typeof f==="string"&&Bq(f,d.Ag)||(a[e]=void 0):a[e]=void 0}return a};var Cq;function Dq(){function a(g){c(g.target||g.srcElement||{})}function b(g){d(g.target||g.srcElement||{})}var c=Eq,d=Fq,e=Gq();if(!e.init){$c(B,"mousedown",a);$c(B,"keyup",a);$c(B,"submit",b);var f=HTMLFormElement.prototype.submit;HTMLFormElement.prototype.submit=function(){d(this);f.call(this)};e.init=!0}}function Hq(a,b,c,d,e){var f={callback:a,domains:b,fragment:c===2,placement:c,forms:d,sameHost:e};Gq().decorators.push(f)}
function Iq(a,b,c){for(var d=Gq().decorators,e={},f=0;f<d.length;++f){var g=d[f],h;if(h=!c||g.forms)a:{var l=g.domains,n=a,p=!!g.sameHost;if(l&&(p||n!==B.location.hostname))for(var q=0;q<l.length;q++)if(l[q]instanceof RegExp){if(l[q].test(n)){h=!0;break a}}else if(n.indexOf(l[q])>=0||p&&l[q].indexOf(n)>=0){h=!0;break a}h=!1}if(h){var r=g.placement;r===void 0&&(r=g.fragment?2:1);r===b&&Qb(e,g.callback())}}return e}
function Gq(){var a=Mc("google_tag_data",{}),b=a.gl;b&&b.decorators||(b={decorators:[]},a.gl=b);return b};var Jq=/(.*?)\*(.*?)\*(.*)/,Kq=/^https?:\/\/([^\/]*?)\.?cdn\.ampproject\.org\/?(.*)/,Lq=/^(?:www\.|m\.|amp\.)+/,Mq=/([^?#]+)(\?[^#]*)?(#.*)?/;function Nq(a){var b=Mq.exec(a);if(b)return{hk:b[1],query:b[2],fragment:b[3]}}function Oq(a){return new RegExp("(.*?)(^|&)"+a+"=([^&]*)&?(.*)")}
function Pq(a,b){var c=[Hc.userAgent,(new Date).getTimezoneOffset(),Hc.userLanguage||Hc.language,Math.floor(Nb()/60/1E3)-(b===void 0?0:b),a].join("*"),d;if(!(d=Cq)){for(var e=Array(256),f=0;f<256;f++){for(var g=f,h=0;h<8;h++)g=g&1?g>>>1^3988292384:g>>>1;e[f]=g}d=e}Cq=d;for(var l=4294967295,n=0;n<c.length;n++)l=l>>>8^Cq[(l^c.charCodeAt(n))&255];return((l^-1)>>>0).toString(36)}
function Qq(a){return function(b){var c=Rj(A.location.href),d=c.search.replace("?",""),e=Ij(d,"_gl",!1,!0)||"";b.query=Rq(e)||{};var f=Lj(c,"fragment"),g;var h=-1;if(Sb(f,"_gl="))h=4;else{var l=f.indexOf("&_gl=");l>0&&(h=l+3+2)}if(h<0)g=void 0;else{var n=f.indexOf("&",h);g=n<0?f.substring(h):f.substring(h,n)}b.fragment=Rq(g||"")||{};a&&Sq(c,d,f)}}function Tq(a,b){var c=Oq(a).exec(b),d=b;if(c){var e=c[2],f=c[4];d=c[1];f&&(d=d+e+f)}return d}
function Sq(a,b,c){function d(g,h){var l=Tq("_gl",g);l.length&&(l=h+l);return l}if(Gc&&Gc.replaceState){var e=Oq("_gl");if(e.test(b)||e.test(c)){var f=Lj(a,"path");b=d(b,"?");c=d(c,"#");Gc.replaceState({},"",""+f+b+c)}}}function Uq(a,b){var c=Qq(!!b),d=Gq();d.data||(d.data={query:{},fragment:{}},c(d.data));var e={},f=d.data;f&&(Qb(e,f.query),a&&Qb(e,f.fragment));return e}
var Rq=function(a){try{var b=Vq(a,3);if(b!==void 0){for(var c={},d=b?b.split("*"):[],e=0;e+1<d.length;e+=2){var f=d[e],g=qb(d[e+1]);c[f]=g}sb("TAGGING",6);return c}}catch(h){sb("TAGGING",8)}};function Vq(a,b){if(a){var c;a:{for(var d=a,e=0;e<3;++e){var f=Jq.exec(d);if(f){c=f;break a}d=Kj(d)||""}c=void 0}var g=c;if(g&&g[1]==="1"){var h=g[3],l;a:{for(var n=g[2],p=0;p<b;++p)if(n===Pq(h,p)){l=!0;break a}l=!1}if(l)return h;sb("TAGGING",7)}}}
function Wq(a,b,c,d,e){function f(p){p=Tq(a,p);var q=p.charAt(p.length-1);p&&q!=="&"&&(p+="&");return p+n}d=d===void 0?!1:d;e=e===void 0?!1:e;var g=Nq(c);if(!g)return"";var h=g.query||"",l=g.fragment||"",n=a+"="+b;d?l.substring(1).length!==0&&e||(l="#"+f(l.substring(1))):h="?"+f(h.substring(1));return""+g.hk+h+l}
function Xq(a,b){function c(n,p,q){var r;a:{for(var t in n)if(n.hasOwnProperty(t)){r=!0;break a}r=!1}if(r){var u,v=[],x;for(x in n)if(n.hasOwnProperty(x)){var y=n[x];y!==void 0&&y===y&&y!==null&&y.toString()!=="[object Object]"&&(v.push(x),v.push(pb(String(y))))}var z=v.join("*");u=["1",Pq(z),z].join("*");d?(Yf(3)||Yf(1)||!p)&&Yq("_gl",u,a,p,q):Zq("_gl",u,a,p,q)}}var d=(a.tagName||"").toUpperCase()==="FORM",e=Iq(b,1,d),f=Iq(b,2,d),g=Iq(b,4,d),h=Iq(b,3,d);c(e,!1,!1);c(f,!0,!1);Yf(1)&&c(g,!0,!0);for(var l in h)h.hasOwnProperty(l)&&
$q(l,h[l],a)}function $q(a,b,c){c.tagName.toLowerCase()==="a"?Zq(a,b,c):c.tagName.toLowerCase()==="form"&&Yq(a,b,c)}function Zq(a,b,c,d,e){d=d===void 0?!1:d;e=e===void 0?!1:e;var f;if(f=c.href){var g;if(!(g=d)){var h=A.location.href,l=Nq(c.href),n=Nq(h);g=!(l&&n&&l.hk===n.hk&&l.query===n.query&&l.fragment)}f=g}if(f){var p=Wq(a,b,c.href,d,e);vc.test(p)&&(c.href=p)}}
function Yq(a,b,c,d,e){d=d===void 0?!1:d;e=e===void 0?!1:e;if(c){var f=c.getAttribute("action")||"";if(f){var g=(c.method||"").toLowerCase();if(g!=="get"||d){if(g==="get"||g==="post"){var h=Wq(a,b,f,d,e);vc.test(h)&&(c.action=h)}}else{for(var l=c.childNodes||[],n=!1,p=0;p<l.length;p++){var q=l[p];if(q.name===a){q.setAttribute("value",b);n=!0;break}}if(!n){var r=B.createElement("input");r.setAttribute("type","hidden");r.setAttribute("name",a);r.setAttribute("value",b);c.appendChild(r)}}}}}
function Eq(a){try{var b;a:{for(var c=a,d=100;c&&d>0;){if(c.href&&c.nodeName.match(/^a(?:rea)?$/i)){b=c;break a}c=c.parentNode;d--}b=null}var e=b;if(e){var f=e.protocol;f!=="http:"&&f!=="https:"||Xq(e,e.hostname)}}catch(g){}}function Fq(a){try{var b=a.getAttribute("action");if(b){var c=Lj(Rj(b),"host");Xq(a,c)}}catch(d){}}function ar(a,b,c,d){Dq();var e=c==="fragment"?2:1;d=!!d;Hq(a,b,e,d,!1);e===2&&sb("TAGGING",23);d&&sb("TAGGING",24)}
function br(a,b){Dq();Hq(a,[Nj(A.location,"host",!0)],b,!0,!0)}function cr(){var a=B.location.hostname,b=Kq.exec(B.referrer);if(!b)return!1;var c=b[2],d=b[1],e="";if(c){var f=c.split("/"),g=f[1];e=g==="s"?Kj(f[2])||"":Kj(g)||""}else if(d){if(d.indexOf("xn--")===0)return!1;e=d.replace(/-/g,".").replace(/\.\./g,"-")}var h=a.replace(Lq,""),l=e.replace(Lq,"");return h===l||Tb(h,"."+l)}function dr(a,b){return a===!1?!1:a||b||cr()};var er=function(a){this.value=0;this.value=a===void 0?0:a};er.prototype.set=function(a){return this.value|=1<<a};var fr=function(a,b){b<=0||(a.value|=1<<b-1)};er.prototype.get=function(){return this.value};er.prototype.clear=function(a){this.value&=~(1<<a)};er.prototype.clearAll=function(){this.value=0};er.prototype.equals=function(a){return this.value===a.value};function gr(a){if(a)try{return new Uint8Array(atob(a.replace(/-/g,"+").replace(/_/g,"/")).split("").map(function(b){return b.charCodeAt(0)}))}catch(b){}}function hr(a,b){var c=0,d=0,e,f=b;do{if(f>=a.length)return;e=a[f++];c|=(e&127)<<d;d+=7}while(e&128);return[c,f]};function ir(){var a=String,b=A.location.hostname,c=A.location.pathname,d=b=bc(b);d.split(".").length>2&&(d=d.replace(/^(www[0-9]*|web|ftp|wap|home|m|w|amp|mobile)\./,""));b=d;c=bc(c);var e=c.split(";")[0];e=e.replace(/\/(ar|slp|web|index)?\/?$/,"");return a(ng((""+b+e).toLowerCase()))};var jr=["ad_storage","ad_user_data"];function kr(a,b){if(!a)return sb("TAGGING",32),10;if(b===null||b===void 0||b==="")return sb("TAGGING",33),11;var c=lr(!1);if(c.error!==0)return sb("TAGGING",34),c.error;if(!c.value)return sb("TAGGING",35),2;c.value[a]=b;var d=mr(c);d!==0&&sb("TAGGING",36);return d}
function nr(a){if(!a)return sb("TAGGING",27),{error:10};var b=lr();if(b.error!==0)return sb("TAGGING",29),b;if(!b.value)return sb("TAGGING",30),{error:2};if(!(a in b.value))return sb("TAGGING",31),{value:void 0,error:15};var c=b.value[a];return c===null||c===void 0||c===""?(sb("TAGGING",28),{value:void 0,error:11}):{value:c,error:0}}
function or(a){if(a){var b=lr(!1);b.error!==0?sb("TAGGING",38):b.value?a in b.value?(delete b.value[a],mr(b)!==0&&sb("TAGGING",41)):sb("TAGGING",40):sb("TAGGING",39)}else sb("TAGGING",37)}
function lr(a){a=a===void 0?!0:a;if(!Bl(jr))return sb("TAGGING",43),{error:3};try{if(!A.localStorage)return sb("TAGGING",44),{error:1}}catch(f){return sb("TAGGING",45),{error:14}}var b={schema:"gcl",version:1},c=void 0;try{c=A.localStorage.getItem("_gcl_ls")}catch(f){return sb("TAGGING",46),{error:13}}try{if(c){var d=JSON.parse(c);if(d&&typeof d==="object")b=d;else return sb("TAGGING",47),{error:12}}}catch(f){return sb("TAGGING",48),{error:8}}if(b.schema!=="gcl")return sb("TAGGING",49),{error:4};
if(b.version!==1)return sb("TAGGING",50),{error:5};try{var e=pr(b);a&&e&&mr({value:b,error:0})}catch(f){return sb("TAGGING",48),{error:8}}return{value:b,error:0}}
function pr(a){if(!a||typeof a!=="object")return!1;if("expires"in a&&"value"in a){var b;typeof a.expires==="number"?b=a.expires:b=typeof a.expires==="string"?Number(a.expires):NaN;if(isNaN(b)||!(Date.now()<=b))return a.value=null,a.error=9,sb("TAGGING",54),!0}else{for(var c=!1,d=m(Object.keys(a)),e=d.next();!e.done;e=d.next())c=pr(a[e.value])||c;return c}return!1}
function mr(a){if(a.error)return a.error;if(!a.value)return sb("TAGGING",42),2;var b=a.value,c;try{c=JSON.stringify(b)}catch(d){return sb("TAGGING",52),6}try{A.localStorage.setItem("_gcl_ls",c)}catch(d){return sb("TAGGING",53),7}return 0};var qr={},rr=(qr.gclid=!0,qr.dclid=!0,qr.gbraid=!0,qr.wbraid=!0,qr),sr=/^\w+$/,tr=/^[\w-]+$/,ur={},vr=(ur.aw="FPGCLAW",ur),wr={},xr=(wr.ag="_ag",wr.gb="_gb",wr.aw="_aw",wr.dc="_dc",wr.gf="_gf",wr.ha="_ha",wr.gp="_gp",wr.gs="_gs",wr),yr=/^(?:www\.)?google(?:\.com?)?(?:\.[a-z]{2}t?)?$/,zr=/^www\.googleadservices\.com$/;function Ar(){return["ad_storage","ad_user_data"]}function Br(a){return!Yf(5)||Bl(a)}function Cr(a,b){function c(){var d=Br(b);d&&a();return d}Hl(function(){c()||Il(c,b)},b)}
function Dr(a){return Er(a).map(function(b){return b.gclid})}function Fr(a){return Gr(a).filter(function(b){return b.gclid}).map(function(b){return b.gclid})}function Gr(a,b){b=b===void 0?!1:b;var c=Hr(a.prefix),d=Ir("gb",c),e=Ir("ag",c);if(!e||!d)return[];var f=function(l){return function(n){n.zg=l;return n}},g=Er(d,b).map(f("gb")),h=Jr(e).map(f("ag"));return g.concat(h).sort(function(l,n){return n.timestamp-l.timestamp})}
function Kr(a,b,c,d,e){var f=Cb(a,function(g){return g.gclid===b});f?(f.timestamp<c&&(f.timestamp=c,f.od=e),f.labels=Lr(f.labels||[],d||[])):a.push({version:"2",gclid:b,timestamp:c,labels:d,od:e})}function Mr(a){for(var b=wq(a,5)||[],c=[],d=m(b),e=d.next();!e.done;e=d.next()){var f=e.value,g=f,h=Nr(f);h&&Kr(c,g.k,h,g.b||[],f.u)}return c.sort(function(l,n){return n.timestamp-l.timestamp})}
function Er(a,b){b=b===void 0?!1:b;var c=[];Or(c,a,1);if(b)if(Tb(a,"_aw")){var d=Pr();d&&(d.od=void 0,d.oa=d.oa||[2],Qr(c,d));Or(c,"gcl_aw",2)}else Tb(a,"_gb")&&Yf(6)&&Or(c,"gcl_gb",2);c.sort(function(e,f){return f.timestamp-e.timestamp});return Rr(c)}function Sr(a,b){for(var c=[],d=m(a),e=d.next();!e.done;e=d.next()){var f=e.value;c.includes(f)||c.push(f)}for(var g=m(b),h=g.next();!h.done;h=g.next()){var l=h.value;c.includes(l)||c.push(l)}return c}
function Qr(a,b,c){c=c===void 0?!1:c;for(var d,e,f=m(a),g=f.next();!g.done;g=f.next()){var h=g.value;if(h.gclid===b.gclid){d=h;break}h.qa&&b.qa&&h.qa.equals(b.qa)&&(e=h)}if(d){var l,n,p=(l=d.qa)!=null?l:new er,q=(n=b.qa)!=null?n:new er;p.value|=q.value;d.qa=p;d.timestamp<b.timestamp&&(d.timestamp=b.timestamp,d.od=b.od);d.labels=Sr(d.labels||[],b.labels||[]);d.oa=Sr(d.oa||[],b.oa||[])}else c&&e?na(Object,"assign").call(Object,e,b):a.push(b)}
function Tr(a){if(!a)return new er;var b=new er;if(a===1)return fr(b,2),fr(b,3),b;fr(b,a);return b}
function Pr(){var a=nr("gclid");if(!a||a.error||!a.value||typeof a.value!=="object")return null;var b=a.value;try{if(!("value"in b&&b.value)||typeof b.value!=="object")return null;var c=b.value,d=c.value;if(!d||!d.match(tr))return null;var e=c.linkDecorationSource,f=c.linkDecorationSources,g=new er;typeof e==="number"?g=Tr(e):typeof f==="number"&&(g.value=f);return{version:"",gclid:d,timestamp:Number(c.creationTimeMs)||0,labels:[],qa:g,oa:[2]}}catch(h){return null}}
function Ur(a){var b=nr(a);if(b.error!==0)return null;try{return b.value.reduce(function(c,d){if(!d.value||typeof d.value!=="object")return c;var e=d.value,f=e.value;if(!f||!f.match(tr))return c;var g=new er,h=e.linkDecorationSources;typeof h==="number"&&(g.value=h);var l;c.push({version:"",gclid:f,timestamp:Number(e.creationTimeMs)||0,expires:Number(d.expires)||0,labels:(l=e.labels)!=null?l:[],qa:g,oa:[2]});return c},[])}catch(c){return null}}
function Or(a,b,c){if(c===1)for(var d=cq(b,B.cookie,void 0,Ar()),e=m(d),f=e.next();!f.done;f=e.next()){var g=Vr(f.value.split(".")),h=g.length===0?null:{version:g[0],gclid:g[2],timestamp:(Number(g[1])||0)*1E3,labels:g.slice(3)};h!=null&&(h.od=void 0,h.qa=new er,h.oa=[c],Qr(a,h))}else if(c===2){var l=Ur(b);if(l)for(var n=m(l),p=n.next();!p.done;p=n.next()){var q=p.value;q.od=void 0;q.oa=q.oa;Qr(a,q)}}}
function Zr(a){var b=Er(a),c=Ur("gcl_dc");if(c)for(var d=m(c),e=d.next();!e.done;e=d.next()){var f=e.value;f.od=void 0;f.oa=f.oa||[2];Qr(b,f)}b.sort(function(g,h){var l=g.oa&&g.oa.includes(1),n=h.oa&&h.oa.includes(1);return l&&!n?-1:!l&&n?1:h.timestamp-g.timestamp});return Rr(b)}function Jr(a){return Mr(a).map(function(b){b.qa=new er;b.oa=[1];return b})}
function Lr(a,b){if(!a.length)return b;if(!b.length)return a;var c={};return a.concat(b).filter(function(d){return c.hasOwnProperty(d)?!1:c[d]=!0})}function Hr(a){return a&&typeof a==="string"&&a.match(sr)?a:"_gcl"}function $r(a,b){if(a){var c={value:a,qa:new er};fr(c.qa,b);return c}}
function as(a,b,c){var d=Rj(a),e=Lj(d,"query",!1,void 0,"gclsrc"),f=$r(Lj(d,"query",!1,void 0,"gclid"),c?4:2);if(b&&(!f||!e)){var g=d.hash.replace("#","");f||(f=$r(Ij(g,"gclid",!1),3));e||(e=Ij(g,"gclsrc",!1))}return f&&(e===void 0||e==="aw"||e==="aw.ds"||Yf(8)&&e==="aw.dv")?[f]:[]}
function bs(a,b){var c=Rj(a),d=Lj(c,"query",!1,void 0,"gclid"),e=Lj(c,"query",!1,void 0,"gclsrc"),f=Lj(c,"query",!1,void 0,"wbraid");f=$b(f);var g=Lj(c,"query",!1,void 0,"gbraid"),h=Lj(c,"query",!1,void 0,"gad_source"),l=Lj(c,"query",!1,void 0,"dclid");if(b&&!(d&&e&&f&&g)){var n=c.hash.replace("#","");d=d||Ij(n,"gclid",!1);e=e||Ij(n,"gclsrc",!1);f=f||Ij(n,"wbraid",!1);g=g||Ij(n,"gbraid",!1);h=h||Ij(n,"gad_source",!1)}return cs(d,e,l,f,g,h)}
function ds(a,b,c){var d=Rj(a),e=Lj(d,"query",!1,void 0,"gclsrc"),f=$r(Lj(d,"query",!1,void 0,"gclid"),c?4:2),g=$r(Lj(d,"query",!1,void 0,"dclid"),c?4:2);if(b&&(!e||!f)){var h=d.hash.replace("#","");f||(f=$r(Ij(h,"gclid",!1),3));e||(e=Ij(h,"gclsrc",!1))}return f&&e&&(e==="aw.ds"||e==="aw.dv"||e==="3p.ds"||e==="ds")?[f]:g?[g]:[]}function es(){return bs(A.location.href,!0)}
function cs(a,b,c,d,e,f){var g={},h=function(l,n){g[n]||(g[n]=[]);g[n].push(l)};g.gclid=a;g.gclsrc=b;g.dclid=c;if(a!==void 0&&a.match(tr))switch(b){case void 0:h(a,"aw");break;case "aw.ds":h(a,"aw");h(a,"dc");break;case "aw.dv":Yf(8)&&(h(a,"aw"),h(a,"dc"));break;case "ds":h(a,"dc");break;case "3p.ds":h(a,"dc");break;case "gf":h(a,"gf");break;case "ha":h(a,"ha")}c&&h(c,"dc");d!==void 0&&tr.test(d)&&(g.wbraid=d,h(d,"gb"));e!==void 0&&tr.test(e)&&(g.gbraid=e,h(e,"ag"));f!==void 0&&tr.test(f)&&(g.gad_source=
f,h(f,"gs"));return g}function fs(){for(var a=es(),b=!0,c=m(Object.keys(a)),d=c.next();!d.done;d=c.next())if(a[d.value]!==void 0){b=!1;break}b&&(a=bs(A.document.referrer,!1),a.gad_source=void 0);return a}function gs(a){var b=fs();hs(b,!1,a)}
function is(a){var b=as(A.location.href,!0,!1);b.length||(b=as(A.document.referrer,!1,!0));a=a||{};js(a);if(b.length){var c=b[0],d=Nb(),e=uq(a,d,!0),f=Ar(),g=function(){Br(f)&&e.expires!==void 0&&kr("gclid",{value:{value:c.value,creationTimeMs:d,linkDecorationSources:c.qa.get()},expires:Number(e.expires)})};Hl(function(){g();Br(f)||Il(g,f)},f)}}
function js(a){var b=B.referrer?Lj(Rj(B.referrer),"host"):"";if(yr.test(b)||zr.test(b)||ks()){var c;a:{for(var d=Rj(A.location.href),e=Jj(Lj(d,"query")),f=m(Object.keys(e)),g=f.next();!g.done;g=f.next()){var h=g.value;if(!rr[h]){var l=e[h][0]||"",n;if(!l||l.length<50||l.length>200)n=!1;else{var p=gr(l),q;if(p)c:{var r=p;if(r&&r.length!==0){var t=0;try{for(var u=10;t<r.length&&!(u--<=0);){var v=hr(r,t);if(v===void 0)break;var x=m(v),y=x.next().value,z=x.next().value,C=y,D=z,I=C&7;if(C>>3===16382){if(I!==
0)break;var G=hr(r,D);if(G===void 0)break;q=m(G).next().value===1;break c}var N;d:{var S=void 0,W=r,ea=D;switch(I){case 0:N=(S=hr(W,ea))==null?void 0:S[1];break d;case 1:N=ea+8;break d;case 2:var ja=hr(W,ea);if(ja===void 0)break;var fa=m(ja),sa=fa.next().value;N=fa.next().value+sa;break d;case 5:N=ea+4;break d}N=void 0}if(N===void 0||N>r.length||N<=t)break;t=N}}catch(ma){}}q=!1}else q=!1;n=q}if(n){c=l;break a}}}c=void 0}var da=c;da&&ls("gcl_aw",da,7,a)}}
function ls(a,b,c,d){ms(a,[{version:"",gclid:b,timestamp:Nb(),qa:Tr(c)}],d)}
function ms(a,b,c){c=c||{};var d=Ar(),e=function(){if(Br(d)&&b.length>0){var f=Ur(a)||[];b.forEach(function(g){var h=uq(c,g.timestamp,!0);h.expires!==void 0&&Qr(f,{version:"",gclid:g.gclid,timestamp:g.timestamp,expires:Number(h.expires),qa:g.qa,labels:g.labels},!0)});f.length&&kr(a,f.map(function(g){var h={value:g.gclid,creationTimeMs:g.timestamp,linkDecorationSources:g.qa?g.qa.get():0},l;if((l=g.labels)==null?0:l.length)h.labels=g.labels;return{value:h,expires:Number(g.expires)}}))}};Hl(function(){Br(d)?
e():Il(e,d)},d)}
function hs(a,b,c,d,e){c=c||{};e=e||[];var f=Hr(c.prefix),g=d||Nb(),h=Math.round(g/1E3),l=Ar(),n=!1,p=!1,q=Yf(9),r=function(){if(Br(l)){var t=uq(c,g,!0);t.Mc=l;for(var u=function(W,ea){var ja=Ir(W,f);ja&&(oq(ja,ea,t),W!=="gb"&&(n=!0))},v=function(W){var ea=["GCL",h,W];e.length>0&&ea.push(e.join("."));return ea.join(".")},x=m(["aw","dc","gf","ha","gp"]),y=x.next();!y.done;y=x.next()){var z=y.value;a[z]&&u(z,v(a[z][0]))}if((!n||q)&&a.gb){var C=a.gb[0],D=Ir("gb",f);!b&&Er(D).some(function(W){return W.gclid===C&&
W.labels&&W.labels.length>0})||u("gb",v(C))}}if(!p&&a.gbraid&&Br("ad_storage")&&(p=!0,!n||q)){var I=a.gbraid,G=Ir("ag",f);if(b||!Jr(G).some(function(W){return W.gclid===I&&W.labels&&W.labels.length>0})){var N={},S=(N.k=I,N.i=""+h,N.b=e,N);Aq(G,S,5,c,g)}}ns(a,f,g,c)};Hl(function(){r();Br(l)||Il(r,l)},l)}
function ns(a,b,c,d){if(a.gad_source!==void 0&&Br("ad_storage")){var e=qd();if(e!=="r"&&e!=="h"){var f=a.gad_source,g=Ir("gs",b);if(g){var h=Math.floor((Nb()-(pd()||0))/1E3),l,n=ir(),p={};l=(p.k=f,p.i=""+h,p.u=n,p);Aq(g,l,5,d,c)}}}}function os(a,b,c){for(var d=wq(b,c),e=0;e<d.length;++e)if(Nr(d[e])>a)return!0;return!1}
function ps(a){var b=qs,c=rs(a.prefix);Cr(function(){for(var d=Hr(a.prefix),e=m(b),f=e.next();!f.done;f=e.next()){var g=f.value,h=c[g];if(h){var l=Math.min(ss(h),Nb()),n=uq(a,l,!0);n.Mc=Ar();var p=Ir(g,d);p&&oq(p,h,n)}}var q=Uq(!0);hs(cs(q.gclid,q.gclsrc),!1,a)},Ar())}
function rs(a){var b=Uq(!0),c=Hr(a),d={},e;for(e in xr)if(xr.hasOwnProperty(e)){var f=e,g=Ir(f,c);if(g!==void 0){var h=b[g];if(h){var l=ss(h),n;a:{for(var p=Math.min(l,Nb())||Nb(),q=cq(g,B.cookie,void 0,Ar()),r=0;r<q.length;++r)if(ss(q[r])>p){n=!0;break a}n=!1}n||(d[f]=h)}}}return d}
function ts(a){var b=["ag"],c=Uq(!0),d=Hr(a.prefix);Cr(function(){for(var e=0;e<b.length;++e){var f=Ir(b[e],d);if(f){var g=c[f];if(g){var h=$p(g,5);if(h){var l=Nr(h);l||(l=Nb());if(os(l,f,5))break;h.i=""+Math.round(l/1E3);Aq(f,h,5,a,l)}}}}},["ad_storage"])}function Ir(a,b){var c=xr[a];if(c!==void 0)return b+c}function ss(a){return Vr(a.split(".")).length!==0?(Number(a.split(".")[1])||0)*1E3:0}function Nr(a){return a?(Number(a.i)||0)*1E3:0}
function Vr(a){return a.length<3||a[0]!=="GCL"&&a[0]!=="1"||!/^\d+$/.test(a[1])||!tr.test(a[2])?[]:a}function us(a,b,c,d){var e=qs;if(Array.isArray(a)&&Sp(A)){var f=Hr(d),g=function(){for(var h={},l=0;l<e.length;++l){var n=Ir(e[l],f);if(n){var p=cq(n,B.cookie,void 0,Ar());p.length&&(h[n]=p.sort()[p.length-1])}}return h};Cr(function(){ar(g,a,b,c)},Ar())}}
function vs(a,b,c){var d=qs;if(Yf(13)&&Array.isArray(a)&&Sp(A)){var e=function(){for(var f={},g=0;g<d.length;++g){var h=vr[d[g]];if(h){var l=cq(h,B.cookie,void 0,Ar());if(l.length){for(var n=void 0,p=0,q=m(l),r=q.next();!r.done;r=q.next()){var t=r.value,u=$p(t,4);if(u&&(u.m==="1"||Yf(16))){var v=Nr(u);v>=p&&(p=v,n=t)}}n&&(f[h]=n)}}}return f};Cr(function(){ar(e,a,b,c)},Ar())}}
function ws(a,b,c,d){if(Array.isArray(a)&&Sp(A)){var e=["ag"],f=Hr(d),g=function(){for(var h={},l=0;l<e.length;++l){var n=Ir(e[l],f);if(!n)return{};var p=wq(n,5);if(p.length){var q=p.sort(function(r,t){return Nr(t)-Nr(r)})[0];h[n]=aq(q,5)}}return h};Cr(function(){ar(g,a,b,c)},["ad_storage"])}}function Rr(a){return a.filter(function(b){return tr.test(b.gclid)})}
function xs(a,b){if(Sp(A)){for(var c=Hr(b.prefix),d={},e=0;e<a.length;e++)xr[a[e]]&&(d[a[e]]=xr[a[e]]);Cr(function(){Gb(d,function(f,g){var h=cq(c+g,B.cookie,void 0,Ar());h.sort(function(t,u){return ss(u)-ss(t)});if(h.length){var l=h[0],n=ss(l),p=Vr(l.split(".")).length!==0?l.split(".").slice(3):[],q={},r;r=Vr(l.split(".")).length!==0?l.split(".")[2]:void 0;q[f]=[r];hs(q,!0,b,n,p)}})},Ar())}}
function ys(a){var b=["ag"],c=["gbraid"];Cr(function(){for(var d=Hr(a.prefix),e=0;e<b.length;++e){var f=Ir(b[e],d);if(!f)break;var g=wq(f,5);if(g.length){var h=g.sort(function(q,r){return Nr(r)-Nr(q)})[0],l=Nr(h),n=h.b,p={};p[c[e]]=h.k;hs(p,!0,a,l,n)}}},["ad_storage"])}function zs(a,b){for(var c=0;c<b.length;++c)if(a[b[c]])return!0;return!1}
function As(a){function b(h,l,n){n&&(h[l]=n)}if(El()){var c=es(),d;a.includes("gad_source")&&(d=c.gad_source!==void 0?c.gad_source:Uq(!1)._gs);if(zs(c,a)||d){var e={};b(e,"gclid",c.gclid);b(e,"dclid",c.dclid);b(e,"gclsrc",c.gclsrc);b(e,"wbraid",c.wbraid);b(e,"gbraid",c.gbraid);br(function(){return e},3);var f={},g=(f._up="1",f);b(g,"_gs",d);br(function(){return g},1)}}}function ks(){var a=Rj(A.location.href);return Lj(a,"query",!1,void 0,"gad_source")}
function Bs(a){if(!Yf(1))return null;var b=Uq(!0).gad_source;if(b!=null)return A.location.hash="",b;if(Yf(2)){b=ks();if(b!=null)return b;var c=es();if(zs(c,a))return"0"}return null}function Cs(a){var b=Bs(a);b!=null&&br(function(){var c={};return c.gad_source=b,c},4)}
function Ds(a,b,c){var d=[];if(b.length===0)return d;for(var e={},f=0;f<b.length;f++){var g=b[f],h=g.zg?g.zg:"gcl";if((g.labels||[]).indexOf(c)===-1){a.push(0);var l=!1,n=void 0;if((n=g.oa)==null?0:n.includes(2))l=!0;var p=void 0;((p=g.oa)==null?0:p.includes(1))&&!e[h]&&(l=!0,e[h]=!0);l&&d.push(g)}else{a.push(1);var q=void 0;if((q=g.oa)==null?0:q.includes(1))e[h]=!0}}return d}
function Es(a,b,c,d,e){e=e===void 0?!1:e;var f=[];c=c||{};if(!Br(Ar()))return f;var g=Er(a,e),h=Ds(f,g,b);if(h.length&&!d){for(var l=[],n=!1,p=m(h),q=p.next();!q.done;q=p.next()){var r=q.value,t=r,u=t.version,v=t.gclid,x=t.timestamp,y=t.oa,z=(t.labels||[]).concat([b]),C=void 0;if(((C=y)==null?0:C.includes(1))&&!n){var D=[u,Math.round(x/1E3),v].concat(z).join("."),I=uq(c,x,!0);I.Mc=Ar();oq(a,D,I);n=!0}var G=void 0;e&&((G=y)==null?0:G.includes(2))&&l.push(na(Object,"assign").call(Object,{},r,{labels:z}))}l.length&&
ms("gcl_gb",l,c)}return f}
function Fs(a,b,c){c=c===void 0?!1:c;var d=[];b=b||{};var e=Gr(b,c),f=Ds(d,e,a);if(f.length){for(var g=[],h={},l=m(f),n=l.next();!n.done;n=l.next()){var p=n.value,q=Hr(b.prefix),r=Ir(p.zg,q);if(!r)return d;var t=p,u=t.version,v=t.gclid,x=t.timestamp,y=t.oa,z=Math.round(x/1E3),C=Lr(t.labels||[],[a]),D=void 0;if((D=y)==null?0:D.includes(1))if(p.zg==="ag"&&!h.ag){var I={},G=(I.k=v,I.i=""+z,I.b=C,I);Aq(r,G,5,b,x);h.ag=!0}else if(p.zg==="gb"&&!h.gb){var N=[u,z,v].concat(C).join("."),S=uq(b,x,!0);S.Mc=
Ar();oq(r,N,S);h.gb=!0}var W=void 0;c&&((W=y)==null?0:W.includes(2))&&g.push(na(Object,"assign").call(Object,{},p,{labels:C}))}g.length&&ms("gcl_gb",g,b)}return d}function Gs(a,b){var c=Hr(b),d=Ir(a,c);if(!d)return 0;var e;e=a==="ag"?Jr(d):Er(d);for(var f=0,g=0;g<e.length;g++)f=Math.max(f,e[g].timestamp);return f}function Hs(a){for(var b=0,c=m(Object.keys(a)),d=c.next();!d.done;d=c.next())for(var e=a[d.value],f=0;f<e.length;f++)b=Math.max(b,Number(e[f].timestamp));return b}
function Is(a){var b=Math.max(Gs("aw",a),Hs(Br(Ar())?Rp():{})),c=Math.max(Gs("gb",a),Hs(Br(Ar())?Rp("_gac_gb",!0):{}));c=Math.max(c,Gs("ag",a));return c>b};var Js=RegExp("^UA-\\d+-\\d+%3A[\\w-]+(?:%2C[\\w-]+)*(?:%3BUA-\\d+-\\d+%3A[\\w-]+(?:%2C[\\w-]+)*)*$"),Ks=/^~?[\w-]+(?:\.~?[\w-]+)*$/,Ls=/^\d+\.fls\.doubleclick\.net$/,Ms=/;gac=([^;?]+)/,Ns=/;gacgb=([^;?]+)/;
function Os(a,b){if(Ls.test(B.location.host)){var c=B.location.href.match(b);return c&&c.length===2&&c[1].match(Js)?Kj(c[1])||"":""}for(var d=[],e=m(Object.keys(a)),f=e.next();!f.done;f=e.next()){for(var g=f.value,h=[],l=a[g],n=0;n<l.length;n++)h.push(l[n].gclid);d.push(g+":"+h.join(","))}return d.length>0?d.join(";"):""}
function Ps(a,b,c){for(var d=Br(Ar())?Rp("_gac_gb",!0):{},e=[],f=!1,g=m(Object.keys(d)),h=g.next();!h.done;h=g.next()){var l=h.value,n=Es("_gac_gb_"+l,a,b,c);f=f||n.length!==0&&n.some(function(p){return p===1});e.push(l+":"+n.join(","))}return{Rr:f?e.join(";"):"",Qr:Os(d,Ns)}}function Qs(a){var b=B.location.href.match(new RegExp(";"+a+"=([^;?]+)"));return b&&b.length===2&&b[1].match(Ks)?b[1]:void 0}
function Rs(a){var b={},c,d,e;Ls.test(B.location.host)&&(c=Qs("gclgs"),d=Qs("gclst"),e=Qs("gcllp"));if(c&&d&&e)b.Eg=c,b.Wh=d,b.Uh=e;else{var f=Nb(),g=Mr((a||"_gcl")+"_gs"),h=g.map(function(p){return p.gclid}),l=g.map(function(p){return f-p.timestamp}),n=g.map(function(p){return p.od});h.length>0&&l.length>0&&n.length>0&&(b.Eg=h.join("."),b.Wh=l.join("."),b.Uh=n.join("."))}return b}
function Ss(a,b){var c=a.split("."),d=b?b.split("."):[],e=d.length===c.length?d:void 0;return c.map(function(f,g){var h={gclid:f};if(e){var l=e[g].split("_");if(l.length===2){h.qa=new er(Number(l[0]));var n;var p=Number(l[1]);if(p===0)n=[0];else{var q=[];p&1&&q.push(1);p&2&&q.push(2);p&4&&q.push(3);p&8&&q.push(4);p&16&&q.push(5);n=q}h.oa=n}}return h})}
function Ts(a,b,c,d){d=d===void 0?!1:d;if(Ls.test(B.location.host)){var e=Qs(c);if(e){if(Yf(17)){var f=Qs(c+"_src");return Ss(e,f)}if(d){var g=new er;fr(g,2);fr(g,3);return e.split(".").map(function(r){return{gclid:r,qa:g,oa:[1]}})}return e.split(".").map(function(r){return{gclid:r,qa:new er,oa:[1]}})}}else{if(b==="gclid"){for(var h=Er((a||"_gcl")+"_aw",d),l=Number(Xf[4]===void 0?0:Xf[4]),n=m(Us()),p=n.next();!p.done;p=n.next()){var q=p.value;q.timestamp>l&&Qr(h,q)}return h}if(b==="wbraid")return Er((a||
"_gcl")+"_gb",d);if(b==="braids")return Gr({prefix:a},d)}return[]}function Us(){return(wq(vr.aw,4)||[]).filter(function(a){return a.m==="1"}).map(function(a){return{gclid:a.k,timestamp:Number(a.i),version:"",oa:[5]}})}function Vs(a){for(var b=0,c=m(a),d=c.next();!d.done;d=c.next()){var e=d.value;e>0&&(b|=1<<e-1)}return b.toString()}function Ws(a){return Ls.test(B.location.host)?!(Qs("gclaw")||Qs("gac")):Is(a)}
function Xs(a,b,c,d){d=d===void 0?!1:d;var e;e=c?Fs(a,b,d):Es((b&&b.prefix||"_gcl")+"_gb",a,b,void 0,d);return e.length===0||e.every(function(f){return f===0})?"":e.join(".")};function ht(a,b,c){var d=R(a,F.D.Ta);if(d&&typeof d==="object")for(var e=m(Object.keys(d)),f=e.next();!f.done;f=e.next()){var g=f.value,h=d[g];if(h!==void 0){h===null&&(h="");var l="gap."+g,n=String(h);c?c(l,n):b[l]=n}}};var it=!1,jt=[];function kt(){if(!it){it=!0;for(var a=jt.length-1;a>=0;a--)jt[a]();jt=[]}};function lt(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b};function mt(a,b,c){return typeof a.addEventListener==="function"?(a.addEventListener(b,c,!1),!0):!1}function nt(a,b,c){typeof a.removeEventListener==="function"&&a.removeEventListener(b,c,!1)};function ot(a,b,c,d){d=d===void 0?!1:d;a.google_image_requests||(a.google_image_requests=[]);var e=Pp(a.document);if(c){var f=function(){if(c){var g=a.google_image_requests,h=Dc(g,e);h>=0&&Array.prototype.splice.call(g,h,1)}nt(e,"load",f);nt(e,"error",f)};mt(e,"load",f);mt(e,"error",f)}d&&(e.attributionSrc="");e.src=b;a.google_image_requests.push(e)}
function pt(a){var b;b=b===void 0?!1:b;var c="https://pagead2.googlesyndication.com/pagead/gen_204?id=tcfe";Ip(a,function(d,e){if(d||d===0)c+="&"+e+"="+encodeURIComponent(String(d))});qt(c,b)}
function qt(a,b){var c=window,d;b=b===void 0?!1:b;d=d===void 0?!1:d;if(c.fetch){var e={keepalive:!0,credentials:"include",redirect:"follow",method:"get",mode:"no-cors"};d&&(e.mode="cors","setAttributionReporting"in XMLHttpRequest.prototype?e.attributionReporting={eventSourceEligible:"true",triggerEligible:"false"}:e.headers={"Attribution-Reporting-Eligible":"event-source"});c.fetch(a,e)}else ot(c,a,b===void 0?!1:b,d===void 0?!1:d)};function rt(){this.fa=this.fa;this.R=this.R}rt.prototype.fa=!1;rt.prototype.dispose=function(){this.fa||(this.fa=!0,this.N())};rt.prototype[Symbol.dispose]=function(){this.dispose()};rt.prototype.addOnDisposeCallback=function(a,b){this.fa?b!==void 0?a.call(b):a():(this.R||(this.R=[]),b&&(a=a.bind(b)),this.R.push(a))};rt.prototype.N=function(){if(this.R)for(;this.R.length;)this.R.shift()()};function st(a){a.addtlConsent===void 0||vf(a.addtlConsent)||(a.addtlConsent=void 0);a.gdprApplies===void 0||wf(a.gdprApplies)||(a.gdprApplies=void 0);return a.tcString!==void 0&&!vf(a.tcString)||a.listenerId!==void 0&&!uf(a.listenerId)?2:a.cmpStatus&&a.cmpStatus!=="error"?0:3}var tt=function(a,b){b=b===void 0?{}:b;rt.call(this);this.H=null;this.ja={};this.ya=0;this.Z=null;this.K=a;var c;this.timeoutMs=(c=b.timeoutMs)!=null?c:500;var d;this.Ej=(d=b.Ej)!=null?d:!1};wa(tt,rt);
tt.prototype.N=function(){this.ja={};this.Z&&(nt(this.K,"message",this.Z),delete this.Z);delete this.ja;delete this.K;delete this.H;rt.prototype.N.call(this)};var vt=function(a){return typeof a.K.__tcfapi==="function"||ut(a)!=null};
tt.prototype.addEventListener=function(a){var b=this,c={internalBlockOnErrors:this.Ej},d=Hp(function(){a(c)}),e=0;this.timeoutMs!==-1&&(e=setTimeout(function(){c.tcString="tcunavailable";c.internalErrorState=1;d()},this.timeoutMs));var f=function(g,h){clearTimeout(e);g?(c=g,c.internalErrorState=st(c),c.internalBlockOnErrors=b.Ej,h&&c.internalErrorState===0||(c.tcString="tcunavailable",h||(c.internalErrorState=3))):(c.tcString="tcunavailable",c.internalErrorState=3);a(c)};try{wt(this,"addEventListener",
f)}catch(g){c.tcString="tcunavailable",c.internalErrorState=3,e&&(clearTimeout(e),e=0),d()}};tt.prototype.removeEventListener=function(a){a&&a.listenerId&&wt(this,"removeEventListener",null,a.listenerId)};
var zt=function(a,b,c){var d;d=d===void 0?"755":d;var e;a:{if(a.publisher&&a.publisher.restrictions){var f=a.publisher.restrictions[b];if(f!==void 0){e=f[d===void 0?"755":d];break a}}e=void 0}var g=e;if(g===0)return!1;var h=c;c===2?(h=0,g===2&&(h=1)):c===3&&(h=1,g===1&&(h=0));var l;if(h===0)if(a.purpose&&a.vendor){var n=xt(a.vendor.consents,d===void 0?"755":d);l=n&&b==="1"&&a.purposeOneTreatment&&a.publisherCC==="CH"?!0:n&&xt(a.purpose.consents,b)}else l=!0;else l=h===1?a.purpose&&a.vendor?xt(a.purpose.legitimateInterests,
b)&&xt(a.vendor.legitimateInterests,d===void 0?"755":d):!0:!0;return l},xt=function(a,b){return!(!a||!a[b])},wt=function(a,b,c,d){c||(c=function(){});var e=a.K;if(typeof e.__tcfapi==="function"){var f=e.__tcfapi;f(b,2,c,d)}else if(ut(a)){At(a);var g=++a.ya;a.ja[g]=c;if(a.H){var h={};a.H.postMessage((h.__tcfapiCall={command:b,version:2,callId:g,parameter:d},h),"*")}}else c({},!1)},ut=function(a){if(a.H)return a.H;a.H=Np(a.K,"__tcfapiLocator");return a.H},At=function(a){if(!a.Z){var b=function(c){if(c.source===
a.H)try{var d;d=(vf(c.data)?JSON.parse(c.data):c.data).__tcfapiReturn;a.ja[d.callId](d.returnValue,d.success)}catch(e){}};a.Z=b;mt(a.K,"message",b)}},Bt=function(a){if(a.gdprApplies===!1)return!0;a.internalErrorState===void 0&&(a.internalErrorState=st(a));return a.cmpStatus==="error"||a.internalErrorState!==0?a.internalBlockOnErrors?(pt({e:String(a.internalErrorState)}),!1):!0:a.cmpStatus!=="loaded"||a.eventStatus!=="tcloaded"&&a.eventStatus!=="useractioncomplete"?!1:!0};var Ct={1:0,3:0,4:0,7:3,9:3,10:3};function Dt(){return kj("tcf",function(){return{}})}var Et=function(){return new tt(A,{timeoutMs:-1})};
function Ft(){var a=Dt(),b=Et();vt(b)&&!Gt()&&!Ht()&&P(124);if(!a.active&&vt(b)){Gt()&&(a.active=!0,a.purposes={},a.cmpId=0,a.tcfPolicyVersion=0,tl().active=!0,a.tcString="tcunavailable");cp();try{b.addEventListener(function(c){if(c.internalErrorState!==0)It(a),dp([F.D.ka,F.D.Xa,F.D.ma]),tl().active=!0;else if(a.gdprApplies=c.gdprApplies,a.cmpId=c.cmpId,a.enableAdvertiserConsentMode=c.enableAdvertiserConsentMode,Ht()&&(a.active=!0),!Jt(c)||Gt()||Ht()){a.tcfPolicyVersion=c.tcfPolicyVersion;var d;if(c.gdprApplies===
!1){var e={},f;for(f in Ct)Ct.hasOwnProperty(f)&&(e[f]=!0);d=e;b.removeEventListener(c)}else if(Jt(c)){var g={},h;for(h in Ct)if(Ct.hasOwnProperty(h))if(h==="1"){var l,n=c,p={Ur:!0};p=p===void 0?{}:p;l=Bt(n)?n.gdprApplies===!1?!0:n.tcString==="tcunavailable"?!p.idpcApplies:(p.idpcApplies||n.gdprApplies!==void 0||p.Ur)&&(p.idpcApplies||vf(n.tcString)&&n.tcString.length)?zt(n,"1",0):!0:!1;g["1"]=l}else g[h]=zt(c,h,Ct[h]);d=g}if(d){a.tcString=c.tcString||"tcempty";a.purposes=d;var q={},r=(q[F.D.ka]=
a.purposes["1"]?"granted":"denied",q);a.gdprApplies!==!0?(dp([F.D.ka,F.D.Xa,F.D.ma]),tl().active=!0):(r[F.D.Xa]=a.purposes["3"]&&a.purposes["4"]?"granted":"denied",typeof a.tcfPolicyVersion==="number"&&a.tcfPolicyVersion>=4?r[F.D.ma]=a.purposes["1"]&&a.purposes["7"]?"granted":"denied":dp([F.D.ma]),Vo(r,{eventId:0},{gdprApplies:a?a.gdprApplies:void 0,tcString:Kt()||""}))}}else dp([F.D.ka,F.D.Xa,F.D.ma])})}catch(c){It(a),dp([F.D.ka,F.D.Xa,F.D.ma]),tl().active=!0}}}
function It(a){a.type="e";a.tcString="tcunavailable"}function Jt(a){return a.eventStatus==="tcloaded"||a.eventStatus==="useractioncomplete"||a.eventStatus==="cmpuishown"}function Gt(){return A.gtag_enable_tcf_support===!0}function Ht(){return Dt().enableAdvertiserConsentMode===!0}function Kt(){var a=Dt();if(a.active)return a.tcString}function Lt(){var a=Dt();if(a.active&&a.gdprApplies!==void 0)return a.gdprApplies?"1":"0"}
function Mt(a){if(!Ct.hasOwnProperty(String(a)))return!0;var b=Dt();return b.active&&b.purposes?!!b.purposes[String(a)]:!0};var Nt=[F.D.ka,F.D.ra,F.D.ma,F.D.Xa],Ot={},Pt=(Ot[F.D.ka]=1,Ot[F.D.ra]=2,Ot);function Qt(a){if(a===void 0)return 0;switch(O(a,F.D.Rc)){case void 0:return 1;case !1:return 3;default:return 2}}function Rt(){return(M(183)?Lf(16).split("~"):Lf(17).split("~")).indexOf(zm())!==-1&&Hc.globalPrivacyControl===!0}function St(a){if(Rt())return!1;var b=Qt(a);if(b===3)return!1;switch(Cl(F.D.Xa)){case 1:case 3:return!0;case 2:return!1;case 4:return b===2;case 0:return!0;default:return!1}}
function Tt(){return El()||!Bl(F.D.ka)||!Bl(F.D.ra)}function Ut(){var a={},b;for(b in Pt)Pt.hasOwnProperty(b)&&(a[Pt[b]]=Cl(b));return"G1"+yf(a[1]||0)+yf(a[2]||0)}var Vt={},Wt=(Vt[F.D.ka]=0,Vt[F.D.ra]=1,Vt[F.D.ma]=2,Vt[F.D.Xa]=3,Vt);function Xt(a){switch(a){case void 0:return 1;case !0:return 3;case !1:return 2;default:return 0}}
function Yt(a){for(var b="1",c=0;c<Nt.length;c++){var d=b,e,f=Nt[c],g=Al.delegatedConsentTypes[f];e=g===void 0?0:Wt.hasOwnProperty(g)?12|Wt[g]:8;var h=tl();h.accessedAny=!0;var l=h.entries[f]||{};e=e<<2|Xt(l.implicit);b=d+(""+"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[e]+"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[Xt(l.declare)<<4|Xt(l.default)<<2|Xt(l.update)])}var n=b,p=(Rt()?1:0)<<3,q=(El()?1:0)<<2,r=Qt(a);b=n+"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[p|
q|r];return b+=""+"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[Al.containerScopedDefaults.ad_storage<<4|Al.containerScopedDefaults.analytics_storage<<2|Al.containerScopedDefaults.ad_user_data]+"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[(Al.usedContainerScopedDefaults?1:0)<<2|Al.containerScopedDefaults.ad_personalization]}function Zt(){return Bl(F.D.ma)?"a":"-"}function $t(){return Bm()||(Gt()||Ht())&&Lt()==="1"?"1":"0"}
function au(){return(Bm()?!0:!(!Gt()&&!Ht())&&Lt()==="1")||!Bl(F.D.ma)}
function bu(){var a="0",b="0",c;var d=Dt();c=d.active?d.cmpId:void 0;typeof c==="number"&&c>=0&&c<=4095&&(a="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[c>>6&63],b="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[c&63]);var e="0",f;var g=Dt();f=g.active?g.tcfPolicyVersion:void 0;typeof f==="number"&&f>=0&&f<=63&&(e="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[f]);var h=0;Bm()&&(h|=1);Lt()==="1"&&(h|=2);Gt()&&(h|=4);var l;var n=Dt();l=n.enableAdvertiserConsentMode!==
void 0?n.enableAdvertiserConsentMode?"1":"0":void 0;l==="1"&&(h|=8);tl().waitPeriodTimedOut&&(h|=16);return"1"+a+b+e+"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[h]};var cu={UA:1,AW:2,DC:3,G:4,GF:5,GT:12,GTM:14,HA:6,MC:7};
function du(a){a=a===void 0?{}:a;var b=E(5).split("-")[0].toUpperCase(),c,d={ctid:E(5),Do:Jf(15),Io:E(14),Ls:If(7)?2:1,Dt:a.pf,canonicalId:E(6),nt:(c=Ak())==null?void 0:c.canonicalContainerId,Et:a.Tg===void 0?void 0:a.Tg?10:12};d.canonicalId!==a.mc&&(d.mc=a.mc);var e=xk();d.Us=e?e.canonicalContainerId:void 0;If(45)?(d.hi=cu[b],d.hi||(d.hi=0)):d.hi=Dj?13:10;If(47)?(d.bk=0,d.qr=2):If(50)?d.bk=1:d.bk=3;var f=a,g={6:!1};Jf(54)===2?g[7]=!0:Jf(54)===1&&(g[2]=!0);if(Kc){var h=Lj(Rj(Kc),"host");h&&(g[8]=
h.match(/^(www\.)?googletagmanager\.com$/)===null)}var l;g[9]=(l=f.ef)!=null?l:!1;var n=Fk(),p;g[10]=(p=n==null?void 0:n.fromContainerExecution)!=null?p:!1;d.zr=g;return Cf(d,a.Pn)};var gu=function(a,b,c,d,e){this.endpoint=a;this.fa=c;this.ja=d;this.parameterEncoding=e;this.Z=b.slice()};gu.prototype.K=function(){return Xo(this.Z)};gu.prototype.isSupported=function(){return!0};gu.prototype.R=function(){var a=Mm[this.endpoint](void 0);return Sb(a,"https://")?a.substring(8):Sb(a,"http://")?a.substring(7):a};var hu=function(a,b){this.methodName=a;this.R=b};hu.prototype.sendRequest=function(a,b,c){if(this.isSupported())if((c==null?void 0:c.body)===void 0||this.H())try{this.K(a,b,c)}catch(d){a.rd(d)}else a.rd("Request method "+this.methodName+" does not support a request body.");else a.rd("Request method "+this.methodName+" is not supported.")};var iu=function(){hu.call(this,"ImagePixel",3)};wa(iu,hu);iu.prototype.isSupported=function(){return!0};iu.prototype.H=function(){return!1};
iu.prototype.K=function(a,b,c){Zc(b,function(){a.jf()},function(){a.onFailure(void 0)},c==null?void 0:c.af)};var ju=function(){hu.call(this,"SendBeacon",1)};wa(ju,hu);ju.prototype.isSupported=function(){return kd()};ju.prototype.H=function(){return!0};ju.prototype.K=function(a,b,c){jd(b,c==null?void 0:c.body)?a.jf():a.rd(void 0)};var ku=function(){hu.call(this,"Fetch",1)};wa(ku,hu);ku.prototype.isSupported=function(){return yb(A.fetch)};ku.prototype.H=function(){return!0};
ku.prototype.K=function(a,b,c){A.fetch(b,c==null?void 0:c.Gb).then(function(d){if(d.ok)a.pe(d);else if(d.status===0)a.jf();else a.onFailure("Fetch failed with status code "+d.status+".")}).catch(function(d){a.rd(d)})};var lu=new iu,mu=new ju,nu=new ku;var ou=function(){};ou.prototype.K=function(){return[]};var T={W:{Jk:1,nj:2,Fk:3,ml:4,Gk:5,yd:6,kl:7,Mq:8,qn:9,Hk:10,Ik:11,Fh:12,Dm:13,Am:14,Cm:15,zm:16,Bm:17,ym:18,To:19,xq:20,yq:21,fj:22,un:24,Om:25,Sk:26,Tk:27,Rk:28,Uk:29,rj:30,Ok:31,Zo:32}};T.W[T.W.Jk]="ALLOW_INTEREST_GROUPS";T.W[T.W.nj]="SERVER_CONTAINER_URL";T.W[T.W.Fk]="ADS_DATA_REDACTION";T.W[T.W.ml]="CUSTOMER_LIFETIME_VALUE";T.W[T.W.Gk]="ALLOW_CUSTOM_SCRIPTS";T.W[T.W.yd]="ANY_COOKIE_PARAMS";T.W[T.W.kl]="COOKIE_EXPIRES";T.W[T.W.Mq]="LEGACY_ENHANCED_CONVERSION_JS_VARIABLE";T.W[T.W.qn]="RESTRICTED_DATA_PROCESSING";
T.W[T.W.Hk]="ALLOW_DISPLAY_FEATURES";T.W[T.W.Ik]="ALLOW_GOOGLE_SIGNALS";T.W[T.W.Fh]="GENERATED_TRANSACTION_ID";T.W[T.W.Dm]="FLOODLIGHT_COUNTING_METHOD_UNKNOWN";T.W[T.W.Am]="FLOODLIGHT_COUNTING_METHOD_STANDARD";T.W[T.W.Cm]="FLOODLIGHT_COUNTING_METHOD_UNIQUE";T.W[T.W.zm]="FLOODLIGHT_COUNTING_METHOD_PER_SESSION";T.W[T.W.Bm]="FLOODLIGHT_COUNTING_METHOD_TRANSACTIONS";T.W[T.W.ym]="FLOODLIGHT_COUNTING_METHOD_ITEMS_SOLD";T.W[T.W.To]="ADS_OGT_V1_USAGE";T.W[T.W.xq]="FORM_INTERACTION_PERMISSION_DENIED";
T.W[T.W.yq]="FORM_SUBMIT_PERMISSION_DENIED";T.W[T.W.fj]="MICROTASK_NOT_SUPPORTED";T.W[T.W.un]="SET_ENCRYPTED_DATA_TO_CACHE";T.W[T.W.Om]="GET_ENCRYPTED_DATA_FROM_CACHE";T.W[T.W.Sk]="CONFIG_DETECTED_WITH_NO_PARAM";T.W[T.W.Tk]="CONFIG_DETECTED_WITH_PARAM";T.W[T.W.Rk]="CONFIG_CONSENT_SET_BEFORE";T.W[T.W.Uk]="CONFIG_SET_USED_BEFORE";T.W[T.W.rj]="SHADOW_DOM_AUTO_PII";T.W[T.W.Ok]="CCD_USER_DATA_WEB_ON_CONFIG";T.W[T.W.Zo]="BLENDED_USER_DATA";var Bu={},Cu=(Bu[F.D.ui]=T.W.Jk,Bu[F.D.dd]=T.W.nj,Bu[F.D.yc]=T.W.nj,Bu[F.D.mb]=T.W.Fk,Bu[F.D.Ge]=T.W.ml,Bu[F.D.ri]=T.W.Gk,Bu[F.D.Jd]=T.W.yd,Bu[F.D.nb]=T.W.yd,Bu[F.D.Lb]=T.W.yd,Bu[F.D.Id]=T.W.yd,Bu[F.D.vc]=T.W.yd,Bu[F.D.Tb]=T.W.yd,Bu[F.D.Cb]=T.W.kl,Bu[F.D.Wb]=T.W.qn,Bu[F.D.hh]=T.W.Hk,Bu[F.D.Sc]=T.W.Ik,Bu),Du={},Eu=(Du.unknown=T.W.Dm,Du.standard=T.W.Am,Du.unique=T.W.Cm,Du.per_session=T.W.zm,Du.transactions=T.W.Bm,Du.items_sold=T.W.ym,Du);var Fu=function(a,b,c){c=c===void 0?!1:c;sb("GTAG_EVENT_FEATURE_CHANNEL",b);c&&(a.H[b]=!0)},vb=new function(){this.H=[]};function Gu(a){Fu(vb,a,!1)}function Hu(a,b){var c=b===void 0?!1:b,d=vb;c=c===void 0?!1:c;for(var e=Object.keys(a),f=m(Object.keys(Cu)),g=f.next();!g.done;g=f.next()){var h=g.value;e.includes(h)&&Fu(d,Cu[h],c)}};function Iu(a,b){a?a.then(b):b(void 0)}function Ju(a){return Promise.allSettled(a).then(function(b){return b.filter(function(c){return c.status==="fulfilled"}).map(function(c){return c.value})})}function Ku(){var a,b;return{promise:new Promise(function(c,d){a=c;b=d}),resolve:a,reject:b}};function Lu(a,b,c,d,e,f){var g=c.slice(),h;d==null||(h=d.uv)==null||h.call(d,a,b,c,e);var l=Ku(),n=l.promise,p=l.resolve,q=[],r=function(){p(q);var u;d==null||(u=d.Rs)==null||u.call(d,a,b,c,e,q)},t=function(){var u=g.shift();u?u.method.isSupported()?Mu(a,b,u.endpoint,d,q,u.method,e,f,t,r):t():r()};t();return n}
function Mu(a,b,c,d,e,f,g,h,l,n){var p=c.R(a),q={tk:b,endpoint:c,isPrimary:g,sb:void 0,pk:f,jt:{}},r=!1,t=function(z,C){if(r)P(187);else if(r=!0,!u){var D=C||{},I=D.body,G=D.Gb,N=D.af;C=Object.freeze(na(Object,"assign").call(Object,{},I?{body:I}:{},G?{Gb:G}:{},N?{af:N}:{}));if(I&&!f.H())x(),l();else{var S=Nu(z),W=p[0]==="/"?""+p+S:"https://"+p+S;q.sb=W;q.jt=C;var ea;d==null||(ea=d.Ss)==null||ea.call(d,a,na(Object,"assign").call(Object,{},q));var ja={destinationId:a.target.destinationId,endpoint:c.endpoint,
eventId:a.M.eventId,priorityId:a.M.priorityId};f.R===void 0||c.fa!==2&&(c.fa!==1||e.length)||kn.register(ja,f.R,W);var fa=function(da,ma){x();if(q.status!==void 0)return P(192),!1;q.status=da;e.push(q);var Pa;d==null||(Pa=d.uo)==null||Pa.call(d,a,na(Object,"assign").call(Object,{},q),ma);return!0},sa={Fo:ja,rd:function(){fa(2)&&l()},onFailure:function(){fa(3)&&l()},pe:function(da){fa(da.status===0?1:da.ok?0:3,da)&&n()},jf:function(){fa(1)&&n()}};Ou(c,a,W,S,I);f.sendRequest(sa,W,na(Object,"assign").call(Object,
{},I&&{body:I},G&&{Gb:G},N&&{af:N}))}}},u=!1,v,x=function(){v!==void 0&&(A.clearTimeout(v),v=void 0)};M(574)&&(v=A.setTimeout(function(){v=void 0;u=!0;if(q.status===void 0){q.status=4;q.sb===void 0&&(q.sb="[failed to build] "+p);e.push(q);var z;d==null||(z=d.uo)==null||z.call(d,a,na(Object,"assign").call(Object,{},q),void 0);l()}},5E3));var y={Ic:p,method:f,yv:e,isPrimary:g,Ct:h};try{c.H(a,y,t)}catch(z){x(),P(188),l()}}
function Ou(a,b,c,d,e){if(a.ja){var f=b.target.destinationId,g=a.endpoint;if(g===45||g===46||g===69||g===58||g===57){var h=/[?&]tids=([^&]+)/.exec(d);f=h?decodeURIComponent(h[1]).split("~"):[f]}Ml({targetId:f,request:na(Object,"assign").call(Object,{},{url:c,parameterEncoding:a.parameterEncoding,endpoint:a.endpoint},e?{postBody:e}:{}),qb:{eventId:b.M.eventId,priorityId:b.M.priorityId},Fj:{eventId:Q(b,H.J.uf),priorityId:Q(b,H.J.vf)}})}}
function Nu(a){return a&&a!=="?"?a[0]!=="?"?"?".concat(a):a:""};function Pu(a,b,c,d,e){var f;e==null||(f=e.vv)==null||f.call(e,a,b);if(!c.length){var g;e==null||(g=e.Ts)==null||g.call(e,a,b,[]);return Promise.resolve([])}var h=[],l={tk:b,mk:c,jk:d};h.push(Lu(a,b,c,e,!0,l));for(var n=m(d),p=n.next();!p.done;p=n.next())h.push(Lu(a,b,p.value,e,!1,l));return Ju(h).then(function(q){for(var r=[],t=m(q),u=t.next();!u.done;u=t.next())r.push.apply(r,w(u.value));var v;e==null||(v=e.Ts)==null||v.call(e,a,b,r);return r})};function Qu(a,b){var c=Oa.apply(2,arguments),d;b==null||(d=b.wv)==null||d.call(b,a,c);for(var e=[],f=m(c),g=f.next();!g.done;g=f.next())e.push(Ru(a,g.value));for(var h=[],l=m(e),n=l.next();!n.done;n=l.next()){var p=n.value;h.push(Pu(a,p.tk,p.mk,p.jk,b))}Ju(h).then(function(q){for(var r=[],t=m(q),u=t.next();!u.done;u=t.next())r.push.apply(r,w(u.value));var v;b==null||(v=b.Qs)==null||v.call(b,a,c,r)})}
function Ru(a,b){var c=function(f){return f.method.isSupported()&&f.endpoint.isSupported(a)&&f.endpoint.K(a)},d=(b.H(a)||[]).filter(c),e=[];d.length&&(e=(b.K(a)||[]).map(function(f){return f.filter(c)}).filter(function(f){return f.length>0}));return{tk:b,mk:d,jk:e}};var X={V:{Mk:"call_conversion",zd:"ccm_conversion",Qk:"common_aw",xa:"conversion",wq:"floodlight",Yd:"ga_conversion",Zd:"gcp_remarketing",Ka:"page_view",ub:"remarketing",Ob:"user_data_lead",Fb:"user_data_web"}};function bv(a,b){b&&Gb(b,function(c,d){typeof d!=="object"&&d!==void 0&&(a["1p."+c]=String(d))})};var mv={Ng:"value",pb:"conversionCount",Og:1},nv={Ng:"timeouts",pb:"timeouts",Og:0},ov={Ng:"eopCount",pb:"endOfPageCount",Og:0},pv={Ng:"errors",pb:"errors",Og:0},qv=[mv,nv,pv,ov];function rv(a,b){b=b===void 0?1:b;if(!sv(a))return{};var c=tv(qv),d=c[a.pb];if(d===void 0||d===-1)return c;var e={},f=na(Object,"assign").call(Object,{},c,(e[a.pb]=d+b,e));return uv(f)?f:c}
function tv(a){var b;a:{var c=nr("gcl_ctr");if(c.error===0&&c.value&&typeof c.value==="object"){var d=c.value;try{b="value"in d&&typeof d.value==="object"?d.value:void 0;break a}catch(p){}}b=void 0}for(var e=b,f={},g=m(a),h=g.next();!h.done;h=g.next()){var l=h.value;if(e&&sv(l)){var n=e[l.Ng];n===void 0||Number.isNaN(n)?f[l.pb]=-1:f[l.pb]=Number(n)}else f[l.pb]=-1}return f}
function uv(a,b){b=b||{};for(var c=Nb(),d=uq(b,c,!0),e={},f=m(qv),g=f.next();!g.done;g=f.next()){var h=g.value,l=a[h.pb];l!==void 0&&l!==-1&&(e[h.Ng]=l)}e.creationTimeMs=c;return kr("gcl_ctr",{value:e,expires:Number(d.expires)})===0?!0:!1}function sv(a){return Bl(["ad_storage","ad_user_data"])?!a.ft||Yf(a.ft):!1}function vv(a){return Bl(["ad_storage","ad_user_data"])?!a.As||Yf(a.As):!1};function wv(){if(xv()){var a=nr("last_convs");if(a.error===0&&a.value&&typeof a.value==="object"){var b=a.value;if(b.value&&Array.isArray(b.value)){var c=b.value;if(!(c.length>1)){for(var d=[],e=m(c),f=e.next();!f.done;f=e.next()){var g=f.value;if(typeof g!=="object"||g===null||typeof g.random!=="number"||typeof g.label!=="string"||g.label.length>200)return;d.push({random:g.random,label:g.label})}return d}}}}}
function yv(a,b){!xv()||a.length>1||a.length===1&&a[0].label.length>200||(b=b||{},kr("last_convs",{value:a,expires:Number(uq(b).expires)}))}function xv(){return Bl(["ad_storage","ad_user_data"])&&Yf(11)};function zv(a){var b=Math.round(Math.random()*2147483647);return a?String(b^ng(a)&2147483647):String(b)}function Av(a){return[zv(a),Math.round(Nb()/1E3)].join(".")}function Bv(a,b,c,d,e){var f=rq(b),g;return(g=gq(a,f,sq(c),d,e))==null?void 0:g.Cr};var Cv=["1"],Dv={},Ev={};function Fv(a){return Ev[Gv(a)]}function Hv(a,b){b=b===void 0?!0:b;var c=Gv(a.prefix);if(Dv[c])Iv(a),Jv(a);else if(Kv(c,a.path,a.domain)){var d=Fv(a.prefix)||{id:void 0,kc:void 0};b&&Lv(a,d);Iv(a);Jv(a)}else{var e=Tj("auiddc");if(e)sb("TAGGING",17),Dv[c]=e;else if(b){var f=Gv(a.prefix),g=Av();Mv(f,g,a);Kv(c,a.path,a.domain);Iv(a,!0);Jv(a,!0)}}}
function Iv(a,b){(b===void 0?0:b)&&sv(mv)&&or("gcl_ctr");if(vv(mv)&&tv([mv])[mv.pb]===-1){for(var c={},d=(c[mv.pb]=0,c),e=m(qv),f=e.next();!f.done;f=e.next()){var g=f.value;g!==mv&&vv(g)&&(d[g.pb]=0)}uv(d,a)}}function Jv(a,b){(b===void 0?0:b)&&xv()&&or("last_convs");!Bl(["ad_storage","ad_user_data"])||!Yf(12)||wv()||yv([],a)}
function Lv(a,b){var c=Gv(a.prefix),d=Dv[c];if(d){var e=d.split(".");if(e.length===2){var f=Number(e[1])||0;if(f){var g=d;Yf(19)&&b.fi?g=d+"."+(b.sessionId||"-.-")+"."+(b.kc?b.kc:Math.floor(Nb()/1E3))+"."+b.fi+"."+(b.Lc?b.Lc:Math.floor(Nb()/1E3)):b.sessionId&&(g=d+"."+b.sessionId+"."+(b.kc?b.kc:Math.floor(Nb()/1E3)));Mv(c,g,a,f*1E3)}}}}function Mv(a,b,c,d){var e;e=["1",tq(c.domain,c.path),b].join(".");var f=uq(c,d);f.Mc=Nv();oq(a,e,f)}
function Kv(a,b,c){var d=Bv(a,b,c,Cv,Nv());if(!d)return!1;Ov(a,d);return!0}function Ov(a,b){var c=b.split(".");if(c.length===3)Ev[a]={sessionId:c[0]+"."+c[1],kc:Number(c[2])||0,Lc:0};else if(c.length>=2&&(Dv[a]=c[0]+"."+c[1],c.shift(),c.shift(),c.length>=3)){var d={sessionId:c[0]==="-"?void 0:c[0]+"."+c[1],kc:Number(c[2])||0,Lc:0};if(Yf(19)&&c.length>=6){var e=c[3]+"."+c[4],f=Number(c[5])||0;e&&f!==0&&(d.fi=e,d.Lc=f)}Ev[a]=d}}function Gv(a){return(a||"_gcl")+"_au"}
function Pv(a){function b(){Bl(c)&&a()}var c=Nv();Hl(function(){b();Bl(c)||Il(b,c)},c)}function Qv(a){var b=Uq(!0),c=Gv(a.prefix);Pv(function(){var d=b[c];if(d){Ov(c,d);var e=Number(Dv[c].split(".")[1])*1E3;if(e){sb("TAGGING",16);var f=uq(a,e);f.Mc=Nv();var g=["1",tq(a.domain,a.path),d].join(".");oq(c,g,f)}}})}function Rv(a,b,c,d,e){e=e||{};var f=function(){var g={},h=Bv(a,e.path,e.domain,Cv,Nv());h&&(g[a]=h);return g};Pv(function(){ar(f,b,c,d)})}
function Nv(){return["ad_storage","ad_user_data"]};var Vv="email email_address sha256_email_address phone_number sha256_phone_number first_name last_name".split(" "),Wv="first_name sha256_first_name last_name sha256_last_name street sha256_street city region country postal_code".split(" ");function Xv(a,b){if(!b._tag_metadata){for(var c={},d=0,e=0;e<a.length;e++)d+=Yv(a[e],b,c)?1:0;d>0&&(b._tag_metadata=c)}}
function Yv(a,b,c){var d=b[a];if(d===void 0||d===null)return!1;c[a]=Array.isArray(d)?d.map(function(){return{mode:"c"}}):{mode:"c"};return!0}function Zv(a){if(M(523)&&a){Xv(Vv,a);for(var b=Bb(a.address),c=0;c<b.length;c++){var d=b[c];d&&Xv(Wv,d)}var e=a.home_address;e&&Xv(Wv,e)}}
function $v(a,b,c){function d(f,g){g=String(g).substring(0,100);e.push(""+f+encodeURIComponent(g))}if(!c)return"";var e=[];d("i",String(a));d("f",b);c.mode&&d("m",c.mode);c.isPreHashed&&d("p","1");c.rawLength&&d("r",String(c.rawLength));c.normalizedLength&&d("n",String(c.normalizedLength));c.location&&d("l",c.location);c.selector&&d("s",c.selector);return e.join(".")};var aw=void 0;function bw(){if(!aw){var a=om(jm.ba.op,new Map);aw=new og(a)}return aw};var mx=Object.freeze({attributionsrc:""}),nx=Object.freeze({eventSourceEligible:!1,triggerEligible:!0});function ox(){var a=XMLHttpRequest.prototype;return a&&yb(a.setAttributionReporting)};var px=Object.freeze({cache:"no-store",credentials:"include",method:"GET",keepalive:!0,redirect:"follow"});
function qx(a,b,c,d,e,f){if(!yb(A.fetch))return f==null||f(void 0,void 0),!1;var g=na(Object,"assign").call(Object,{},px);b&&(g.body=b,g.method="POST");na(Object,"assign").call(Object,g,d);A.fetch(a,g).then(function(h){if(h.ok){if(h.body){var l=h.body.getReader(),n=new TextDecoder;return new Promise(function(p){function q(){l.read().then(function(r){var t;t=r.done;var u=n.decode(r.value,{stream:!t});u=c.R+u;for(var v=u.indexOf("\n\n");v!==-1;){var x=Zg,y;a:{var z=m(u.substring(0,v).split("\n")),C=
z.next().value,D=z.next().value;if(Sb(C,"event: message")&&Sb(D,"data: ")){var I=D.substring(6);try{y=JSON.parse(I);break a}catch(G){}}y=void 0}x(c,y);u=u.substring(v+2);v=u.indexOf("\n\n")}c.R=u;t?(e==null||e(h),p()):q()}).catch(function(){e==null||e(h);p()})}q()})}e==null||e(h)}else f==null||f(h,void 0)}).catch(function(h){f==null||f(void 0,h)});return!0};var rx=function(a){hu.call(this,"FetchRichResponse",1);this.N=a};wa(rx,hu);rx.prototype.isSupported=function(){return yb(A.fetch)};rx.prototype.H=function(){return!0};rx.prototype.K=function(a,b,c){qx(b,c==null?void 0:c.body,this.N,c==null?void 0:c.Gb,a.pe,function(d,e){a.onFailure(e)})};var Cx=function(){Yg.apply(this,arguments)};wa(Cx,Yg);Cx.prototype.K=function(a,b){Zc(a,void 0,$g(this,b),b.attribution_reporting&&ox()?mx:{})};Cx.prototype.H=function(a,b){var c=b.attribution_reporting&&ox()?{attributionReporting:nx}:{},d=$g(this,b);b.process_response?qx(a,void 0,this,c,void 0,d):md(a,void 0,c,void 0,d)};var Qx=function(a,b){this.H=a;this.timeoutMs=b;this.Rb=void 0},Rx=function(a){a.Rb||(a.Rb=setTimeout(function(){a.H();a.Rb=void 0},a.timeoutMs))},Tn=function(a){a.Rb&&(clearTimeout(a.Rb),a.Rb=void 0)};var Sx=function(){var a=Nf(66,0);this.K=[];this.R=a;this.H=Ya()},Ux=function(a){var b=Tx;b.K.push(a);b.N||(b.N=function(){for(var c=m(b.K),d=c.next();!d.done;d=c.next()){var e=d.value;try{e()}catch(l){}}for(var f=m(b.H.values()),g=f.next();!g.done;g=f.next()){var h=void 0;(h=g.value.we)==null||Tn(h)}b.H.clear()},$c(A,"pagehide",b.N))},Vx=function(a){var b=a.match(Mn)[3]||null,c=(b?decodeURI(b):b)||"",d=Pn(a,"label")||"",e=Pn(a,"random")||"";return c+":"+Ln(d)+":"+Ln(e)},Wx=function(a,b,c){var d=Tx,
e=Vx(a);if(!(d.H.has(e)||d.H.size>=d.R)){var f={};b&&b>0&&c&&(f.we=new Qx(c,b));d.H.set(e,f);var g;(g=f.we)==null||Rx(g)}},Un=function(a,b){var c=Vx(b),d,e;(d=a.H.get(c))==null||(e=d.we)==null||Tn(e);a.H.delete(c)};Sx.prototype.getSize=function(){return this.H.size};var dg;function hy(a,b){var c;(c=dg)==null||$f(c.H,a,b)};var iy=Aa(["/"]),jy=function(a){this.H=a;this.failureType=void 0};jy.prototype.io=function(a,b,c){try{var d=this.H.active;d?(d.postMessage({type:1,command:a}),b({data:""})):c({failureType:13,data:""})}catch(e){c({failureType:11,data:e.message})}};var ky=function(a,b){this.failureType=a;this.H=b};ky.prototype.io=function(a,b,c){c({failureType:this.failureType,data:"f"+this.failureType+("t"+((new Date).getTime()-this.H))})};
var ny=function(a){var b=this;this.initTime=(new Date).getTime();this.H=new ky(15,this.initTime);var c=new Promise(function(e){A.setTimeout(function(){e()},20)}),d=ly(a).then(function(e){b.H=new jy(e);my(b,e)}).catch(function(){b.H=new ky(4,b.initTime)});this.K=Promise.race([c,d])},my=function(a,b){var c=function(d){d&&d.addEventListener("statechange",function(){if(d.state==="redundant"){var e=b.active;e&&e.state!=="redundant"||(a.H=new ky(10,a.initTime))}})};c(b.active);c(b.waiting);c(b.installing);
b.addEventListener("updatefound",function(){c(b.installing)})};ny.prototype.delegate=function(a,b,c){var d=this;this.K.then(function(){d.H.io(a,b,c)})};ny.prototype.getState=function(){return 2};
var ly=function(a){var b,c=Lf(11);c=Lf(10);b=c;var d={scope:(Tb(a.href,"/")?a.href.slice(0,-1):a.href)+"/_/service_worker"};b&&(d.updateViaCache="all");var e,f=oy(a,b),g=new Map([["path",a.pathname]]),h=Jp(kc(f).toString());e=Lp(h.zk,h.params,h.fragment,g);var l=Ic(),n=kc(e);try{return l.register(n,d)}catch(p){try{return l.register(n.toString(),d)}catch(q){return Promise.reject(q)}}};
function oy(a,b){for(var c=Kp(iy),d=a.pathname.split("/").filter(function(h){return h.length>0}),e=[].concat(w(d),["_","service_worker",b,"sw.js"]),f=m(e),g=f.next();!g.done;g=f.next())c=Mp(c,g.value);return c};function py(a){var b=nm(jm.ba.Oh),c=b==null?void 0:b[a];c||a!=="lite"||(c=b==null?void 0:b.full);return c}var qy=function(a,b,c){var d=py("full");d?d.delegate(a,b,c):c({failureType:16})};function ry(a,b,c,d,e){qy({commandType:0,params:{url:a,method:1,templates:b,body:"",processResponse:!1,encryptionKeyString:e,soReferrer:A.location.href}},c,function(f){d(f.failureType,f.data)})};var Dy=function(){var a=this;this.H=0;this.K=!1;M(462)&&Um("fs",function(){return a.H>0&&a.H<5?String(a.H):void 0},!1)},Ey;function Fy(a,b){Ey||(Ey=new Dy);var c=Ey;M(462)&&fn.K&&(b==="gtm.formSubmit"||b==="form_submit"&&If(45))&&(a===1||c.K)&&(c.K=!0,c.H=a,a!==5?Vm("fs"):Qm.H.fs=!1)};var Hy={X:{Wq:0,Ek:1,Zg:2,Xk:3,mi:4,Vk:5,Wk:6,Yk:7,ni:8,tm:9,sm:10,Ti:11,vm:12,Bh:13,Em:14,ij:15,Sq:16,jd:17,uj:18,vj:19,wj:20,Cn:21,xj:22}};Hy.X[Hy.X.Wq]="RESERVED_ZERO";Hy.X[Hy.X.Ek]="ADS_CONVERSION_HIT";Hy.X[Hy.X.Zg]="CONTAINER_EXECUTE_START";Hy.X[Hy.X.Xk]="CONTAINER_SETUP_END";Hy.X[Hy.X.mi]="CONTAINER_SETUP_START";Hy.X[Hy.X.Vk]="CONTAINER_BLOCKING_END";Hy.X[Hy.X.Wk]="CONTAINER_EXECUTE_END";Hy.X[Hy.X.Yk]="CONTAINER_YIELD_END";Hy.X[Hy.X.ni]="CONTAINER_YIELD_START";Hy.X[Hy.X.tm]="EVENT_EXECUTE_END";
Hy.X[Hy.X.sm]="EVENT_EVALUATION_END";Hy.X[Hy.X.Ti]="EVENT_EVALUATION_START";Hy.X[Hy.X.vm]="EVENT_SETUP_END";Hy.X[Hy.X.Bh]="EVENT_SETUP_START";Hy.X[Hy.X.Em]="GA4_CONVERSION_HIT";Hy.X[Hy.X.ij]="PAGE_LOAD";Hy.X[Hy.X.Sq]="PAGEVIEW";Hy.X[Hy.X.jd]="SNIPPET_LOAD";Hy.X[Hy.X.uj]="TAG_CALLBACK_ERROR";Hy.X[Hy.X.vj]="TAG_CALLBACK_FAILURE";Hy.X[Hy.X.wj]="TAG_CALLBACK_SUCCESS";Hy.X[Hy.X.Cn]="TAG_EXECUTE_END";Hy.X[Hy.X.xj]="TAG_EXECUTE_START";var Iy={};Iy.X=Hy.X;var Jy={Ru:"L",Xq:"S",kv:"Y",Rt:"B",nu:"E",Nu:"I",fv:"TC",vu:"HTC",ou:"F",Mu:"C"},Ky={Xq:"S",lu:"V",au:"E",dv:"tag"},Ly={},My=(Ly[Iy.X.vj]="6",Ly[Iy.X.wj]="5",Ly[Iy.X.uj]="7",Ly);function Ny(a){var b=E(5),c=Number(a.eventId),d=Number(a.tagId);return(Sb(b,"GTM-")?b:"GTM-"+b)+":"+(Ab(c)?c+":":"")+(Ab(d)?d+":":"")+a.stage};function Oy(){var a=rd();return!!(a&&a.mark instanceof Function&&a.measure instanceof Function&&a.clearMeasures instanceof Function&&a.clearMarks instanceof Function)};var Py=function(){this.H={}},Qy;function Ry(){Qy||(Qy=new Py);return Qy}function Sy(a){var b=Ry(),c=Ny(a);return b.H[c]}function Ty(a,b){var c;a:{var d=Ry();if(Oy()){var e=Ny(a),f,g;if(f=(g=rd())==null?void 0:g.mark(e,b)){c=d.H[e]=f;break a}}c=void 0}return c};function Uy(a,b){if(Oy()){a.entry=Ny(a);var c=na(Object,"assign").call(Object,{},a);c.stage=b;delete c.sent;var d=Sy(b===Iy.X.jd?{stage:Iy.X.jd}:c),e=Sy(a);if(d&&e&&!(d.startTime>e.startTime)){c.stage=b+":"+a.stage;var f=Ny(c),g={start:d.name,end:e.name},h,l;return(l=(h=rd())==null?void 0:h.measure(f,g))==null?void 0:l.duration}}};var Wy=function(){var a=5;Vy.Ro>0&&(a=Vy.Ro);this.K=a;this.H=0;this.N=[]},Xy=function(a){return a.H<a.K?!1:Nb()-a.N[a.H%a.K]<1E3},Yy=function(a){var b=a.H++%a.K;a.N[b]=Nb()};var Vy={Ro:Nf(3,0)},$y=function(){var a=this;this.ya=[];this.H=void 0;this.Z={};this.K=void 0;this.ja=new Wy;this.La=1E3;this.R=this.N=!1;this.fa=Db();Zy(this,function(){var b=[["v","3"],["t","t"],["pid",String(a.fa)]],c=du();c&&b.push(["gtm",c]);return b});cd(function(){a.fa=Db()},864E5)},Zy=function(a,b){a.ya.push(b)},az=function(a,b,c){var d=a.H;if(d===void 0)if(c)d=rj();else return"";for(var e=[fk("https://"+E(21)),"/a","?id="+E(5)],f=m(a.ya),g=f.next();!g.done;g=f.next())for(var h=g.value,l=
h({eventId:d,tf:!!b}),n=m(l),p=n.next();!p.done;p=n.next()){var q=m(p.value),r=q.next().value,t=q.next().value;e.push("&"+r+"="+t)}e.push("&z=0");return e.join("")},bz=function(a){if($k(26)&&(a.K&&(A.clearTimeout(a.K),a.K=void 0),a.H!==void 0&&a.R)){var b=lo(co.ia.Zb);if(go(b))a.N||(a.N=!0,io(b,function(){return void bz(a)}));else if(a.Z[a.H]||Xy(a.ja)||a.La--<=0)P(1),a.Z[a.H]=!0;else{Yy(a.ja);var c=az(a,!0);Xn({destinationId:E(5),endpoint:56,eventId:a.H},c);a.R=!1;a.N=!1}}},cz=function(a){a.K||(a.K=
A.setTimeout(function(){return void bz(a)},500))},ez=function(a){var b=dz;b.Z[a]||(a!==b.H&&(bz(b),b.H=a),b.R=!0,cz(b),az(b).length>=2022&&bz(b))},dz;function fz(a){gz();Zy(dz,a)}function hz(){var a;a=a===void 0?!1:a;gz();var b=a,c=dz;b=b===void 0?!1:b;if(fn.N&&$k(26)){var d=az(c,!0,!0);b?Vn({destinationId:E(5),endpoint:56,eventId:c.H},d):Xn({destinationId:E(5),endpoint:56,eventId:c.H},d)}}function gz(){dz||(dz=new $y)};function iz(){function a(c,d){var e=wb(rb[d]||[]);e&&b.push([c,e])}var b=[];a("u","GTM");a("ut","TAGGING");a("h","HEALTH");return b};var jz="https://"+E(21),kz=function(){this.N=!1;this.R=[];this.Z=[];this.H={TC:0,HTC:0};this.K={}},lz=function(a,b,c,d){a.K[b]||(a.K[b]={});a.K[b][c]=d},oz=function(a){var b="",c="",d=mz();Ab(d)&&(a.H.I=Math.floor(d));c=nz(a.H,Jy).toString();for(var e=m(Object.keys(a.K)),f=e.next();!f.done;f=e.next()){var g=f.value,h=a.K[g].name,l="",n=nz(a.K[g],Ky);n&&(l=h+"."+n.toString(),b+="~"+l)}var p="~AWCT"+a.R.join("."),q="~GA"+a.Z.join("."),r="&ccid="+vk().toString()+"&cid="+E(5).toString()+"&l="+c+b+(a.R.length?
p:"")+(a.Z.length?q:"");if(M(214)){var t,u=(t=rd())==null?void 0:t.getEntriesByName(Kc).map(function(v){return String(v.duration)}).join(".");u&&(r+="~SS"+u)}return r},pz=function(a,b){if(!b.stage||a.N||!Oy()||Sy(b))return!1;var c,d=(c=rd())==null?void 0:c.timeOrigin;if(!Ab(d))a.N=!0;else if(Ab($k(25))&&!Sy({stage:Iy.X.jd})&&!a.N&&Oy())try{var e=Number($k(25));Ty({stage:Iy.X.jd},{startTime:Math.max(e-d,0)});Ty({stage:Iy.X.ij},{startTime:0});var f=Uy({stage:Iy.X.jd},Iy.X.ij);f&&(a.H.L=Math.floor(f))}catch(g){a.N=
!0}if(a.N)return!1;try{if(!Ty(b))return!1}catch(g){return a.N=!0,!1}return!0},qz=function(a,b,c){if(pz(a,b))try{var d=Uy(b,c);if(d)return Math.floor(d)}catch(e){a.N=!0}},sz=function(){var a=rz();pz(a,{stage:Iy.X.mi})},tz=function(){var a=rz(),b=qz(a,{stage:Iy.X.Xk},Iy.X.mi);b!==void 0&&(a.H.S=b)},uz=function(){var a=rz();pz(a,{stage:Iy.X.ni})},vz=function(a,b){var c=rz();pz(c,{stage:Iy.X.Bh,eventId:a});c.K[a]&&c.K[a].name||lz(c,a,"name",Sb(b,"gtm.")?b:"*")},wz=function(a){var b=rz(),c=qz(b,{stage:Iy.X.vm,
eventId:a},Iy.X.Bh);c!==void 0&&lz(b,a,"S",c)},yz=function(a,b){var c=rz(),d=qz(c,{stage:Iy.X.tm,eventId:a},Iy.X.Bh);d!==void 0&&lz(c,a,"E",d);if(b==="gtm.load"){var e=qz(c,{stage:Iy.X.Wk},Iy.X.Zg);e!==void 0&&(c.H.E=e);io(lo(co.ia.Zb),function(){if(!c.N&&Oy()&&E(5)){var f=xz();f!==void 0&&(c.H.F=Math.floor(f));try{for(var g=iz({eventId:0,tf:!1}),h=[],l=m(g),n=l.next();!n.done;n=l.next()){var p=m(n.value),q=p.next().value,r=p.next().value;h.push("&"+q+"="+r)}var t=Cp(),u=[[fk(jz),"/a?v=3&t=l","&pid="+
Db().toString(),"&rv="+E(14),t?"&tag_exp="+t:"",h.join("")].join(""),"&gtm=",du(),oz(c)].join("");if(u.length>2022){var v=Math.max(u.lastIndexOf(".TS",2022),u.lastIndexOf("~",2022));u=u.slice(0,v)}Xn({destinationId:E(5),endpoint:56},u)}catch(x){}}})}},zz;function rz(){zz||(zz=new kz);return zz}function mz(){try{var a;return((a=rd())==null?void 0:a.getEntriesByType("navigation")[0]).domInteractive}catch(b){}}
function nz(a,b){return Object.keys(b).map(function(c){return b[c]}).filter(function(c){return a[c]!==void 0}).map(function(c){return(""+(c==="tag"?"":c)).concat(a[c].toString())}).join(".")}function Az(a){var b=rz(),c=qz(b,{stage:Iy.X.Em,eventId:a},Iy.X.jd);c!==void 0&&b.Z.push(c)}function Bz(a){var b=rz(),c=qz(b,{stage:Iy.X.Ek,eventId:a},Iy.X.jd);c!==void 0&&b.R.push(c)}function Cz(a){var b=rz();pz(b,{stage:Iy.X.Ti,eventId:a})}
function Dz(a){var b=rz(),c=qz(b,{stage:Iy.X.sm,eventId:a},Iy.X.Ti);c!==void 0&&lz(b,a,"V",c)}function xz(){try{var a,b;return(b=(a=rd())==null?void 0:a.getEntriesByType("paint").find(function(c){return c.name==="first-contentful-paint"}))==null?void 0:b.startTime}catch(c){}}function Ez(a,b){var c=rz();pz(c,{stage:Iy.X.xj,eventId:a.id,tagId:Number(b[Gf.yj])})}
function Fz(a,b,c){var d=rz(),e=dn(b),f=Number(b[Gf.yj]),g=qz(d,{stage:c,eventId:a.id,tagId:f},Iy.X.xj);if(g!==void 0&&d.K[a.id]){var h=d.K[a.id].tag||"",l,n=(l=My[c])!=null?l:"1",p=new RegExp("TS\\d"+e+".TI"+f),q="TS"+n+e+".TI"+f+".TE"+g;h.search(p)>=0?n!=="1"&&lz(d,a.id,"tag",h.replace(p,q.replace(".TE"+g,""))):(lz(d,a.id,"tag",(h?h+".":"")+q),e==="html"&&(d.H.HTC+=1),d.H.TC+=1)}};var Kz={gj:{bp:"1",uq:"2",Vq:"3"}};var Pz,Qz;
function Rz(a,b){var c=a[Gf.Yb],d=b&&b.event;if(!c)throw Error("Error: No function name given for function call.");var e=Qz[c],f={},g;for(g in a)a.hasOwnProperty(g)&&(Sb(g,"vtp_")?f[e!==void 0?g:g.substring(4)]=a[g]:g===Gf.Fq.toString()&&(f[e!==void 0?"vtp_gtmGeneratedTaggingMetadata":g]=a[g]));If(61)&&e&&(f.vtp_extraExperimentIds=!0);e&&d&&d.cachedModelValues&&(f.vtp_gtmCachedValues=d.cachedModelValues);b&&e&&(f.vtp_gtmEntityIndex=b.index,f.vtp_gtmEntityName=b.name);return e!==void 0?e(f):Pz(c,f,
b)}var Tz=function(){var a=Sz;if(M(585)&&fn.K){var b=E(5).indexOf("GTM-")===0&&If(62),c,d=((c=Fk())==null?void 0:c.source)===1;b&&!d||a.H||(a.H=!0,Um("abl","1"),to())}},Sz=new function(){this.H=!1};var Uz=function(a,b,c,d){this.H=a;this.index=b;this.tags=c;this.macros=d;this.name=String(this.H[Gf.Rm]||"")};
Uz.prototype.evaluate=function(a,b){if(!b[this.index]&&!a.isBlocked(this.H)){b[this.index]=!0;this.H[Gf.pl.toString()]&&Tz();var c=this.name,d;try{var e={},f;for(f in this.H)this.H.hasOwnProperty(f)&&(e[f]=el(this.H[f],a,this.tags,this.macros,b));e.vtp_gtmEventId=a.id;a.priorityId&&(e.vtp_gtmPriorityId=a.priorityId);var g=d=Rz(e,{event:a,index:this.index,type:2,name:c});e[Gf.Zk]&&typeof g==="string"&&(g=e[Gf.Zk]===1?g.toLowerCase():g.toUpperCase());e.hasOwnProperty(Gf.ah)&&(g=Yf(18)?e[Gf.ah]===1?
Vf(g,"PERIOD"):e[Gf.ah]===2?Vf(g,"COMMA"):Vf(g,"AUTOMATIC"):e[Gf.ah]===1?Vf(g,"PERIOD"):Vf(g,"COMMA"));e.hasOwnProperty(Gf.bl)&&g===null&&(g=e[Gf.bl]);e.hasOwnProperty(Gf.il)&&g===void 0&&(g=e[Gf.il]);e.hasOwnProperty(Gf.ep)&&(g=Jb(g));e.hasOwnProperty(Gf.fl)&&g===!0&&(g=e[Gf.fl]);e.hasOwnProperty(Gf.al)&&g===!1&&(g=e[Gf.al]);d=g}catch(h){a.logMacroError&&a.logMacroError(h,Number(this.index),c),d=!1}b[this.index]=!1;return d}};Uz.prototype.Fg=function(){return na(Object,"assign").call(Object,{},this.H)};var Vz=function(a,b,c){this.H=a;this.tags=b;this.macros=c};Vz.prototype.evaluate=function(a,b){try{for(var c={},d=m(Object.keys(this.H)),e=d.next();!e.done;e=d.next()){var f=e.value;c[f]=f==="function"?this.H[f]:el(this.H[f],a,this.tags,this.macros,b)}return cl(c)}catch(g){JSON.stringify(this.H)}return 2};Vz.prototype.Fg=function(){return na(Object,"assign").call(Object,{},this.H)};var Wz=function(a,b){this.index=b;this.N=[];this.R=[];this.K=[];this.H=[];this.name="";for(var c=m(a),d=c.next();!d.done;d=c.next()){var e=m(d.value),f=e.next().value,g=ya(e),h=f,l=g;h==="if"?this.N=l:h==="unless"?this.R=l:h==="add"?this.K=l:h==="block"?this.H=l:h==="ruleName"&&(this.name=l[0])}};
Wz.prototype.evaluate=function(a,b){var c=Xz(this,b),d=[],e=[];c?(d.push.apply(d,w(this.K)),e.push.apply(e,w(this.H))):c===null&&e.push.apply(e,w(this.H));return{firingTags:d,blockingTags:e}};
var Xz=function(a,b){for(var c=m(a.N),d=c.next();!d.done;d=c.next()){var e=b(d.value);if(e===0)return!1;if(e===2)return null}for(var f=m(a.R),g=f.next();!g.done;g=f.next()){var h=b(g.value);if(h===2)return null;if(h===1)return!1}return!0};Wz.prototype.getName=function(){return this.name};var Yz=function(a,b,c,d){this.Ia=a;this.index=b;this.tags=c;this.macros=d;this.O=String(this.Ia[Gf.Yb]);this.name=String(this.Ia[Gf.Rm]||"");this.tagId=Number(this.Ia[Gf.yj])};
Yz.prototype.evaluate=function(a,b,c){c=c===void 0?{}:c;var d,e=c;e=e===void 0?{}:e;var f={},g;for(g in this.Ia)this.Ia.hasOwnProperty(g)&&(f[g]=el(this.Ia[g],a,this.tags,this.macros,[]));d=na(Object,"assign").call(Object,{},f,e);d.vtp_gtmTagId=this.tagId;this.Ia[Gf.pl.toString()]&&Tz();Rz(d,{event:a,index:this.index,type:1,name:this.name})};Yz.prototype.Fg=function(){return na(Object,"assign").call(Object,{},this.Ia)};
var Zz=function(a,b){if(a.Ia[Gf.tn])return el(a.Ia[Gf.tn],b,a.tags,a.macros,[])},$z=function(a,b){if(a.Ia[Gf.Dn])return el(a.Ia[Gf.Dn],b,a.tags,a.macros,[])},aA=function(a,b){var c=a.Ia[Gf.cp];if(c)return el(c,b,a.tags,a.macros,[])};Yz.prototype.getMetadata=function(a){return el(this.Ia[Gf.METADATA],a,this.tags,this.macros,[])};Yz.prototype.getName=function(){return this.name};var bA=function(){this.macros=[];this.rules=[];this.predicates=[];this.tags=[];this.vk=[]};bA.prototype.getRules=function(){return this.rules};var cA=new bA;function dA(a,b,c,d){var e=Wc(),f;if(e===1)a:{var g=E(3);g=g.toLowerCase();for(var h="https://"+g,l="http://"+g,n=1,p=B.getElementsByTagName("script"),q=0;q<p.length&&q<100;q++){var r=p[q].src;if(r){r=r.toLowerCase();if(r.indexOf(l)===0){f=3;break a}n===1&&r.indexOf(h)===0&&(n=2)}}f=n}else f=e;return(f===2||d||"http:"!==A.location.protocol?a:b)+c};var eA=function(){var a=this;this.K={};this.H={};fz(function(b){var c=[],d;for(d in a.K)Object.prototype.hasOwnProperty.call(a.K,d)&&c.push(d+"~"+a.K[d]);var e=[],f;for(f in a.H)Object.prototype.hasOwnProperty.call(a.H,f)&&e.push(f+"~"+a.H[f]);b.tf&&(a.K={},a.H={});var g=[];c.length>0&&g.push(["bcs",c.join(".")]);e.length>0&&g.push(["bet",e.join(".")]);return g})},fA;function gA(){fA||(fA=new eA)};function hA(a,b,c,d,e){if(!Ek(a)){d.loadExperiments=yj();Hk(a,d,e);var f=iA(a),g=function(){ok().container[a]&&(ok().container[a].state=3);jA()},h={destinationId:a,endpoint:0};if(Wj()){var l=Xj(),n=l+"/"+kA(f,a);Zn(h,n,void 0,function(){lA(a,n,l+"/"+f,h,g)})}else{var p=Sb(a,"GTM-"),q=dk(),r=c?"/gtag/js":"/gtm.js",t=mA(b,r+f,a);if(!t){var u=E(3)+r;q&&Kc&&p&&(u=Kc.replace(/^(?:https?:\/\/)?/i,"").split(/[?#]/)[0]);t=dA("https://","http://",u+f)}Zn(h,t,void 0,g)}}}
function jA(){Kk()||Gb(Lk(),function(a,b){nA(a,b.transportUrl,b.context);P(92)})}function nA(a,b,c,d){if(!Gk(a))if(c.loadExperiments||(c.loadExperiments=yj()),Kk())Jk(a,b,c,d);else{Ik(a,c,d);var e={destinationId:a,endpoint:0};if(Wj()){var f=Xj(),g="gtd"+iA(a,!0),h=f+"/"+kA(g,a);Zn(e,h,void 0,function(){lA(a,h,f+"/"+g,e)})}else{var l="/gtag/destination"+iA(a,!0),n=mA(b,l,a);n||(n=dA("https://","http://",E(3)+l));Zn(e,n)}}}
function lA(a,b,c,d,e){if(M(413)){gA();var f=fA;if(fn.N){var g=A.performance,h=-1;if(g&&g.getEntriesByType){var l=Rj(b).href,n=g.getEntriesByName(l).pop();if(!n)for(var p=g.getEntriesByType("resource"),q=0;q<p.length;q++){var r=p[q];if(r.name&&r.name.indexOf(b)!==-1){n=r;break}}n&&n.responseStatus!==void 0&&(h=n.responseStatus)}f.K[a]=h}P(190);var t=nm(jm.ba.kj)||{};t[a]=!0;mm(jm.ba.kj,t);var u=c+(c.indexOf("?")===-1?"?f=1":"&f=1");e?Zn(d,u,void 0,e):Zn(d,u)}else e&&e()}
function iA(a,b){b=b===void 0?!1:b;var c="?id="+encodeURIComponent(a),d=E(19);d!=="dataLayer"&&(c+="&l="+d);var e=Sb(a,"GTM-");if(!e||b)c+="&cx=c";e&&If(62)&&(c+="&google_only=true");var f=c,g,h={Do:Jf(15),Io:E(14)};g=Cf(h);c=f+("&gtm="+g);dk()&&(c+="&sign="+Aj.qj);var l=c,n=Jf(54);if(n===1){l+="&fps=fc";var p=E(60);p&&(l+="&gdev="+p)}else n===2&&(l+="&fps=fe");return l}
function kA(a,b){if(!M(413)||!Xj())return a;var c=E(58);if(!c)return P(182),a;try{var d=Nb(),e=Ef(a,c),f=Nb()-d;gA();var g=fA;fn.N&&(g.H[b]=f);return e}catch(h){return P(183),a}}function mA(a,b,c){if(ak()&&a){var d=E(58),e=Xj();if(d&&e)try{var f=Nb();b=e+"/"+Ef(b,d);var g=Nb()-f;gA();var h=fA;fn.N&&(h.H[c]=g)}catch(l){P(183)}return Yj(a,b)}};var pA=function(){var a=this;this.K=new Fb;this.H={};this.N={};this.R={name:E(19),set:function(b,c){Ed(Vb(b,c),a.H);oA(a)},get:function(b){return a.get(b,2)},reset:function(){a.K=new Fb;a.H={};oA(a)}}};pA.prototype.get=function(a,b){return b!=2?this.K.get(a):qA(this,a)};var qA=function(a,b,c){var d=b.split(".");c=c||[];for(var e=a.H,f=0;f<d.length;f++){if(e===null)return!1;if(e===void 0)break;e=e[d[f]];if(c.indexOf(e)!==-1)return}return e};
pA.prototype.set=function(a,b){this.N.hasOwnProperty(a)||(this.K.set(a,b),Ed(Vb(a,b),this.H),oA(this))};var sA=function(){for(var a=["gtm.allowlist","gtm.blocklist","gtm.whitelist","gtm.blacklist","tagTypeBlacklist"],b=rA,c=0;c<a.length;c++){var d=a[c],e=b.get(d,1);if(Array.isArray(e)||Cd(e))e=Ed(e,null);b.N[d]=e}},oA=function(a,b){Gb(a.N,function(c,d){a.K.set(c,d);Ed(Vb(c),a.H);Ed(Vb(c,d),a.H);b&&delete a.N[c]})},rA=new pA,tA=rA.R;function uA(a,b){return rA.get(a,b)}
function vA(a,b){var c=b===void 0?2:b,d=rA,e,f=(c===void 0?2:c)!==1?qA(d,a):d.K.get(a);Ad(f)==="array"||Ad(f)==="object"?e=Ed(f,null):e=f;return e};var wA=new RegExp(/^(.*\.)?(google|youtube|blogger|withgoogle)(\.com?)?(\.[a-z]{2})?\.?$/),xA={cl:["ecl"],customPixels:["nonGooglePixels"],ecl:["cl"],ehl:["hl"],gaawc:["googtag"],hl:["ehl"],html:["customScripts","customPixels","nonGooglePixels","nonGoogleScripts","nonGoogleIframes"],customScripts:["html","customPixels","nonGooglePixels","nonGoogleScripts","nonGoogleIframes"],nonGooglePixels:[],nonGoogleScripts:["nonGooglePixels"],nonGoogleIframes:["nonGooglePixels"]},yA={cl:["ecl"],customPixels:["customScripts",
"html"],ecl:["cl"],ehl:["hl"],gaawc:["googtag"],hl:["ehl"],html:["customScripts"],customScripts:["html"],nonGooglePixels:["customPixels","customScripts","html","nonGoogleScripts","nonGoogleIframes"],nonGoogleScripts:["customScripts","html"],nonGoogleIframes:["customScripts","html","nonGoogleScripts"]},zA="google customPixels customScripts html nonGooglePixels nonGoogleScripts nonGoogleIframes".split(" ");
function AA(){var a=uA("gtm.allowlist")||uA("gtm.whitelist");a&&P(9);If(62)&&(a=void 0);BA()&&(If(62)?P(116):(P(117),If(48)&&(a=[],window.console&&window.console.log&&window.console.log("GTM blocked. See go/13687728."))));var b=a&&Rb(Kb(a),xA),c=uA("gtm.blocklist")||uA("gtm.blacklist");c||(c=uA("tagTypeBlacklist"))&&P(3);c?P(8):c=[];BA()&&(c=Kb(c),c.push("nonGooglePixels","nonGoogleScripts","sandboxedScripts"));Kb(c).indexOf("google")>=0&&P(2);var d=c&&Rb(Kb(c),yA),e={};return function(f){var g=f&&
f[Gf.Yb];if(!g||typeof g!=="string")return!0;g=g.replace(/^_*/,"");if(e[g]!==void 0)return e[g];var h=al(27,function(){return{}})[g]||[],l=!0;a&&(l=l&&CA(g,h,b));var n=!1;c&&(n=DA(g,h,d));var p=!l||n;!p&&(h.indexOf("sandboxedScripts")===-1||b&&b.indexOf("sandboxedScripts")!==-1?0:Eb(d,zA))&&(p=!0);return e[g]=p}}function CA(a,b,c){if(c.indexOf(a)<0)if(b&&b.length>0)for(var d=0;d<b.length;d++){if(c.indexOf(b[d])<0)return P(11),!1}else return!1;return!0}
function DA(a,b,c){var d=c.indexOf(a)>=0;if(d)return d;var e=Eb(c,b||[]);e&&P(10);return e}function BA(){return wA.test(A.location&&A.location.hostname)};function EA(a){for(var b=[],c=[],d=FA(a),e=m(cA.getRules()),f=e.next();!f.done;f=e.next()){for(var g=f.value.evaluate(a,d),h=g.firingTags,l=g.blockingTags,n=0;n<h.length;n++)b[h[n]]=!0;for(var p=0;p<l.length;p++)c[l[p]]=!0}for(var q=[],r=0;r<cA.tags.length;r++)b[r]&&!c[r]&&(q[r]=!0);return q}function FA(a){var b=[];return function(c){b[c]===void 0&&(b[c]=cA.predicates[c].evaluate(a,[]));return b[c]}};var GA=function(){this.K=0;this.H={}};GA.prototype.addListener=function(a,b,c){var d=++this.K;this.H[a]=this.H[a]||{};this.H[a][String(d)]={listener:b,rf:c};return d};GA.prototype.removeListener=function(a,b){var c=this.H[a],d=String(b);if(!c||!c[d])return!1;delete c[d];return!0};var IA=function(a,b){var c=[];Gb(HA.H[a],function(d,e){c.indexOf(e.listener)<0&&(e.rf===void 0||b.indexOf(e.rf)>=0)&&c.push(e.listener)});return c};function JA(a,b,c){return{entityType:a,indexInOriginContainer:b,nameInOriginContainer:c,originContainerId:E(5),originCId:vk()}};function KA(a,b){if(data.entities){var c=data.entities[a];if(c)return c[b]}};var MA=function(a,b){this.H=!1;this.R=[];this.eventData={tags:[]};this.Z=!1;this.K=this.N=0;LA(this,a,b)},NA=function(a,b,c,d){if(Cj.hasOwnProperty(b)||b==="__zone")return-1;var e={};Cd(d)&&(e=Ed(d,e));e.id=c;e.status="timeout";return a.eventData.tags.push(e)-1},OA=function(a,b,c,d){var e=a.eventData.tags[b];e&&(e.status=c,e.executionTime=d)},PA=function(a){if(!a.H){for(var b=a.R,c=0;c<b.length;c++)b[c]();a.H=!0;a.R.length=0}},LA=function(a,b,c){b!==void 0&&a.wg(b);c&&A.setTimeout(function(){PA(a)},
Number(c))};MA.prototype.wg=function(a){var b=this,c=Pb(function(){bd(function(){a(E(5),b.eventData)})});this.H?c():this.R.push(c)};var QA=function(a){a.N++;return Pb(function(){a.K++;a.Z&&a.K>=a.N&&PA(a)})},RA=function(a){a.Z=!0;a.K>=a.N&&PA(a)};function SA(){return A[TA()]}
function TA(){return A.GoogleAnalyticsObject||"ga"}var WA=new function(){this.H={}};function XA(){a:{var a=E(5);}}
function YA(a,b){return function(){var c=SA(),d=c&&c.getByName&&c.getByName(a);if(d){var e=d.get("sendHitTask");d.set("sendHitTask",function(f){var g=f.get("hitPayload"),h=f.get("hitCallback"),l=g.indexOf("&tid="+b)<0;l&&(f.set("hitPayload",g.replace(/&tid=UA-[0-9]+-[0-9]+/,"&tid="+b),!0),f.set("hitCallback",void 0,!0));e(f);l&&(f.set("hitPayload",g,!0),f.set("hitCallback",h,!0),f.set("_x_19",void 0,!0),e(f))})}}};var aB=["es","1"],bB=function(){var a=this;this.eventData={};this.H={};fz(function(b){var c;var d=b.eventId,e=b.tf;if(a.eventData[d]){var f=[];a.H[d]||f.push(aB);f.push.apply(f,w(a.eventData[d]));e&&(a.H[d]=!0);c=f}else c=[];return c})},cB;function dB(a,b){var c;if((c=cB)!=null&&fn.N){var d=c.eventData,e;e=b.match(/^(gtm|gtag)\./)?encodeURIComponent(b):"*";d[a]=[["e",e],["eid",String(a)]];gz();ez(a)}};var eB=function(){var a=this;this.H={};this.K={};fz(function(b){var c=b.eventId,d=b.tf,e=[],f=a.H[c]||[];f.length&&e.push(["tr",f.join(".")]);var g=a.K[c]||[];g.length&&e.push(["ti",g.join(".")]);d&&(delete a.H[c],delete a.K[c]);return e})},fB;
function gB(a,b,c){fB||(fB=new eB);var d=fB;if(fn.N&&b){var e=dn(b);d.H[a]=d.H[a]||[];d.H[a].push(c+e);var f=b[Gf.Yb];if(!f)throw Error("Error: No function name given for function call.");var g=(Qz[f]?"1":"2")+e;d.K[a]=d.K[a]||[];d.K[a].push(g);gz();ez(a)}};function hB(a,b,c){c=c===void 0?!1:c;iB().addRestriction(0,a,b,c)}function jB(){var a=vk();return iB().getRestrictions(0,a)}function kB(a,b,c){c=c===void 0?!1:c;iB().addRestriction(1,a,b,c)}function lB(){var a=vk();return iB().getRestrictions(1,a)}var mB=function(){this.container={};this.H={}},nB=function(a,b){var c=a.container[b];c||(c={_entity:{internal:[],external:[]},_event:{internal:[],external:[]}},a.container[b]=c);return c};
mB.prototype.addRestriction=function(a,b,c,d){d=d===void 0?!1:d;if(!d||!this.H[b]){var e=nB(this,b);a===0?d?e._entity.external.push(c):e._entity.internal.push(c):a===1&&(d?e._event.external.push(c):e._event.internal.push(c))}};
mB.prototype.getRestrictions=function(a,b){var c=nB(this,b);if(a===0){var d,e;return[].concat(w((c==null?void 0:(d=c._entity)==null?void 0:d.internal)||[]),w((c==null?void 0:(e=c._entity)==null?void 0:e.external)||[]))}if(a===1){var f,g;return[].concat(w((c==null?void 0:(f=c._event)==null?void 0:f.internal)||[]),w((c==null?void 0:(g=c._event)==null?void 0:g.external)||[]))}return[]};
mB.prototype.getExternalRestrictions=function(a,b){var c=nB(this,b),d,e;return a===0?(c==null?void 0:(d=c._entity)==null?void 0:d.external)||[]:(c==null?void 0:(e=c._event)==null?void 0:e.external)||[]};mB.prototype.removeExternalRestrictions=function(a){var b=nB(this,a);b._event&&(b._event.external=[]);b._entity&&(b._entity.external=[]);this.H[a]=!0};function iB(){return kj("r",function(){return new mB})};function oB(a,b,c,d){var e=cA.tags[a],f=pB(a,b,c,d);if(!f)return null;var g=Zz(e,c);if(g&&g.length){var h=g[0];f=oB(h.index,{onSuccess:f,onFailure:h.bo===1?b.terminate:f,terminate:b.terminate},c,d)}return f}
function pB(a,b,c,d){function e(){function y(){im(3);var S=Nb()-N;JA(1,a,f.getName());gB(c.id,g,"7");OA(c.ld,D,"exception",S);fn.H&&Fz(c,g,Iy.X.uj);I||(I=!0,l())}if(f.Ia[Gf.Oq])l();else{var z=aA(f,c);if(z!=null)for(var C=0;C<z.length;C++)if(!Xo(z[C])){l();return}var D=NA(c.ld,f.O,f.tagId,f.getMetadata(c)),I=!1,G={vtp_gtmOnSuccess:function(){if(!I){I=!0;var S=Nb()-N;gB(c.id,g,"5");OA(c.ld,D,"success",S);fn.H&&Fz(c,g,Iy.X.wj);h()}},vtp_gtmOnFailure:function(){if(!I){I=!0;var S=Nb()-N;gB(c.id,g,"6");
OA(c.ld,D,"failure",S);fn.H&&Fz(c,g,Iy.X.vj);l()}}};G.vtp_gtmEventId=c.id;c.priorityId&&(G.vtp_gtmPriorityId=c.priorityId);gB(c.id,g,"1");fn.H&&Ez(c,g);var N=Nb();try{f.evaluate(c,d,G)}catch(S){y(S)}fn.H&&Fz(c,g,Iy.X.Cn)}}var f=cA.tags[a],g=f.Fg(),h=b.onSuccess,l=b.onFailure,n=b.terminate;if(c.isBlocked(g))return null;var p=$z(f,c);if(p&&p.length){var q=p[0],r=oB(q.index,{onSuccess:h,onFailure:l,terminate:n},c,d);if(!r)return null;h=r;l=q.bo===2?n:r}if(f.Ia[Gf.kn]||f.Ia[Gf.Qq]){var t=f.Ia[Gf.kn]?
cA.vk:c.vk,u=h,v=l;if(!t[a]){var x=qB(a,t,Pb(e));h=x.onSuccess;l=x.onFailure}return function(){t[a](u,v)}}return e}function qB(a,b,c){var d=[],e=[];b[a]=rB(d,e,c);return{onSuccess:function(){b[a]=sB;for(var f=0;f<d.length;f++)d[f]()},onFailure:function(){b[a]=tB;for(var f=0;f<e.length;f++)e[f]()}}}function rB(a,b,c){return function(d,e){a.push(d);b.push(e);c()}}function sB(a){a()}function tB(a,b){b()};var wB=function(a,b){for(var c=[],d=0;d<cA.tags.length;d++)if(a[d]){var e=cA.tags[d];var f=QA(b.ld);try{var g=oB(d,{onSuccess:f,onFailure:f,terminate:f},b,d);if(g){var h=Qz[e.O];c.push({No:d,priorityOverride:(h?h.priorityOverride||0:0)||KA(e.O,1)||0,execute:g})}else uB(d,b),f()}catch(n){f()}}c.sort(vB);for(var l=0;l<c.length;l++)c[l].execute();return c.length>0};
function xB(a,b){if(!HA)return!1;var c=a["gtm.triggers"]&&String(a["gtm.triggers"]),d=IA(a.event,c?String(c).split(","):[]);if(!d.length)return!1;for(var e=0;e<d.length;++e){var f=QA(b);try{d[e](a,f)}catch(g){f()}}return!0}function vB(a,b){var c,d=b.priorityOverride,e=a.priorityOverride;c=d>e?1:d<e?-1:0;var f;if(c!==0)f=c;else{var g=a.No,h=b.No;f=g>h?1:g<h?-1:0}return f}
function uB(a,b){if(fn.N){var c=function(d){var e=b.isBlocked(cA.tags[d].Fg())?"3":"4",f=Zz(cA.tags[d],b);f&&f.length&&c(f[0].index);gB(b.id,cA.tags[d].Fg(),e);var g=$z(cA.tags[d],b);g&&g.length&&c(g[0].index)};c(a)}}var HA;function yB(){HA||(HA=new GA);return HA}
function zB(a){var b=a["gtm.uniqueEventId"],c=a["gtm.priorityId"],d=a["gtm.priorityQueue"],e=a.event;fn.H&&vz(b,e);if(e==="gtm.js"){if($k(13))return!1;Zk(13,!0)}var f=!1,g=lB(),h=Ed(a,null);if(!g.every(function(u){return u({originalEventData:h})})){if(e!=="gtm.js"&&e!=="gtm.init"&&e!=="gtm.init_consent")return!1;f=!0}dB(b,e);var l=a.eventCallback,n=a.eventTimeout,p={id:b,priorityId:c,priorityQueue:d,name:e,isBlocked:AB(h,f),vk:[],logMacroError:function(u,v,x){P(6);im(4);JA(2,v,x)},cachedModelValues:BB(),
ld:new MA(function(){fn.H&&yz(b,e);Fy(5,e);l&&l.apply(l,Array.prototype.slice.call(arguments,0))},n),originalEventData:h};fn.H&&Cz(p.id);var q=EA(p);fn.H&&Dz(p.id);Fy(2,e);cA.getRules();f&&(q=CB(q));fn.H&&wz(b);var r=wB(q,p);r&&Fy(4,e);var t=xB(a,p.ld);RA(p.ld);e!=="gtm.js"&&e!=="gtm.sync"||XA();return DB(q,r)||t}
function BB(){var a={};a.event=vA("event",1);a.ecommerce=vA("ecommerce",1);a.gtm=vA("gtm");a.eventModel=vA("eventModel");return a}
function AB(a,b){var c=AA();return function(d){var e=c(d);if(e)return!0;var f=d&&d[Gf.Yb];if(!f||typeof f!=="string")return!0;f=f.replace(/^_*/,"");var g=jB(),h=a;b&&(h=Ed(a,null),h["gtm.uniqueEventId"]=Number.MAX_SAFE_INTEGER);for(var l=!1,n=al(27,function(){return{}})[f]||[],p=m(g),q=p.next();!q.done;q=p.next()){var r=q.value;try{r({entityId:f,securityGroups:n,originalEventData:h})||(l=!0)}catch(t){l=!0}}return l||e}}
function CB(a){for(var b=[],c=0;c<a.length;c++)if(a[c]){var d=cA.tags[c].O;if(Bj[d]||cA.tags[c].Ia[Gf.Rq]!==void 0||KA(d,2))b[c]=!0}return b}function DB(a,b){if(!b)return b;for(var c=0;c<a.length;c++)if(a[c]&&cA.tags[c]&&!Cj[cA.tags[c].O])return!0;return!1};var EB=Nf(61,1E3),FB=Nf(68,2E3),Zo=["ad_storage","analytics_storage"];function GB(a,b){if(a){var c=kj("gth",function(){return{}}),d;a!==2||((d=HB())==null?void 0:d.status)!==3||b!==void 0&&b<=FB||(a=3,c.dl=b?Math.floor(b/1E3):void 0);c.s=a;IB(c)}}function IB(a){if(a.s){var b=function(){var c={status:a.s,expires:Date.now()+864E5};a.dl!==void 0&&(c.delay=a.dl);kr("gtg_load_status",c)};bp(function(){if(Yo())b();else for(var c=Pb(b),d=m(Zo),e=d.next();!e.done;e=d.next())Il(c,e.value)},Zo)}}
function JB(){var a=KB(!0);return a?(LB(a.status,a.delay),!1):!0}function KB(a){a=a===void 0?!1:a;if(ak()){var b=nr("gtg_load_status"),c=b.value,d=a&&Ab(c==null?void 0:c.expires)&&(c==null?void 0:c.expires)<Date.now()+36E5;if(b.error===0&&Ab(c==null?void 0:c.status)&&!d){var e={status:c.status};(c==null?void 0:c.delay)!==void 0&&(e.delay=c.delay);return e}return HB()}}function LB(a,b){var c=kj("gth",function(){return{}});c.s=a;b!==void 0&&(c.dl=b)}
function HB(){var a=mj("gth");if(a!=null&&a.s){var b={status:a.s};a.dl!==void 0&&(b.delay=a.dl);return b}}function MB(){var a;((a=HB())==null?void 0:a.status)===1&&GB(3)}function NB(){if(JB()){var a=Date.now();nj("gth",{l:function(){GB(2,Date.now()-a)},s:1});var b=E(5),c=Sb(b,"GTM-")?"/gtm.js":"/gtag/js",d="https://"+E(3)+c+"?id="+b+"&gtg_health=1";Uc(d,MB,MB);A.setTimeout(MB,EB)}};function OB(){yB().addListener("gtm.init",function(a,b){Zk(26,!0);M(556)&&ak()&&!If(45)&&(fo.H[co.ia.Zb]=bo.Ma.Lh);if(ak()){var c;c=lo(co.ia.Zb);go(c)?io(c,NB):NB()}to(!1,!0);b()})};function PB(){if(mj("pscdl")!==void 0)nm(jm.ba.oi)===void 0&&mm(jm.ba.oi,mj("pscdl"));else{var a=function(c){nj("pscdl",c);mm(jm.ba.oi,c)},b=function(){a("error")};try{Hc.cookieDeprecationLabel?(a("pending"),Hc.cookieDeprecationLabel.getValue().then(a).catch(b)):a("noapi")}catch(c){b(c)}}};var RB=function(){var a=this;this.ready=!1;this.K=0;this.H=[];var b=A;if(B.readyState==="interactive"&&!B.createEventObject||B.readyState==="complete")this.onReady();else{$c(B,"DOMContentLoaded",function(d){return void a.onReady(d)});$c(B,"readystatechange",function(d){return void a.onReady(d)});if(B.createEventObject&&B.documentElement.doScroll){var c=!0;try{c=!b.frameElement}catch(d){}c&&QB(this)}$c(b,"load",function(d){return void a.onReady(d)})}};RB.prototype.isReady=function(){return this.ready};
RB.prototype.onReady=function(a){if(!this.ready){var b=B.createEventObject,c=B.readyState==="complete",d=B.readyState==="interactive";if(!a||a.type!=="readystatechange"||c||!b&&d){this.ready=!0;for(var e=0;e<this.H.length;e++)bd(this.H[e])}this.H.push=function(){for(var f=Oa.apply(0,arguments),g=0;g<f.length;g++)bd(f[g]);return 0}}};
var QB=function(a){if(!a.ready&&a.K<140){a.K++;try{var b,c;(c=(b=B.documentElement).doScroll)==null||c.call(b,"left");a.onReady()}catch(d){A.setTimeout(function(){return void QB(a)},50)}}},SB;function TB(){SB||(SB=new RB)}function UB(){TB();var a;return(a=SB)==null?void 0:a.isReady()}function VB(a){TB();var b;(b=SB)!=null&&(b.ready?bd(a):b.H.push(a))};var XB=function(a,b,c){var d=WB,e;if((e=d.H)==null||!e.Or){var f=Object.keys(b).length>0?2:1,g,h,l=(c==null?void 0:(h=c.originatingEntity)==null?void 0:h.originContainerId)||"";g=l?Sb(l,"GTM-")?3:2:1;if(!a)d.H={type:f,source:g,params:b};else if(d.H){P(184);var n=!1;d.H.source===g||d.H.source!==3&&g!==3||(Um("idcs","1"),n=!0);d.H.type!==2&&f!==2||P(186);var p;if(p=d.H.type===2&&f===2)a:{var q=d.H.params,r=Object.keys(q),t=Object.keys(b);if(r.length!==t.length)p=!0;else{for(var u=m(r),v=u.next();!v.done;v=
u.next()){var x=v.value;if(!b.hasOwnProperty(x)||q[x]!==b[x]){p=!0;break a}}p=!1}}p&&(Um("idcc","1"),n=!0);n&&(to(),d.H.Or=!0)}}},WB=new function(){this.H=void 0};var ZB=function(a){var b=YB;(!fn.K||Sb(E(5),"GTM-")?0:a===void 0)&&b.H===0&&(Um("mcc","1"),b.H=1)},YB=new function(){var a=this;this.H=0;Um("ncc",function(){if(If(45)&&a.H!==2)return"1"})};var $B=/^(?:AW|DC|G|GF|GT|HA|MC|UA)$/,aC=/\s/;
function bC(a,b){if(zb(a)){a=Lb(a);var c=a.indexOf("-");if(!(c<0)){var d=a.substring(0,c);if($B.test(d)){var e=a.substring(c+1),f;if(b){var g=function(n){var p=n.indexOf("/");return p<0?[n]:[n.substring(0,p),n.substring(p+1)]};f=g(e);if(d==="DC"&&f.length===2){var h=g(f[1]);h.length===2&&(f[1]=h[0],f.push(h[1]))}}else{f=e.split("/");for(var l=0;l<f.length;l++)if(!f[l]||aC.test(f[l])&&(d!=="AW"||l!==1))return}return{id:a,prefix:d,destinationId:d+"-"+f[0],ids:f,Jc:function(){return this.id!==this.destinationId}}}}}}
function cC(a,b){for(var c={},d=0;d<a.length;++d){var e=bC(a[d],b);e&&(c[e.id]=e)}var f=[],g;for(g in c)if(c.hasOwnProperty(g)){var h=c[g];h.prefix==="AW"&&h.ids[dC[1]]&&f.push(h.destinationId)}for(var l=0;l<f.length;++l)delete c[f[l]];for(var n=[],p=m(Object.keys(c)),q=p.next();!q.done;q=p.next())n.push(c[q.value]);return n}var eC={},dC=(eC[0]=0,eC[1]=1,eC[2]=2,eC[3]=0,eC[4]=1,eC[5]=0,eC[6]=0,eC[7]=0,eC);var fC={initialized:11,complete:12,interactive:13},gC={},hC=Object.freeze((gC[F.D.Td]=!0,gC)),iC=function(){this.R=Nf(34,500);this.H={};this.N={};this.K=void 0},jC=function(a,b,c){if(c.length&&fn.K){var d;(d=a.H)[b]!=null||(d[b]=[]);var e;(e=a.N)[b]!=null||(e[b]=[]);var f=c.filter(function(g){return!a.N[b].includes(g)});a.H[b].push.apply(a.H[b],w(f));a.N[b].push.apply(a.N[b],w(f));!a.K&&f.length>0&&(Vm("tdc",!0),a.K=A.setTimeout(function(){to();a.H={};a.K=void 0},a.R))}};
iC.prototype.bind=function(){var a=this;Um("tdc",function(){a.K&&(A.clearTimeout(a.K),a.K=void 0);var b=[],c;for(c in a.H)a.H.hasOwnProperty(c)&&b.push(c+"*"+a.H[c].join("."));return b.length?b.join("!"):void 0},!1)};
var kC=function(a,b){var c={},d;for(d in b)b.hasOwnProperty(d)&&(c[d]=!0);for(var e in a)a.hasOwnProperty(e)&&(c[e]=!0);return c},lC=function(a,b,c,d,e){d=d===void 0?{}:d;e=e===void 0?"":e;if(b===c)return[];var f=function(t,u){var v;Ad(u)==="object"?v=u[t]:Ad(u)==="array"&&(v=u[t]);return v===void 0?hC[t]:v},g=kC(b,c),h;for(h in g)if(g.hasOwnProperty(h)&&h!==F.D.Xb){var l=(e?e+".":"")+h,n=f(h,b),p=f(h,c),q=Ad(n)==="object"||Ad(n)==="array",r=Ad(p)==="object"||Ad(p)==="array";if(q&&r)lC(a,n,p,d,l);
else if(q||r||n!==p)d[l]=!0}return Object.keys(d)},mC=new iC;var nC=function(a,b,c,d){this.K=Nb();this.H=b;this.args=c;this.messageContext=d;this.type=a},oC=function(){this.Wa={};this.ib={};this.K={};this.N=null;this.hb={};this.H=!1;this.status=1};function pC(a,b){return arguments.length===1?qC("set",a):qC("set",a,b)}function rC(a,b){return arguments.length===1?qC("config",a):qC("config",a,b)}function sC(a,b,c){c=c||{};c[F.D.Xb]=a;return qC("event",b,c)}function qC(){return arguments};var tC=function(a,b,c,d,e,f,g,h,l,n,p,q,r){this.eventId=a;this.priorityId=b;this.priorityQueue=c;this.Ea=d;this.Wa=e;this.hb=f;this.Hc=g;this.Bg=h;this.ib=l;this.eventMetadata=n;this.onSuccess=p;this.onFailure=q;this.isGtmEvent=r},uC=function(a){var b={onSuccess:xb,onFailure:xb};b=b===void 0?{}:b;var c,d,e,f,g,h,l,n,p,q,r,t,u,v,x,y,z,C,D,I,G,N,S,W,ea,ja;return new tC((v=(c=b)==null?void 0:c.eventId)!=null?v:a.eventId,(x=(d=b)==null?void 0:d.priorityId)!=null?x:a.priorityId,(y=(e=b)==null?void 0:e.priorityQueue)!=
null?y:a.priorityQueue,(z=(f=b)==null?void 0:f.Ea)!=null?z:a.Ea,(C=(g=b)==null?void 0:g.Wa)!=null?C:a.Wa,(D=(h=b)==null?void 0:h.hb)!=null?D:a.hb,(I=(l=b)==null?void 0:l.Hc)!=null?I:a.Hc,(G=(n=b)==null?void 0:n.Bg)!=null?G:a.Bg,(N=(p=b)==null?void 0:p.ib)!=null?N:a.ib,(S=(q=b)==null?void 0:q.eventMetadata)!=null?S:a.eventMetadata,(W=(r=b)==null?void 0:r.onSuccess)!=null?W:a.onSuccess,(ea=(t=b)==null?void 0:t.onFailure)!=null?ea:a.onFailure,(ja=(u=b)==null?void 0:u.isGtmEvent)!=null?ja:a.isGtmEvent)},
vC=function(a,b){var c=[];switch(b){case 3:c.push(a.Ea);c.push(a.Wa);c.push(a.hb);c.push(a.Hc);c.push(a.ib);break;case 2:c.push(a.Ea);break;case 1:c.push(a.Wa);c.push(a.hb);c.push(a.Hc);c.push(a.ib);break;case 4:c.push(a.Ea),c.push(a.Wa),c.push(a.hb),c.push(a.Hc)}return c},O=function(a,b,c,d){for(var e=m(vC(a,d===void 0?3:d)),f=e.next();!f.done;f=e.next()){var g=f.value;if(g[b]!==void 0)return g[b]}return c},wC=function(a){for(var b={},c=vC(a,4),d=m(c),e=d.next();!e.done;e=d.next())for(var f=Object.keys(e.value),
g=m(f),h=g.next();!h.done;h=g.next())b[h.value]=1;return Object.keys(b)};tC.prototype.getMergedValues=function(a,b,c){b=b===void 0?3:b;var d={},e=!1,f=function(n){Cd(n)&&Gb(n,function(p,q){e=!0;d[p]=q})};c&&f(c);var g=vC(this,b);g.reverse();for(var h=m(g),l=h.next();!l.done;l=h.next())f(l.value[a]);return e?d:void 0};
var xC=function(a){for(var b=[F.D.Kf,F.D.Gf,F.D.Hf,F.D.If,F.D.Jf,F.D.Lf,F.D.Mf],c=vC(a,3),d=m(c),e=d.next();!e.done;e=d.next()){for(var f=e.value,g={},h=!1,l=m(b),n=l.next();!n.done;n=l.next()){var p=n.value;f[p]!==void 0&&(g[p]=f[p],h=!0)}var q=h?g:void 0;if(q)return q}return{}},yC=function(a,b,c){this.eventId=a;this.priorityId=b;this.priorityQueue=c;this.Ea={};this.Wa={};this.hb={};this.Hc={};this.Bg={};this.ib={};this.eventMetadata={};this.isGtmEvent=!1;this.onSuccess=function(){};this.onFailure=
function(){}},zC=function(a,b){a.Ea=b;return a},AC=function(a,b){a.Wa=b;return a},BC=function(a,b){a.hb=b;return a},CC=function(a,b){a.Hc=b;return a},DC=function(a,b){a.Bg=b;return a},EC=function(a,b){a.ib=b;return a},FC=function(a,b){a.eventMetadata=b||{};return a},GC=function(a,b){a.onSuccess=b;return a},HC=function(a,b){a.onFailure=b;return a},IC=function(a,b){a.isGtmEvent=b;return a},JC=function(a){return new tC(a.eventId,a.priorityId,a.priorityQueue,a.Ea,a.Wa,a.hb,a.Hc,a.Bg,a.ib,a.eventMetadata,
a.onSuccess,a.onFailure,a.isGtmEvent)};function KC(a,b){Gb(a,function(c){var d;if(d=c.charAt(0)==="_"){var e;a:switch(c){case F.D.Vb:case F.D.Rf:case F.D.sh:e=!0;break a;default:e=!1}d=!e}d&&(b&&b(c),delete a[c])})};var LC=function(){var a=this;this.H={};fz(function(b){var c=b.eventId,d=b.tf,e=[],f=a.H[c]||[];f.length&&e.push(["epr",f.join(".")]);d&&delete a.H[c];return e})},NC=function(a,b,c){var d=MC;fn.N&&a!==void 0&&(d.H[a]=d.H[a]||[],d.H[a].push(c+b),gz(),ez(a))},MC;function OC(){MC||(MC=new LC)};var PC=function(){this.destinations={};this.H={};this.commands=[]},QC=function(a,b){return a.destinations[b.destinationId]=a.destinations[b.destinationId]||new oC},RC=function(a,b,c,d){if(d.H){var e=QC(a,d.H),f=e.N;if(f){var g=Ed(c,null),h=Ed(e.Wa[d.H.destinationId],null),l=Ed(e.hb,null),n=Ed(e.ib,null),p=Ed(a.H,null),q={};if(fn.N)try{q=Ed(rA.H,null)}catch(x){P(72)}var r=d.H.prefix,t=function(x){var y=d.messageContext.eventId;OC();NC(y,r,x)},u=JC(IC(HC(GC(FC(DC(CC(EC(BC(AC(zC(new yC(d.messageContext.eventId,
d.messageContext.priorityId,d.messageContext.priorityQueue),g),h),l),n),p),q),d.messageContext.eventMetadata),function(){if(t){var x=t;t=void 0;x("2");if(d.messageContext.onSuccess)d.messageContext.onSuccess()}}),function(){if(t){var x=t;t=void 0;x("3");if(d.messageContext.onFailure)d.messageContext.onFailure()}}),!!d.messageContext.isGtmEvent)),v=function(){try{var x=d.messageContext.eventId;OC();NC(x,r,"1");var y=d.H.id,z=mC;if(fn.K&&b===F.D.wa){var C,D=(C=bC(y))==null?void 0:C.ids;if(!(D&&D.length>
1)){var I=u.Ea[F.D.Xb];if(!I||I===y){var G,N=Mc("google_tag_data",{});N.td||(N.td={});G=N.td;var S=Ed(u.Hc,null);Ed(u.Ea,S);var W=[],ea;for(ea in G)G.hasOwnProperty(ea)&&lC(z,G[ea],S).length&&W.push(ea);W.length&&(jC(z,y,W),sb("TAGGING",fC[B.readyState]||14));G[y]=S}}}f(d.H.id,b,d.K,u)}catch(fa){var ja=d.messageContext.eventId;OC();NC(ja,r,"4")}};b==="gtag.get"?v():io(e.R,v)}}},SC=function(a,b){if(b.type!=="require"){var c=void 0;b.type==="event"&&(c=b.args[1]);if(b.H)for(var d=QC(a,b.H).K[b.type]||
[],e=0;e<d.length;e++)d[e](c);else for(var f in a.destinations)if(a.destinations.hasOwnProperty(f)){var g=a.destinations[f];if(g&&g.K)for(var h=g.K[b.type]||[],l=0;l<h.length;l++)h[l](c)}}};PC.prototype.register=function(a,b,c,d){var e=QC(this,a);e.status!==3&&(e.N=b,e.status=3,e.R=lo(c),TC(this,a,d||{}),this.flush())};
PC.prototype.push=function(a,b,c,d){c!==void 0&&(QC(this,c).status===1&&(QC(this,c).status=2,this.push("require",[{}],c,{})),QC(this,c).H&&(d.deferrable=!1),d.eventMetadata||(d.eventMetadata={}),d.eventMetadata[H.J.sg]||(d.eventMetadata[H.J.sg]=[c.destinationId]),d.eventMetadata[H.J.mj]||(d.eventMetadata[H.J.mj]=[c.id]));this.commands.push(new nC(a,c,b,d));d.deferrable||this.flush()};
PC.prototype.flush=function(a){for(var b=this,c=[],d=!1,e={};this.commands.length;e={Zn:void 0}){var f=this.commands[0],g=f.H;if(f.messageContext.deferrable)!g||QC(this,g).H?(f.messageContext.deferrable=!1,this.commands.push(f)):c.push(f),this.commands.shift();else{switch(f.type){case "require":if(QC(this,g).status!==3&&!a){this.commands.push.apply(this.commands,c);return}break;case "set":var h=f.args[0];KC(h);UC(h);Gb(h,function(x,y){Ed(Vb(x,y),b.H)});Hu(h,!0);break;case "event":e.Zn=f.args[1];var l=
VC(f.args[0],function(){return function(){}}(e)),n=l[F.D.Xb];n&&n!==g.id||Hu(l);RC(this,e.Zn,l,f);break;case "get":var p={},q=(p[F.D.Tf]=f.args[0],p[F.D.Sf]=f.args[1],p);RC(this,F.D.Jb,q,f);break;case "container_config":var r=QC(this,g),t=VC(f.args[0],function(){});Hu(t,!0);r.H=!0;Ed(t,r.hb);d=!0;break;case "destination_config":var u=QC(this,g),v=VC(f.args[0],function(){});Hu(v,!0);u.Wa[g.id]||(u.Wa[g.id]={});u.H=!0;Ed(v,u.Wa[g.id]);d=!0;break;case "reset_container_config":QC(this,g).hb={};break;
case "reset_target_config":QC(this,g).Wa[g.id]={}}this.commands.shift();SC(this,f)}}this.commands.push.apply(this.commands,c);d&&this.flush()};var TC=function(a,b,c){var d=Ed(c,null);Ed(QC(a,b).ib,d);QC(a,b).ib=d};function VC(a,b){var c={};Gb(a,function(d,e){Ed(Vb(d,e),c)});KC(c,b);UC(c);return c}
function UC(a){if(M(601)&&BA()){for(var b=!1,c=m(new Set([F.D.yc,F.D.dd])),d=c.next();!d.done;d=c.next()){var e=d.value;a[e]!==void 0&&(b=!0,delete a[e])}b&&!al(35,function(){return!1})&&(Zk(35,!0),window.console&&window.console.log&&window.console.log("Google Tag Manager: Server-side GTM parameters (transport_url/server_container_url) are not permitted on this domain and have been ignored."),P(197))}};var WC=function(){this.H=new PC;this.K=!1};WC.prototype.flush=function(){this.H.flush()};var XC;function YC(){XC||(XC=new WC);return XC}function ZC(a,b,c,d){var e=YC(),f=bC(c,d.isGtmEvent);f&&(e.K&&(d.deferrable=!0),e.H.push("event",[b,a],f,d))}function $C(a,b,c,d){var e=YC(),f=bC(c,d.isGtmEvent);f&&e.H.push("get",[a,b],f,d)}function aD(a,b,c){var d=YC(),e=bC(a,c.isGtmEvent);e&&d.H.push("container_config",[b],e,c)}
function bD(a,b,c){var d=YC(),e=bC(a,c.isGtmEvent);e&&d.H.push("destination_config",[b],e,c)}function cD(a){var b=YC(),c=bC(a,!0);c&&b.H.push("reset_container_config",[],c,{})}function dD(a){var b=YC(),c=bC(a,!0);c&&b.H.push("reset_target_config",[],c,{})}function eD(a){var b=YC(),c=bC(a,!0);return c?QC(b.H,c).ib:{}}function fD(a){return YC().H.H[a]}function gD(a){var b=YC(),c=bC(a,!0);return c?QC(b.H,c).H:!1};function hD(a,b){a.hasOwnProperty("gtm.uniqueEventId")||Object.defineProperty(a,"gtm.uniqueEventId",{value:rj()});b.eventId=a["gtm.uniqueEventId"];b.priorityId=a["gtm.priorityId"];return{eventId:b.eventId,priorityId:b.priorityId}}function iD(a){for(var b=m([F.D.dd,F.D.yc]),c=b.next();!c.done;c=b.next()){var d=c.value,e=a&&a[d]||fD(d);if(e)return e}}function jD(a){return!a.isGtmEvent||a.eventMetadata&&a.eventMetadata[H.J.Cc]&&a.eventMetadata[H.J.Nb]!==vk()?!1:!0};var kD=new function(){this.H=!1};var lD=function(){this.messages=[];this.H=[]};lD.prototype.enqueue=function(a,b,c){var d=this.messages.length+1;a["gtm.uniqueEventId"]=b;a["gtm.priorityId"]=d;var e=na(Object,"assign").call(Object,{},c,{eventId:b,priorityId:d,fromContainerExecution:!0});if(M(595)){var f=c.priorityQueue?[].concat(w(c.priorityQueue),[d]):[d];a["gtm.priorityQueue"]=f;e.priorityQueue=f}var g={message:a,notBeforeEventId:b,priorityId:d,messageContext:e};this.messages.push(g);for(var h=0;h<this.H.length;h++)try{this.H[h](g)}catch(l){}};
lD.prototype.listen=function(a){this.H.push(a)};lD.prototype.get=function(){for(var a={},b=0;b<this.messages.length;b++){var c=this.messages[b],d=a[c.notBeforeEventId];d||(d=[],a[c.notBeforeEventId]=d);d.push(c)}return a};lD.prototype.prune=function(a){for(var b=[],c=[],d=0;d<this.messages.length;d++){var e=this.messages[d];e.notBeforeEventId===a?b.push(e):c.push(e)}this.messages=c;return b};
function mD(a,b,c){c.eventMetadata=c.eventMetadata||{};c.eventMetadata[H.J.Nb]=M(550)?vk():E(6);nD().enqueue(a,b,c)}function nD(){return kj("mb",function(){return new lD})};var pD=function(a,b){var c=oD;b=String(b).split(",");for(var d=0;d<b.length;d++){var e=c.N[b[d]]||[];c.N[b[d]]=e;e.indexOf(a)<0&&e.push(a)}},qD=function(a,b){for(var c=oD,d=[],e=[],f={},g=0;g<a.length;f={lk:void 0,Qj:void 0,Rj:void 0},g++){var h=a[g];if(h.indexOf("-")>=0){if(f.lk=bC(h,b),f.lk){var l=tk();Cb(l,function(x){return function(y){return x.lk.destinationId===y}}(f))?d.push(h):e.push(h)}}else{if(M(550)){var n=c.K[h]||[];f.Rj={};n.forEach(function(x){return function(y){x.Rj[y]=!0}}(f));for(var p=
tk(),q=0;q<p.length;q++)f.Rj[p[q]]&&d.push(p[q])}else{var r=c.H[h]||[];f.Qj={};r.forEach(function(x){return function(y){x.Qj[y]=!0}}(f));for(var t=wk(),u=0;u<t.length;u++)if(f.Qj[t[u]]){d=d.concat(tk());break}}var v=c.N[h]||[];v.length&&(d=d.concat(v))}}return{ek:d,Ps:e}},rD=function(a){Gb(oD.H,function(b,c){var d=c.indexOf(a);d>=0&&c.splice(d,1)})},sD=function(a){Gb(oD.K,function(b,c){var d=c.indexOf(a);d>=0&&c.splice(d,1)})},tD=function(a){Gb(oD.N,function(b,c){var d=c.indexOf(a);d>=0&&c.splice(d,
1)})},oD=new function(){this.H={};this.N={};this.K={}};function uD(a,b,c){var d=Ed(a,null);d.eventId=void 0;d.inheritParentConfig=void 0;Object.keys(b).some(function(f){return b[f]!==void 0})&&P(136);var e=Ed(b,null);Ed(c,e);mD(rC(wk()[0],e),a.eventId,d)}
function vD(a,b,c,d){var e={},f=(e[F.D.Ub]=F.D.wa,e["gtm.configContainerId"]=a.id,e["gtm.configParameters"]=b,e["gtm.uniqueEventId"]=d.eventId,e);c.priorityQueue&&(f["gtm.priorityQueue"]=c.priorityQueue);c.eventMetadata&&(f["gtm.eventMetadata"]=c.eventMetadata);a.Jc()&&(f["gtm.configContainerId"]=wk()[0],f["gtm.originalConfigTargetId"]=a.id);return f}function wD(a,b,c){if(If(11)&&!c&&!a[F.D.Vd]){var d=al(10,function(){return!1});Zk(10,!0);XB(d,a,b);if(d)return!0}return!1};function xD(a,b){var c={},d=(c.event=a,c);b&&(d.eventModel=Ed(b,null),b[F.D.Pf]&&(d.eventCallback=b[F.D.Pf]),b[F.D.ph]&&(d.eventTimeout=b[F.D.ph]));return d}
function yD(a,b){var c=a&&a[F.D.Xb];c===void 0&&(c=uA(F.D.Xb,2),c===void 0&&(c="default"));if(zb(c)||Array.isArray(c)){var d;d=b.isGtmEvent?zb(c)?[c]:c:c.toString().replace(/\s+/g,"").split(",");var e=qD(d,b.isGtmEvent),f=e.ek,g=e.Ps;if(g.length)for(var h=iD(a),l=0;l<g.length;l++){var n=bC(g[l],b.isGtmEvent);if(n){var p=n.destinationId,q=void 0;((q=nk(n.destinationId))==null?void 0:q.state)===0||nA(p,h,{source:3,fromContainerExecution:b.fromContainerExecution})}}var r=f.concat(g);return{ek:cC(f,b.isGtmEvent),
mr:cC(r,b.isGtmEvent)}}};var zD={},AD=(zD.config=function(a,b){var c=hD(a,b),d;a:{if(!(a.length<2)&&zb(a[1])){var e={};if(a.length>2){if(a[2]!==void 0&&!Cd(a[2])||a.length>3){d=void 0;break a}e=a[2]}var f=bC(a[1],b.isGtmEvent);if(f){d={target:f,params:e};break a}}d=void 0}var g=d;if(g){var h=g.target,l=g.params,n;a:{if(!If(7)){var p=yk(zk());if(Mk(p)){var q=p.parent,r=q.isDestination;n={Vs:yk(q),Ms:r};break a}}n=void 0}var t=n,u=t==null?void 0:t.Vs,v=t==null?void 0:t.Ms;dB(c.eventId,"gtag.config");var x,y=h.destinationId;
if(h.Jc()?tk().indexOf(y)!==-1:wk().indexOf(y)!==-1)a:{if(u&&(P(128),v&&P(130),b.inheritParentConfig)){var z;var C=$k(12);if(C)uD(b,C,l),z=!1;else{var D=$k(11);!l[F.D.Vd]&&(M(550)||If(11))&&D||Zk(11,Ed(l,null));z=!0}z&&u.containers&&u.containers.join(",");x=void 0;break a}var I=!If(45),G=!Sb(h.id,"GTM-");I&&G&&(Object.keys(l).length===0?Gu(T.W.Sk):Gu(T.W.Tk),El()&&Gu(T.W.Rk),$k(31)&&Gu(T.W.Uk));var N=YB;fn.K&&(N.H===1&&(Qm.H.mcc=!1),N.H=2);if(M(550)||!wD(l,b,h.Jc())){kD.H||P(43);if(!M(550)){if(!b.noTargetGroup){var S=
h.id;if(h.Jc())tD(S),pD(S,l[F.D.Od]||"default");else{rD(S);var W=l[F.D.Od]||"default",ea=oD;W=W.toString().split(",");for(var ja=0;ja<W.length;ja++){var fa=ea.H[W[ja]]||[];ea.H[W[ja]]=fa;fa.indexOf(S)<0&&fa.push(S)}}}delete l[F.D.Od]}var sa=b.eventMetadata||{};sa.hasOwnProperty(H.J.ae)||(sa[H.J.ae]=!b.fromContainerExecution);b.eventMetadata=sa;delete l[F.D.Pf];if(M(550)){x=vD(h,l,b,c);break a}var da=!!l[F.D.Vd];delete l[F.D.Vd];var ma=tk(),Pa=cD,Fa=aD;h.Jc()&&(ma=[h.id],Pa=dD,Fa=bD);for(var qa=0;qa<
ma.length;qa++){da||Pa(ma[qa]);var ib=gD(ma[qa]);Fa(ma[qa],Ed(l,null),Ed(b,null));ib&&da||ZC(F.D.wa,Ed(l,null),ma[qa],Ed(b,null))}}x=void 0}else a:{if(!b.inheritParentConfig&&!l[F.D.Zc]){var Xb=iD(l),Lc=h.destinationId;if(h.Jc())nA(Lc,Xb,{source:2,fromContainerExecution:b.fromContainerExecution});else if(u!==void 0&&u.containers.indexOf(Lc)!==-1){var Qd=$k(11),Yc=$k(12);Qd?uD(b,l,Qd):Yc||Zk(12,Ed(l,null))}else if(hA(Lc,Xb,!0,{source:2,fromContainerExecution:b.fromContainerExecution}),M(550)){x=vD(h,
l,b,c);break a}}x=void 0}return x}},zD.consent=function(a,b){if(a.length===3){P(39);var c=hD(a,b),d=a[1],e={},f=Oo(a[2]),g;for(g in f)if(f.hasOwnProperty(g)){var h=f[g];e[g]=g===F.D.Yg?Array.isArray(h)?NaN:Number(h):g===F.D.nc?(Array.isArray(h)?h:[h]).map(Po):Qo(h)}b.fromContainerExecution||(e[F.D.ma]&&P(139),e[F.D.Xa]&&P(140));d==="default"?To(e):d==="update"?Vo(e,c):d==="declare"&&b.fromContainerExecution&&So(e)}},zD.container_config=function(a,b){if(jD(b)&&a.length===3&&zb(a[1])&&Cd(a[2])){var c=
a[2],d=bC(a[1],!0);d&&aD(d.destinationId,c,Ed(b,null))}},zD.destination_config=function(a,b){if(jD(b)&&a.length===3&&zb(a[1])&&Cd(a[2])){var c=a[2],d=bC(a[1],!0);if(d){if(M(550)){if(!b.noTargetGroup){var e=d.id;if(d.Jc())tD(e),pD(e,c[F.D.Od]||"default");else{sD(e);var f=c[F.D.Od]||"default",g=oD;f=String(f).split(",");for(var h=0;h<f.length;h++){var l=g.K[f[h]]||[];g.K[f[h]]=l;l.indexOf(e)<0&&l.push(e)}}}delete c[F.D.Od]}bD(d.id,c,Ed(b,null))}}},zD.event=function(a,b){var c=a[1];if(!(a.length<2)&&
zb(c)){var d=void 0;if(a.length>2){if(!Cd(a[2])&&a[2]!==void 0||a.length>3)return;d=a[2]}var e=xD(c,d),f=hD(a,b),g=f.eventId,h=f.priorityId;e["gtm.uniqueEventId"]=g;h&&(e["gtm.priorityId"]=h);b.priorityQueue&&(e["gtm.priorityQueue"]=b.priorityQueue);if(c==="optimize.callback")return e.eventModel=e.eventModel||{},e;var l=yD(d,b);if(l){for(var n=l.ek,p=l.mr,q=p.map(function(N){return N.id}),r=p.map(function(N){return N.destinationId}),t=n.map(function(N){return N.id}),u=m(tk()),v=u.next();!v.done;v=
u.next()){var x=v.value;r.indexOf(x)<0&&t.push(x)}dB(g,c);for(var y=m(t),z=y.next();!z.done;z=y.next()){var C=z.value,D=Ed(b,null),I=Ed(d,null);delete I[F.D.Pf];var G=D.eventMetadata||{};G.hasOwnProperty(H.J.ae)||(G[H.J.ae]=!D.fromContainerExecution);G[H.J.mj]=q.slice();G[H.J.sg]=r.slice();D.eventMetadata=G;ZC(c,I,C,D)}e.eventModel=e.eventModel||{};q.length>0?e.eventModel[F.D.Xb]=q.join(","):delete e.eventModel[F.D.Xb];kD.H||P(43);b.noGtmEvent===void 0&&b.eventMetadata&&b.eventMetadata[H.J.Bn]&&(b.noGtmEvent=
!0);e.eventModel[F.D.Yc]&&(b.noGtmEvent=!0);return b.noGtmEvent?void 0:e}}},zD.get=function(a,b){P(53);if(a.length===4&&zb(a[1])&&zb(a[2])&&yb(a[3])){var c=bC(a[1],b.isGtmEvent),d=String(a[2]),e=a[3];if(c){kD.H||P(43);var f=iD();if(Cb(tk(),function(h){return c.destinationId===h})){hD(a,b);var g={};Ed((g[F.D.Tf]=d,g[F.D.Sf]=e,g),null);$C(d,function(h){bd(function(){e(h)})},c.id,b)}else nA(c.destinationId,f,{source:4,fromContainerExecution:b.fromContainerExecution})}}},zD.js=function(a,b){var c;if(a.length===
2&&a[1].getTime){kD.H=!0;var d=hD(a,b),e=d.eventId,f=d.priorityId,g={};c=(g.event="gtm.js",g["gtm.start"]=a[1].getTime(),g["gtm.uniqueEventId"]=e,g["gtm.priorityId"]=f,g)}else c=void 0;return c},zD.policy=function(a){if(a.length===3&&zb(a[1])&&yb(a[2])){if(hy(a[1],a[2]),P(74),a[1]==="all"){P(75);var b=!1;try{b=a[2](E(5),"unknown",{})}catch(c){}b||P(76)}}else P(73)},zD.reset_target_config=function(a,b){if(jD(b)&&a.length===2&&zb(a[1])){var c=bC(a[1],!0);c&&dD(c.id)}},zD.set=function(a,b){var c=void 0;
a.length===2&&Cd(a[1])?c=Ed(a[1],null):a.length===3&&zb(a[1])&&(c={},Cd(a[2])||Array.isArray(a[2])?c[a[1]]=Ed(a[2],null):c[a[1]]=a[2]);if(c){Zk(31,!0);var d=hD(a,b),e=d.eventId,f=d.priorityId;Ed(c,null);E(5);var g=Ed(c,null);YC().H.push("set",[g],void 0,b);c["gtm.uniqueEventId"]=e;f&&(c["gtm.priorityId"]=f);delete c.event;b.overwriteModelFields=!0;return c}},zD),BD={},CD=(BD.policy=!0,BD);var ED=function(a){if(DD(a))return a;this.value=a};ED.prototype.getUntrustedMessageValue=function(){return this.value};var DD=function(a){return!a||Ad(a)!=="object"||Cd(a)?!1:"getUntrustedMessageValue"in a};ED.prototype.getUntrustedMessageValue=ED.prototype.getUntrustedMessageValue;var FD={Bb:"1",ee:"2",Xd:"3",ce:"4",xf:"5",qg:"6",Kh:"7",tj:"8",li:"9",jj:"10"};var dE=function(){var a=this;this.loaded=!1;this.H=[];if(B.readyState==="complete")this.onLoad();else $c(A,"load",function(){return void a.onLoad()})};dE.prototype.onLoad=function(){if(!this.loaded){this.loaded=!0;for(var a=0;a<this.H.length;a++)bd(this.H[a])}};var fE=function(a){var b=eE;b.loaded?bd(a):b.H.push(a)},eE=new dE;var gE=function(){this.Z=0;this.K={};this.H=[];this.N=[];this.fa=this.R=this.ja=!1},iE=function(a,b,c){var d=hE;a.eventCallback=b;c&&(a.eventTimeout=c);return d.push(a)},jE=function(a,b){if(!Ab(b)||b<0)b=0;var c=qj(),d=0,e=!1,f=void 0;f=A.setTimeout(function(){e||(e=!0,a());f=void 0},b);return function(){var g=c?c.subscribers:1;++d===g&&(f&&(A.clearTimeout(f),f=void 0),e||(a(),e=!0))}},lE=function(a){var b;if(a.N.length)b=a.N.shift();else if(a.H.length)b=a.H.shift();else return;var c;var d=b;if(a.ja||
!kE(d.message))c=d;else{a.ja=!0;var e=d.message["gtm.uniqueEventId"],f,g;typeof e==="number"?(f=e-2,g=e-1):(f=rj(),g=rj(),d.message["gtm.uniqueEventId"]=rj());var h={},l={message:(h.event="gtm.init_consent",h["gtm.uniqueEventId"]=f,h),messageContext:{eventId:f}},n={},p={message:(n.event="gtm.init",n["gtm.uniqueEventId"]=g,n),messageContext:{eventId:g}};a.H.unshift(p,d);c=l}return c},oE=function(a){a.fa||P(196);for(var b=!1,c;!a.R&&(c=lE(a));){a.R=!0;var d=rA;delete d.H.eventModel;oA(d);var e=c,f=
e.message,g=e.messageContext;if(f==null)a.R=!1;else{g.fromContainerExecution&&sA();try{if(yb(f))try{f.call(tA)}catch(S){}else if(Array.isArray(f)){if(zb(f[0])){var h=f[0].split("."),l=h.pop(),n=f.slice(1),p=uA(h.join("."),2);if(p!=null)try{p[l].apply(p,n)}catch(S){}}}else{var q=void 0;if(Hb(f))a:{if(f.length&&zb(f[0])){var r=AD[f[0]];if(r&&(!g.fromContainerExecution||!CD[f[0]])){q=r(f,g);break a}}q=void 0}else q=f;if(q){var t;for(var u=q,v=u._clear||g.overwriteModelFields,x=m(Object.keys(u)),y=x.next();!y.done;y=
x.next()){var z=y.value;z!=="_clear"&&(v&&rA.set(z,void 0),rA.set(z,u[z]))}M(592)&&SD(u);$k(25)||Zk(25,u["gtm.start"]);var C=u["gtm.uniqueEventId"];u.event?(typeof C!=="number"&&(C=rj(),u["gtm.uniqueEventId"]=C,rA.set("gtm.uniqueEventId",C)),t=zB(u)):t=!1;b=t||b}}}finally{g.fromContainerExecution&&oA(rA,!0);var D=f["gtm.uniqueEventId"];if(typeof D==="number"){for(var I=a,G=I.K[String(D)]||[],N=0;N<G.length;N++)I.N.push(mE(G[N]));G.length&&I.N.sort(nE);delete I.K[String(D)];D>a.Z&&(a.Z=D)}a.R=!1}}}return!b},
pE=function(){var a=hE;a.fa&&P(195);a.fa=!0;if(fn.H){var b=!If(51),c=rz();pz(c,{stage:Iy.X.Zg});if(b){var d=qz(c,{stage:Iy.X.Yk},Iy.X.ni);d!==void 0&&(c.H.Y=d)}var e=a.H.length;rz().H.C=e}oE(a);if(fn.H){var f=rz(),g=qz(f,{stage:Iy.X.Vk},Iy.X.Zg);g!==void 0&&(f.H.B=g)}try{var h=A[E(19)],l=E(5),n=h.hide;if(n&&n[l]!==void 0&&n.end){n[l]=!1;var p=!0,q;for(q in n)if(n.hasOwnProperty(q)&&n[q]===!0){p=!1;break}p&&(n.end(),n.end=null)}}catch(r){E(5)}},qE=function(a,b){if(a.Z<b.notBeforeEventId){var c=String(b.notBeforeEventId);
a.K[c]=a.K[c]||[];a.K[c].push(b)}else{a.N.push(mE(b));a.N.sort(nE);var d=function(){a.R||oE(a)};M(580)?dd(d):bd(d)}};
gE.prototype.bind=function(){function a(h){var l={};if(DD(h)){var n=h;h=DD(n)?n.getUntrustedMessageValue():void 0;l.fromContainerExecution=!0}return{message:h,messageContext:l}}var b=this,c=Mc(E(19),[]),d=pj();d.pruned===!0&&P(83);this.K=nD().get();nD().listen(function(h){qE(b,h)});d.subscribers=(d.subscribers||0)+1;var e=c.push,f=this;c.push=function(){var h;lj();if(jj.H.SANDBOXED_JS_SEMAPHORE>0){h=[];for(var l=0;l<arguments.length;l++)h[l]=new ED(arguments[l])}else h=[].slice.call(arguments,0);
var n=h.map(function(t){return a(t)});f.H.push.apply(f.H,n);var p=e.apply(c,h),q=Math.max(100,Nf(1,300));if(this.length>q)for(P(4),d.pruned=!0;this.length>q;)this.shift();var r=typeof p!=="boolean"||p;return oE(f)&&r};var g=c.slice(0).map(function(h){return a(h)});this.H.push.apply(this.H,g);If(51)||(fn.H&&uz(),bd(rE));VB(function(){if(!d.gtmDom){d.gtmDom=!0;var h={};c.push((h.event="gtm.dom",h))}});fE(function(){if(!d.gtmLoad){d.gtmLoad=!0;var h={};c.push((h.event="gtm.load",h))}})};
gE.prototype.push=function(a){return A[E(19)].push(a)};var hE=new gE;function nE(a,b){var c=a.messageContext,d=b.messageContext;if(c.eventId!==d.eventId)return c.eventId-d.eventId;if(!M(595))return c.priorityId-d.priorityId;var e,f,g;a:{for(var h=(e=c.priorityQueue)!=null?e:[c.priorityId],l=(f=d.priorityQueue)!=null?f:[d.priorityId],n=Math.min(h.length,l.length),p=0;p<n;p++)if(h[p]!==l[p]){g=h[p]-l[p];break a}g=h.length-l.length}return g}
function kE(a){if(a==null||typeof a!=="object")return!1;if(a.event)return!0;if(Hb(a)){var b=a[0];if(b==="config"||b==="event"||b==="js"||b==="get")return!0}return!1}function mE(a){return{message:a.message,messageContext:a.messageContext}}function sE(a,b,c){return iE(a,b,c)}function tE(a,b){return jE(a,b)}function rE(){pE()}function uE(a){return hE.push(a)};var vE=function(){};vE.prototype.bind=function(){var a,b=Rj(A.location.href);(a=b.hostname+b.pathname)&&Um("dl",encodeURIComponent(a));var c;var d=E(5);if(d){var e=If(7)?1:0,f=Fk(),g=f&&f.fromContainerExecution?1:0,h=f&&f.source||0,l=E(6);c=d+";"+l+";"+g+";"+h+";"+e}else c=void 0;var n=c;n&&Um("tdp",n);var p=Op(!0);p!==void 0&&Um("frm",String(p))};var wE=new vE;var xE=function(){this.H=Xm();this.K=void 0},yE=function(a,b){return Zm(a,function(c){return c.jb>0?b?c.jb+"_"+Wm(c):String(c.jb):void 0})};
xE.prototype.bind=function(){var a=this;if(pl()||fn.K)Um("csp",function(){var b=yE(a.H,!0);$m(a.H);return b},!1),Um("mde",function(){var b=cn.H,c=yE(b,!1);$m(b);return c},!1),A.addEventListener("securitypolicyviolation",function(b){if(b.disposition==="enforce"){P(179);var c=nn(b.effectiveDirective);if(c){var d;a:{var e=b.blockedURI,f=kn;if(fn.K&&e){var g=jn(c,e);if(g){var h;d=(h=ln(f,c))==null?void 0:h[g];break a}}d=void 0}var l=d;if(l){var n;a:{try{var p=new URL(b.blockedURI),q=p.pathname.indexOf(";");
n=q>=0?p.origin+p.pathname.substring(0,q):p.origin+p.pathname;break a}catch(D){}n=void 0}var r=n;if(r){for(var t=m(l),u=t.next();!u.done;u=t.next()){var v=u.value;if(!v.Eo){v.Eo=!0;var x={eventId:v.eventId,priorityId:v.priorityId};if(pl()){var y=x,z={type:1,blockedUrl:r,endpoint:v.endpoint,violation:b.effectiveDirective};if(pl()){var C=Ll("TAG_DIAGNOSTICS",{eventId:y==null?void 0:y.eventId,priorityId:y==null?void 0:y.priorityId});C.tagDiagnostics=z;ol(C)}}zE(a,v.destinationId,v.endpoint,c)}}mn(c,
b.blockedURI)}}}}})};var zE=function(a,b,c,d){an(a.H,b,c,1,d);Vm("csp",!0);Vm("mde",!0);c!==61&&c!==56&&a.K===void 0&&(a.K=A.setTimeout(function(){a.H.jb>0&&to(!1);a.K=void 0},500))},AE=new xE;var BE=function(){this.sequenceNumber=0};BE.prototype.bind=function(){var a=this;CE(this);If(65)&&Um("mtbl","1");Um("v","3");Um("t","t");Um("pid",function(){return String(nm(jm.ba.bh))});Um("gtm",function(){return du()});Um("seq",function(){return String(++a.sequenceNumber)});Um("exp",function(){return Cp()})};var CE=function(a){if(nm(jm.ba.bh)===void 0){var b=function(){mm(jm.ba.bh,Db());a.sequenceNumber=0};b();cd(b,864E5)}else pm(jm.ba.bh,function(){a.sequenceNumber=0});a.sequenceNumber=0},DE=new BE;function EE(a){return function(){return A[a]}}
var FE={},GE=(FE[14]=function(){var a;return(a=A.crypto)==null?void 0:a.getRandomValues},FE[15]=function(){var a,b;return(a=A.crypto)==null?void 0:(b=a.subtle)==null?void 0:b.digest},FE[1]=EE("fetch"),FE[6]=EE("Map"),FE[2]=function(){return Math.random},FE[8]=function(){return na(Object,"assign")},FE[9]=function(){return Object.entries},FE[10]=function(){return Object.fromEntries},FE[5]=EE("Promise"),FE[13]=EE("RegExp"),FE[3]=function(){return Hc.sendBeacon},FE[7]=EE("Set"),FE[12]=function(){return String.prototype.endsWith},
FE[11]=function(){return String.prototype.startsWith},FE[4]=EE("XMLHttpRequest"),FE),HE={},IE=(HE[15]=!0,HE);var NE=/^(https?:)?\/\//;
function hF(){};function iF(){If(62)&&(hy("detect_link_click_events",function(a,b,c){var d;return((d=c.options)==null?void 0:d.waitForTags)!==!0}),hy("detect_form_submit_events",function(a,b,c){var d;return((d=c.options)==null?void 0:d.waitForTags)!==!0}),hy("detect_youtube_activity_events",function(a,b,c){var d;return((d=c.options)==null?void 0:d.fixMissingApi)!==!0}))};var jF=function(){this.H=this.gppString=void 0};jF.prototype.reset=function(){this.H=this.gppString=void 0};var kF=new jF;[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2].reduce(function(a,b){return a+b});[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2].reduce(function(a,b){return a+b});[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2].reduce(function(a,b){return a+b});[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2].reduce(function(a,b){return a+b});[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2].reduce(function(a,b){return a+b});[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2].reduce(function(a,b){return a+b});lt({Gu:0,Fu:1,Cu:2,xu:3,Du:4,yu:5,Eu:6,Au:7,Bu:8,wu:9,zu:10,Hu:11}).map(function(a){return Number(a)});lt({Ju:0,Ku:1,Iu:2}).map(function(a){return Number(a)});var lF=function(a,b,c,d){rt.call(this);this.fe=b;this.kd=c;this.ac=d;this.La=new Map;this.he=0;this.ja=new Map;this.ya=new Map;this.Z=void 0;this.K=a};wa(lF,rt);lF.prototype.N=function(){delete this.H;this.La.clear();this.ja.clear();this.ya.clear();this.Z&&(nt(this.K,"message",this.Z),delete this.Z);delete this.K;delete this.ac;rt.prototype.N.call(this)};
var mF=function(a){if(a.H)return a.H;a.kd&&a.kd(a.K)?a.H=a.K:a.H=Np(a.K,a.fe);var b;return(b=a.H)!=null?b:null},oF=function(a,b,c){if(mF(a))if(a.H===a.K){var d=a.La.get(b);d&&d(a.H,c)}else{var e=a.ja.get(b);if(e&&e.dk){nF(a);var f=++a.he;a.ya.set(f,{pe:e.pe,Ir:e.no(c),persistent:b==="addEventListener"});a.H.postMessage(e.dk(c,f),"*")}}},nF=function(a){a.Z||(a.Z=function(b){if(b.source===a.H)try{var c;c=a.ac?a.ac(b):void 0;if(c){var d=c.Ys,e=a.ya.get(d);if(e){e.persistent||a.ya.delete(d);var f;(f=
e.pe)==null||f.call(e,e.Ir,c.payload)}}}catch(g){}},mt(a.K,"message",a.Z))};var pF=function(a,b){var c=b.listener,d=(0,a.__gpp)("addEventListener",c);d&&c(d,!0)},qF=function(a,b){(0,a.__gpp)("removeEventListener",b.listener,b.listenerId)},rF={no:function(a){return a.listener},dk:function(a,b){var c={};return c.__gppCall={callId:b,command:"addEventListener",version:"1.1"},c},pe:function(a,b){var c=b.__gppReturn;a(c.returnValue,c.success)}},sF={no:function(a){return a.listener},dk:function(a,b){var c={};return c.__gppCall={callId:b,command:"removeEventListener",version:"1.1",
parameter:a.listenerId},c},pe:function(a,b){var c=b.__gppReturn,d=c.returnValue.data;a==null||a(d,c.success)}};function tF(a){var b={};vf(a.data)?b=JSON.parse(a.data):b=a.data;return{payload:b,Ys:b.__gppReturn.callId}}
var uF=function(a,b){var c;c=(b===void 0?{}:b).timeoutMs;rt.call(this);this.caller=new lF(a,"__gppLocator",function(d){return typeof d.__gpp==="function"},tF);this.caller.La.set("addEventListener",pF);this.caller.ja.set("addEventListener",rF);this.caller.La.set("removeEventListener",qF);this.caller.ja.set("removeEventListener",sF);this.timeoutMs=c!=null?c:500};wa(uF,rt);uF.prototype.N=function(){this.caller.dispose();rt.prototype.N.call(this)};
uF.prototype.addEventListener=function(a){var b=this,c=Hp(function(){a(vF,!0)}),d=this.timeoutMs===-1?void 0:setTimeout(function(){c()},this.timeoutMs);oF(this.caller,"addEventListener",{listener:function(e,f){clearTimeout(d);try{var g;var h;((h=e.pingData)==null?void 0:h.gppVersion)===void 0||e.pingData.gppVersion==="1"||e.pingData.gppVersion==="1.0"?(b.removeEventListener(e.listenerId),g={eventName:"signalStatus",data:"ready",pingData:{internalErrorState:1,gppString:"GPP_ERROR_STRING_IS_DEPRECATED_SPEC",
applicableSections:[-1]}}):Array.isArray(e.pingData.applicableSections)?g=e:(b.removeEventListener(e.listenerId),g={eventName:"signalStatus",data:"ready",pingData:{internalErrorState:2,gppString:"GPP_ERROR_STRING_EXPECTED_APPLICATION_SECTION_ARRAY",applicableSections:[-1]}});a(g,f)}catch(l){if(e==null?0:e.listenerId)try{b.removeEventListener(e.listenerId)}catch(n){a(wF,!0);return}a(xF,!0)}}})};
uF.prototype.removeEventListener=function(a){oF(this.caller,"removeEventListener",{listener:function(){},listenerId:a})};
var xF={eventName:"signalStatus",data:"ready",pingData:{internalErrorState:2,gppString:"GPP_ERROR_STRING_UNAVAILABLE",applicableSections:[-1]},listenerId:-1},vF={eventName:"signalStatus",data:"ready",pingData:{gppString:"GPP_ERROR_STRING_LISTENER_REGISTRATION_TIMEOUT",internalErrorState:2,applicableSections:[-1]},listenerId:-1},wF={eventName:"signalStatus",data:"ready",pingData:{gppString:"GPP_ERROR_STRING_REMOVE_EVENT_LISTENER_ERROR",internalErrorState:2,applicableSections:[-1]},listenerId:-1};function yF(a){var b;if(!(b=a.pingData.signalStatus==="ready")){var c=a.pingData.applicableSections;b=!c||c.length===1&&c[0]===-1}if(b){kF.gppString=a.pingData.gppString;var d=a.pingData.applicableSections.join(",");kF.H=d}}function zF(){try{var a=new uF(A,{timeoutMs:-1});mF(a.caller)&&a.addEventListener(yF)}catch(b){}};function AF(){var a=[["cv",E(1)],["rv",E(14)],["tc",cA.tags.filter(function(d){return d}).length]],b=Jf(15);b&&a.push(["x",b]);var c=Cp();c&&a.push(["tag_exp",c]);return a};var BF=function(){var a=this;this.H={};this.K={};fz(function(b){var c=b.eventId,d=b.tf,e=[],f=a.H[c]||[];f.length&&e.push(["hf",f.join(".")]);var g=a.K[c]||[];g.length&&e.push(["ht",g.join(".")]);d&&(delete a.H[c],delete a.K[c]);return e})},CF=function(){var a=0;return function(b){switch(b){case 1:a|=1;break;case 2:a|=2;break;case 3:a|=4}return a}},DF;var EF=function(){var a=this;this.H="";fn.N&&M(516)&&fz(function(){var b=[];a.H&&b.push(["psd",a.H]);return b})},FF;function GF(){return!1}
function HF(){var a={};return function(b,c,d){}};function IF(){var a=JF;return function(b,c,d){var e=d&&d.event;KF(c);var f=Bh(b)?void 0:1,g=new kb;Gb(c,function(r,t){var u=Ud(t,void 0,f);u===void 0&&t!==void 0&&P(44);g.set(r,u)});a.Qb(Qf());var h={Rn:hg(b),eventId:e==null?void 0:e.id,priorityId:e!==void 0?e.priorityId:void 0,priorityQueue:e!==void 0?e.priorityQueue:void 0,wg:e!==void 0?function(r){e.ld.wg(r)}:void 0,Pb:function(){return b},log:function(){},Nr:{index:d==null?void 0:d.index,type:d==null?void 0:d.type,name:d==null?void 0:d.name},
it:!!KA(b,3),originalEventData:e==null?void 0:e.originalEventData};e&&e.cachedModelValues&&(h.cachedModelValues={gtm:e.cachedModelValues.gtm,ecommerce:e.cachedModelValues.ecommerce});if(GF()){var l=HF(),n,p;h.Ab={wk:[],yg:{},jc:function(r,t,u){t===1&&(n=r);t===7&&(p=u);l(r,t,u)},ei:Vh()};h.log=function(r){var t=Oa.apply(1,arguments);n&&l(n,4,{level:r,source:p,message:t})}}
var q=rf(a,h,[b,g]);a.Qb();q instanceof Ta&&(q.type==="return"?q=q.data:q=void 0);return Td(q,void 0,f)}}function KF(a){var b=a.gtmOnSuccess,c=a.gtmOnFailure;yb(b)&&(a.gtmOnSuccess=function(){bd(b)});yb(c)&&(a.gtmOnFailure=function(){bd(c)})};function NF(){return Math.floor(Math.random()*20)};var OF=[F.D.zi].map(function(a){return a.slice(2)});function QF(a){}QF.P="internal.addAdsClickIds";function RF(a,b){var c=this;}RF.publicName="addConsentListener";var SF=!1;function TF(a){for(var b=0;b<a.length;++b)if(SF)try{a[b]()}catch(c){P(77)}else a[b]()}function UF(a,b,c){var d=this,e;return e}UF.P="internal.addDataLayerEventListener";function VF(a,b,c){}VF.publicName="addDocumentEventListener";function WF(a,b,c,d){}WF.publicName="addElementEventListener";function XF(a){return a.T.xb()};function YF(a){}YF.publicName="addEventCallback";
function iG(a){if(a.form){var b;return((b=a.form)==null?0:b.tagName)?a.form:B.getElementById(a.form)}return hd(a,["form"],100)};
function mG(a){}mG.P="internal.addFormAbandonmentListener";function nG(a,b,c,d){}
nG.P="internal.addFormData";
function sG(a){}sG.P="internal.addGaSendListener";function tG(a){if(!a)return{};var b=a.Nr;return JA(b.type,b.index,b.name)}function uG(a){if(!a)return{};var b={originatingEntity:tG(a)};a.priorityQueue&&(b.priorityQueue=a.priorityQueue);return b};function CG(a){var b=mj("zones");return b?b.getIsAllowedFn(wk(),a):function(){return!0}}function DG(){var a=mj("zones");a&&a.unregisterChild(wk())}
function EG(){kB(vk(),function(a){var b=a.originalEventData["gtm.uniqueEventId"],c=mj("zones");return c?c.isActive(wk(),b):!0});hB(vk(),function(a){var b,c;b=a.entityId;c=a.securityGroups;return CG(Number(a.originalEventData["gtm.uniqueEventId"]))(b,c)})};var FG=function(a,b){this.tagId=a;this.canonicalId=b};
function GG(a,b){var c=this;return a}GG.P="internal.loadGoogleTag";function HG(a){return new Kd("",function(b){var c=this.evaluate(b);if(c instanceof Kd)return new Kd("",function(){var d=Oa.apply(0,arguments),e=this,f=Ed(XF(this),null);f.eventId=a.eventId;f.priorityId=a.priorityId;f.originalEventData=a.originalEventData;var g=d.map(function(l){return e.evaluate(l)}),h=this.T.wb();h.ue(f);return c.Nc.apply(c,[h].concat(w(g)))})})};function IG(a,b,c){var d=this;}IG.P="internal.addGoogleTagRestriction";
function PG(a,b){}PG.P="internal.addHistoryChangeListener";function QG(a,b,c){}QG.publicName="addWindowEventListener";function RG(a,b){return!0}RG.publicName="aliasInWindow";function SG(a,b,c){}SG.P="internal.appendRemoteConfigParameter";function TG(a){var b;return b}
TG.publicName="callInWindow";function UG(a){}UG.publicName="callLater";function VG(a){}VG.P="callOnDomReady";function WG(a){}WG.P="callOnWindowLoad";function ZG(a,b){return c}ZG.P="internal.claimDestination";function $G(a,b){var c;return c}$G.P="internal.computeGtmParameter";function aH(a,b){var c=this;}aH.P="internal.consentScheduleFirstTry";function bH(a,b){var c=this;}bH.P="internal.consentScheduleRetry";function cH(a){var b;return b}cH.P="internal.copyFromCrossContainerData";function dH(a,b){var c;if(!lh(a)||!qh(b)&&b!==null&&!gh(b))throw K(this.getName(),["string","number|undefined"],arguments);L(this,"read_data_layer",a);var d;(b||2)!==2?d=uA(a,1):d=qA(rA,a,[A,B]);c=d;var e=Ud(c,this.T,Bh(XF(this).Pb())?2:1);e===void 0&&c!==void 0&&P(45);return e}dH.publicName="copyFromDataLayer";
function eH(a){var b=void 0;return b}eH.P="internal.copyFromDataLayerCache";function fH(a){var b;return b}fH.publicName="copyFromWindow";function gH(a){var b=void 0;return Ud(b,this.T,1)}gH.P="internal.copyKeyFromWindow";var hH=function(a){return a===co.ia.cb&&fo.H[a]===bo.Ma.Ue&&!Xo(F.D.ka)};var iH=function(){return"0"},jH=function(a){if(typeof a!=="string")return"";var b=["gclid","dclid","wbraid","_gl"];M(102)&&b.push("gbraid");return Sj(a,b,"0")};var kH={},lH={},mH={},nH={},oH={},pH={},qH={},rH={},sH={},tH={},uH={},vH={},wH={},xH={},yH={},zH={},AH={},BH={},CH={},DH={},EH={},FH={},GH={},HH={},IH={},JH={},KH=(JH[F.D.fb]=(kH[2]=[hH],kH),JH[F.D.Zf]=(lH[2]=[hH],lH),JH[F.D.Ji]=(mH[2]=[hH],mH),JH[F.D.gm]=(nH[2]=[hH],nH),JH[F.D.hm]=(oH[2]=[hH],oH),JH[F.D.im]=(pH[2]=[hH],pH),JH[F.D.jm]=(qH[2]=[hH],qH),JH[F.D.km]=(rH[2]=[hH],rH),JH[F.D.Bc]=(sH[2]=[hH],sH),JH[F.D.cg]=(tH[2]=[hH],tH),JH[F.D.dg]=(uH[2]=[hH],uH),JH[F.D.eg]=(vH[2]=[hH],vH),JH[F.D.fg]=(wH[2]=
[hH],wH),JH[F.D.gg]=(xH[2]=[hH],xH),JH[F.D.hg]=(yH[2]=[hH],yH),JH[F.D.ig]=(zH[2]=[hH],zH),JH[F.D.jg]=(AH[2]=[hH],AH),JH[F.D.lb]=(BH[1]=[hH],BH),JH[F.D.Dd]=(CH[1]=[hH],CH),JH[F.D.Kd]=(DH[1]=[hH],DH),JH[F.D.Ee]=(EH[1]=[hH],EH),JH[F.D.Bf]=(FH[1]=[function(a){return M(102)&&hH(a)}],FH),JH[F.D.Uc]=(GH[1]=[hH],GH),JH[F.D.za]=(HH[1]=[hH],HH),JH[F.D.Ua]=(IH[1]=[hH],IH),JH),LH={},MH=(LH[F.D.lb]=iH,LH[F.D.Dd]=iH,LH[F.D.Kd]=iH,LH[F.D.Ee]=iH,LH[F.D.Bf]=iH,LH[F.D.Uc]=function(a){if(!Cd(a))return{};var b=Ed(a,
null);delete b.match_id;return b},LH[F.D.za]=jH,LH[F.D.Ua]=jH,LH),NH={},OH={},PH=(OH[H.J.Ya]=(NH[2]=[hH],NH),OH),QH={};var RH=function(a,b,c,d){this.H=a;this.N=b;this.R=c;this.Z=d};RH.prototype.getValue=function(a){a=a===void 0?co.ia.gd:a;if(!this.N.some(function(b){return b(a)}))return this.R.some(function(b){return b(a)})?this.Z(this.H):this.H};RH.prototype.K=function(){return Ad(this.H)==="array"||Cd(this.H)?Ed(this.H,null):this.H};
var SH=function(){},TH=function(a,b){this.conditions=a;this.H=b},UH=function(a,b,c){var d,e=((d=a.conditions[b])==null?void 0:d[2])||[],f,g=((f=a.conditions[b])==null?void 0:f[1])||[];return new RH(c,e,g,a.H[b]||SH)},VH,WH;var YH=function(a){a.K=!0;a.H=!1;if(If(52)){if(M(516)&&XH()){var b;a.settings=(b=data.productSettings)!=null?b:{};a.H=!0}else{var c;a.settings=(c=productSettings)!=null?c:{}}productSettings=void 0;data.productSettings=void 0;var d;(d=FF)!=null&&fn.N&&M(516)&&(d.H=a.H?"1":"0")}},$H=function(a){var b=ZH;b.K||YH(b);return b.settings[a]},ZH=new function(){this.settings={};this.K=this.H=!1};
function XH(){if(!data.productSettings&&!productSettings)return!0;if(!data.productSettings||!productSettings||Object.keys(data.productSettings).length!==Object.keys(productSettings).length)return!1;for(var a in productSettings)if(!data.productSettings.hasOwnProperty(a)||data.productSettings[a].preAutoPii!==productSettings[a].preAutoPii)return!1;return!0};var aI=function(a,b,c){this.eventName=b;this.M=c;this.H={};this.isAborted=!1;this.target=a;this.metadata={};for(var d=c.eventMetadata||{},e=m(Object.keys(d)),f=e.next();!f.done;f=e.next()){var g=f.value;V(this,g,d[g])}},R=function(a,b){var c,d;return(c=a.H[b])==null?void 0:(d=c.getValue)==null?void 0:d.call(c,Q(a,H.J.tg))},eu=function(a){return Object.keys(a.H)},U=function(a,b,c){var d=a.H,e;c===void 0?e=void 0:(VH!=null||(VH=new TH(KH,MH)),e=UH(VH,b,c));d[b]=e};
aI.prototype.mergeHitDataForKey=function(a,b){var c,d,e;c=(d=this.H[a])==null?void 0:(e=d.K)==null?void 0:e.call(d);if(!c)return U(this,a,b),!0;if(!Cd(c))return!1;U(this,a,na(Object,"assign").call(Object,c,b));return!0};var bI=function(a,b){b=b===void 0?{}:b;for(var c=m(Object.keys(a.H)),d=c.next();!d.done;d=c.next()){var e=d.value,f=void 0,g=void 0,h=void 0;b[e]=(f=a.H[e])==null?void 0:(h=(g=f).K)==null?void 0:h.call(g)}return b};
aI.prototype.copyToHitData=function(a,b,c){var d=O(this.M,a);d===void 0&&(d=b);if(zb(d)&&c!==void 0)try{d=c(d)}catch(e){}d!==void 0&&U(this,a,d)};
var Q=function(a,b){var c=a.metadata[b];if(b===H.J.tg){var d;return c==null?void 0:(d=c.K)==null?void 0:d.call(c)}var e;return c==null?void 0:(e=c.getValue)==null?void 0:e.call(c,Q(a,H.J.tg))},V=function(a,b,c){var d=a.metadata,e;c===void 0?e=c:(WH!=null||(WH=new TH(PH,QH)),e=UH(WH,b,c));d[b]=e},cI=function(a,b){b=b===void 0?{}:b;for(var c=m(Object.keys(a.metadata)),d=c.next();!d.done;d=c.next()){var e=d.value,f=void 0,g=void 0,h=void 0;b[e]=(f=a.metadata[e])==null?void 0:(h=(g=f).K)==null?void 0:
h.call(g)}return b},dI=function(a,b,c){var d=$H(a.target.destinationId);return d&&d[b]!==void 0?d[b]:c},Zu=function(a,b){for(var c=new aI((b==null?void 0:b.target)||a.target,(b==null?void 0:b.eventName)||a.eventName,(b==null?void 0:b.M)||a.M),d=bI(a),e=m(Object.keys(d)),f=e.next();!f.done;f=e.next()){var g=f.value;U(c,g,d[g])}for(var h=cI(a),l=m(Object.keys(h)),n=l.next();!n.done;n=l.next()){var p=n.value;V(c,p,h[p])}c.isAborted=a.isAborted;return c},eI=function(a){var b=a.M,c=b.eventId,d=b.priorityId;
return d?c+"_"+d:String(c)};aI.prototype.accept=function(){var a=om(jm.ba.Si,{}),b=eI(this),c=this.target.destinationId;a[b]||(a[b]={});a[b][c]=vk();var d=jm.ba.Si;if(km(d)){var e;(e=lm(d))==null||e.notify()}};aI.prototype.canBeAccepted=function(a){var b=nm(jm.ba.Si);if(!b)return!0;var c=b[eI(this)];if(!c)return!0;var d=c[a!=null?a:this.target.destinationId];return d===void 0||d===vk()};function fI(a){return{getDestinationId:function(){return a.target.destinationId},getEventName:function(){return a.eventName},setEventName:function(b){a.eventName=b},getHitData:function(b){return R(a,b)},setHitData:function(b,c){U(a,b,c)},setHitDataIfNotDefined:function(b,c){R(a,b)===void 0&&U(a,b,c)},copyToHitData:function(b,c){a.copyToHitData(b,c)},getMetadata:function(b){return Q(a,b)},setMetadata:function(b,c){V(a,b,c)},isAborted:function(){return a.isAborted},abort:function(){a.isAborted=!0},
getFromEventContext:function(b){return O(a.M,b)},rb:function(){return a},getHitKeys:function(){return eu(a)},getMergedValues:function(b){return a.M.getMergedValues(b,3)},mergeHitDataForKey:function(b,c){return Cd(c)?a.mergeHitDataForKey(b,c):!1},accept:function(){a.accept()},canBeAccepted:function(b){return a.canBeAccepted(b)}}};function gI(a,b){var c;return c}gI.P="internal.copyPreHit";function hI(a,b){var c=null;return Ud(c,this.T,2)}hI.publicName="createArgumentsQueue";function iI(a){return Ud(function(c){var d=SA();if(typeof c==="function")d(function(){c(function(f,g,h){var l=
SA(),n=l&&l.getByName&&l.getByName(f);return(new A.gaplugins.Linker(n)).decorate(g,h)})});else if(Array.isArray(c)){var e=String(c[0]).split(".");b[e.length===1?e[0]:e[1]]&&d.apply(null,c)}else if(c==="isLoaded")return!!d.loaded},this.T,1)}iI.P="internal.createGaCommandQueue";function jI(a){return Ud(function(){if(!yb(e.push))throw Error("Object at "+a+" in window is not an array.");e.push.apply(e,Array.prototype.slice.call(arguments,0))},this.T,
Bh(XF(this).Pb())?2:1)}jI.publicName="createQueue";function kI(a,b){var c=null;if(!lh(a)||!mh(b))throw K(this.getName(),["string","string|undefined"],arguments);try{var d=(b||"").split("").filter(function(e){return"ig".indexOf(e)>=0}).join("");c=new Pd(new RegExp(a,d))}catch(e){}return c}kI.P="internal.createRegex";function lI(a){}lI.P="internal.declareConsentState";function mI(a){var b="";return b}mI.P="internal.decodeUrlHtmlEntities";function nI(a,b,c){var d;return d}nI.P="internal.decorateUrlWithGaCookies";function oI(){}oI.P="internal.deferCustomEvents";function pI(a,b){try{return a.closest(b)}catch(c){return null}};function qI(){var a=A.screen;return{width:a?a.width:0,height:a?a.height:0}}
function rI(a){if(B.hidden)return!0;var b=a.getBoundingClientRect();if(b.top===b.bottom||b.left===b.right||!A.getComputedStyle)return!0;var c=A.getComputedStyle(a,null);if(c.visibility==="hidden")return!0;for(var d=a,e=c;d;){if(e.display==="none")return!0;var f=e.opacity,g=e.filter;if(g){var h=g.indexOf("opacity(");h>=0&&(g=g.substring(h+8,g.indexOf(")",h)),g.charAt(g.length-1)==="%"&&(g=g.substring(0,g.length-1)),f=String(Math.min(Number(g),Number(f))))}if(f!==void 0&&Number(f)<=0)return!0;(d=d.parentElement)&&
(e=A.getComputedStyle(d,null))}return!1}function fJ(a){var b;return b}fJ.P="internal.detectUserProvidedData";
function mJ(a,b){return f}mJ.P="internal.enableAutoEventOnClick";
function tJ(a,b){return p}tJ.P="internal.enableAutoEventOnElementVisibility";function uJ(){}uJ.P="internal.enableAutoEventOnError";
function AJ(a,b){var c=this;return d}AJ.P="internal.enableAutoEventOnFormInteraction";
function FJ(a,b){var c=this;return f}FJ.P="internal.enableAutoEventOnFormSubmit";
function KJ(){var a=this;}KJ.P="internal.enableAutoEventOnGaSend";
function RJ(a,b){var c=this;return f}RJ.P="internal.enableAutoEventOnHistoryChange";var SJ=["http://","https://","javascript:","file://"];
function WJ(a,b){var c=this;return h}WJ.P="internal.enableAutoEventOnLinkClick";
function gK(a,b){var c=this;return g}gK.P="internal.enableAutoEventOnScroll";function hK(a){return function(){if(a.limit&&a.gk>=a.limit)a.ai&&A.clearInterval(a.ai);else{a.gk++;var b=Nb();uE({event:a.eventName,"gtm.timerId":a.ai,"gtm.timerEventNumber":a.gk,"gtm.timerInterval":a.interval,"gtm.timerLimit":a.limit,"gtm.timerStartTime":a.Mo,"gtm.timerCurrentTime":b,"gtm.timerElapsedTime":b-a.Mo,"gtm.triggers":a.Lt})}}}
function iK(a,b){
return f}iK.P="internal.enableAutoEventOnTimer";var Ac=Aa(["data-gtm-yt-inspected-"]),kK=["www.youtube.com","www.youtube-nocookie.com"],lK;
function vK(a,b){var c=this;return e}vK.P="internal.enableAutoEventOnYouTubeActivity";function wK(a,b){if(!lh(a)||!fh(b))throw K(this.getName(),["string","Object|undefined"],arguments);var c=b?Td(b):{};c.regexCache=al(3,function(){return new Map});return Gh(a,c)}wK.P="internal.evaluateBooleanExpression";function xK(a){var b=!1;return b}xK.P="internal.evaluateMatchingRules";var yK=new Map([["aw",4]]);function zK(a){var b=vr[a],c=yK.get(a);return c?(wq(b,c)||[]).some(function(d){return d.m==="0"||d.m===void 0}):!1}
function AK(a,b){if(M(495)){for(var c=new Map,d=m(yK),e=d.next();!e.done;e=d.next()){var f=m(e.value),g=f.next().value,h=f.next().value,l=g,n=a[l],p=Array.isArray(n)?n[0]:n;if(p!==void 0){var q={},r=(q.k=p,q.i=String(Math.floor(Date.now()/1E3)),q.b=[],q.m="1",q),t=aq(r,h);t&&(zK(l)||c.set(l,t))}}if(c.size){var u,v=[],x=b.path||"/";v.push(encodeURIComponent("p")+"="+encodeURIComponent(x));b.Ar&&v.push(encodeURIComponent("ce")+"="+encodeURIComponent(String(b.Ar)));var y=b.domain&&b.domain!=="auto"?
b.domain:"auto:"+A.location.hostname;v.push(encodeURIComponent("d")+"="+encodeURIComponent(y));for(var z=m(c),C=z.next();!C.done;C=z.next()){var D=m(C.value),I=D.next().value,G=D.next().value;v.push(encodeURIComponent(I)+"="+encodeURIComponent(G))}u="_/set_cookie?"+v.join("&");var N,S=E(58);N=Ef(u,S);var W=Xj()+"/"+N;md(W)}}};function BK(a){return"CWVWebViewMessage"in a}function CK(a){var b=A,c=b.webkit;delete b.webkit;a(b.webkit);b.webkit=c}function DK(a,b){var c={action:"gcl_setup"};if(BK(a.messageHandlers))return a.messageHandlers.CWVWebViewMessage.postMessage({command:b,payload:c}),!0;var d=a.messageHandlers[b];return d?(d.postMessage(c),!0):!1};var EK={},FK=(EK.awb={notFound:178},EK.ytb={notFound:194},EK);function GK(a){var b,c=(b=FK[a])==null?void 0:b.notFound;c&&P(c)}
function HK(a){if(!nm(jm.ba.jn)&&"webkit"in A&&A.webkit.messageHandlers){var b=function(){try{CK(function(c){if(c){var d;d=BK(c.messageHandlers)||"awb"in c.messageHandlers?{command:"awb",source:5}:(BK(c.messageHandlers)||"ytb"in c.messageHandlers)&&M(499)?{command:"ytb",source:8}:void 0;d&&(mm(jm.ba.jn,function(e){var f=d.source;e.gclid&&ls("gcl_aw",e.gclid,f,a);e.wbraid&&ls("gcl_gb",e.wbraid,f,a)}),DK(c,d.command)||GK(d.command))}})}catch(c){P(193)}};Hl(function(){Br(fp)?b():Il(b,fp)},fp)}};var IK=["https://www.google.com","https://www.youtube.com","https://m.youtube.com"];function JK(a){return a.data.action!=="gcl_transfer"?(P(173),!0):a.data.gadSource?a.data.gclid?!1:(P(181),!0):(P(180),!0)}
function KK(a,b){if(!a||M(a)){if(nm(jm.ba.Ve))return P(176),jm.ba.Ve;if(nm(jm.ba.mn))return P(170),jm.ba.Ve;var c=Fp();if(!c)P(171);else if(c.opener){var d=function(g){if(!IK.includes(g.origin))P(172);else if(!JK(g)){var h={gadSource:g.data.gadSource};h.gclid=g.data.gclid;mm(jm.ba.Ve,h);b&&g.data.gclid&&ls("gcl_aw",String(g.data.gclid),6,b);var l;(l=g.stopImmediatePropagation)==null||l.call(g);nt(c,"message",d)}};if(mt(c,"message",d)){mm(jm.ba.mn,!0);for(var e=m(IK),f=e.next();!f.done;f=e.next())c.opener.postMessage({action:"gcl_setup"},
f.value);P(174);return jm.ba.Ve}P(175)}}};function VK(){return Mt(7)&&Mt(9)&&Mt(10)};
var aL=function(a,b){a&&($K("sid",a.targetId,b),$K("cc",a.clientCount,b),$K("tl",a.totalLifeMs,b),$K("hc",a.heartbeatCount,b),$K("cl",a.clientLifeMs,b))},$K=function(a,b,c){b!=null&&c.push(a+"="+b)},bL=function(){var a=B.referrer;if(a){var b;return Lj(Rj(a),"host")===((b=A.location)==null?void 0:b.host)?1:2}return 0},dL=function(){this.ja=cL;this.N=0;this.ya=Nf(57,5);this.R=Nf(58,50);this.fa=Db();this.La="https://"+E(21)+"/a?"};dL.prototype.K=function(a,b,c,d){
var e=bL(),f,g=[];f=A===A.top&&e!==0&&b?(b==null?void 0:b.clientCount)>1?e===2?1:2:e===2?0:3:4;a&&$K("si",a.Jg,g);$K("m",0,g);$K("iss",f,g);$K("if",c,g);aL(b,g);d&&$K("fm",encodeURIComponent(d.substring(0,this.R)),g);this.Z(g);};dL.prototype.H=function(a,b,c,d,e){var f=[];$K("m",1,f);$K("s",a,f);$K("po",bL(),f);b&&($K("st",b.state,f),$K("si",b.Jg,f),$K("sm",b.Ug,f));aL(c,f);$K("c",d,f);e&&$K("fm",encodeURIComponent(e.substring(0,
this.R)),f);this.Z(f);};dL.prototype.Z=function(a){a=a===void 0?[]:a;!fn.N||this.N>=this.ya||($K("pid",this.fa,a),$K("bc",++this.N,a),a.unshift("ctid="+E(5)+"&t=s"),this.ja(""+this.La+a.join("&")))};function eL(a){return a.performance&&a.performance.now()||Date.now()}
var fL=function(a,b){var c=A,d=Nf(53,500),e=Nf(54,5E3),f=Nf(8,20),g=Nf(55,5E3),h;var l=function(n,p,q){q=q===void 0?{qo:function(){},so:function(){},po:function(){},onFailure:function(){}}:q;this.Ij=n;this.H=p;this.N=q;this.fa=this.ja=this.heartbeatCount=this.Dj=0;this.fe=!1;this.K={};this.id=String(Math.floor(Number.MAX_SAFE_INTEGER*Math.random()));this.state=0;this.Jg=eL(this.H);this.Ug=eL(this.H);this.Z=10};l.prototype.init=function(){this.R(1);
this.La()};l.prototype.getState=function(){return{state:this.state,Jg:Math.round(eL(this.H)-this.Jg),Ug:Math.round(eL(this.H)-this.Ug)}};l.prototype.R=function(n){this.state!==n&&(this.state=n,this.Ug=eL(this.H))};l.prototype.vg=function(){return String(this.Dj++)};l.prototype.La=function(){var n=this;this.heartbeatCount++;this.ya({type:0,clientId:this.id,requestId:this.vg(),maxDelay:this.he()},function(p){if(p.type===0){var q;if(((q=p.failure)==null?void 0:q.failureType)!=null)if(p.stats&&(n.stats=
p.stats),n.fa++,p.isDead||n.fa>f){var r=p.isDead&&p.failure.failureType;n.Z=r||10;n.R(4);n.Aj();var t,u;(u=(t=n.N).po)==null||u.call(t,{failureType:r||10,data:p.failure.data})}else n.R(3),n.Ph();else{if(n.heartbeatCount>p.stats.heartbeatCount+f){n.heartbeatCount=p.stats.heartbeatCount;var v,x;(x=(v=n.N).onFailure)==null||x.call(v,{failureType:13})}n.stats=p.stats;var y=n.state;n.R(2);if(y!==2)if(n.fe){var z,C;(C=(z=n.N).so)==null||C.call(z)}else{n.fe=!0;var D,I;(I=(D=n.N).qo)==null||I.call(D)}n.fa=
0;n.Nj();n.Ph()}}})};l.prototype.he=function(){return this.state===2?e:d};l.prototype.Ph=function(){var n=this;this.H.setTimeout(function(){n.La()},Math.max(0,this.he()-(eL(this.H)-this.ja)))};l.prototype.kr=function(n,p,q){var r=this;this.ya({type:1,clientId:this.id,requestId:this.vg(),command:n},function(t){if(t.type===1)if(t.result)p(t.result);else{var u,v,x,y={failureType:(x=(u=t.failure)==null?void 0:u.failureType)!=null?x:12,data:(v=t.failure)==null?void 0:v.data},z,C;(C=(z=r.N).onFailure)==
null||C.call(z,y);q(y)}})};l.prototype.ya=function(n,p){var q=this;if(this.state===4)n.failure={failureType:this.Z},p(n);else{var r=this.state!==2&&n.type!==0,t=n.requestId,u,v=this.H.setTimeout(function(){var y=q.K[t];y&&(im(6),q.kd(y,7))},(u=n.maxDelay)!=null?u:g),x={request:n,Ho:p,zo:r,Ns:v};this.K[t]=x;r||this.sendRequest(x)}};l.prototype.sendRequest=function(n){this.ja=eL(this.H);n.zo=!1;this.Ij(n.request)};l.prototype.Nj=function(){for(var n=m(Object.keys(this.K)),p=n.next();!p.done;p=n.next()){var q=
this.K[p.value];q.zo&&this.sendRequest(q)}};l.prototype.Aj=function(){for(var n=m(Object.keys(this.K)),p=n.next();!p.done;p=n.next())this.kd(this.K[p.value],this.Z)};l.prototype.kd=function(n,p){this.ac(n);var q=n.request;q.failure={failureType:p};n.Ho(q)};l.prototype.ac=function(n){delete this.K[n.request.requestId];this.H.clearTimeout(n.Ns)};l.prototype.ks=function(n){this.ja=eL(this.H);var p=this.K[n.requestId];if(p)this.ac(p),p.Ho(n);else{var q,r;(r=(q=this.N).onFailure)==null||r.call(q,{failureType:14})}};
h=new l(a,c,b);return h};
var gL=function(){return al(18,function(){return new dL})},cL=function(a){io(lo(co.ia.Zb),function(){Zc(a)})},hL=function(a){var b=a.substring(0,a.indexOf("/_/service_worker"));return"&1p=1"+(b?"&path="+encodeURIComponent(b):"")},iL=function(a){var b=A.location.origin;if(!b)return null;(M(432)?Wj():Wj()&&!a)&&(a=""+b+Xj()+"/_/service_worker");var c=a,d,e=Lf(11);e=Lf(10);d=e;c?(c.charAt(c.length-1)!=="/"&&
(c+="/"),a=c+d):a="https://www.googletagmanager.com/static/service_worker/"+d+"/";var f;try{f=new URL(a)}catch(g){return null}return f.protocol!=="https:"?null:f},jL=function(a){var b=nm(jm.ba.Oh);return b&&b[a]},kL=function(a){var b=this;this.K=gL();this.Z=this.R=!1;this.fa=null;this.initTime=Math.round(Nb());this.H=15;this.N=this.Fr(a);A.setTimeout(function(){b.initialize()},1E3);bd(function(){b.zs(a)})};k=kL.prototype;k.delegate=function(a,b,c){this.getState()!==2?(this.K.H(this.H,{state:this.getState(),
Jg:this.initTime,Ug:Math.round(Nb())-this.initTime},void 0,a.commandType),c({failureType:this.H})):this.N.kr(a,b,c)};k.getState=function(){return this.N.getState().state};k.zs=function(a){var b=A.location.origin,c=this,d=Xc();try{var e=d.contentDocument.createElement("iframe"),f=a.pathname,g=f[f.length-1]==="/"?a.toString():a.toString()+"/",h=a.origin!=="https://www.googletagmanager.com"?hL(f):"",l;M(133)&&(l={sandbox:"allow-same-origin allow-scripts"});Xc(g+"sw_iframe.html?origin="+encodeURIComponent(b)+
h,void 0,l,void 0,e);var n=function(){d.contentDocument.body.appendChild(e);e.addEventListener("load",function(){c.fa=e.contentWindow;d.contentWindow.addEventListener("message",function(p){p.origin===a.origin&&c.N.ks(p.data)});c.initialize()})};d.contentDocument.readyState==="complete"?n():d.contentWindow.addEventListener("load",function(){n()})}catch(p){d.parentElement.removeChild(d),this.H=11,this.K.K(void 0,void 0,this.H,p.toString())}};k.Fr=function(a){var b=this,c=fL(function(d){var e;(e=b.fa)==
null||e.postMessage(d,a.origin)},{qo:function(){b.R=!0;b.K.K(c.getState(),c.stats)},so:function(){},po:function(d){b.R?(b.H=(d==null?void 0:d.failureType)||10,b.K.H(b.H,c.getState(),c.stats,void 0,d==null?void 0:d.data)):(b.H=(d==null?void 0:d.failureType)||4,b.K.K(c.getState(),c.stats,b.H,d==null?void 0:d.data))},onFailure:function(d){b.H=d.failureType;b.K.H(b.H,c.getState(),c.stats,d.command,d.data)}});return c};k.initialize=function(){this.Z||this.N.init();this.Z=!0};
var lL=function(a,b,c,d){var e;if((e=jL(a))==null||!e.delegate){var f=Ic()?16:6;gL().H(f,void 0,void 0,b.commandType);d({failureType:f});return}jL(a).delegate(b,c,d);};
function mL(a,b,c,d){var e=iL(a);if(e===null){d("_is_sw=f"+(Ic()?16:6)+"te");return}var f=b?1:0,g=Math.round(Nb()),h,l=(h=jL(e.origin))==null?void 0:h.initTime,n=l?g-l:void 0,p;M(432)?p=Wj()?void 0:A.location.href:p=A.location.href;lL(e.origin,{commandType:0,params:{url:a,method:f,templates:c,body:b||"",processResponse:!0,sinceInit:n,attributionReporting:!0,referer:p,strict:M(584)}},function(){},function(q){var r="_is_sw=f"+q.failureType,t,u=(t=jL(e.origin))==
null?void 0:t.getState();u!==void 0&&(r+="s"+u);d(n?r+("t"+n):r+"te")});};function nL(a){if(If(47)&&dI(a,"ccd_add_1p_data",!1)&&Wj()){var b=a.M;if(Ic()&&bg("internal_sw_allowed","")){var c=ek(b),d=Wj()?Xj():void 0,e;e=d?{path:d,eo:"full"}:c?{path:c,eo:"lite"}:void 0;if(e){var f=e.eo,g=new URL(e.path,A.location.origin);if(g.origin===A.location.origin&&py(f)===void 0){var h=om(jm.ba.Oh,{});h[f]||(h[f]=new ny(g))}}}}};function sL(){var a;a=a===void 0?document:a;var b;return!((b=a.featurePolicy)==null||!b.allowedFeatures().includes("attribution-reporting"))};function wL(a,b,c,d){d=d===void 0?!1:d;var e=Fp(),f=Dp(e);if(f.url)if(d){var g=c(f.url);b!==g&&U(a,F.D.Pe,g)}else{var h=f.url;b!==h&&U(a,F.D.Pe,c(h))}};function AL(a){V(a,H.J.Ja,!0);V(a,H.J.Eb,Nb());V(a,H.J.yn,a.M.eventMetadata[H.J.Ja])};var TL=new function(){this.H={}};function WL(a){var b=KB(!1);if(b!=null&&b.status){var c={gtb:b.status};b.delay&&(c.gtbd=b.delay);a.mergeHitDataForKey(F.D.Ta,c)}};var YL={Ra:{Ck:1,zn:2,Hn:3,In:4,Jn:5,wn:6}};YL.Ra[YL.Ra.Ck]="ADOBE_COMMERCE";YL.Ra[YL.Ra.zn]="SQUARESPACE";YL.Ra[YL.Ra.Hn]="WOO_COMMERCE";YL.Ra[YL.Ra.In]="WOO_COMMERCE_LEGACY";YL.Ra[YL.Ra.Jn]="WORD_PRESS";YL.Ra[YL.Ra.wn]="SHOPIFY";function ZL(a){var b=A;return Kj(b.escape(b.atob(a)))}
function $L(){try{if(!M(498)&&!M(425))return[];var a=nm(jm.ba.ln);if(Array.isArray(a))return a;var b=[],c;a:{try{c=!!B.querySelector('script[data-requiremodule^="mage/"]');break a}catch(y){}c=!1}c&&b.push(YL.Ra.Ck);var d;a:{try{var e=ZL("YXNzZXRzLnNxdWFyZXNwYWNlLmNvbS8=");d=e?!!B.querySelector('script[src^="//'+e+'"]'):!1;break a}catch(y){}d=!1}d&&b.push(YL.Ra.zn);var f;a:{if(M(425))try{var g=ZL("c2hvcGlmeS5jb20="),h=ZL("c2hvcGlmeWNkbi5jb20=");f=g&&h?!!B.querySelector('script[src*="cdn.'+g+'"],meta[property="og:image"][content*="cdn.'+
(g+'"],link[rel="preconnect"][href*="cdn.')+(g+'"],link[rel="preconnect"][href*="fonts.')+(h+'"],link[rel="preconnect"][href*="iterable-shopify"],link[rel="preconnect"][href*="v.')+(g+'"]')):!1;break a}catch(y){}f=!1}f&&b.push(YL.Ra.wn);var l;a:{try{l=!!B.querySelector('script[src*="woocommerce"],link[href*="woocommerce"],[class|="woocommerce"]');break a}catch(y){}l=!1}l&&b.push(YL.Ra.In);var n;a:{try{var p,q=((p=B.location)==null?void 0:p.hostname)||"",r,t=((r=B.location)==null?void 0:r.origin)||
"",u=ZL("LndvcmRwcmVzcy5jb20="),v=ZL("Ly9zLncub3Jn");n=u&&v?Tb(q,u)||!!B.querySelector('[src^="'+t+'/wp-content"],meta[name="generator"][content^="WordPress "],link[rel="dns-prefetch"][href="'+(v+'"]')):!1;break a}catch(y){}n=!1}n&&b.push(YL.Ra.Jn);var x;a:{try{x=!!B.querySelector('[class*="woocommerce"],meta[name="generator"][content^="WooCommerce "]');break a}catch(y){}x=!1}x&&b.push(YL.Ra.Hn);UB()&&mm(jm.ba.ln,b);return b}catch(y){}return[]};function wM(a){if(M(425)&&Q(a,H.J.Fc)){var b=Nf(67,1500),c=a.mergeHitDataForKey,d=F.D.Ta,e={};c.call(a,d,e)}};var xM="platform platformVersion architecture model uaFullVersion bitness fullVersionList wow64".split(" ");function yM(a){var b;return(b=a.google_tag_data)!=null?b:a.google_tag_data={}}function zM(a){var b,c;return(c=(b=a.google_tag_data)==null?void 0:b.uach_promise)!=null?c:null}function AM(a){var b,c;return typeof((b=a.navigator)==null?void 0:(c=b.userAgentData)==null?void 0:c.getHighEntropyValues)==="function"}
function BM(a){if(!AM(a))return null;var b=yM(a);if(b.uach_promise)return b.uach_promise;var c=a.navigator.userAgentData.getHighEntropyValues(xM).then(function(d){b.uach!=null||(b.uach=d);return d});return b.uach_promise=c};function HM(a,b){b=b===void 0?!1:b;var c=Q(a,H.J.sg),d=dI(a,"custom_event_accept_rules",!1)&&!b;if(c){var e=c.indexOf(a.target.destinationId)>=0,f=!0;Q(a,H.J.Cc)&&(f=Q(a,H.J.Nb)===vk());e&&f?V(a,H.J.ki,!0):(V(a,H.J.ki,!1),d||(a.isAborted=!0));if(a.canBeAccepted()){var g=uk().indexOf(a.target.destinationId)>=0,h=!1;if(!g){var l,n=(l=nk(a.target.destinationId))==null?void 0:l.canonicalContainerId;n&&(h=vk()===n)}g||h?Q(a,H.J.ki)&&a.accept():a.isAborted=!0}else a.isAborted=!0}};function QM(){return kj("dedupe_gclid",function(){return Av()})};var RM=/^(www\.)?google(\.com?)?(\.[a-z]{2}t?)?$/,SM=/^www.googleadservices.com$/;function TM(a){a||(a=UM());return a.Nt?!1:a.ns||a.qs||a.vs||a.rs||a.Dg||a.Th||a.Tr||a.Vh==="aw.ds"||M(235)&&a.Vh==="aw.dv"||a.Yr?!0:!1}
function UM(){var a={},b=Uq(!0);a.Nt=!!b._up;var c=es(),d=at();a.ns=c.aw!==void 0;a.qs=c.dc!==void 0;a.vs=c.wbraid!==void 0;a.rs=c.gbraid!==void 0;a.Vh=typeof c.gclsrc==="string"?c.gclsrc:void 0;a.Dg=d.Dg;a.Th=d.Th;var e=B.referrer?Lj(Rj(B.referrer),"host"):"";a.Yr=RM.test(e);a.Tr=SM.test(e);return a};function VM(){var a=A.__uspapi;if(yb(a)){var b="";try{a("getUSPData",1,function(c,d){if(d&&c){var e=c.uspString;e&&RegExp("^[\\da-zA-Z-]{1,20}$").test(e)&&(b=e)}})}catch(c){}return b}};function ZM(a){if(fn.K)if(wo.H=!0,a.eventName===F.D.wa)zo(a.M,a.target.id);else{Q(a,H.J.Pc)||(wo.K[a.target.id]=!0);var b=Q(a,H.J.Nb);ZB(b)}};function bN(a,b){return kr("gsid_dc",{value:{joinId:a,lastJoinedTimeMs:b},expires:b+3E5})===0?!0:!1};var eN={zq:{Ut:"cd",fp:"ce",Vt:"cf",Wt:"cpf",Xt:"cu"}};function gN(a,b){b=b===void 0?!0:b;var c=wb(rb.GTAG_EVENT_FEATURE_CHANNEL||[]);c&&(U(a,F.D.Vf,c),b&&ub())};function FO(a,b,c,d){}FO.P="internal.executeEventProcessor";function GO(a){var b;return Ud(b,this.T,1)}GO.P="internal.executeJavascriptString";function HO(a){var b;return b};function IO(a){var b="";return b}IO.P="internal.generateClientId";function JO(a){var b={};return Ud(b)}JO.P="internal.getAdsCookieWritingOptions";function KO(a,b){var c=!1;return c}KO.P="internal.getAllowAdPersonalization";function LO(){var a;return a}LO.P="internal.getAndResetEventUsage";function MO(a,b){b=b===void 0?!0:b;var c;return c}MO.P="internal.getAuid";function NO(){var a=[];return Ud(a)}NO.P="internal.getContainerIds";function OO(){var a=new kb;return a}OO.publicName="getContainerVersion";function PO(a,b){b=b===void 0?!0:b;var c;return c}PO.publicName="getCookieValues";function QO(){var a="";return a}QO.P="internal.getCorePlatformServicesParam";function RO(){return ym()}RO.P="internal.getCountryCode";function SO(){var a=[];return Ud(a)}SO.P="internal.getDestinationIds";function TO(a){var b=new kb;return b}TO.P="internal.getDeveloperIds";function UO(a){var b;return b}UO.P="internal.getEcsidCookieValue";function VO(a,b){var c=null;return c}VO.P="internal.getElementAttribute";function WO(a){var b=null;return b}WO.P="internal.getElementById";function XO(a){var b="";return b}XO.P="internal.getElementInnerText";function YO(a){var b=null;return b}YO.P="internal.getElementParent";function ZO(a){var b=null;return b}ZO.P="internal.getElementPreviousSibling";function $O(a,b){var c=null;return Ud(c)}$O.P="internal.getElementProperty";function aP(a){var b;return b}aP.P="internal.getElementValue";function bP(a){var b=0;return b}bP.P="internal.getElementVisibilityRatio";function cP(a){var b=null;return b}cP.P="internal.getElementsByCssSelector";
function dP(a){var b;if(!lh(a))throw K(this.getName(),["string"],arguments);L(this,"read_event_data",a);var c;a:{var d=a,e=XF(this).originalEventData;if(e){for(var f=e,g={},h={},l={},n=[],p=d.split("\\\\"),q=0;q<p.length;q++){for(var r=p[q].split("\\."),t=0;t<r.length;t++){for(var u=r[t].split("."),v=0;v<u.length;v++)n.push(u[v]),v!==u.length-1&&n.push(l);t!==r.length-1&&n.push(h)}q!==p.length-1&&n.push(g)}for(var x=[],y="",z=m(n),C=z.next();!C.done;C=
z.next()){var D=C.value;D===l?(x.push(y),y=""):y=D===g?y+"\\":D===h?y+".":y+D}y&&x.push(y);for(var I=m(x),G=I.next();!G.done;G=I.next()){if(f==null){c=void 0;break a}f=f[G.value]}c=f}else c=void 0}b=Ud(c,this.T,1);return b}dP.P="internal.getEventData";function eP(a){var b=null;return b}eP.P="internal.getFirstElementByCssSelector";function fP(){var a;return a}fP.P="internal.getGsaExperimentId";function gP(){return new Pd(Pk)}gP.P="internal.getHtmlId";function hP(){var a;return a}hP.P="internal.getIframingState";function iP(a,b){var c={};return Ud(c)}iP.P="internal.getLinkerValueFromLocation";function jP(){var a=new kb;return a}jP.P="internal.getPrivacyStrings";function kP(a,b){var c;return c}kP.P="internal.getProductSettingsParameter";function lP(a,b){var c;return c}lP.publicName="getQueryParameters";function mP(a,b){var c;return c}mP.publicName="getReferrerQueryParameters";function nP(a){var b="";if(!mh(a))throw K(this.getName(),["string|undefined"],arguments);L(this,"get_referrer",a);b=Nj(Rj(B.referrer),a);return b}nP.publicName="getReferrerUrl";function oP(){return zm()}oP.P="internal.getRegionCode";function pP(a,b){var c;return c}pP.P="internal.getRemoteConfigParameter";function qP(a,b){var c=null;
return c}qP.P="internal.getScopedElementsByCssSelector";function rP(){var a=new kb;a.set("width",0);a.set("height",0);return a}rP.P="internal.getScreenDimensions";function sP(){var a="";return a}sP.P="internal.getTopSameDomainUrl";function tP(){var a="";return a}tP.P="internal.getTopWindowUrl";function uP(a){var b="";if(!mh(a))throw K(this.getName(),["string|undefined"],arguments);L(this,"get_url",a);b=Lj(Rj(A.location.href),a);return b}uP.publicName="getUrl";function vP(){L(this,"get_user_agent");return Hc.userAgent}vP.publicName="getUserAgent";vP.P="internal.getUserAgent";function wP(){var a;return a?Ud(EM(a)):a}wP.P="internal.getUserAgentClientHints";function zP(){var a=A;return a.gaGlobal=a.gaGlobal||{}}function AP(a,b){var c=zP();if(c.vid===void 0||b&&!c.from_cookie)c.vid=a,c.from_cookie=b};function bQ(a){(bk(ZK(a))||Wj())&&U(a,F.D.om,zm()||ym());!bk(ZK(a))&&Wj()&&U(a,F.D.Yi,"::")}function cQ(a){Wj()&&(bk(ZK(a))||Dm()||U(a,F.D.Sl,!0))};function hQ(a,b,c,d){var e;if((nd()||kd())&&Xj()&&Xj()!=="/"){var f=Rj(a);e=If(50)&&d&&Tb(f.pathname,"/g/collect")?2:(d||!Wj()||Dm()?0:Tb(f.pathname,"/ga/g/c")||Tb(f.pathname,"/ag/g/c"))?1:0}else e=0;switch(e){case 2:var g;if(M(546)){var h=Tb(a,"/g/collect")?a.substring(0,a.length-10):a,l=iQ(),n=h+l,p=jQ("/g/collect",b,c);g={Ic:n,kf:"",body:p}}else g={Ic:a,kf:b,body:c};return g;case 1:var q;if(M(547)){var r=iQ(),t=a.indexOf(r),u=a.substring(0,t)+r,v=jQ(a.substring(t+r.length-1),b,c);q={Ic:u,kf:"",
body:v}}else q={Ic:a,kf:b,body:c};return q;default:return{Ic:a,kf:b,body:c}}}function iQ(){var a=Xj();if(!a)return"";Sb(a,"/")||(a="/"+a);Tb(a,"/")||(a+="/");return a}function jQ(a,b,c){var d=[a];b&&d.push("?",b);c&&d.push("\r\n",c);return d.join("")};function sR(a){a.copyToHitData(F.D.fb);var b=O(a.M,F.D.Wd);b&&(KC(b,function(){}),U(a,F.D.Wd,b))};function vR(a){var b=function(c){return!!c&&c.conversion};V(a,H.J.mg,b(XK(a)));Q(a,H.J.ng)&&V(a,H.J.Ym,b(XK(a,"first_visit")));Q(a,H.J.Te)&&V(a,H.J.bn,b(XK(a,"session_start")))};var AR=function(a){for(var b={},c=String(zR.cookie).split(";"),d=0;d<c.length;d++){var e=c[d].split("="),f=e[0].trim();if(f&&a(f)){var g=e.slice(1).join("=").trim();g&&(g=decodeURIComponent(g));var h=void 0,l=void 0;((h=b)[l=f]||(h[l]=[])).push(g)}}return b};var BR=window,zR=document,CR=function(a){var b=BR._gaUserPrefs;if(b&&b.ioo&&b.ioo()||zR.documentElement.hasAttribute("data-google-analytics-opt-out")||a&&BR["ga-disable-"+a]===!0)return!0;try{var c=BR.external;if(c&&c._gaUserPrefs&&c._gaUserPrefs=="oo")return!0}catch(f){}for(var d=AR(function(f){return f==="AMP_TOKEN"}).AMP_TOKEN||[],e=0;e<d.length;e++)if(d[e]=="$OPT_OUT")return!0;return zR.getElementById("__gaOptOutExtension")?!0:!1};var MR="gclid dclid gclsrc wbraid gbraid gad_source gad_campaignid utm_source utm_medium utm_campaign utm_term utm_content utm_id".split(" ");function NR(){var a=B.location,b,c=a==null?void 0:(b=a.search)==null?void 0:b.replace("?",""),d;if(c){for(var e=[],f=Jj(c,!0),g=m(MR),h=g.next();!h.done;h=g.next()){var l=h.value,n=f[l];if(n)for(var p=0;p<n.length;p++){var q=n[p];q!==void 0&&e.push({name:l,value:q})}}d=e}else d=[];return d};var PR=[F.D.ra,F.D.ka],QR=[F.D.ra,F.D.ka,F.D.ma];
function RR(a){var b,c=M(506)&&!dI(a,"ccd_ga_ads_ids_opt_out",!1),d=!!dI(a,"google_ng",!1),e=Xo(c?d?QR:fp:PR),f;f=dI(a,F.D.Uf,O(a.M,F.D.Uf))||!!dI(a,"google_ng",!1);b={hf:c,Es:d,Go:e,ff:f,Lg:!!dI(a,"ga4_ads_linked",!1),bi:Am(),Gj:!VK(),Fs:bk(ZK(a)),Ds:!!Q(a,H.J.be),Gs:!!Q(a,H.J.Te),us:!!O(a.M,F.D.Nl),Ks:!!Q(a,H.J.ej),xg:O(a.M,F.D.Sc),nr:O(a.M,F.D.Sc,void 0,4),Hs:!!Q(a,H.J.Fc)};V(a,H.J.cj,b.ff);V(a,H.J.bj,SR(b));b.hf&&!b.ff&&b.Lg&&SR(b)&&U(a,"_&ibt","1");SR(b)&&b.Go&&(b.hf?b.xg!==!1||b.Lg:1)&&V(a,
H.J.rn,!0);b.Es&&!b.bi&&U(a,F.D.Le,1);(b.hf?b.xg:b.nr)===!1&&U(a,"_&ngs","1");V(a,H.J.hd,TR(b)&&(b.Gs||b.us));V(a,H.J.rg,TR(b)&&b.Ks&&!b.bi)}function SR(a){return a.hf?(a.Lg||a.ff)&&!a.bi&&!a.Gj:a.ff&&a.xg!==!1&&!a.Gj&&!a.bi}function TR(a){if(a.Hs)return!1;if(a.hf){if(!a.ff&&!a.Lg)return!1}else if(!a.ff)return!1;return a.Fs||a.Ds||a.Gj||(a.hf?a.xg===!1&&!a.Lg:a.xg===!1)||!a.Go?!1:!0};function hS(a){}function iS(a){var b=function(){};return b}
function jS(a,b){}var kS=J.U.ql,lS=J.U.rl;function mS(a,b){var c=tk();c&&c.indexOf(b)>-1&&(a[H.J.Cc]=!0)}function oS(a,b,c){var d=this;}oS.P="internal.gtagConfig";function pS(a,b,c,d){var e=this;}pS.P="internal.gtagDestinationConfig";
function rS(a,b){}
rS.publicName="gtagSet";function sS(){var a={};return a};function tS(a){}tS.P="internal.initializeServiceWorker";function uS(a,b){}uS.publicName="injectHiddenIframe";function vS(a,b,c,d,e){}vS.P="internal.injectHtml";var AS={dl:1,id:1};
function BS(a,b,c,d){}BS.publicName="injectScript";function CS(){var a=vm,b=!1;return b}CS.P="internal.isAutoPiiEligible";function DS(a){var b=!0;return b}DS.publicName="isConsentGranted";function ES(a){var b=!1;return b}ES.P="internal.isDebugMode";function FS(a){var b=!1;return b}FS.P="internal.isDestinationInitialized";function GS(){return Bm()}GS.P="internal.isDmaRegion";function HS(){return UB()}HS.P="internal.isDomReady";function IS(a){var b=!1;return b}IS.P="internal.isEntityInfrastructure";function JS(a){var b=!1;return b}JS.P="internal.isFeatureEnabled";function KS(){var a=!1;return a}KS.P="internal.isFpfe";function LS(){var a=!1;return a}LS.P="internal.isGcpBrowser";function MS(){var a=!1;return a}MS.P="internal.isLandingPage";function NS(){var a=!1;return a}NS.P="internal.isOgt";function OS(){var a;return a}OS.P="internal.isSafariPcmEligibleBrowser";function PS(){var a=Qh(function(b){XF(this).log("error",b)});a.publicName="JSON";return a};function QS(a){var b=void 0;if(!lh(a))throw K(this.getName(),["string"],arguments);b=Rj(a);return Ud(b)}QS.P="internal.legacyParseUrl";function RS(){return!1}
var SS={getItem:function(a){var b=null;return b},setItem:function(a,b){return!1},removeItem:function(a){}};function TS(){}TS.publicName="logToConsole";function US(a,b){}US.P="internal.mergeRemoteConfig";function VS(a,b,c){c=c===void 0?!0:c;var d=[];return Ud(d)}VS.P="internal.parseCookieValuesFromString";function WS(a){var b=void 0;if(typeof a!=="string")return;a&&Sb(a,"//")&&(a=B.location.protocol+a);if(typeof URL==="function"){var c;a:{var d;try{d=new URL(a)}catch(x){c=void 0;break a}for(var e={},f=Array.from(d.searchParams),g=0;g<f.length;g++){var h=f[g][0],l=f[g][1];e.hasOwnProperty(h)?typeof e[h]==="string"?e[h]=[e[h],l]:e[h].push(l):e[h]=l}c={href:d.href,origin:d.origin,protocol:d.protocol,username:d.username,password:d.password,host:d.host,hostname:d.hostname,
port:d.port,pathname:d.pathname,search:d.search,searchParams:e,hash:d.hash}}return Ud(c)}var n;try{n=Rj(a)}catch(x){return}if(!n.protocol||!n.host)return;var p={};if(n.search)for(var q=n.search.replace("?","").split("&"),r=0;r<q.length;r++){var t=q[r].split("="),u=t[0],v=Kj(t.splice(1).join("="))||"";v=v.replace(/\+/g," ");p.hasOwnProperty(u)?typeof p[u]==="string"?p[u]=[p[u],v]:p[u].push(v):p[u]=v}n.searchParams=p;n.origin=n.protocol+"//"+n.host;n.username="";n.password="";b=Ud(n);
return b}WS.publicName="parseUrl";function XS(a){}XS.P="internal.processAsNewEvent";function YS(a,b,c){var d;return d}YS.P="internal.pushToDataLayer";function ZS(a){var b=Oa.apply(1,arguments),c=!1;return c}ZS.publicName="queryPermission";function $S(a){var b=this;}$S.P="internal.queueAdsTransmission";function aT(a){var b=void 0;return b}aT.publicName="readAnalyticsStorage";function bT(){var a="";return a}bT.publicName="readCharacterSet";function cT(){return E(19)}cT.P="internal.readDataLayerName";function dT(){var a="";return a}dT.publicName="readTitle";function eT(a,b){var c=this;}eT.P="internal.registerCcdCallback";function fT(a,b){return!0}fT.P="internal.registerDestination";var gT=["event"];function hT(a,b,c){}hT.P="internal.registerGtagCommandListener";function iT(a,b){var c=!1;return c}iT.P="internal.removeDataLayerEventListener";function jT(a,b){}
jT.P="internal.removeFormData";function kT(){}kT.publicName="resetDataLayer";function lT(a,b,c){var d=void 0;return d}lT.P="internal.scrubUrlParams";function mT(a){}mT.P="internal.sendAdsHit";function nT(a,b,c,d){}nT.P="internal.sendGtagEvent";function oT(a,b,c){}oT.publicName="sendPixel";function pT(a,b){}pT.P="internal.setAnchorHref";function qT(a){}qT.P="internal.setContainerConsentDefaults";function rT(a,b,c,d){var e=this;d=d===void 0?!0:d;var f=!1;
return f}rT.publicName="setCookie";function sT(a){}sT.P="internal.setCorePlatformServices";function tT(a,b){}tT.P="internal.setDataLayerValue";function uT(a){}uT.publicName="setDefaultConsentState";function vT(a,b){}vT.P="internal.setDelegatedConsentType";function wT(a,b){}wT.P="internal.setFormAction";function xT(a,b,c){c=c===void 0?!1:c;}xT.P="internal.setInCrossContainerData";function yT(a,b,c){return!1}yT.publicName="setInWindow";function zT(a,b,c){}zT.P="internal.setProductSettingsParameter";function AT(a,b,c){}AT.P="internal.setRemoteConfigParameter";function BT(a,b){}
BT.P="internal.setTransmissionMode";function CT(a,b,c,d){var e=this;}CT.publicName="sha256";function DT(a,b,c){}
DT.P="internal.sortRemoteConfigParameters";function ET(a){}ET.P="internal.storeAdsBraidLabels";function FT(a,b){var c=void 0;return c}FT.P="internal.subscribeToCrossContainerData";function GT(a){}GT.P="internal.taskSendAdsHits";var HT={getItem:function(a){var b=null;return b},setItem:function(a,b){},
removeItem:function(a){},clear:function(){},
publicName:"templateStorage"};function IT(a,b){var c=!1;return c}IT.P="internal.testRegex";function JT(a){var b;return b};function KT(a,b){}KT.P="internal.trackUsage";function LT(a,b){var c;return c}LT.P="internal.unsubscribeFromCrossContainerData";function MT(a){}MT.publicName="updateConsentState";function NT(a){var b=!1;return b}NT.P="internal.userDataNeedsEncryption";var OT=function(){this.H=new ai},QT=function(){return function(a){var b;var c=PT.H;if(c.contains(a))b=c.get(a,this);else{var d;if(d=c.H.hasOwnProperty(a)){var e=this.T.xb();if(e){var f=!1,g=e.Pb();if(g){Bh(g)||(f=!0);}d=f}else d=!0}if(d){var h=c.H.hasOwnProperty(a)?c.H[a]:void 0;b=h}else throw Error(a+" is not a valid API name.");}return b}},PT;function RT(a,b,c){PT||(PT=new OT);PT.H.add(a,b,c)}function ST(a,b){PT||(PT=new OT);var c=PT.H;if(c.H.hasOwnProperty(a))throw Error("Attempting to add a private function which already exists: "+a+".");if(c.contains(a))throw Error("Attempting to add a private function with an existing API name: "+a+".");c.H[a]=yb(b)?th(a,b):uh(a,b)};function TT(a,b){function c(d){if(!eh(d))throw K(this.getName(),["Object"],arguments);var e=Td(d,this.T,1).rb();a(e)}c.P="internal."+b;return c};function UT(){var a=function(c){return void ST(c.P,c)},b=function(c){return void RT(c.publicName,c)};b(RF);b(YF);b(RG);b(TG);b(UG);b(dH);b(fH);b(hI);b(PS());b(jI);b(OO);b(PO);b(lP);b(mP);b(nP);b(uP);b(vP);b(rS);b(uS);b(BS);b(DS);b(TS);b(WS);b(ZS);b(aT);b(bT);b(dT);b(oT);b(rT);b(uT);b(yT);b(CT);b(HT);b(MT);RT("Math",zh());RT("Object",Zh);RT("TestHelper",ci());RT("assertApi",wh);RT("assertThat",xh);RT("decodeUri",Ch);RT("decodeUriComponent",Dh);RT("encodeUri",Eh);RT("encodeUriComponent",Fh);RT("fail",
Lh);RT("generateRandom",Nh);RT("getTimestamp",Oh);RT("getTimestampMillis",Oh);RT("getType",Ph);RT("makeInteger",Rh);RT("makeNumber",Sh);RT("makeString",Th);RT("makeTableMap",Uh);RT("mock",Xh);RT("mockObject",Yh);RT("fromBase64",HO,!("atob"in A));RT("localStorage",SS,!RS());RT("toBase64",JT,!("btoa"in A));a(QF);a(UF);a(nG);a(sG);a(IG);a(PG);a(SG);a(VG);a(WG);a(ZG);a($G);a(aH);a(bH);a(cH);a(eH);a(gH);a(gI);a(iI);a(kI);a(lI);a(mI);a(nI);a(oI);a(fJ);a(mJ);a(tJ);a(uJ);a(AJ);a(FJ);a(KJ);a(RJ);a(WJ);a(gK);
a(iK);a(vK);a(wK);a(xK);a(FO);a(GO);a(IO);a(JO);a(KO);a(LO);a(MO);a(NO);a(QO);a(RO);a(SO);a(TO);a(UO);a(VO);a(WO);a(XO);a(YO);a(ZO);a($O);a(aP);a(bP);a(cP);a(dP);a(eP);a(fP);a(gP);a(hP);a(iP);a(jP);a(kP);a(oP);a(pP);a(qP);a(rP);a(sP);a(tP);a(wP);a(oS);a(pS);a(tS);a(vS);a(CS);a(ES);a(FS);a(GS);a(HS);a(IS);a(JS);a(KS);a(LS);a(MS);a(NS);a(OS);a(QS);a(GG);a(US);a(VS);a(XS);a(YS);a($S);a(cT);a(eT);a(fT);a(hT);a(iT);a(jT);a(lT);a(mT);a(nT);a(pT);a(qT);a(sT);a(tT);a(vT);a(wT);a(xT);a(zT);a(AT);a(BT);a(DT);
a(ET);a(FT);a(GT);a(IT);a(KT);a(LT);a(NT);ST("internal.IframingStateSchema",sS());ST("internal.quickHash",Mh);PT||(PT=new OT);return QT()};var JF;function VT(){JF.sd(function(a,b,c){lj();var d=jj;d.H.SANDBOXED_JS_SEMAPHORE=d.H.SANDBOXED_JS_SEMAPHORE||0;d.H.SANDBOXED_JS_SEMAPHORE++;try{return a.apply(b,c)}finally{lj(),jj.H.SANDBOXED_JS_SEMAPHORE--}})}function WT(a){if(a&&a.length)for(var b=al(27,function(){return{}}),c=0;c<a.length;c++){var d=a[c].replace(/^_*/,"");b[d]=["sandboxedScripts"]}}
function XT(a){if(a){var b=al(27,function(){return{}});Gb(a,function(c,d){for(var e=0;e<d.length;e++){var f=d[e].replace(/^_*/,"");b[f]=b[f]||[];b[f].push(c)}})}};function ZT(a){mD(pC("developer_id."+a,!0),0,{})};function $T(a,b){return Ed(a,b||null)}function Y(a){return window.encodeURIComponent(a)}function aU(a){Zc(a,void 0,void 0)}function bU(a){var b=["veinteractive.com","ve-interactive.cn"];if(!a)return!1;var c=Lj(Rj(a),"host");if(!c)return!1;for(var d=0;b&&d<b.length;d++){var e=b[d]&&b[d].toLowerCase();if(e){var f=c.length-e.length;f>0&&e.charAt(0)!=="."&&(f--,e="."+e);if(f>=0&&c.indexOf(e,f)===f)return!0}}return!1}
function cU(a,b,c){for(var d={},e=!1,f=0;a&&f<a.length;f++)a[f]&&a[f].hasOwnProperty(b)&&a[f].hasOwnProperty(c)&&(d[a[f][b]]=a[f][c],e=!0);return e?d:null}function dU(a,b){var c={};if(a)for(var d in a)a.hasOwnProperty(d)&&(c[d]=a[d]);if(b){var e=cU(b,"parameter","parameterValue");e&&(c=$T(e,c))}return c}function eU(a,b,c){return a===void 0||a===c?b:a}function fU(a,b,c){return Uc(a,b,c,void 0)}function gU(a,b){A[a]=b}function hU(a,b,c){var d=A;b&&(d[a]===void 0||c&&!d[a])&&(d[a]=b);return d[a]}var iU={},jU=X.V;var Z={securityGroups:{}};
Z.securityGroups.get_referrer=["google"],function(){function a(b,c,d){return{component:c,queryKey:d}}(function(b){Z.__get_referrer=b;Z.__get_referrer.O="get_referrer";Z.__get_referrer.isVendorTemplate=!0;Z.__get_referrer.priorityOverride=0;Z.__get_referrer.isInfrastructure=!1;Z.__get_referrer["5"]=!1;Z.__get_referrer["6"]=!1})(function(b){var c=b.vtp_urlParts==="any"?null:[];c&&(b.vtp_protocol&&c.push("protocol"),b.vtp_host&&c.push("host"),b.vtp_port&&c.push("port"),b.vtp_path&&c.push("path"),b.vtp_extension&&
c.push("extension"),b.vtp_query&&c.push("query"));var d=c&&b.vtp_queriesAllowed!=="any"?b.vtp_queryKeys||[]:null,e=b.vtp_createPermissionError;return{assert:function(f,g,h){if(g){if(!zb(g))throw e(f,{},"URL component must be a string.");if(c&&c.indexOf(g)<0)throw e(f,{},"Prohibited URL component: "+g);if(g==="query"&&d){if(!h)throw e(f,{},"Prohibited from getting entire URL query when query keys are specified.");if(!zb(h))throw e(f,{},"Query key must be a string.");if(d.indexOf(h)<0)throw e(f,{},
"Prohibited query key: "+h);}}else if(c)throw e(f,{},"Prohibited from getting entire URL when components are specified.");},aa:a}})}();
Z.securityGroups.read_event_data=["google"],function(){function a(b,c){return{key:c}}(function(b){Z.__read_event_data=b;Z.__read_event_data.O="read_event_data";Z.__read_event_data.isVendorTemplate=!0;Z.__read_event_data.priorityOverride=0;Z.__read_event_data.isInfrastructure=!1;Z.__read_event_data["5"]=!1;Z.__read_event_data["6"]=!1})(function(b){var c=b.vtp_eventDataAccess,d=b.vtp_keyPatterns||[],e=b.vtp_createPermissionError;return{assert:function(f,g){if(g!=null&&!zb(g))throw e(f,{key:g},"Key must be a string.");
if(c!=="any"){try{if(c==="specific"&&g!=null&&Eg(g,d))return}catch(h){throw e(f,{key:g},"Invalid key filter.");}throw e(f,{key:g},"Prohibited read from event data.");}},aa:a}})}();
Z.securityGroups.read_data_layer=["google"],function(){function a(b,c){return{key:c}}(function(b){Z.__read_data_layer=b;Z.__read_data_layer.O="read_data_layer";Z.__read_data_layer.isVendorTemplate=!0;Z.__read_data_layer.priorityOverride=0;Z.__read_data_layer.isInfrastructure=!1;Z.__read_data_layer["5"]=!1;Z.__read_data_layer["6"]=!1})(function(b){var c=b.vtp_allowedKeys||"specific",d=b.vtp_keyPatterns||[],e=b.vtp_createPermissionError;return{assert:function(f,g){if(!zb(g))throw e(f,{},"Keys must be strings.");
if(c!=="any"){try{if(Eg(g,d))return}catch(h){throw e(f,{},"Invalid key filter.");}throw e(f,{},"Prohibited read from data layer variable: "+g+".");}},aa:a}})}();
Z.securityGroups.get_url=["google"],function(){function a(b,c,d){return{component:c,queryKey:d}}(function(b){Z.__get_url=b;Z.__get_url.O="get_url";Z.__get_url.isVendorTemplate=!0;Z.__get_url.priorityOverride=0;Z.__get_url.isInfrastructure=!1;Z.__get_url["5"]=!1;Z.__get_url["6"]=!1})(function(b){var c=b.vtp_urlParts==="any"?null:[];c&&(b.vtp_protocol&&c.push("protocol"),b.vtp_host&&c.push("host"),b.vtp_port&&c.push("port"),b.vtp_path&&c.push("path"),b.vtp_extension&&c.push("extension"),b.vtp_query&&
c.push("query"),b.vtp_fragment&&c.push("fragment"));var d=c&&b.vtp_queriesAllowed!=="any"?b.vtp_queryKeys||[]:null,e=b.vtp_createPermissionError;return{assert:function(f,g,h){if(g){if(!zb(g))throw e(f,{},"URL component must be a string.");if(c&&c.indexOf(g)<0)throw e(f,{},"Prohibited URL component: "+g);if(g==="query"&&d){if(!h)throw e(f,{},"Prohibited from getting entire URL query when query keys are specified.");if(!zb(h))throw e(f,{},"Query key must be a string.");if(d.indexOf(h)<0)throw e(f,{},
"Prohibited query key: "+h);}}else if(c)throw e(f,{},"Prohibited from getting entire URL when components are specified.");},aa:a}})}();
function kU(){var a={},b={dataLayer:tA,callback:function(c){a.hasOwnProperty(c)&&yb(a[c])&&a[c]();delete a[c]},bootstrap:0};return b}
function lU(){var a=kU();oj(a);Ck();jA();var b=al(27,function(){return{}});Qb(b,Z.securityGroups);var c=yk(zk()),d,e=c==null?void 0:(d=c.context)==null?void 0:d.source;Kl(e,c==null?void 0:c.parent);e!==2&&e!==4&&e!==3||P(142);return a}function mU(){var a=E(60);if(a)for(var b=a.split("."),c=0;c<b.length;c++){var d=b[c],e=TL;d&&(e.H[d]=!0)}}
function nU(){zp();lj();for(var a=data.resource||{},b=cA,c=a.macros||[],d=0;d<c.length;d++)b.macros.push(new Uz(c[d],d,b.tags,b.macros));for(var e=a.tags||[],f=0;f<e.length;f++)b.tags.push(new Yz(e[f],f,b.tags,b.macros));for(var g=a.predicates||[],h=0;h<g.length;h++)b.predicates.push(new Vz(g[h],b.tags,b.macros));for(var l=a.rules||[],n=0;n<l.length;n++)b.rules.push(new Wz(l[n],n));Qz=Z;var p=data.permissions||{},q=Z;dg=new gg(E(5),p,q);var r=data.sandboxed_scripts,t=data.security_groups,u=data.runtime||
[],v=data.runtime_lines;JF=new pf;VT();Pz=IF();var x=JF,y=UT(),z=new Ld("require",y);z.Za();x.H.H.set("require",z);db.set("require",z);for(var C=0;C<u.length;C++){var D=u[C];if(!Array.isArray(D)||D.length<3){if(D.length===0)continue;break}v&&v[C]&&v[C].length&&Pf(D,v[C]);try{JF.execute(D)}catch(oU){}}WT(r);XT(t);var I=lU();iF();vm.bind();if(!Dj)for(var G=Bm()?ep(Lf(5)):ep(Lf(4)),N=m(Ro),S=N.next();!S.done;S=N.next()){var W=S.value,ea=W,ja=G[W]?"granted":"denied";tl().implicit(ea,ja)}hE.bind();TB();
OB();fn.N&&(gz(),fz(AF),gA(),cB=new bB,fz(iz),OC(),DF||(DF=new BF),fB||(fB=new eB),FF=new EF);if(fn.K){DE.bind();mC.bind();wE.bind();var fa=Ak();if(fa){var sa;a:{var da,ma=(da=fa.scriptElement)==null?void 0:da.src;if(ma){var Pa;try{var Fa;Pa=(Fa=rd())==null?void 0:Fa.getEntriesByType("resource")}catch(oU){}if(Pa){for(var qa=-1,ib=m(Pa),Xb=ib.next();!Xb.done;Xb=ib.next()){var Lc=Xb.value;if(Lc.initiatorType===
"script"&&(qa+=1,Lc.name.replace(NE,"")===ma.replace(NE,""))){sa=qa;break a}}P(146)}else P(145)}sa=void 0}var Qd=sa;Qd!==void 0&&(fa.canonicalContainerId&&Um("rtg",String(fa.canonicalContainerId)),Um("slo",String(Qd)),Um("hlo",fa.htmlLoadOrder||"-1"),Um("lst",String(fa.loadScriptType||"0")))}else P(144);var Yc;var Dd=xk();if(Dd)if(Dd.canonicalContainerId)Yc=Dd.canonicalContainerId;else{var jf,vh=Dd.scriptContainerId||((jf=Dd.destinations)==null?void 0:jf[0]);Yc=vh?"_"+vh:void 0}else Yc=void 0;var JE=
Yc;JE&&Um("pcid",JE);Um("bt",String(If(47)?2:If(50)?1:0));Um("ct",String(If(47)?0:If(50)?1:3));AE.bind();for(var Wr=[],Xr=[],KE=m(Object.keys(GE)),Yr=KE.next();!Yr.done;Yr=KE.next()){var rm=Yr.value;if(window.isSecureContext||!IE[rm]){var LE=GE[rm]();if(yb(LE)){var ME=Function.prototype.toString.call(LE);Tb(ME,"{ [native code] }")||Tb(ME,"{\n [native code]\n}")||Xr.push(rm)}else Wr.push(rm)}}Wr.length>0&&Um("jsm",Wr.join("~"));Xr.length>0&&Um("jsp",Xr.join("~"));Ey||(Ey=new Dy)}hF();im(1);EG();return I}
function um(){try{if(!hk()&&(If(47)||!Nk())){If(64)&&wj.H.K.add(118517917);zj();fn.H&&sz();Wf[5]=!0;var a=kj("debugGroupId",function(){return String(Math.floor(Number.MAX_SAFE_INTEGER*Math.random()))});Sl(a);kt();zF();Ft();PB();if(Dk()){E(5);DG();iB().removeExternalRestrictions(vk());}else{nU().bootstrap=Nb();If(51)&&pE();
fn.H&&tz();typeof A.name==="string"&&Sb(A.name,"web-pixel-sandbox-CUSTOM")&&sd()?ZT("dMDg0Yz"):A.Shopify&&(ZT("dN2ZkMj"),sd()&&ZT("dNTU0Yz"));mU()}}}catch(b){im(5),hz()}}
(function(a){function b(){n=B.documentElement.getAttribute("data-tag-assistant-present");gl(n)&&(l=h.xm)}function c(){l&&Kc?g(l):a()}if(!A[E(37)]){var d=!1;if(B.referrer){var e=Rj(B.referrer);d=Nj(e,"host")===E(38)}if(!d){var f=cq(E(39));d=!(!f.length||!f[0].length)}d&&(A[E(37)]=!0,Uc(E(40)))}var g=function(u){var v="GTM",x="GTM";If(45)&&(v="OGT",x="GTAG");var y=E(23),z=A[y];z||(z=[],A[y]=z,Uc("https://"+E(3)+"/debug/bootstrap?id="+E(5)+"&src="+x+"&cond="+String(u)+"&gtm="+du()));var C={messageType:"CONTAINER_STARTING",
data:{scriptSource:Kc,containerProduct:v,debug:!1,id:E(5),targetRef:{ctid:E(5),isDestination:sk(),canonicalId:E(6)},aliases:wk(),destinations:tk()}},D=C.data;D.resume=function(){a()};D.resumeWithMemos=function(){sl(1);a()};If(2)&&(C.data.initialPublish=!0);z.push(C)},h={Gq:1,Pm:2,on:3,jl:4,xm:5};h[h.Gq]="GTM_DEBUG_LEGACY_PARAM";h[h.Pm]="GTM_DEBUG_PARAM";h[h.on]="REFERRER";h[h.jl]="COOKIE";h[h.xm]="EXTENSION_PARAM";var l=void 0,n=void 0,p=Lj(A.location,"query",!1,void 0,"gtm_debug");gl(p)&&(l=h.Pm);
if(!l&&B.referrer){var q=Rj(B.referrer);Nj(q,"host")===E(24)&&(l=h.on)}if(!l){var r=cq("__TAG_ASSISTANT");r.length&&r[0].length&&(l=h.jl)}l||b();if(!l&&fl(n)){var t=!1;$c(B,"TADebugSignal",function(){t||(t=!0,b(),c())},!1);A.setTimeout(function(){t||(t=!0,b(),c())},200)}else c()})(function(){!If(47)||tm()["0"]?um():xm()});
})()
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,35 @@
window.__tcfapi = function (command, version, callback, parameter) {
if (command === 'getTCData' || command === 'addEventListener' || command === 'removeEventListener') {
const tcData = {
gdprApplies: false,
tcString: '',
eventStatus: 'tcloaded',
cmpId: 299,
cmpVersion: 10,
cmpStatus: 'disabled',
isServiceSpecific: true,
useNonStandardStacks: false,
purposeOneTreatment: false,
purpose: {
consents: {},
legitimateInterests: {}
},
vendor: {
consents: {},
legitimateInterests: {}
}
};
callback(tcData, true);
} else if (command === 'ping') {
callback({
gdprApplies: false,
cmpId: 299,
cmpVersion: 10,
cmpStatus: 'disabled'
}, true);
} else {
callback(null, false);
}
};
window.dispatchEvent(new Event('tcfapiready'));
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 85 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Some files were not shown because too many files have changed in this diff Show More