diff --git a/README.md b/README.md index 91638a6..436c84c 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,26 @@ On init the PN532 is configured for **high passive-activation retries** (`RFConf ## Build +### One-command local run + +```bash +./start-firmware.sh +``` + +What it does: + +- bootstraps ESP-IDF locally if needed +- builds the web UI into `firmware/data` +- configures target `esp32s3` +- auto-detects the serial port +- builds and flashes the device + +Useful options: + +- `./start-firmware.sh --build-only` +- `./start-firmware.sh --monitor` +- `./start-firmware.sh --port /dev/cu.usbmodemXXXX` + ### Web UI → flash image ```bash diff --git a/firmware/components/net_service/app_net.c b/firmware/components/net_service/app_net.c index b3a58b2..2d483ec 100644 --- a/firmware/components/net_service/app_net.c +++ b/firmware/components/net_service/app_net.c @@ -1,4 +1,5 @@ #include "net_service/app_net.h" +#include "esp_event.h" #include "esp_log.h" #include "esp_system.h" #include "esp_http_server.h" @@ -7,6 +8,7 @@ #include "esp_timer.h" #include "esp_wifi.h" #include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" #include "freertos/task.h" #include "mdns.h" #include "nfc_engine/nfc_brute.h" @@ -16,7 +18,6 @@ #include "nvs_flash.h" #include "pn532_host/pn532_core.h" #include "cJSON.h" -#include "http_parser.h" #include #include #include @@ -28,13 +29,28 @@ static const char *TAG = "app_net"; /* SoftAP: open network (no password) for lab / fastest join. Change SSID here if you want. */ #define SOFTAP_SSID "PN532-Toolkit" -#define MAX_JSON 4096 #define WS_BROADCAST_BUF 4096 +#define STATIC_PATH_MAX 192 static httpd_handle_t s_server; -static bool s_scan = true; +static SemaphoreHandle_t s_nfc_op_mu; +static volatile bool s_scan = true; static TaskHandle_t s_scan_task; +static void nfc_access_lock(void) +{ + if (s_nfc_op_mu) { + xSemaphoreTake(s_nfc_op_mu, portMAX_DELAY); + } +} + +static void nfc_access_unlock(void) +{ + if (s_nfc_op_mu) { + xSemaphoreGive(s_nfc_op_mu); + } +} + static int hexval(char c) { if (c >= '0' && c <= '9') { @@ -76,6 +92,19 @@ static bool hex_decode_flex(const char *hex, uint8_t *out, size_t out_cap, size_ return hex_to_bin(hex, out, *out_len); } +static bool copy_json_string(const cJSON *item, char *dst, size_t cap) +{ + if (!dst || cap == 0 || !cJSON_IsString(item) || !item->valuestring) { + return false; + } + size_t len = strlen(item->valuestring); + if (len >= cap) { + return false; + } + memcpy(dst, item->valuestring, len + 1); + return true; +} + /** Read full POST body (httpd may return partial data in multiple recv calls). */ static int recv_body_capped(httpd_req_t *req, char *buf, size_t cap) { @@ -130,7 +159,6 @@ static char *recv_body_alloc(httpd_req_t *req, size_t max_len, int *out_len) esp_err_t app_net_broadcast_json(const char *channel, const char *json_text) { - (void)channel; if (!s_server || !json_text) { return ESP_ERR_INVALID_STATE; } @@ -157,6 +185,10 @@ esp_err_t app_net_broadcast_json(const char *channel, const char *json_text) static esp_err_t send_json(httpd_req_t *req, cJSON *j, int status) { + if (!req || !j) { + cJSON_Delete(j); + return ESP_ERR_INVALID_ARG; + } char *p = cJSON_PrintUnformatted(j); cJSON_Delete(j); if (!p) { @@ -166,15 +198,65 @@ static esp_err_t send_json(httpd_req_t *req, cJSON *j, int status) httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); httpd_resp_set_hdr(req, "Access-Control-Allow-Methods", "GET, POST, OPTIONS"); httpd_resp_set_hdr(req, "Access-Control-Allow-Headers", "Content-Type"); - httpd_resp_set_status(req, status == 200 ? "200 OK" : "400 Bad Request"); + switch (status) { + case 200: + httpd_resp_set_status(req, "200 OK"); + break; + case 400: + httpd_resp_set_status(req, "400 Bad Request"); + break; + case 404: + httpd_resp_set_status(req, "404 Not Found"); + break; + case 409: + httpd_resp_set_status(req, "409 Conflict"); + break; + case 500: + httpd_resp_set_status(req, "500 Internal Server Error"); + break; + case 501: + httpd_resp_set_status(req, "501 Not Implemented"); + break; + default: + httpd_resp_set_status(req, "200 OK"); + break; + } esp_err_t e = httpd_resp_send(req, p, HTTPD_RESP_USE_STRLEN); free(p); return e; } +static esp_err_t ensure_ultralight_tag_locked(nfc_tag_info_t *tag) +{ + if (!tag) { + return ESP_ERR_INVALID_ARG; + } + esp_err_t err = nfc_poll_passive_target(tag); + if (err != ESP_OK) { + return err; + } + return nfc_tag_is_type2(tag) ? ESP_OK : ESP_ERR_NOT_SUPPORTED; +} + +static esp_err_t ensure_mifare_classic_tag_locked(nfc_tag_info_t *tag) +{ + if (!tag) { + return ESP_ERR_INVALID_ARG; + } + esp_err_t err = nfc_poll_passive_target(tag); + if (err != ESP_OK) { + return err; + } + return nfc_tag_is_mifare_classic(tag) ? ESP_OK : ESP_ERR_NOT_SUPPORTED; +} + static esp_err_t api_status(httpd_req_t *req) { cJSON *o = cJSON_CreateObject(); + if (!o) { + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "out of memory"); + return ESP_ERR_NO_MEM; + } cJSON_AddStringToObject(o, "app", "pn532_nfc_toolkit"); cJSON_AddNumberToObject(o, "uptimeMs", (double)(esp_timer_get_time() / 1000)); cJSON_AddNumberToObject(o, "freeHeap", (double)esp_get_free_heap_size()); @@ -182,6 +264,7 @@ static esp_err_t api_status(httpd_req_t *req) esp_wifi_get_mode(&mode); cJSON_AddNumberToObject(o, "wifiMode", mode); uint8_t ic = 0, hi = 0, lo = 0; + nfc_access_lock(); if (pn532_get_firmware_version(&ic, &hi, &lo) == ESP_OK) { cJSON *pn = cJSON_CreateObject(); cJSON_AddNumberToObject(pn, "ic", ic); @@ -189,12 +272,18 @@ static esp_err_t api_status(httpd_req_t *req) cJSON_AddNumberToObject(pn, "fwLo", lo); cJSON_AddItemToObject(o, "pn532", pn); } + nfc_access_unlock(); cJSON_AddBoolToObject(o, "scanning", s_scan); size_t cap_u = 0; uint32_t cap_l = 0; bool cap_f = false; session_capture_get_status(&cap_u, &cap_l, &cap_f); cJSON *cap = cJSON_CreateObject(); + if (!cap) { + cJSON_Delete(o); + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "out of memory"); + return ESP_ERR_NO_MEM; + } cJSON_AddNumberToObject(cap, "usedBytes", (double)cap_u); cJSON_AddNumberToObject(cap, "maxBytes", (double)session_capture_max()); cJSON_AddNumberToObject(cap, "lines", (double)cap_l); @@ -226,7 +315,7 @@ static esp_err_t api_session_export(httpd_req_t *req) } char *buf = malloc(n); if (!buf) { - return send_json(req, cJSON_CreateString("out of memory"), 400); + return send_json(req, cJSON_CreateString("out of memory"), 500); } size_t got = 0; session_capture_copy_to(buf, n, &got); @@ -255,6 +344,11 @@ static esp_err_t api_session_deep(httpd_req_t *req) if (r < 0) { return send_json(req, cJSON_CreateString("body required or too large"), 400); } + if (r == 0) { + cJSON *o = cJSON_CreateObject(); + cJSON_AddBoolToObject(o, "deepCapture", session_capture_deep_enabled()); + return send_json(req, o, 200); + } cJSON *j = cJSON_Parse(buf); if (!j) { return send_json(req, cJSON_CreateString("bad json"), 400); @@ -275,20 +369,28 @@ static esp_err_t api_nfc_poll(httpd_req_t *req) (void)recv_body_capped(req, drain, sizeof(drain)); nfc_tag_info_t tag; + nfc_access_lock(); esp_err_t e = nfc_poll_passive_target(&tag); if (e == ESP_ERR_NOT_FOUND) { + nfc_access_unlock(); cJSON *o = cJSON_CreateObject(); cJSON_AddBoolToObject(o, "present", false); return send_json(req, o, 200); } if (e != ESP_OK) { + nfc_access_unlock(); cJSON *o = cJSON_CreateObject(); cJSON_AddStringToObject(o, "error", esp_err_to_name(e)); return send_json(req, o, 400); } + cJSON *tj = nfc_tag_to_json(&tag); + nfc_access_unlock(); + if (!tj) { + return send_json(req, cJSON_CreateString("out of memory building tag"), 500); + } cJSON *o = cJSON_CreateObject(); cJSON_AddBoolToObject(o, "present", true); - cJSON_AddItemToObject(o, "tag", nfc_tag_to_json(&tag)); + cJSON_AddItemToObject(o, "tag", tj); return send_json(req, o, 200); } @@ -299,6 +401,11 @@ static esp_err_t api_scan(httpd_req_t *req) if (r < 0) { return send_json(req, cJSON_CreateString("no body or too large"), 400); } + if (r == 0) { + cJSON *o = cJSON_CreateObject(); + cJSON_AddBoolToObject(o, "enable", s_scan); + return send_json(req, o, 200); + } cJSON *j = cJSON_Parse(buf); if (!j) { return send_json(req, cJSON_CreateString("bad json"), 400); @@ -317,7 +424,9 @@ static esp_err_t api_general_status(httpd_req_t *req) { uint8_t gs[32]; size_t gl = 0; + nfc_access_lock(); esp_err_t e = pn532_get_general_status(gs, sizeof(gs), &gl); + nfc_access_unlock(); if (e != ESP_OK) { cJSON *o = cJSON_CreateObject(); cJSON_AddStringToObject(o, "error", esp_err_to_name(e)); @@ -325,6 +434,10 @@ static esp_err_t api_general_status(httpd_req_t *req) } cJSON *o = cJSON_CreateObject(); cJSON *arr = cJSON_CreateArray(); + if (!arr) { + cJSON_Delete(o); + return send_json(req, cJSON_CreateString("out of memory"), 500); + } for (size_t i = 0; i < gl; i++) { cJSON_AddItemToArray(arr, cJSON_CreateNumber(gs[i])); } @@ -335,6 +448,7 @@ static esp_err_t api_general_status(httpd_req_t *req) static esp_err_t api_mifare_read(httpd_req_t *req) { char buf[512]; + char key_hex[13]; int r = recv_body_capped(req, buf, sizeof(buf)); if (r < 0) { return send_json(req, cJSON_CreateString("no body or too large"), 400); @@ -346,30 +460,40 @@ static esp_err_t api_mifare_read(httpd_req_t *req) cJSON *jbk = cJSON_GetObjectItem(j, "block"); cJSON *jk = cJSON_GetObjectItem(j, "key"); int block = cJSON_IsNumber(jbk) ? (int)cJSON_GetNumberValue(jbk) : -1; - const char *key_hex = cJSON_IsString(jk) ? jk->valuestring : NULL; cJSON *jb = cJSON_GetObjectItem(j, "keyB"); bool key_b = cJSON_IsTrue(jb); + bool have_key = copy_json_string(jk, key_hex, sizeof(key_hex)); cJSON_Delete(j); - if (block < 0 || !key_hex) { - return send_json(req, cJSON_CreateString("block/key required"), 400); + if (block < 0 || block > 255 || !have_key) { + return send_json(req, cJSON_CreateString("block/key required (block 0-255)"), 400); } uint8_t keyb[6]; if (!hex_to_bin(key_hex, keyb, 6)) { return send_json(req, cJSON_CreateString("key must be 12 hex chars"), 400); } nfc_tag_info_t tag; - if (nfc_poll_passive_target(&tag) != ESP_OK) { + nfc_access_lock(); + esp_err_t err = ensure_mifare_classic_tag_locked(&tag); + if (err == ESP_ERR_NOT_SUPPORTED) { + nfc_access_unlock(); + return send_json(req, cJSON_CreateString("tag is not MIFARE Classic"), 400); + } + if (err != ESP_OK) { + nfc_access_unlock(); return send_json(req, cJSON_CreateString("no tag"), 400); } nfc_mifare_key_t k = {.key_b = key_b}; memcpy(k.key, keyb, 6); if (nfc_mifare_authenticate_block(&tag, (uint8_t)block, &k) != ESP_OK) { + nfc_access_unlock(); return send_json(req, cJSON_CreateString("auth failed"), 400); } uint8_t blk[NFC_BLOCK_LEN]; if (nfc_mifare_read_block((uint8_t)block, blk) != ESP_OK) { + nfc_access_unlock(); return send_json(req, cJSON_CreateString("read failed"), 400); } + nfc_access_unlock(); char hexout[NFC_BLOCK_LEN * 2 + 1]; for (int i = 0; i < NFC_BLOCK_LEN; i++) { snprintf(hexout + i * 2, 3, "%02X", blk[i]); @@ -383,6 +507,8 @@ static esp_err_t api_mifare_read(httpd_req_t *req) static esp_err_t api_mifare_write(httpd_req_t *req) { char buf[512]; + char key_hex[13]; + char data_hex[33]; int r = recv_body_capped(req, buf, sizeof(buf)); if (r < 0) { return send_json(req, cJSON_CreateString("no body or too large"), 400); @@ -395,30 +521,40 @@ static esp_err_t api_mifare_write(httpd_req_t *req) cJSON *jk = cJSON_GetObjectItem(j, "key"); cJSON *jd = cJSON_GetObjectItem(j, "data"); int block = cJSON_IsNumber(jbk) ? (int)cJSON_GetNumberValue(jbk) : -1; - const char *key_hex = cJSON_IsString(jk) ? jk->valuestring : NULL; - const char *data_hex = cJSON_IsString(jd) ? jd->valuestring : NULL; cJSON *jb = cJSON_GetObjectItem(j, "keyB"); bool key_b = cJSON_IsTrue(jb); + bool have_key = copy_json_string(jk, key_hex, sizeof(key_hex)); + bool have_data = copy_json_string(jd, data_hex, sizeof(data_hex)); cJSON_Delete(j); - if (block < 0 || !key_hex || !data_hex) { - return send_json(req, cJSON_CreateString("block/key/data required"), 400); + if (block < 0 || block > 255 || !have_key || !have_data) { + return send_json(req, cJSON_CreateString("block/key/data required (block 0-255)"), 400); } uint8_t keyb[6], blk[NFC_BLOCK_LEN]; if (!hex_to_bin(key_hex, keyb, 6) || !hex_to_bin(data_hex, blk, NFC_BLOCK_LEN)) { return send_json(req, cJSON_CreateString("bad hex"), 400); } nfc_tag_info_t tag; - if (nfc_poll_passive_target(&tag) != ESP_OK) { + nfc_access_lock(); + esp_err_t err = ensure_mifare_classic_tag_locked(&tag); + if (err == ESP_ERR_NOT_SUPPORTED) { + nfc_access_unlock(); + return send_json(req, cJSON_CreateString("tag is not MIFARE Classic"), 400); + } + if (err != ESP_OK) { + nfc_access_unlock(); return send_json(req, cJSON_CreateString("no tag"), 400); } nfc_mifare_key_t k = {.key_b = key_b}; memcpy(k.key, keyb, 6); if (nfc_mifare_authenticate_block(&tag, (uint8_t)block, &k) != ESP_OK) { + nfc_access_unlock(); return send_json(req, cJSON_CreateString("auth failed"), 400); } if (nfc_mifare_write_block((uint8_t)block, blk) != ESP_OK) { + nfc_access_unlock(); return send_json(req, cJSON_CreateString("write failed"), 400); } + nfc_access_unlock(); return send_json(req, cJSON_CreateObject(), 200); } @@ -436,13 +572,26 @@ static esp_err_t api_ul_read(httpd_req_t *req) cJSON *jp = cJSON_GetObjectItem(j, "page"); int page = cJSON_IsNumber(jp) ? (int)cJSON_GetNumberValue(jp) : -1; cJSON_Delete(j); - if (page < 0) { - return send_json(req, cJSON_CreateString("page required"), 400); + if (page < 0 || page > 255) { + return send_json(req, cJSON_CreateString("page required (0-255)"), 400); } uint8_t d[4]; + nfc_tag_info_t tag; + nfc_access_lock(); + esp_err_t e = ensure_ultralight_tag_locked(&tag); + if (e == ESP_ERR_NOT_SUPPORTED) { + nfc_access_unlock(); + return send_json(req, cJSON_CreateString("tag is not Ultralight/NTAG"), 400); + } + if (e != ESP_OK) { + nfc_access_unlock(); + return send_json(req, cJSON_CreateString("no tag"), 400); + } if (nfc_ultralight_read_page((uint8_t)page, d) != ESP_OK) { + nfc_access_unlock(); return send_json(req, cJSON_CreateString("read failed"), 400); } + nfc_access_unlock(); char hx[9]; snprintf(hx, sizeof hx, "%02X%02X%02X%02X", d[0], d[1], d[2], d[3]); cJSON *o = cJSON_CreateObject(); @@ -454,6 +603,7 @@ static esp_err_t api_ul_read(httpd_req_t *req) static esp_err_t api_ul_write(httpd_req_t *req) { char buf[128]; + char data_hex[9]; int r = recv_body_capped(req, buf, sizeof(buf)); if (r < 0) { return send_json(req, cJSON_CreateString("no body or too large"), 400); @@ -465,18 +615,31 @@ static esp_err_t api_ul_write(httpd_req_t *req) cJSON *jp = cJSON_GetObjectItem(j, "page"); cJSON *jd = cJSON_GetObjectItem(j, "data"); int page = cJSON_IsNumber(jp) ? (int)cJSON_GetNumberValue(jp) : -1; - const char *data_hex = cJSON_IsString(jd) ? jd->valuestring : NULL; + bool have_data = copy_json_string(jd, data_hex, sizeof(data_hex)); cJSON_Delete(j); - if (page < 0 || !data_hex) { - return send_json(req, cJSON_CreateString("page and data (8 hex) required"), 400); + if (page < 0 || page > 255 || !have_data) { + return send_json(req, cJSON_CreateString("page and data (8 hex) required (page 0-255)"), 400); } uint8_t d[4]; if (!hex_to_bin(data_hex, d, 4)) { return send_json(req, cJSON_CreateString("data must be 8 hex chars (4 bytes)"), 400); } + nfc_tag_info_t tag; + nfc_access_lock(); + esp_err_t e = ensure_ultralight_tag_locked(&tag); + if (e == ESP_ERR_NOT_SUPPORTED) { + nfc_access_unlock(); + return send_json(req, cJSON_CreateString("tag is not Ultralight/NTAG"), 400); + } + if (e != ESP_OK) { + nfc_access_unlock(); + return send_json(req, cJSON_CreateString("no tag"), 400); + } if (nfc_ultralight_write_page((uint8_t)page, d) != ESP_OK) { + nfc_access_unlock(); return send_json(req, cJSON_CreateString("write failed"), 400); } + nfc_access_unlock(); cJSON *o = cJSON_CreateObject(); cJSON_AddNumberToObject(o, "page", page); cJSON_AddBoolToObject(o, "ok", true); @@ -485,19 +648,8 @@ static esp_err_t api_ul_write(httpd_req_t *req) static esp_err_t api_ota_stub(httpd_req_t *req) { - (void)req; cJSON *o = cJSON_CreateString("Use idf.py app-flash or extend with esp_https_ota + bundle URL"); - char *p = cJSON_PrintUnformatted(o); - cJSON_Delete(o); - if (!p) { - return ESP_ERR_NO_MEM; - } - httpd_resp_set_type(req, "application/json"); - httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); - httpd_resp_set_status(req, "501 Not Implemented"); - esp_err_t e = httpd_resp_send(req, p, HTTPD_RESP_USE_STRLEN); - free(p); - return e; + return send_json(req, o, 501); } static esp_err_t api_mifare_dictionary_attack(httpd_req_t *req) @@ -544,30 +696,23 @@ static esp_err_t api_mifare_dictionary_attack(httpd_req_t *req) cJSON_Delete(j); nfc_tag_info_t tag; + nfc_access_lock(); if (nfc_poll_passive_target(&tag) != ESP_OK) { + nfc_access_unlock(); return send_json(req, cJSON_CreateString("no tag present"), 400); } - int attempts = 0; - cJSON *out = nfc_mifare_dictionary_attack(&tag, s0, s1, extra_n ? extra : NULL, extra_n, variations, &attempts); + cJSON *out = nfc_mifare_dictionary_attack(&tag, s0, s1, extra_n ? extra : NULL, extra_n, variations, NULL); + nfc_access_unlock(); if (!out) { return send_json(req, cJSON_CreateString("attack failed"), 400); } - char *p = cJSON_PrintUnformatted(out); - cJSON_Delete(out); - if (!p) { - return send_json(req, cJSON_CreateString("print failed"), 400); - } - httpd_resp_set_type(req, "application/json"); - httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); - httpd_resp_set_status(req, "200 OK"); - esp_err_t e = httpd_resp_send(req, p, HTTPD_RESP_USE_STRLEN); - free(p); - return e; + return send_json(req, out, 200); } static esp_err_t api_nfc_emulate_raw(httpd_req_t *req) { char buf[1024]; + char hex[521]; int r = recv_body_capped(req, buf, sizeof(buf)); if (r < 0) { return send_json(req, cJSON_CreateString("no body or too large"), 400); @@ -577,22 +722,27 @@ static esp_err_t api_nfc_emulate_raw(httpd_req_t *req) return send_json(req, cJSON_CreateString("bad json"), 400); } cJSON *jh = cJSON_GetObjectItem(j, "hex"); - const char *hex = cJSON_IsString(jh) ? jh->valuestring : NULL; + bool have_hex = copy_json_string(jh, hex, sizeof(hex)); cJSON_Delete(j); uint8_t bin[260]; size_t blen = 0; - if (!hex || !hex_decode_flex(hex, bin, sizeof(bin), &blen)) { + if (!have_hex || !hex_decode_flex(hex, bin, sizeof(bin), &blen)) { return send_json(req, cJSON_CreateString("hex command required"), 400); } uint8_t resp[300]; size_t rlen = 0; + nfc_access_lock(); esp_err_t err = pn532_send_cmd(bin, blen, resp, sizeof(resp), &rlen, 800); + nfc_access_unlock(); if (err != ESP_OK) { cJSON *o = cJSON_CreateObject(); cJSON_AddStringToObject(o, "error", esp_err_to_name(err)); return send_json(req, o, 400); } char *rh = calloc(1, rlen * 2 + 1); + if (!rh) { + return send_json(req, cJSON_CreateString("out of memory"), 500); + } for (size_t i = 0; i < rlen; i++) { snprintf(rh + i * 2, 3, "%02X", resp[i]); } @@ -605,6 +755,7 @@ static esp_err_t api_nfc_emulate_raw(httpd_req_t *req) static esp_err_t api_raw_pn532(httpd_req_t *req) { char buf[1024]; + char hex[521]; int r = recv_body_capped(req, buf, sizeof(buf)); if (r < 0) { return send_json(req, cJSON_CreateString("no body or too large"), 400); @@ -614,22 +765,27 @@ static esp_err_t api_raw_pn532(httpd_req_t *req) return send_json(req, cJSON_CreateString("bad json"), 400); } cJSON *jf = cJSON_GetObjectItem(j, "frame"); - const char *hex = cJSON_IsString(jf) ? jf->valuestring : NULL; + bool have_hex = copy_json_string(jf, hex, sizeof(hex)); cJSON_Delete(j); size_t blen = 0; uint8_t bin[260]; - if (!hex || !hex_decode_flex(hex, bin, sizeof(bin), &blen)) { + if (!have_hex || !hex_decode_flex(hex, bin, sizeof(bin), &blen)) { return send_json(req, cJSON_CreateString("frame hex required, even length, max 260B"), 400); } uint8_t resp[300]; size_t rlen = 0; + nfc_access_lock(); esp_err_t e = pn532_send_cmd(bin, blen, resp, sizeof(resp), &rlen, 300); + nfc_access_unlock(); if (e != ESP_OK) { cJSON *o = cJSON_CreateObject(); cJSON_AddStringToObject(o, "error", esp_err_to_name(e)); return send_json(req, o, 400); } char *rh = calloc(1, rlen * 2 + 1); + if (!rh) { + return send_json(req, cJSON_CreateString("out of memory"), 500); + } for (size_t i = 0; i < rlen; i++) { snprintf(rh + i * 2, 3, "%02X", resp[i]); } @@ -652,6 +808,7 @@ static esp_err_t api_cors_preflight(httpd_req_t *req) static esp_err_t static_any(httpd_req_t *req) { + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); if (strcmp(req->uri, "/") == 0) { httpd_resp_set_hdr(req, "Cache-Control", "no-cache"); FILE *f = fopen("/spiffs/index.html", "r"); @@ -662,7 +819,6 @@ static esp_err_t static_any(httpd_req_t *req) char buf[512]; size_t n; httpd_resp_set_type(req, "text/html"); -httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); while ((n = fread(buf, 1, sizeof(buf), f)) > 0) { if (httpd_resp_send_chunk(req, buf, n) != ESP_OK) { fclose(f); @@ -676,8 +832,12 @@ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "bad path"); return ESP_FAIL; } - char path[96]; - snprintf(path, sizeof path, "/spiffs%s", req->uri); + char path[STATIC_PATH_MAX]; + int path_len = snprintf(path, sizeof path, "/spiffs%s", req->uri); + if (path_len < 0 || path_len >= (int)sizeof(path)) { + httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "path too long"); + return ESP_FAIL; + } struct stat st; if (stat(path, &st) != 0) { httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "not found"); @@ -690,10 +850,10 @@ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); } if (strstr(req->uri, ".js")) { httpd_resp_set_type(req, "application/javascript"); -httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); } else if (strstr(req->uri, ".css")) { httpd_resp_set_type(req, "text/css"); -httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + } else if (strstr(req->uri, ".html")) { + httpd_resp_set_type(req, "text/html"); } char buf[512]; size_t n; @@ -720,7 +880,7 @@ static esp_err_t ws_handler(httpd_req_t *req) if (ret != ESP_OK) { return ret; } - if (ws.type == HTTPD_WS_TYPE_TEXT && ws.len < sizeof(buf)) { + if (ws.type == HTTPD_WS_TYPE_TEXT && ws.len + 1 < sizeof(buf)) { buf[ws.len] = 0; if (strcmp((char *)buf, "ping") == 0) { ws.type = HTTPD_WS_TYPE_TEXT; @@ -747,20 +907,24 @@ static void scan_loop_task(void *arg) continue; } nfc_tag_info_t tag; + nfc_access_lock(); esp_err_t e = nfc_poll_passive_target(&tag); if (e == ESP_OK) { bool is_new = (last.uid_len != tag.uid_len || memcmp(last.uid, tag.uid, tag.uid_len) != 0); if (is_new) { last = tag; cJSON *j = nfc_tag_to_json(&tag); - char *raw = cJSON_PrintUnformatted(j); - cJSON_Delete(j); - if (raw) { - app_net_broadcast_json("scan", raw); - free(raw); + if (j) { + char *raw = cJSON_PrintUnformatted(j); + cJSON_Delete(j); + if (raw) { + app_net_broadcast_json("scan", raw); + free(raw); + } } if (session_capture_deep_enabled() && !session_capture_is_full()) { cJSON *deep = nfc_tag_deep_profile(&tag); + nfc_access_unlock(); char *line = deep ? cJSON_PrintUnformatted(deep) : NULL; cJSON_Delete(deep); if (line) { @@ -796,9 +960,14 @@ static void scan_loop_task(void *arg) } free(line); } + } else { + nfc_access_unlock(); } + } else { + nfc_access_unlock(); } } else { + nfc_access_unlock(); if (last.uid_len) { memset(&last, 0, sizeof(last)); app_net_broadcast_json("scan", "{\"present\":false}"); @@ -812,6 +981,24 @@ void app_net_set_continuous_scan(bool on) { s_scan = on; } bool app_net_continuous_scan(void) { return s_scan; } +static bool register_uri_checked(httpd_handle_t server, const httpd_uri_t *uri) +{ + if (!server || !uri) { + return false; + } + esp_err_t err = httpd_register_uri_handler(server, uri); + if (err != ESP_OK) { + ESP_LOGE(TAG, "register %s %s failed: %s", + uri->method == HTTP_GET ? "GET" + : uri->method == HTTP_POST ? "POST" + : uri->method == HTTP_OPTIONS ? "OPTIONS" + : "?", + uri->uri ? uri->uri : "(null)", esp_err_to_name(err)); + return false; + } + return true; +} + static httpd_handle_t start_server(void) { httpd_config_t cfg = HTTPD_DEFAULT_CONFIG(); @@ -824,66 +1011,155 @@ static httpd_handle_t start_server(void) } httpd_uri_t u = {.uri = "/*", .method = HTTP_OPTIONS, .handler = api_cors_preflight}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/status", .method = HTTP_GET, .handler = api_status}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/nfc/poll", .method = HTTP_POST, .handler = api_nfc_poll}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/nfc/scan", .method = HTTP_POST, .handler = api_scan}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/pn532/general-status", .method = HTTP_GET, .handler = api_general_status}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/mifare/read-block", .method = HTTP_POST, .handler = api_mifare_read}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/mifare/write-block", .method = HTTP_POST, .handler = api_mifare_write}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/ul/read-page", .method = HTTP_POST, .handler = api_ul_read}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/ul/write-page", .method = HTTP_POST, .handler = api_ul_write}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/raw/pn532", .method = HTTP_POST, .handler = api_raw_pn532}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/ota", .method = HTTP_POST, .handler = api_ota_stub}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/session/export", .method = HTTP_GET, .handler = api_session_export}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/session/clear", .method = HTTP_POST, .handler = api_session_clear}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/session/deep", .method = HTTP_POST, .handler = api_session_deep}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/mifare/dictionary-attack", .method = HTTP_POST, .handler = api_mifare_dictionary_attack}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/api/nfc/emulate-raw", .method = HTTP_POST, .handler = api_nfc_emulate_raw}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/ws", .method = HTTP_GET, .handler = ws_handler, .is_websocket = true}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } u = (httpd_uri_t){.uri = "/*", .method = HTTP_GET, .handler = static_any}; - httpd_register_uri_handler(s, &u); + if (!register_uri_checked(s, &u)) { + httpd_stop(s); + return NULL; + } return s; } esp_err_t app_net_init(void) { - ESP_ERROR_CHECK(nvs_flash_init()); + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + err = nvs_flash_erase(); + if (err != ESP_OK) { + return err; + } + err = nvs_flash_init(); + } + if (err != ESP_OK) { + return err; + } - esp_netif_init(); - esp_event_loop_create_default(); - esp_netif_create_default_wifi_ap(); + err = esp_netif_init(); + if (err != ESP_OK) { + return err; + } + err = esp_event_loop_create_default(); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + return err; + } + esp_netif_t *ap_if = esp_netif_create_default_wifi_ap(); + if (!ap_if) { + return ESP_FAIL; + } + s_nfc_op_mu = xSemaphoreCreateMutex(); + if (!s_nfc_op_mu) { + return ESP_ERR_NO_MEM; + } wifi_init_config_t wcfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&wcfg)); + err = esp_wifi_init(&wcfg); + if (err != ESP_OK) { + return err; + } wifi_config_t ap = {0}; strncpy((char *)ap.ap.ssid, SOFTAP_SSID, sizeof(ap.ap.ssid)); ap.ap.ssid_len = (uint8_t)strlen(SOFTAP_SSID); ap.ap.channel = 6; ap.ap.max_connection = 8; ap.ap.authmode = WIFI_AUTH_OPEN; - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap)); - ESP_ERROR_CHECK(esp_wifi_start()); + err = esp_wifi_set_mode(WIFI_MODE_AP); + if (err != ESP_OK) { + return err; + } + err = esp_wifi_set_config(WIFI_IF_AP, &ap); + if (err != ESP_OK) { + return err; + } + err = esp_wifi_start(); + if (err != ESP_OK) { + return err; + } esp_vfs_spiffs_conf_t sp = { .base_path = "/spiffs", @@ -891,18 +1167,27 @@ esp_err_t app_net_init(void) .max_files = 16, .format_if_mount_failed = true, }; - ESP_ERROR_CHECK(esp_vfs_spiffs_register(&sp)); + err = esp_vfs_spiffs_register(&sp); + if (err != ESP_OK) { + return err; + } - mdns_init(); - mdns_hostname_set("pn532tool"); - mdns_instance_name_set("PN532 NFC Toolkit"); - mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0); + err = mdns_init(); + if (err == ESP_OK) { + (void)mdns_hostname_set("pn532tool"); + (void)mdns_instance_name_set("PN532 NFC Toolkit"); + (void)mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0); + } else { + ESP_LOGW(TAG, "mDNS init failed: %s", esp_err_to_name(err)); + } s_server = start_server(); if (!s_server) { return ESP_FAIL; } - xTaskCreate(scan_loop_task, "nfc_scan", 20480, NULL, 5, &s_scan_task); + if (xTaskCreate(scan_loop_task, "nfc_scan", 20480, NULL, 5, &s_scan_task) != pdPASS) { + return ESP_ERR_NO_MEM; + } return ESP_OK; } diff --git a/firmware/components/nfc_engine/include/nfc_engine/nfc_engine.h b/firmware/components/nfc_engine/include/nfc_engine/nfc_engine.h index c10d8a6..6a553d3 100644 --- a/firmware/components/nfc_engine/include/nfc_engine/nfc_engine.h +++ b/firmware/components/nfc_engine/include/nfc_engine/nfc_engine.h @@ -29,6 +29,9 @@ typedef struct { esp_err_t nfc_engine_init(void); esp_err_t nfc_poll_passive_target(nfc_tag_info_t *out); +bool nfc_tag_is_mifare_classic(const nfc_tag_info_t *tag); +bool nfc_tag_is_mifare_classic_4k(const nfc_tag_info_t *tag); +bool nfc_tag_is_type2(const nfc_tag_info_t *tag); esp_err_t nfc_mifare_authenticate_block(const nfc_tag_info_t *tag, uint8_t block_no, const nfc_mifare_key_t *key); diff --git a/firmware/components/nfc_engine/include/nfc_engine/session_capture.h b/firmware/components/nfc_engine/include/nfc_engine/session_capture.h index 15da6a5..ea3c1a6 100644 --- a/firmware/components/nfc_engine/include/nfc_engine/session_capture.h +++ b/firmware/components/nfc_engine/include/nfc_engine/session_capture.h @@ -25,7 +25,6 @@ bool session_capture_append_line(const char *line); /** Export raw bytes (entire buffer) for HTTP download. */ size_t session_capture_export_size(void); -const char *session_capture_export_ptr(void); /** Copy up to `cap` bytes (typically cap >= session_capture_export_size()). */ void session_capture_copy_to(char *dst, size_t cap, size_t *out_len); diff --git a/firmware/components/nfc_engine/nfc_brute.c b/firmware/components/nfc_engine/nfc_brute.c index c811c8a..ea83778 100644 --- a/firmware/components/nfc_engine/nfc_brute.c +++ b/firmware/components/nfc_engine/nfc_brute.c @@ -36,6 +36,27 @@ static const uint8_t k_builtin[][6] = { #define MAX_VARIANTS_PER_KEY 14 #define MAX_TRIES_BEFORE_WDT 48 +static bool add_sector_hit(cJSON *hits, uint8_t sector, const uint8_t key[6], const char *key_type) +{ + if (!hits || !key || !key_type) { + return false; + } + char hx[16]; + for (int i = 0; i < 6; i++) { + snprintf(hx + i * 2, 3, "%02X", key[i]); + } + hx[12] = 0; + cJSON *h = cJSON_CreateObject(); + if (!h) { + return false; + } + cJSON_AddNumberToObject(h, "sector", sector); + cJSON_AddStringToObject(h, "keyHex", hx); + cJSON_AddStringToObject(h, "keyType", key_type); + cJSON_AddItemToArray(hits, h); + return true; +} + static int push_variant(const uint8_t base[6], int idx, uint8_t out[6]) { memcpy(out, base, 6); @@ -76,7 +97,7 @@ static bool try_key_on_trailer(nfc_tag_info_t *tag, uint8_t trailer, const uint8 /** Trailer block for MIFARE Classic sector index (0..15 for 1K, 0..39 for 4K). */ static uint8_t classic_trailer_for_sector(const nfc_tag_info_t *tag, uint8_t sec) { - if (tag->sak == 0x19) { + if (nfc_tag_is_mifare_classic_4k(tag)) { if (sec <= 31) { return (uint8_t)(sec * 4 + 3); } @@ -102,7 +123,13 @@ cJSON *nfc_mifare_dictionary_attack(nfc_tag_info_t *tag, uint8_t sector_first, u return NULL; } - if (tag->type_hint != 1) { + if (!tag) { + cJSON_Delete(root); + cJSON_Delete(hits); + return NULL; + } + + if (!nfc_tag_is_mifare_classic(tag)) { cJSON_AddStringToObject(root, "error", "not_classic_sak_hint"); cJSON_AddItemToObject(root, "sectorHits", hits); if (attempts_out) { @@ -111,13 +138,22 @@ cJSON *nfc_mifare_dictionary_attack(nfc_tag_info_t *tag, uint8_t sector_first, u return root; } + uint8_t sector_max = nfc_tag_is_mifare_classic_4k(tag) ? 39 : 15; + if (sector_first > sector_last) { uint8_t t = sector_first; sector_first = sector_last; sector_last = t; } + if (sector_first > sector_max) { + sector_first = sector_max; + } + if (sector_last > sector_max) { + sector_last = sector_max; + } - for (uint8_t sec = sector_first; sec <= sector_last; sec++) { + for (int sec_i = sector_first; sec_i <= sector_last; sec_i++) { + uint8_t sec = (uint8_t)sec_i; uint8_t trailer = classic_trailer_for_sector(tag, sec); if (trailer == 0xFF) { continue; @@ -133,30 +169,18 @@ cJSON *nfc_mifare_dictionary_attack(nfc_tag_info_t *tag, uint8_t sector_first, u } attempts++; if (try_key_on_trailer(tag, trailer, trial, false)) { - char hx[16]; - for (int i = 0; i < 6; i++) { - snprintf(hx + i * 2, 3, "%02X", trial[i]); + if (!add_sector_hit(hits, sec, trial, "A")) { + cJSON_Delete(root); + return NULL; } - hx[12] = 0; - cJSON *h = cJSON_CreateObject(); - cJSON_AddNumberToObject(h, "sector", sec); - cJSON_AddStringToObject(h, "keyHex", hx); - cJSON_AddStringToObject(h, "keyType", "A"); - cJSON_AddItemToArray(hits, h); got = true; break; } if (try_key_on_trailer(tag, trailer, trial, true)) { - char hx[16]; - for (int i = 0; i < 6; i++) { - snprintf(hx + i * 2, 3, "%02X", trial[i]); + if (!add_sector_hit(hits, sec, trial, "B")) { + cJSON_Delete(root); + return NULL; } - hx[12] = 0; - cJSON *h = cJSON_CreateObject(); - cJSON_AddNumberToObject(h, "sector", sec); - cJSON_AddStringToObject(h, "keyHex", hx); - cJSON_AddStringToObject(h, "keyType", "B"); - cJSON_AddItemToArray(hits, h); got = true; break; } @@ -177,30 +201,18 @@ cJSON *nfc_mifare_dictionary_attack(nfc_tag_info_t *tag, uint8_t sector_first, u } attempts++; if (try_key_on_trailer(tag, trailer, trial, false)) { - char hx[16]; - for (int i = 0; i < 6; i++) { - snprintf(hx + i * 2, 3, "%02X", trial[i]); + if (!add_sector_hit(hits, sec, trial, "A")) { + cJSON_Delete(root); + return NULL; } - hx[12] = 0; - cJSON *h = cJSON_CreateObject(); - cJSON_AddNumberToObject(h, "sector", sec); - cJSON_AddStringToObject(h, "keyHex", hx); - cJSON_AddStringToObject(h, "keyType", "A"); - cJSON_AddItemToArray(hits, h); got = true; break; } if (try_key_on_trailer(tag, trailer, trial, true)) { - char hx[16]; - for (int i = 0; i < 6; i++) { - snprintf(hx + i * 2, 3, "%02X", trial[i]); + if (!add_sector_hit(hits, sec, trial, "B")) { + cJSON_Delete(root); + return NULL; } - hx[12] = 0; - cJSON *h = cJSON_CreateObject(); - cJSON_AddNumberToObject(h, "sector", sec); - cJSON_AddStringToObject(h, "keyHex", hx); - cJSON_AddStringToObject(h, "keyType", "B"); - cJSON_AddItemToArray(hits, h); got = true; break; } @@ -213,6 +225,10 @@ cJSON *nfc_mifare_dictionary_attack(nfc_tag_info_t *tag, uint8_t sector_first, u if (!got) { cJSON *h = cJSON_CreateObject(); + if (!h) { + cJSON_Delete(root); + return NULL; + } cJSON_AddNumberToObject(h, "sector", sec); cJSON_AddBoolToObject(h, "miss", true); cJSON_AddItemToArray(hits, h); diff --git a/firmware/components/nfc_engine/nfc_deep.c b/firmware/components/nfc_engine/nfc_deep.c index 477a862..a1504c6 100644 --- a/firmware/components/nfc_engine/nfc_deep.c +++ b/firmware/components/nfc_engine/nfc_deep.c @@ -9,6 +9,7 @@ static const char *TAG = "nfc_deep"; #define MAX_UL_PAGES 240 +#define DEFAULT_KEY_COUNT (sizeof(k_default_keys) / sizeof(k_default_keys[0])) static const uint8_t k_default_keys[][6] = { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, @@ -37,7 +38,7 @@ static void key_to_hex(const uint8_t k[6], char *out13) static bool mfc_sector_layout(const nfc_tag_info_t *tag, int sector, int *first_block, int *num_blocks, uint8_t *trailer_block) { - bool is4k = (tag->sak == 0x19); + bool is4k = nfc_tag_is_mifare_classic_4k(tag); if (!is4k) { if (sector < 0 || sector > 15) { return false; @@ -65,6 +66,9 @@ static bool mfc_sector_layout(const nfc_tag_info_t *tag, int sector, int *first_ static bool try_sector(nfc_tag_info_t *tag, int sector, cJSON *sec_out) { + if (!tag || !sec_out) { + return false; + } int fb = 0; int nb = 0; uint8_t trailer = 0; @@ -76,16 +80,19 @@ static bool try_sector(nfc_tag_info_t *tag, int sector, cJSON *sec_out) cJSON_AddNumberToObject(sec_out, "trailerBlock", trailer); cJSON_AddNumberToObject(sec_out, "blockCount", nb); - for (size_t ki = 0; ki < sizeof(k_default_keys) / 6; ki++) { + for (size_t ki = 0; ki < DEFAULT_KEY_COUNT; ki++) { nfc_mifare_key_t key; memcpy(key.key, k_default_keys[ki], 6); key.key_b = false; if (nfc_mifare_authenticate_block(tag, trailer, &key) == ESP_OK) { + cJSON *blocks = cJSON_CreateArray(); + if (!blocks) { + return false; + } cJSON_AddStringToObject(sec_out, "keyType", "A"); char kh[16]; key_to_hex(key.key, kh); cJSON_AddStringToObject(sec_out, "keyHex", kh); - cJSON *blocks = cJSON_CreateArray(); for (int b = 0; b < nb; b++) { uint8_t bn = (uint8_t)(fb + b); uint8_t blk[NFC_BLOCK_LEN]; @@ -102,11 +109,14 @@ static bool try_sector(nfc_tag_info_t *tag, int sector, cJSON *sec_out) } key.key_b = true; if (nfc_mifare_authenticate_block(tag, trailer, &key) == ESP_OK) { + cJSON *blocks = cJSON_CreateArray(); + if (!blocks) { + return false; + } cJSON_AddStringToObject(sec_out, "keyType", "B"); char kh[16]; key_to_hex(key.key, kh); cJSON_AddStringToObject(sec_out, "keyHex", kh); - cJSON *blocks = cJSON_CreateArray(); for (int b = 0; b < nb; b++) { uint8_t bn = (uint8_t)(fb + b); uint8_t blk[NFC_BLOCK_LEN]; @@ -128,10 +138,19 @@ static bool try_sector(nfc_tag_info_t *tag, int sector, cJSON *sec_out) static void add_mifare_classic(nfc_tag_info_t *tag, cJSON *root) { - int sectors = (tag->sak == 0x19) ? 40 : 16; + if (!tag || !root) { + return; + } + int sectors = nfc_tag_is_mifare_classic_4k(tag) ? 40 : 16; cJSON *arr = cJSON_CreateArray(); + if (!arr) { + return; + } for (int s = 0; s < sectors; s++) { cJSON *sec = cJSON_CreateObject(); + if (!sec) { + break; + } (void)try_sector(tag, s, sec); cJSON_AddItemToArray(arr, sec); } @@ -140,8 +159,14 @@ static void add_mifare_classic(nfc_tag_info_t *tag, cJSON *root) static void add_ultralight(nfc_tag_info_t *tag, cJSON *root) { + if (!root) { + return; + } (void)tag; cJSON *pages = cJSON_CreateArray(); + if (!pages) { + return; + } uint8_t buf[4]; for (int p = 0; p < MAX_UL_PAGES; p++) { if (nfc_ultralight_read_page((uint8_t)p, buf) != ESP_OK) { @@ -156,26 +181,24 @@ static void add_ultralight(nfc_tag_info_t *tag, cJSON *root) cJSON *nfc_tag_deep_profile(nfc_tag_info_t *tag) { + if (!tag) { + return NULL; + } cJSON *o = cJSON_CreateObject(); if (!o) { return NULL; } cJSON_AddNumberToObject(o, "capturedMs", (double)(esp_timer_get_time() / 1000)); - cJSON_AddItemToObject(o, "tag", nfc_tag_to_json(tag)); - - uint8_t gs[32]; - size_t gl = 0; - if (pn532_get_general_status(gs, sizeof(gs), &gl) == ESP_OK && gl > 0) { - cJSON *g = cJSON_CreateArray(); - for (size_t i = 0; i < gl; i++) { - cJSON_AddItemToArray(g, cJSON_CreateNumber(gs[i])); - } - cJSON_AddItemToObject(o, "pn532GeneralStatus", g); + cJSON *tag_json = nfc_tag_to_json(tag); + if (!tag_json) { + cJSON_Delete(o); + return NULL; } + cJSON_AddItemToObject(o, "tag", tag_json); - if (tag->type_hint == 1) { + if (nfc_tag_is_mifare_classic(tag)) { add_mifare_classic(tag, o); - } else if (tag->type_hint == 2) { + } else if (nfc_tag_is_type2(tag)) { add_ultralight(tag, o); } else { cJSON_AddStringToObject( diff --git a/firmware/components/nfc_engine/nfc_engine.c b/firmware/components/nfc_engine/nfc_engine.c index 963be46..d393628 100644 --- a/firmware/components/nfc_engine/nfc_engine.c +++ b/firmware/components/nfc_engine/nfc_engine.c @@ -3,6 +3,7 @@ #include "esp_log.h" #include #include +#include static const char *TAG = "nfc_engine"; @@ -12,20 +13,34 @@ static void hint_type(nfc_tag_info_t *t) { switch (t->sak) { case 0x08: - case 0x00: - t->type_hint = 2; - break; case 0x09: case 0x18: - case 0x19: t->type_hint = 1; break; + case 0x00: + t->type_hint = 2; + break; default: t->type_hint = 0; break; } } +bool nfc_tag_is_mifare_classic(const nfc_tag_info_t *tag) +{ + return tag && tag->type_hint == 1; +} + +bool nfc_tag_is_mifare_classic_4k(const nfc_tag_info_t *tag) +{ + return nfc_tag_is_mifare_classic(tag) && tag->sak == 0x18; +} + +bool nfc_tag_is_type2(const nfc_tag_info_t *tag) +{ + return tag && tag->type_hint == 2; +} + esp_err_t nfc_engine_init(void) { esp_err_t e = pn532_core_init(); @@ -48,6 +63,9 @@ esp_err_t nfc_engine_init(void) esp_err_t nfc_poll_passive_target(nfc_tag_info_t *out) { + if (!out) { + return ESP_ERR_INVALID_ARG; + } memset(out, 0, sizeof(*out)); uint8_t resp[64]; size_t rlen = 0; @@ -55,23 +73,23 @@ esp_err_t nfc_poll_passive_target(nfc_tag_info_t *out) if (e != ESP_OK) { return e; } - if (rlen < 2 || resp[0] != 0x00) { + if (rlen < 2) { return ESP_ERR_INVALID_RESPONSE; } - if (resp[1] < 1) { + if (resp[0] < 1) { return ESP_ERR_NOT_FOUND; } - if (rlen < 8) { + if (rlen < 7) { return ESP_ERR_INVALID_RESPONSE; } - s_tg = resp[2]; - out->atqa = (uint16_t)(((uint16_t)resp[3] << 8) | resp[4]); - out->sak = resp[5]; - out->uid_len = resp[6]; - if (out->uid_len > NFC_MAX_UID_LEN || (size_t)(7 + out->uid_len) > rlen) { + s_tg = resp[1]; + out->atqa = (uint16_t)(((uint16_t)resp[2] << 8) | resp[3]); + out->sak = resp[4]; + out->uid_len = resp[5]; + if (out->uid_len > NFC_MAX_UID_LEN || (size_t)(6 + out->uid_len) > rlen) { return ESP_ERR_INVALID_RESPONSE; } - memcpy(out->uid, resp + 7, out->uid_len); + memcpy(out->uid, resp + 6, out->uid_len); hint_type(out); return ESP_OK; } @@ -80,7 +98,7 @@ static esp_err_t in_data_tg(const uint8_t *data, size_t data_len, uint8_t *respo size_t *response_len) { uint8_t buf[64]; - if (data_len > sizeof(buf) - 3) { + if (!data || !response || !response_len || data_len == 0 || data_len > sizeof(buf) - 2) { return ESP_ERR_INVALID_SIZE; } buf[0] = PN532_CMD_INDATAEXCHANGE; @@ -92,6 +110,9 @@ static esp_err_t in_data_tg(const uint8_t *data, size_t data_len, uint8_t *respo esp_err_t nfc_mifare_authenticate_block(const nfc_tag_info_t *tag, uint8_t block_no, const nfc_mifare_key_t *key) { + if (!tag || !key) { + return ESP_ERR_INVALID_ARG; + } uint8_t data[12]; data[0] = key->key_b ? PN532_MIFARE_CMD_AUTH_B : PN532_MIFARE_CMD_AUTH_A; data[1] = block_no; @@ -113,7 +134,7 @@ esp_err_t nfc_mifare_authenticate_block(const nfc_tag_info_t *tag, uint8_t block if (e != ESP_OK) { return e; } - if (rlen < 1 || resp[0] != 0x00) { + if (rlen < 2 || resp[0] != (uint8_t)(PN532_CMD_INDATAEXCHANGE + 1) || resp[1] != 0x00) { return ESP_FAIL; } return ESP_OK; @@ -121,6 +142,9 @@ esp_err_t nfc_mifare_authenticate_block(const nfc_tag_info_t *tag, uint8_t block esp_err_t nfc_mifare_read_block(uint8_t block_no, uint8_t block[NFC_BLOCK_LEN]) { + if (!block) { + return ESP_ERR_INVALID_ARG; + } uint8_t d[] = {PN532_MIFARE_CMD_READ, block_no}; uint8_t resp[32]; size_t rlen = 0; @@ -128,15 +152,18 @@ esp_err_t nfc_mifare_read_block(uint8_t block_no, uint8_t block[NFC_BLOCK_LEN]) if (e != ESP_OK) { return e; } - if (rlen < 1 + NFC_BLOCK_LEN || resp[0] != 0x00) { + if (rlen < 2 + NFC_BLOCK_LEN || resp[0] != (uint8_t)(PN532_CMD_INDATAEXCHANGE + 1) || resp[1] != 0x00) { return ESP_ERR_INVALID_RESPONSE; } - memcpy(block, resp + 1, NFC_BLOCK_LEN); + memcpy(block, resp + 2, NFC_BLOCK_LEN); return ESP_OK; } esp_err_t nfc_mifare_write_block(uint8_t block_no, const uint8_t block[NFC_BLOCK_LEN]) { + if (!block) { + return ESP_ERR_INVALID_ARG; + } uint8_t d[2 + NFC_BLOCK_LEN]; d[0] = PN532_MIFARE_CMD_WRITE; d[1] = block_no; @@ -147,7 +174,7 @@ esp_err_t nfc_mifare_write_block(uint8_t block_no, const uint8_t block[NFC_BLOCK if (e != ESP_OK) { return e; } - if (rlen < 1 || resp[0] != 0x00) { + if (rlen < 2 || resp[0] != (uint8_t)(PN532_CMD_INDATAEXCHANGE + 1) || resp[1] != 0x00) { return ESP_FAIL; } return ESP_OK; @@ -155,6 +182,9 @@ esp_err_t nfc_mifare_write_block(uint8_t block_no, const uint8_t block[NFC_BLOCK esp_err_t nfc_ultralight_read_page(uint8_t page, uint8_t data[4]) { + if (!data) { + return ESP_ERR_INVALID_ARG; + } uint8_t d[] = {PN532_MIFARE_CMD_READ, page}; uint8_t resp[32]; size_t rlen = 0; @@ -162,15 +192,18 @@ esp_err_t nfc_ultralight_read_page(uint8_t page, uint8_t data[4]) if (e != ESP_OK) { return e; } - if (rlen < 1 + 16 || resp[0] != 0x00) { + if (rlen < 2 + 16 || resp[0] != (uint8_t)(PN532_CMD_INDATAEXCHANGE + 1) || resp[1] != 0x00) { return ESP_ERR_INVALID_RESPONSE; } - memcpy(data, resp + 1, 4); + memcpy(data, resp + 2, 4); return ESP_OK; } esp_err_t nfc_ultralight_write_page(uint8_t page, const uint8_t data[4]) { + if (!data) { + return ESP_ERR_INVALID_ARG; + } uint8_t d[6] = {0xA2, page, data[0], data[1], data[2], data[3]}; uint8_t resp[16]; size_t rlen = 0; @@ -178,7 +211,7 @@ esp_err_t nfc_ultralight_write_page(uint8_t page, const uint8_t data[4]) if (e != ESP_OK) { return e; } - if (rlen < 1 || resp[0] != 0x00) { + if (rlen < 2 || resp[0] != (uint8_t)(PN532_CMD_INDATAEXCHANGE + 1) || resp[1] != 0x00) { return ESP_FAIL; } return ESP_OK; @@ -186,30 +219,40 @@ esp_err_t nfc_ultralight_write_page(uint8_t page, const uint8_t data[4]) esp_err_t nfc_ul_fast_read(uint8_t start_page, uint8_t *out, size_t out_max, size_t *got) { + if (!out || !got || out_max == 0) { + return ESP_ERR_INVALID_ARG; + } *got = 0; - size_t off = 0; - uint8_t d[2] = {0x3A, start_page}; + size_t max_pages = MAX((size_t)1, MIN((size_t)16, out_max / 4)); + size_t remaining_pages = 256U - (size_t)start_page; + if (max_pages > remaining_pages) { + max_pages = remaining_pages; + } + uint8_t end_page = (uint8_t)(start_page + max_pages - 1); + uint8_t d[3] = {0x3A, start_page, end_page}; uint8_t resp[256]; size_t rlen = 0; esp_err_t e = in_data_tg(d, sizeof(d), resp, sizeof(resp), &rlen); if (e != ESP_OK) { return e; } - if (rlen < 2 || resp[0] != 0x00) { + if (rlen < 2 || resp[0] != (uint8_t)(PN532_CMD_INDATAEXCHANGE + 1) || resp[1] != 0x00) { return ESP_ERR_INVALID_RESPONSE; } - size_t payload = rlen - 1; + size_t payload = rlen - 2; if (payload > out_max) { payload = out_max; } - memcpy(out, resp + 1, payload); - off = payload; - *got = off; + memcpy(out, resp + 2, payload); + *got = payload; return ESP_OK; } cJSON *nfc_tag_to_json(const nfc_tag_info_t *tag) { + if (!tag || tag->uid_len > NFC_MAX_UID_LEN) { + return NULL; + } cJSON *o = cJSON_CreateObject(); if (!o) { return NULL; @@ -233,9 +276,9 @@ cJSON *nfc_tag_to_json(const nfc_tag_info_t *tag) cJSON_AddStringToObject(o, "sakHex", sk); const char *guess = "Unknown / use Raw or RATS"; - if (tag->type_hint == 1) { - guess = (tag->sak == 0x19) ? "MIFARE Classic 4K" : "MIFARE Classic 1K or compatible"; - } else if (tag->type_hint == 2) { + if (nfc_tag_is_mifare_classic(tag)) { + guess = nfc_tag_is_mifare_classic_4k(tag) ? "MIFARE Classic 4K" : "MIFARE Classic 1K or compatible"; + } else if (nfc_tag_is_type2(tag)) { guess = "Ultralight / NTAG / Type 2 family"; } cJSON_AddStringToObject(o, "typeGuess", guess); diff --git a/firmware/components/nfc_engine/session_capture.c b/firmware/components/nfc_engine/session_capture.c index 7390e3d..4f0d753 100644 --- a/firmware/components/nfc_engine/session_capture.c +++ b/firmware/components/nfc_engine/session_capture.c @@ -35,12 +35,40 @@ void session_capture_clear(void) bool session_capture_is_full(void) { - return s_full; + bool full = false; + if (s_mu) { + xSemaphoreTake(s_mu, portMAX_DELAY); + } + full = s_full; + if (s_mu) { + xSemaphoreGive(s_mu); + } + return full; } -bool session_capture_deep_enabled(void) { return s_deep; } +bool session_capture_deep_enabled(void) +{ + bool deep = false; + if (s_mu) { + xSemaphoreTake(s_mu, portMAX_DELAY); + } + deep = s_deep; + if (s_mu) { + xSemaphoreGive(s_mu); + } + return deep; +} -void session_capture_set_deep(bool on) { s_deep = on; } +void session_capture_set_deep(bool on) +{ + if (s_mu) { + xSemaphoreTake(s_mu, portMAX_DELAY); + } + s_deep = on; + if (s_mu) { + xSemaphoreGive(s_mu); + } +} size_t session_capture_max(void) { return sizeof(s_buf) - 2; } @@ -65,7 +93,7 @@ void session_capture_get_status(size_t *used_bytes, uint32_t *line_count, bool * bool session_capture_append_line(const char *line) { - if (!line || s_full) { + if (!line) { return false; } size_t l = strlen(line); @@ -106,8 +134,6 @@ size_t session_capture_export_size(void) return n; } -const char *session_capture_export_ptr(void) { return s_buf; } - void session_capture_copy_to(char *dst, size_t cap, size_t *out_len) { if (s_mu) { diff --git a/firmware/components/pn532_host/pn532_core.c b/firmware/components/pn532_host/pn532_core.c index b778e65..8199644 100644 --- a/firmware/components/pn532_host/pn532_core.c +++ b/firmware/components/pn532_host/pn532_core.c @@ -1,10 +1,7 @@ #include "pn532_host/pn532_core.h" #include "pn532_host/pn532_transport.h" -#include "esp_log.h" #include -static const char *TAG = "pn532_core"; - esp_err_t pn532_send_cmd(const uint8_t *cmd_and_data, size_t len, uint8_t *response, size_t response_max, size_t *response_len, int timeout_ms) { @@ -21,9 +18,6 @@ esp_err_t pn532_send_cmd(const uint8_t *cmd_and_data, size_t len, uint8_t *respo if (*response_len < 1) { return ESP_ERR_INVALID_RESPONSE; } - if (response[0] != 0x00) { - ESP_LOGW(TAG, "chip status 0x%02x", response[0]); - } return ESP_OK; } @@ -34,6 +28,9 @@ esp_err_t pn532_core_init(void) esp_err_t pn532_get_firmware_version(uint8_t *ic_ver, uint8_t *fw_ver_hi, uint8_t *fw_ver_lo) { + if (!ic_ver || !fw_ver_hi || !fw_ver_lo) { + return ESP_ERR_INVALID_ARG; + } uint8_t cmd = PN532_CMD_GETFIRMWAREVERSION; uint8_t resp[16]; size_t rlen = 0; @@ -41,7 +38,7 @@ esp_err_t pn532_get_firmware_version(uint8_t *ic_ver, uint8_t *fw_ver_hi, uint8_ if (e != ESP_OK) { return e; } - if (rlen < 4) { + if (rlen < 5 || resp[0] != (uint8_t)(PN532_CMD_GETFIRMWAREVERSION + 1)) { return ESP_ERR_INVALID_RESPONSE; } *ic_ver = resp[1]; @@ -55,13 +52,36 @@ esp_err_t pn532_sam_config_normal(void) uint8_t buf[] = {PN532_CMD_SAMCONFIGURATION, 0x01, 0x14, 0x01}; uint8_t resp[8]; size_t rlen = 0; - return pn532_send_cmd(buf, sizeof(buf), resp, sizeof(resp), &rlen, 200); + esp_err_t e = pn532_send_cmd(buf, sizeof(buf), resp, sizeof(resp), &rlen, 200); + if (e != ESP_OK) { + return e; + } + return (rlen >= 1 && resp[0] == (uint8_t)(PN532_CMD_SAMCONFIGURATION + 1)) ? ESP_OK + : ESP_ERR_INVALID_RESPONSE; } esp_err_t pn532_get_general_status(uint8_t *buf, size_t buf_len, size_t *out_len) { + if (!buf || !out_len) { + return ESP_ERR_INVALID_ARG; + } uint8_t cmd = PN532_CMD_GETGENERALSTATUS; - return pn532_send_cmd(&cmd, 1, buf, buf_len, out_len, 200); + uint8_t resp[32]; + size_t rlen = 0; + esp_err_t e = pn532_send_cmd(&cmd, 1, resp, sizeof(resp), &rlen, 200); + if (e != ESP_OK) { + return e; + } + if (rlen < 2 || resp[0] != (uint8_t)(PN532_CMD_GETGENERALSTATUS + 1)) { + return ESP_ERR_INVALID_RESPONSE; + } + size_t payload_len = rlen - 1; + if (payload_len > buf_len) { + return ESP_ERR_INVALID_SIZE; + } + memcpy(buf, resp + 1, payload_len); + *out_len = payload_len; + return ESP_OK; } esp_err_t pn532_rf_field(bool on) @@ -69,7 +89,12 @@ esp_err_t pn532_rf_field(bool on) uint8_t buf[] = {PN532_CMD_RFCONFIGURATION, 0x01, on ? 0x01 : 0x00}; uint8_t resp[8]; size_t rlen = 0; - return pn532_send_cmd(buf, sizeof(buf), resp, sizeof(resp), &rlen, 200); + esp_err_t e = pn532_send_cmd(buf, sizeof(buf), resp, sizeof(resp), &rlen, 200); + if (e != ESP_OK) { + return e; + } + return (rlen >= 1 && resp[0] == (uint8_t)(PN532_CMD_RFCONFIGURATION + 1)) ? ESP_OK + : ESP_ERR_INVALID_RESPONSE; } esp_err_t pn532_rf_max_retries(void) @@ -78,37 +103,90 @@ esp_err_t pn532_rf_max_retries(void) uint8_t buf[] = {PN532_CMD_RFCONFIGURATION, 0x05, 0xFF, 0xFF, 0xFF}; uint8_t resp[8]; size_t rlen = 0; - return pn532_send_cmd(buf, sizeof(buf), resp, sizeof(resp), &rlen, 200); + esp_err_t e = pn532_send_cmd(buf, sizeof(buf), resp, sizeof(resp), &rlen, 200); + if (e != ESP_OK) { + return e; + } + return (rlen >= 1 && resp[0] == (uint8_t)(PN532_CMD_RFCONFIGURATION + 1)) ? ESP_OK + : ESP_ERR_INVALID_RESPONSE; } esp_err_t pn532_in_list_passive_target(uint8_t max_targets, uint8_t baud, uint8_t *response, size_t response_max, size_t *response_len) { + if (!response || !response_len) { + return ESP_ERR_INVALID_ARG; + } uint8_t buf[] = {PN532_CMD_INLISTPASSIVETARGET, max_targets, baud}; - return pn532_send_cmd(buf, sizeof(buf), response, response_max, response_len, 500); + uint8_t raw[64]; + size_t raw_len = 0; + esp_err_t e = pn532_send_cmd(buf, sizeof(buf), raw, sizeof(raw), &raw_len, 500); + if (e != ESP_OK) { + return e; + } + if (raw_len < 2 || raw[0] != (uint8_t)(PN532_CMD_INLISTPASSIVETARGET + 1)) { + return ESP_ERR_INVALID_RESPONSE; + } + size_t payload_len = raw_len - 1; + if (payload_len > response_max) { + return ESP_ERR_INVALID_SIZE; + } + memcpy(response, raw + 1, payload_len); + *response_len = payload_len; + return ESP_OK; } esp_err_t pn532_in_data_exchange(const uint8_t *data, size_t data_len, uint8_t *response, size_t response_max, size_t *response_len) { - if (!data || data_len == 0 || data_len > PN532_EEPROM_MAX_CMD_PAYLOAD - 1) { + if (!data || !response || !response_len || data_len == 0 || data_len > PN532_EEPROM_MAX_CMD_PAYLOAD - 2) { return ESP_ERR_INVALID_ARG; } - uint8_t buf[PN532_EEPROM_MAX_CMD_PAYLOAD + 1]; + uint8_t buf[PN532_EEPROM_MAX_CMD_PAYLOAD]; buf[0] = PN532_CMD_INDATAEXCHANGE; buf[1] = 0x01; /* logical target 1 */ memcpy(buf + 2, data, data_len); - return pn532_send_cmd(buf, 2 + data_len, response, response_max, response_len, 500); + uint8_t raw[PN532_EEPROM_MAX_CMD_PAYLOAD]; + size_t raw_len = 0; + esp_err_t e = pn532_send_cmd(buf, 2 + data_len, raw, sizeof(raw), &raw_len, 500); + if (e != ESP_OK) { + return e; + } + if (raw_len < 2 || raw[0] != (uint8_t)(PN532_CMD_INDATAEXCHANGE + 1)) { + return ESP_ERR_INVALID_RESPONSE; + } + size_t payload_len = raw_len - 1; + if (payload_len > response_max) { + return ESP_ERR_INVALID_SIZE; + } + memcpy(response, raw + 1, payload_len); + *response_len = payload_len; + return ESP_OK; } esp_err_t pn532_in_communicate_thru(const uint8_t *data, size_t data_len, uint8_t *response, size_t response_max, size_t *response_len) { - if (!data || data_len > PN532_EEPROM_MAX_CMD_PAYLOAD - 1) { + if (!data || !response || !response_len || data_len > PN532_EEPROM_MAX_CMD_PAYLOAD - 1) { return ESP_ERR_INVALID_ARG; } - uint8_t buf[PN532_EEPROM_MAX_CMD_PAYLOAD + 1]; + uint8_t buf[PN532_EEPROM_MAX_CMD_PAYLOAD]; buf[0] = PN532_CMD_INCOMMUNICATETHRU; memcpy(buf + 1, data, data_len); - return pn532_send_cmd(buf, 1 + data_len, response, response_max, response_len, 500); + uint8_t raw[PN532_EEPROM_MAX_CMD_PAYLOAD]; + size_t raw_len = 0; + esp_err_t e = pn532_send_cmd(buf, 1 + data_len, raw, sizeof(raw), &raw_len, 500); + if (e != ESP_OK) { + return e; + } + if (raw_len < 2 || raw[0] != (uint8_t)(PN532_CMD_INCOMMUNICATETHRU + 1)) { + return ESP_ERR_INVALID_RESPONSE; + } + size_t payload_len = raw_len - 1; + if (payload_len > response_max) { + return ESP_ERR_INVALID_SIZE; + } + memcpy(response, raw + 1, payload_len); + *response_len = payload_len; + return ESP_OK; } diff --git a/firmware/components/pn532_host/pn532_transport.c b/firmware/components/pn532_host/pn532_transport.c index 4c9d6ea..b61073a 100644 --- a/firmware/components/pn532_host/pn532_transport.c +++ b/firmware/components/pn532_host/pn532_transport.c @@ -5,6 +5,7 @@ #include "driver/i2c.h" #include "driver/spi_master.h" #include "driver/uart.h" +#include "esp_check.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" @@ -12,6 +13,7 @@ #include #define PN532_HOST_TO_PN532 0xD4 +#define PN532_PN532_TO_HOST 0xD5 #define PN532_TXBUF_MAX 264 static const char *TAG = "pn532_xport"; @@ -34,13 +36,20 @@ static esp_err_t spi_wait_ready(int timeout_ms) uint8_t status = 0; const int64_t end = esp_timer_get_time() / 1000 + timeout_ms; while ((esp_timer_get_time() / 1000) < (uint64_t)end) { - spi_transaction_t t = {}; - uint8_t tx = 0x02; /* SPIstatus read */ - t.length = 8; - t.tx_buffer = &tx; - t.rx_buffer = &status; gpio_set_level(s_spi_cs_gpio, 0); - esp_err_t e = spi_device_polling_transmit(s_spi, &t); + uint8_t cmd = 0x02; /* Status read */ + spi_transaction_t t_cmd = {}; + t_cmd.length = 8; + t_cmd.tx_buffer = &cmd; + esp_err_t e = spi_device_polling_transmit(s_spi, &t_cmd); + if (e == ESP_OK) { + uint8_t tx = 0x00; + spi_transaction_t t_status = {}; + t_status.length = 8; + t_status.tx_buffer = &tx; + t_status.rx_buffer = &status; + e = spi_device_polling_transmit(s_spi, &t_status); + } gpio_set_level(s_spi_cs_gpio, 1); if (e != ESP_OK) { return e; @@ -58,7 +67,7 @@ static esp_err_t spi_write_frame(const uint8_t *data, size_t len) ESP_RETURN_ON_ERROR(spi_wait_ready(200), TAG, "wait before write"); gpio_set_level(s_spi_cs_gpio, 0); vTaskDelay(pdMS_TO_TICKS(2)); - uint8_t hdr = 0x04; /* Data write */ + uint8_t hdr = 0x01; /* Data write */ spi_transaction_t t0 = {}; t0.length = 8; t0.tx_buffer = &hdr; @@ -126,6 +135,9 @@ static esp_err_t i2c_write_raw(const uint8_t *buf, size_t len) static esp_err_t i2c_read_raw(uint8_t *buf, size_t len) { + if (!buf || len == 0) { + return ESP_ERR_INVALID_ARG; + } i2c_cmd_handle_t c = i2c_cmd_link_create(); i2c_master_start(c); i2c_master_write_byte(c, (CONFIG_PN532_I2C_ADDR << 1) | I2C_MASTER_READ, true); @@ -139,6 +151,37 @@ static esp_err_t i2c_read_raw(uint8_t *buf, size_t len) return e; } +static esp_err_t i2c_read_frame(uint8_t *buf, size_t len) +{ + if (!buf || len == 0) { + return ESP_ERR_INVALID_ARG; + } + uint8_t raw[272]; + if (len + 1 > sizeof(raw)) { + return ESP_ERR_INVALID_SIZE; + } + ESP_RETURN_ON_ERROR(i2c_read_raw(raw, len + 1), TAG, "i2c read"); + if (raw[0] != 0x01) { + ESP_LOGW(TAG, "unexpected i2c status 0x%02x", raw[0]); + return ESP_ERR_INVALID_RESPONSE; + } + memcpy(buf, raw + 1, len); + return ESP_OK; +} + +static esp_err_t i2c_wait_ready(int timeout_ms) +{ + int64_t t0 = esp_timer_get_time() / 1000; + while (((esp_timer_get_time() / 1000) - t0) < timeout_ms) { + uint8_t status = 0; + if (i2c_read_raw(&status, 1) == ESP_OK && status == 0x01) { + return ESP_OK; + } + vTaskDelay(pdMS_TO_TICKS(2)); + } + return ESP_ERR_TIMEOUT; +} + #elif defined(CONFIG_PN532_TRANSPORT_HSU) #define PN532_UART ((uart_port_t)CONFIG_PN532_HSU_UART_NUM) @@ -177,8 +220,8 @@ static esp_err_t read_ack(int timeout_ms) #if defined(CONFIG_PN532_TRANSPORT_SPI) ESP_RETURN_ON_ERROR(spi_read_bytes(ack, sizeof(ack)), TAG, "read ack spi"); #elif defined(CONFIG_PN532_TRANSPORT_I2C) - vTaskDelay(pdMS_TO_TICKS(5)); - ESP_RETURN_ON_ERROR(i2c_read_raw(ack, sizeof(ack)), TAG, "read ack i2c"); + ESP_RETURN_ON_ERROR(i2c_wait_ready(timeout_ms), TAG, "wait ack i2c"); + ESP_RETURN_ON_ERROR(i2c_read_frame(ack, sizeof(ack)), TAG, "read ack i2c"); #elif defined(CONFIG_PN532_TRANSPORT_HSU) ESP_RETURN_ON_ERROR(hsu_read_raw(ack, sizeof(ack), timeout_ms), TAG, "read ack hsu"); #endif @@ -191,67 +234,75 @@ static esp_err_t read_ack(int timeout_ms) static esp_err_t read_response_frame(uint8_t *body_out, size_t body_max, size_t *body_len, int timeout_ms) { - uint8_t hdr[8]; -#if defined(CONFIG_PN532_TRANSPORT_SPI) - ESP_RETURN_ON_ERROR(spi_read_bytes(hdr, 6), TAG, "hdr spi"); -#elif defined(CONFIG_PN532_TRANSPORT_I2C) - { - int64_t t0 = esp_timer_get_time() / 1000; - bool ok = false; - while (((esp_timer_get_time() / 1000) - t0) < timeout_ms) { - uint8_t peek[1]; - if (i2c_read_raw(peek, 1) == ESP_OK && peek[0] == 0x01) { - ok = true; - break; - } - vTaskDelay(pdMS_TO_TICKS(2)); - } - if (!ok) { - return ESP_ERR_TIMEOUT; - } - ESP_RETURN_ON_ERROR(i2c_read_raw(hdr, 6), TAG, "hdr i2c"); + if (!body_out || !body_len) { + return ESP_ERR_INVALID_ARG; } + uint8_t hdr[8]; + size_t frame_len = 0; +#if defined(CONFIG_PN532_TRANSPORT_SPI) + ESP_RETURN_ON_ERROR(spi_read_bytes(hdr, 5), TAG, "hdr spi"); +#elif defined(CONFIG_PN532_TRANSPORT_I2C) + ESP_RETURN_ON_ERROR(i2c_wait_ready(timeout_ms), TAG, "wait frame i2c"); + ESP_RETURN_ON_ERROR(i2c_read_frame(hdr, 5), TAG, "hdr i2c"); #elif defined(CONFIG_PN532_TRANSPORT_HSU) - ESP_RETURN_ON_ERROR(hsu_read_raw(hdr, 6, timeout_ms), TAG, "hdr hsu"); + ESP_RETURN_ON_ERROR(hsu_read_raw(hdr, 5, timeout_ms), TAG, "hdr hsu"); #endif if (hdr[0] != 0x00 || hdr[1] != 0x00 || hdr[2] != 0xFF) { - ESP_LOG_BUFFER_HEX_LEVEL(TAG, hdr, 6, ESP_LOG_WARN); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, hdr, 5, ESP_LOG_WARN); return ESP_ERR_INVALID_RESPONSE; } - uint16_t L = (uint16_t)(hdr[3] * 256 + hdr[4]); - uint8_t lcs = hdr[5]; - if ((uint8_t)((hdr[3] + hdr[4] + lcs) & 0xFF) != 0) { - return ESP_ERR_INVALID_CRC; + + if (hdr[3] == 0xFF && hdr[4] == 0xFF) { +#if defined(CONFIG_PN532_TRANSPORT_SPI) + ESP_RETURN_ON_ERROR(spi_read_bytes(hdr + 5, 3), TAG, "hdr ext spi"); +#elif defined(CONFIG_PN532_TRANSPORT_I2C) + ESP_RETURN_ON_ERROR(i2c_read_frame(hdr + 5, 3), TAG, "hdr ext i2c"); +#elif defined(CONFIG_PN532_TRANSPORT_HSU) + ESP_RETURN_ON_ERROR(hsu_read_raw(hdr + 5, 3, timeout_ms), TAG, "hdr ext hsu"); +#endif + frame_len = (size_t)(((uint16_t)hdr[5] << 8) | hdr[6]); + if ((uint8_t)(hdr[5] + hdr[6] + hdr[7]) != 0) { + return ESP_ERR_INVALID_CRC; + } + } else { + frame_len = hdr[3]; + if ((uint8_t)(hdr[3] + hdr[4]) != 0) { + return ESP_ERR_INVALID_CRC; + } } - if (L < 2) { + + if (frame_len < 2) { return ESP_ERR_INVALID_SIZE; } - /* Read TFI..data (L bytes) + DCS — L includes TFI through last payload byte */ - const size_t read_total = (size_t)L + 1; - if (read_total > 270) { + + const size_t read_total = frame_len + 2; + if (read_total > 272) { return ESP_ERR_INVALID_SIZE; } uint8_t chunk[272]; #if defined(CONFIG_PN532_TRANSPORT_SPI) ESP_RETURN_ON_ERROR(spi_read_bytes(chunk, read_total), TAG, "payload spi"); #elif defined(CONFIG_PN532_TRANSPORT_I2C) - ESP_RETURN_ON_ERROR(i2c_read_raw(chunk, read_total), TAG, "payload i2c"); + ESP_RETURN_ON_ERROR(i2c_read_frame(chunk, read_total), TAG, "payload i2c"); #elif defined(CONFIG_PN532_TRANSPORT_HSU) ESP_RETURN_ON_ERROR(hsu_read_raw(chunk, read_total, timeout_ms), TAG, "payload hsu"); #endif - uint8_t tfi = chunk[0]; - if (tfi != 0xD5) { + + if (chunk[0] != PN532_PN532_TO_HOST) { return ESP_ERR_INVALID_RESPONSE; } uint8_t sum = 0; - for (uint16_t i = 0; i < L; i++) { + for (size_t i = 0; i < frame_len; i++) { sum += chunk[i]; } - uint8_t dcs = chunk[L]; - if ((uint8_t)((sum + dcs) & 0xFF) != 0) { + if ((uint8_t)(sum + chunk[frame_len]) != 0) { return ESP_ERR_INVALID_CRC; } - *body_len = (size_t)L - 1; + if (chunk[frame_len + 1] != 0x00) { + return ESP_ERR_INVALID_RESPONSE; + } + + *body_len = frame_len - 1; if (*body_len > body_max) { return ESP_ERR_INVALID_SIZE; } @@ -262,29 +313,41 @@ static esp_err_t read_response_frame(uint8_t *body_out, size_t body_max, size_t esp_err_t pn532_transport_exchange(const uint8_t *tx_body, size_t tx_body_len, uint8_t *rx_body, size_t rx_body_max, size_t *rx_body_len, int timeout_ms) { - if (tx_body_len == 0 || tx_body_len > 255) { + if (!tx_body || !rx_body || !rx_body_len) { return ESP_ERR_INVALID_ARG; } - uint16_t L = (uint16_t)(1 + tx_body_len); - uint8_t lcs = (uint8_t)(0x100 - (uint8_t)(((L >> 8) + (L & 0xFF)) & 0xFF)); + if (tx_body_len == 0 || tx_body_len > 254) { + return ESP_ERR_INVALID_ARG; + } + size_t frame_len = 1 + tx_body_len; uint8_t sum = PN532_HOST_TO_PN532; for (size_t i = 0; i < tx_body_len; i++) { sum += tx_body[i]; } - dcs = (uint8_t)(256 - sum); + uint8_t dcs = (uint8_t)(0x100 - sum); uint8_t frame[PN532_TXBUF_MAX]; size_t pos = 0; frame[pos++] = 0x00; frame[pos++] = 0x00; frame[pos++] = 0xFF; - frame[pos++] = (uint8_t)((L >> 8) & 0xFF); - frame[pos++] = (uint8_t)(L & 0xFF); - frame[pos++] = lcs; + if (frame_len <= 254) { + uint8_t lcs = (uint8_t)(0x100 - (uint8_t)frame_len); + frame[pos++] = (uint8_t)frame_len; + frame[pos++] = lcs; + } else { + uint16_t ext_len = (uint16_t)frame_len; + frame[pos++] = 0xFF; + frame[pos++] = 0xFF; + frame[pos++] = (uint8_t)((ext_len >> 8) & 0xFF); + frame[pos++] = (uint8_t)(ext_len & 0xFF); + frame[pos++] = (uint8_t)(0x100 - (uint8_t)(((ext_len >> 8) + (ext_len & 0xFF)) & 0xFF)); + } frame[pos++] = PN532_HOST_TO_PN532; memcpy(frame + pos, tx_body, tx_body_len); pos += tx_body_len; frame[pos++] = dcs; + frame[pos++] = 0x00; #if defined(CONFIG_PN532_TRANSPORT_SPI) ESP_RETURN_ON_ERROR(spi_write_frame(frame, pos), TAG, "spi wr"); @@ -354,8 +417,3 @@ esp_err_t pn532_transport_init(void) #endif return ESP_OK; } - -Fixing a typo in `pn532_transport.c` and correcting the DCS checksum calculation. - -<|tool▁calls▁begin|><|tool▁call▁begin|> -Read \ No newline at end of file diff --git a/firmware/data/assets/index-EAAhhled.js b/firmware/data/assets/index-9oJp152C.js similarity index 91% rename from firmware/data/assets/index-EAAhhled.js rename to firmware/data/assets/index-9oJp152C.js index d1131fb..a781585 100644 --- a/firmware/data/assets/index-EAAhhled.js +++ b/firmware/data/assets/index-9oJp152C.js @@ -72,7 +72,7 @@ Error generating stack: `+i.message+` top: ${l}px !important; left: ${u}px !important; } - `),()=>{document.head.removeChild(c)}},[t]),d.jsx(wx,{isPresent:t,childRef:r,sizeRef:s,children:x.cloneElement(e,{ref:r})})}const bx=({children:e,initial:t,isPresent:n,onExitComplete:r,custom:s,presenceAffectsLayout:i,mode:o})=>{const a=cu(kx),l=x.useId(),u=x.useCallback(f=>{a.set(f,!0);for(const h of a.values())if(!h)return;r&&r()},[a,r]),c=x.useMemo(()=>({id:l,initial:t,isPresent:n,custom:s,onExitComplete:u,register:f=>(a.set(f,!1),()=>a.delete(f))}),i?[Math.random(),u]:[n,u]);return x.useMemo(()=>{a.forEach((f,h)=>a.set(h,!1))},[n]),x.useEffect(()=>{!n&&!a.size&&r&&r()},[n]),o==="popLayout"&&(e=d.jsx(Sx,{isPresent:n,children:e})),d.jsx(io.Provider,{value:c,children:e})};function kx(){return new Map}function im(e=!0){const t=x.useContext(io);if(t===null)return[!0,null];const{isPresent:n,onExitComplete:r,register:s}=t,i=x.useId();x.useEffect(()=>{e&&s(i)},[e]);const o=x.useCallback(()=>e&&r&&r(i),[i,r,e]);return!n&&r?[!1,o]:[!0]}const Us=e=>e.key||"";function cd(e){const t=[];return x.Children.forEach(e,n=>{x.isValidElement(n)&&t.push(n)}),t}const fu=typeof window<"u",om=fu?x.useLayoutEffect:x.useEffect,am=({children:e,custom:t,initial:n=!0,onExitComplete:r,presenceAffectsLayout:s=!0,mode:i="sync",propagate:o=!1})=>{const[a,l]=im(o),u=x.useMemo(()=>cd(e),[e]),c=o&&!a?[]:u.map(Us),f=x.useRef(!0),h=x.useRef(u),g=cu(()=>new Map),[v,w]=x.useState(u),[S,m]=x.useState(u);om(()=>{f.current=!1,h.current=u;for(let b=0;b{const k=Us(b),C=o&&!a?!1:u===S||c.includes(k),E=()=>{if(g.has(k))g.set(k,!0);else return;let P=!0;g.forEach(F=>{F||(P=!1)}),P&&(y==null||y(),m(h.current),o&&(l==null||l()),r&&r())};return d.jsx(bx,{isPresent:C,initial:!f.current||n?void 0:!1,custom:C?void 0:t,presenceAffectsLayout:s,mode:i,onExitComplete:C?void 0:E,children:b},k)})})},Ae=e=>e;let lm=Ae;function hu(e){let t;return()=>(t===void 0&&(t=e()),t)}const Jn=(e,t,n)=>{const r=t-e;return r===0?1:(n-e)/r},dt=e=>e*1e3,ft=e=>e/1e3,Cx={useManualTiming:!1};function Px(e){let t=new Set,n=new Set,r=!1,s=!1;const i=new WeakSet;let o={delta:0,timestamp:0,isProcessing:!1};function a(u){i.has(u)&&(l.schedule(u),e()),u(o)}const l={schedule:(u,c=!1,f=!1)=>{const g=f&&r?t:n;return c&&i.add(u),g.has(u)||g.add(u),u},cancel:u=>{n.delete(u),i.delete(u)},process:u=>{if(o=u,r){s=!0;return}r=!0,[t,n]=[n,t],t.forEach(a),t.clear(),r=!1,s&&(s=!1,l.process(u))}};return l}const zs=["read","resolveKeyframes","update","preRender","render","postRender"],Tx=40;function um(e,t){let n=!1,r=!0;const s={delta:0,timestamp:0,isProcessing:!1},i=()=>n=!0,o=zs.reduce((m,p)=>(m[p]=Px(i),m),{}),{read:a,resolveKeyframes:l,update:u,preRender:c,render:f,postRender:h}=o,g=()=>{const m=performance.now();n=!1,s.delta=r?1e3/60:Math.max(Math.min(m-s.timestamp,Tx),1),s.timestamp=m,s.isProcessing=!0,a.process(s),l.process(s),u.process(s),c.process(s),f.process(s),h.process(s),s.isProcessing=!1,n&&t&&(r=!1,e(g))},v=()=>{n=!0,r=!0,s.isProcessing||e(g)};return{schedule:zs.reduce((m,p)=>{const y=o[p];return m[p]=(b,k=!1,C=!1)=>(n||v(),y.schedule(b,k,C)),m},{}),cancel:m=>{for(let p=0;pdd[e].some(n=>!!t[n])};function Ex(e){for(const t in e)qn[t]={...qn[t],...e[t]}}const jx=new Set(["animate","exit","variants","initial","style","values","variants","transition","transformTemplate","custom","inherit","onBeforeLayoutMeasure","onAnimationStart","onAnimationComplete","onUpdate","onDragStart","onDrag","onDragEnd","onMeasureDragConstraints","onDirectionLock","onDragTransitionEnd","_dragX","_dragY","onHoverStart","onHoverEnd","onViewportEnter","onViewportLeave","globalTapTarget","ignoreStrict","viewport"]);function Li(e){return e.startsWith("while")||e.startsWith("drag")&&e!=="draggable"||e.startsWith("layout")||e.startsWith("onTap")||e.startsWith("onPan")||e.startsWith("onLayout")||jx.has(e)}let dm=e=>!Li(e);function Nx(e){e&&(dm=t=>t.startsWith("on")?!Li(t):e(t))}try{Nx(require("@emotion/is-prop-valid").default)}catch{}function Ax(e,t,n){const r={};for(const s in e)s==="values"&&typeof e.values=="object"||(dm(s)||n===!0&&Li(s)||!t&&!Li(s)||e.draggable&&s.startsWith("onDrag"))&&(r[s]=e[s]);return r}function Rx(e){if(typeof Proxy>"u")return e;const t=new Map,n=(...r)=>e(...r);return new Proxy(n,{get:(r,s)=>s==="create"?e:(t.has(s)||t.set(s,e(s)),t.get(s))})}const oo=x.createContext({});function ns(e){return typeof e=="string"||Array.isArray(e)}function ao(e){return e!==null&&typeof e=="object"&&typeof e.start=="function"}const pu=["animate","whileInView","whileFocus","whileHover","whileTap","whileDrag","exit"],mu=["initial",...pu];function lo(e){return ao(e.animate)||mu.some(t=>ns(e[t]))}function fm(e){return!!(lo(e)||e.variants)}function Lx(e,t){if(lo(e)){const{initial:n,animate:r}=e;return{initial:n===!1||ns(n)?n:void 0,animate:ns(r)?r:void 0}}return e.inherit!==!1?t:{}}function Dx(e){const{initial:t,animate:n}=Lx(e,x.useContext(oo));return x.useMemo(()=>({initial:t,animate:n}),[fd(t),fd(n)])}function fd(e){return Array.isArray(e)?e.join(" "):e}const Fx=Symbol.for("motionComponentSymbol");function Dn(e){return e&&typeof e=="object"&&Object.prototype.hasOwnProperty.call(e,"current")}function Mx(e,t,n){return x.useCallback(r=>{r&&e.onMount&&e.onMount(r),t&&(r?t.mount(r):t.unmount()),n&&(typeof n=="function"?n(r):Dn(n)&&(n.current=r))},[t])}const gu=e=>e.replace(/([a-z])([A-Z])/gu,"$1-$2").toLowerCase(),_x="framerAppearId",hm="data-"+gu(_x),{schedule:yu}=um(queueMicrotask,!1),pm=x.createContext({});function Vx(e,t,n,r,s){var i,o;const{visualElement:a}=x.useContext(oo),l=x.useContext(cm),u=x.useContext(io),c=x.useContext(du).reducedMotion,f=x.useRef(null);r=r||l.renderer,!f.current&&r&&(f.current=r(e,{visualState:t,parent:a,props:n,presenceContext:u,blockInitialAnimation:u?u.initial===!1:!1,reducedMotionConfig:c}));const h=f.current,g=x.useContext(pm);h&&!h.projection&&s&&(h.type==="html"||h.type==="svg")&&Ox(f.current,n,s,g);const v=x.useRef(!1);x.useInsertionEffect(()=>{h&&v.current&&h.update(n,u)});const w=n[hm],S=x.useRef(!!w&&!(!((i=window.MotionHandoffIsComplete)===null||i===void 0)&&i.call(window,w))&&((o=window.MotionHasOptimisedAnimation)===null||o===void 0?void 0:o.call(window,w)));return om(()=>{h&&(v.current=!0,window.MotionIsMounted=!0,h.updateFeatures(),yu.render(h.render),S.current&&h.animationState&&h.animationState.animateChanges())}),x.useEffect(()=>{h&&(!S.current&&h.animationState&&h.animationState.animateChanges(),S.current&&(queueMicrotask(()=>{var m;(m=window.MotionHandoffMarkAsComplete)===null||m===void 0||m.call(window,w)}),S.current=!1))}),h}function Ox(e,t,n,r){const{layoutId:s,layout:i,drag:o,dragConstraints:a,layoutScroll:l,layoutRoot:u}=t;e.projection=new n(e.latestValues,t["data-framer-portal-id"]?void 0:mm(e.parent)),e.projection.setOptions({layoutId:s,layout:i,alwaysMeasureLayout:!!o||a&&Dn(a),visualElement:e,animationType:typeof i=="string"?i:"both",initialPromotionConfig:r,layoutScroll:l,layoutRoot:u})}function mm(e){if(e)return e.options.allowProjection!==!1?e.projection:mm(e.parent)}function Ix({preloadedFeatures:e,createVisualElement:t,useRender:n,useVisualState:r,Component:s}){var i,o;e&&Ex(e);function a(u,c){let f;const h={...x.useContext(du),...u,layoutId:Bx(u)},{isStatic:g}=h,v=Dx(u),w=r(u,g);if(!g&&fu){Ux();const S=zx(h);f=S.MeasureLayout,v.visualElement=Vx(s,w,h,t,S.ProjectionNode)}return d.jsxs(oo.Provider,{value:v,children:[f&&v.visualElement?d.jsx(f,{visualElement:v.visualElement,...h}):null,n(s,u,Mx(w,v.visualElement,c),w,g,v.visualElement)]})}a.displayName=`motion.${typeof s=="string"?s:`create(${(o=(i=s.displayName)!==null&&i!==void 0?i:s.name)!==null&&o!==void 0?o:""})`}`;const l=x.forwardRef(a);return l[Fx]=s,l}function Bx({layoutId:e}){const t=x.useContext(uu).id;return t&&e!==void 0?t+"-"+e:e}function Ux(e,t){x.useContext(cm).strict}function zx(e){const{drag:t,layout:n}=qn;if(!t&&!n)return{};const r={...t,...n};return{MeasureLayout:t!=null&&t.isEnabled(e)||n!=null&&n.isEnabled(e)?r.MeasureLayout:void 0,ProjectionNode:r.ProjectionNode}}const $x=["animate","circle","defs","desc","ellipse","g","image","line","filter","marker","mask","metadata","path","pattern","polygon","polyline","rect","stop","switch","symbol","svg","text","tspan","use","view"];function vu(e){return typeof e!="string"||e.includes("-")?!1:!!($x.indexOf(e)>-1||/[A-Z]/u.test(e))}function hd(e){const t=[{},{}];return e==null||e.values.forEach((n,r)=>{t[0][r]=n.get(),t[1][r]=n.getVelocity()}),t}function xu(e,t,n,r){if(typeof t=="function"){const[s,i]=hd(r);t=t(n!==void 0?n:e.custom,s,i)}if(typeof t=="string"&&(t=e.variants&&e.variants[t]),typeof t=="function"){const[s,i]=hd(r);t=t(n!==void 0?n:e.custom,s,i)}return t}const Ja=e=>Array.isArray(e),Wx=e=>!!(e&&typeof e=="object"&&e.mix&&e.toValue),Kx=e=>Ja(e)?e[e.length-1]||0:e,ge=e=>!!(e&&e.getVelocity);function ri(e){const t=ge(e)?e.get():e;return Wx(t)?t.toValue():t}function Hx({scrapeMotionValuesFromProps:e,createRenderState:t,onUpdate:n},r,s,i){const o={latestValues:Gx(r,s,i,e),renderState:t()};return n&&(o.onMount=a=>n({props:r,current:a,...o}),o.onUpdate=a=>n(a)),o}const gm=e=>(t,n)=>{const r=x.useContext(oo),s=x.useContext(io),i=()=>Hx(e,t,r,s);return n?i():cu(i)};function Gx(e,t,n,r){const s={},i=r(e,{});for(const h in i)s[h]=ri(i[h]);let{initial:o,animate:a}=e;const l=lo(e),u=fm(e);t&&u&&!l&&e.inherit!==!1&&(o===void 0&&(o=t.initial),a===void 0&&(a=t.animate));let c=n?n.initial===!1:!1;c=c||o===!1;const f=c?a:o;if(f&&typeof f!="boolean"&&!ao(f)){const h=Array.isArray(f)?f:[f];for(let g=0;gt=>typeof t=="string"&&t.startsWith(e),vm=ym("--"),Xx=ym("var(--"),wu=e=>Xx(e)?Qx.test(e.split("/*")[0].trim()):!1,Qx=/var\(--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)$/iu,xm=(e,t)=>t&&typeof e=="number"?t.transform(e):e,yt=(e,t,n)=>n>t?t:ntypeof e=="number",parse:parseFloat,transform:e=>e},rs={...ir,transform:e=>yt(0,1,e)},$s={...ir,default:1},ps=e=>({test:t=>typeof t=="string"&&t.endsWith(e)&&t.split(" ").length===1,parse:parseFloat,transform:t=>`${t}${e}`}),bt=ps("deg"),st=ps("%"),R=ps("px"),Yx=ps("vh"),Zx=ps("vw"),pd={...st,parse:e=>st.parse(e)/100,transform:e=>st.transform(e*100)},Jx={borderWidth:R,borderTopWidth:R,borderRightWidth:R,borderBottomWidth:R,borderLeftWidth:R,borderRadius:R,radius:R,borderTopLeftRadius:R,borderTopRightRadius:R,borderBottomRightRadius:R,borderBottomLeftRadius:R,width:R,maxWidth:R,height:R,maxHeight:R,top:R,right:R,bottom:R,left:R,padding:R,paddingTop:R,paddingRight:R,paddingBottom:R,paddingLeft:R,margin:R,marginTop:R,marginRight:R,marginBottom:R,marginLeft:R,backgroundPositionX:R,backgroundPositionY:R},qx={rotate:bt,rotateX:bt,rotateY:bt,rotateZ:bt,scale:$s,scaleX:$s,scaleY:$s,scaleZ:$s,skew:bt,skewX:bt,skewY:bt,distance:R,translateX:R,translateY:R,translateZ:R,x:R,y:R,z:R,perspective:R,transformPerspective:R,opacity:rs,originX:pd,originY:pd,originZ:R},md={...ir,transform:Math.round},Su={...Jx,...qx,zIndex:md,size:R,fillOpacity:rs,strokeOpacity:rs,numOctaves:md},e1={x:"translateX",y:"translateY",z:"translateZ",transformPerspective:"perspective"},t1=sr.length;function n1(e,t,n){let r="",s=!0;for(let i=0;i({style:{},transform:{},transformOrigin:{},vars:{}}),wm=()=>({...Cu(),attrs:{}}),Pu=e=>typeof e=="string"&&e.toLowerCase()==="svg";function Sm(e,{style:t,vars:n},r,s){Object.assign(e.style,t,s&&s.getProjectionStyles(r));for(const i in n)e.style.setProperty(i,n[i])}const bm=new Set(["baseFrequency","diffuseConstant","kernelMatrix","kernelUnitLength","keySplines","keyTimes","limitingConeAngle","markerHeight","markerWidth","numOctaves","targetX","targetY","surfaceScale","specularConstant","specularExponent","stdDeviation","tableValues","viewBox","gradientTransform","pathLength","startOffset","textLength","lengthAdjust"]);function km(e,t,n,r){Sm(e,t,void 0,r);for(const s in t.attrs)e.setAttribute(bm.has(s)?s:gu(s),t.attrs[s])}const Di={};function a1(e){Object.assign(Di,e)}function Cm(e,{layout:t,layoutId:n}){return xn.has(e)||e.startsWith("origin")||(t||n!==void 0)&&(!!Di[e]||e==="opacity")}function Tu(e,t,n){var r;const{style:s}=e,i={};for(const o in s)(ge(s[o])||t.style&&ge(t.style[o])||Cm(o,e)||((r=n==null?void 0:n.getValue(o))===null||r===void 0?void 0:r.liveStyle)!==void 0)&&(i[o]=s[o]);return i}function Pm(e,t,n){const r=Tu(e,t,n);for(const s in e)if(ge(e[s])||ge(t[s])){const i=sr.indexOf(s)!==-1?"attr"+s.charAt(0).toUpperCase()+s.substring(1):s;r[i]=e[s]}return r}function l1(e,t){try{t.dimensions=typeof e.getBBox=="function"?e.getBBox():e.getBoundingClientRect()}catch{t.dimensions={x:0,y:0,width:0,height:0}}}const yd=["x","y","width","height","cx","cy","r"],u1={useVisualState:gm({scrapeMotionValuesFromProps:Pm,createRenderState:wm,onUpdate:({props:e,prevProps:t,current:n,renderState:r,latestValues:s})=>{if(!n)return;let i=!!e.drag;if(!i){for(const a in s)if(xn.has(a)){i=!0;break}}if(!i)return;let o=!t;if(t)for(let a=0;a{l1(n,r),z.render(()=>{ku(r,s,Pu(n.tagName),e.transformTemplate),km(n,r)})})}})},c1={useVisualState:gm({scrapeMotionValuesFromProps:Tu,createRenderState:Cu})};function Tm(e,t,n){for(const r in t)!ge(t[r])&&!Cm(r,n)&&(e[r]=t[r])}function d1({transformTemplate:e},t){return x.useMemo(()=>{const n=Cu();return bu(n,t,e),Object.assign({},n.vars,n.style)},[t])}function f1(e,t){const n=e.style||{},r={};return Tm(r,n,e),Object.assign(r,d1(e,t)),r}function h1(e,t){const n={},r=f1(e,t);return e.drag&&e.dragListener!==!1&&(n.draggable=!1,r.userSelect=r.WebkitUserSelect=r.WebkitTouchCallout="none",r.touchAction=e.drag===!0?"none":`pan-${e.drag==="x"?"y":"x"}`),e.tabIndex===void 0&&(e.onTap||e.onTapStart||e.whileTap)&&(n.tabIndex=0),n.style=r,n}function p1(e,t,n,r){const s=x.useMemo(()=>{const i=wm();return ku(i,t,Pu(r),e.transformTemplate),{...i.attrs,style:{...i.style}}},[t]);if(e.style){const i={};Tm(i,e.style,e),s.style={...i,...s.style}}return s}function m1(e=!1){return(n,r,s,{latestValues:i},o)=>{const l=(vu(n)?p1:h1)(r,i,o,n),u=Ax(r,typeof n=="string",e),c=n!==x.Fragment?{...u,...l,ref:s}:{},{children:f}=r,h=x.useMemo(()=>ge(f)?f.get():f,[f]);return x.createElement(n,{...c,children:h})}}function g1(e,t){return function(r,{forwardMotionProps:s}={forwardMotionProps:!1}){const o={...vu(r)?u1:c1,preloadedFeatures:e,useRender:m1(s),createVisualElement:t,Component:r};return Ix(o)}}function Em(e,t){if(!Array.isArray(t))return!1;const n=t.length;if(n!==e.length)return!1;for(let r=0;rwindow.ScrollTimeline!==void 0);class v1{constructor(t){this.stop=()=>this.runAll("stop"),this.animations=t.filter(Boolean)}get finished(){return Promise.all(this.animations.map(t=>"finished"in t?t.finished:t))}getAll(t){return this.animations[0][t]}setAll(t,n){for(let r=0;r{if(y1()&&s.attachTimeline)return s.attachTimeline(t);if(typeof n=="function")return n(s)});return()=>{r.forEach((s,i)=>{s&&s(),this.animations[i].stop()})}}get time(){return this.getAll("time")}set time(t){this.setAll("time",t)}get speed(){return this.getAll("speed")}set speed(t){this.setAll("speed",t)}get startTime(){return this.getAll("startTime")}get duration(){let t=0;for(let n=0;nn[t]())}flatten(){this.runAll("flatten")}play(){this.runAll("play")}pause(){this.runAll("pause")}cancel(){this.runAll("cancel")}complete(){this.runAll("complete")}}class x1 extends v1{then(t,n){return Promise.all(this.animations).then(t).catch(n)}}function Eu(e,t){return e?e[t]||e.default||e:void 0}const qa=2e4;function jm(e){let t=0;const n=50;let r=e.next(t);for(;!r.done&&t=qa?1/0:t}function ju(e){return typeof e=="function"}function vd(e,t){e.timeline=t,e.onfinish=null}const Nu=e=>Array.isArray(e)&&typeof e[0]=="number",w1={linearEasing:void 0};function S1(e,t){const n=hu(e);return()=>{var r;return(r=w1[t])!==null&&r!==void 0?r:n()}}const Fi=S1(()=>{try{document.createElement("div").animate({opacity:0},{easing:"linear(0, 1)"})}catch{return!1}return!0},"linearEasing"),Nm=(e,t,n=10)=>{let r="";const s=Math.max(Math.round(t/n),2);for(let i=0;i`cubic-bezier(${e}, ${t}, ${n}, ${r})`,el={linear:"linear",ease:"ease",easeIn:"ease-in",easeOut:"ease-out",easeInOut:"ease-in-out",circIn:wr([0,.65,.55,1]),circOut:wr([.55,0,1,.45]),backIn:wr([.31,.01,.66,-.59]),backOut:wr([.33,1.53,.69,.99])};function Rm(e,t){if(e)return typeof e=="function"&&Fi()?Nm(e,t):Nu(e)?wr(e):Array.isArray(e)?e.map(n=>Rm(n,t)||el.easeOut):el[e]}const Ke={x:!1,y:!1};function Lm(){return Ke.x||Ke.y}function b1(e,t,n){var r;if(e instanceof Element)return[e];if(typeof e=="string"){let s=document;const i=(r=void 0)!==null&&r!==void 0?r:s.querySelectorAll(e);return i?Array.from(i):[]}return Array.from(e)}function Dm(e,t){const n=b1(e),r=new AbortController,s={passive:!0,...t,signal:r.signal};return[n,s,()=>r.abort()]}function xd(e){return t=>{t.pointerType==="touch"||Lm()||e(t)}}function k1(e,t,n={}){const[r,s,i]=Dm(e,n),o=xd(a=>{const{target:l}=a,u=t(a);if(typeof u!="function"||!l)return;const c=xd(f=>{u(f),l.removeEventListener("pointerleave",c)});l.addEventListener("pointerleave",c,s)});return r.forEach(a=>{a.addEventListener("pointerenter",o,s)}),i}const Fm=(e,t)=>t?e===t?!0:Fm(e,t.parentElement):!1,Au=e=>e.pointerType==="mouse"?typeof e.button!="number"||e.button<=0:e.isPrimary!==!1,C1=new Set(["BUTTON","INPUT","SELECT","TEXTAREA","A"]);function P1(e){return C1.has(e.tagName)||e.tabIndex!==-1}const Sr=new WeakSet;function wd(e){return t=>{t.key==="Enter"&&e(t)}}function zo(e,t){e.dispatchEvent(new PointerEvent("pointer"+t,{isPrimary:!0,bubbles:!0}))}const T1=(e,t)=>{const n=e.currentTarget;if(!n)return;const r=wd(()=>{if(Sr.has(n))return;zo(n,"down");const s=wd(()=>{zo(n,"up")}),i=()=>zo(n,"cancel");n.addEventListener("keyup",s,t),n.addEventListener("blur",i,t)});n.addEventListener("keydown",r,t),n.addEventListener("blur",()=>n.removeEventListener("keydown",r),t)};function Sd(e){return Au(e)&&!Lm()}function E1(e,t,n={}){const[r,s,i]=Dm(e,n),o=a=>{const l=a.currentTarget;if(!Sd(a)||Sr.has(l))return;Sr.add(l);const u=t(a),c=(g,v)=>{window.removeEventListener("pointerup",f),window.removeEventListener("pointercancel",h),!(!Sd(g)||!Sr.has(l))&&(Sr.delete(l),typeof u=="function"&&u(g,{success:v}))},f=g=>{c(g,n.useGlobalTarget||Fm(l,g.target))},h=g=>{c(g,!1)};window.addEventListener("pointerup",f,s),window.addEventListener("pointercancel",h,s)};return r.forEach(a=>{!P1(a)&&a.getAttribute("tabindex")===null&&(a.tabIndex=0),(n.useGlobalTarget?window:a).addEventListener("pointerdown",o,s),a.addEventListener("focus",u=>T1(u,s),s)}),i}function j1(e){return e==="x"||e==="y"?Ke[e]?null:(Ke[e]=!0,()=>{Ke[e]=!1}):Ke.x||Ke.y?null:(Ke.x=Ke.y=!0,()=>{Ke.x=Ke.y=!1})}const Mm=new Set(["width","height","top","left","right","bottom",...sr]);let si;function N1(){si=void 0}const it={now:()=>(si===void 0&&it.set(ue.isProcessing||Cx.useManualTiming?ue.timestamp:performance.now()),si),set:e=>{si=e,queueMicrotask(N1)}};function Ru(e,t){e.indexOf(t)===-1&&e.push(t)}function Lu(e,t){const n=e.indexOf(t);n>-1&&e.splice(n,1)}class Du{constructor(){this.subscriptions=[]}add(t){return Ru(this.subscriptions,t),()=>Lu(this.subscriptions,t)}notify(t,n,r){const s=this.subscriptions.length;if(s)if(s===1)this.subscriptions[0](t,n,r);else for(let i=0;i!isNaN(parseFloat(e));class R1{constructor(t,n={}){this.version="11.18.2",this.canTrackVelocity=null,this.events={},this.updateAndNotify=(r,s=!0)=>{const i=it.now();this.updatedAt!==i&&this.setPrevFrameValue(),this.prev=this.current,this.setCurrent(r),this.current!==this.prev&&this.events.change&&this.events.change.notify(this.current),s&&this.events.renderRequest&&this.events.renderRequest.notify(this.current)},this.hasAnimated=!1,this.setCurrent(t),this.owner=n.owner}setCurrent(t){this.current=t,this.updatedAt=it.now(),this.canTrackVelocity===null&&t!==void 0&&(this.canTrackVelocity=A1(this.current))}setPrevFrameValue(t=this.current){this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt}onChange(t){return this.on("change",t)}on(t,n){this.events[t]||(this.events[t]=new Du);const r=this.events[t].add(n);return t==="change"?()=>{r(),z.read(()=>{this.events.change.getSize()||this.stop()})}:r}clearListeners(){for(const t in this.events)this.events[t].clear()}attach(t,n){this.passiveEffect=t,this.stopPassiveEffect=n}set(t,n=!0){!n||!this.passiveEffect?this.updateAndNotify(t,n):this.passiveEffect(t,this.updateAndNotify)}setWithVelocity(t,n,r){this.set(n),this.prev=void 0,this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt-r}jump(t,n=!0){this.updateAndNotify(t),this.prev=t,this.prevUpdatedAt=this.prevFrameValue=void 0,n&&this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}get(){return this.current}getPrevious(){return this.prev}getVelocity(){const t=it.now();if(!this.canTrackVelocity||this.prevFrameValue===void 0||t-this.updatedAt>bd)return 0;const n=Math.min(this.updatedAt-this.prevUpdatedAt,bd);return _m(parseFloat(this.current)-parseFloat(this.prevFrameValue),n)}start(t){return this.stop(),new Promise(n=>{this.hasAnimated=!0,this.animation=t(n),this.events.animationStart&&this.events.animationStart.notify()}).then(()=>{this.events.animationComplete&&this.events.animationComplete.notify(),this.clearAnimation()})}stop(){this.animation&&(this.animation.stop(),this.events.animationCancel&&this.events.animationCancel.notify()),this.clearAnimation()}isAnimating(){return!!this.animation}clearAnimation(){delete this.animation}destroy(){this.clearListeners(),this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}}function ss(e,t){return new R1(e,t)}function L1(e,t,n){e.hasValue(t)?e.getValue(t).set(n):e.addValue(t,ss(n))}function D1(e,t){const n=uo(e,t);let{transitionEnd:r={},transition:s={},...i}=n||{};i={...i,...r};for(const o in i){const a=Kx(i[o]);L1(e,o,a)}}function F1(e){return!!(ge(e)&&e.add)}function tl(e,t){const n=e.getValue("willChange");if(F1(n))return n.add(t)}function Vm(e){return e.props[hm]}const Om=(e,t,n)=>(((1-3*n+3*t)*e+(3*n-6*t))*e+3*t)*e,M1=1e-7,_1=12;function V1(e,t,n,r,s){let i,o,a=0;do o=t+(n-t)/2,i=Om(o,r,s)-e,i>0?n=o:t=o;while(Math.abs(i)>M1&&++a<_1);return o}function ms(e,t,n,r){if(e===t&&n===r)return Ae;const s=i=>V1(i,0,1,e,n);return i=>i===0||i===1?i:Om(s(i),t,r)}const Im=e=>t=>t<=.5?e(2*t)/2:(2-e(2*(1-t)))/2,Bm=e=>t=>1-e(1-t),Um=ms(.33,1.53,.69,.99),Fu=Bm(Um),zm=Im(Fu),$m=e=>(e*=2)<1?.5*Fu(e):.5*(2-Math.pow(2,-10*(e-1))),Mu=e=>1-Math.sin(Math.acos(e)),Wm=Bm(Mu),Km=Im(Mu),Hm=e=>/^0[^.\s]+$/u.test(e);function O1(e){return typeof e=="number"?e===0:e!==null?e==="none"||e==="0"||Hm(e):!0}const Dr=e=>Math.round(e*1e5)/1e5,_u=/-?(?:\d+(?:\.\d+)?|\.\d+)/gu;function I1(e){return e==null}const B1=/^(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))$/iu,Vu=(e,t)=>n=>!!(typeof n=="string"&&B1.test(n)&&n.startsWith(e)||t&&!I1(n)&&Object.prototype.hasOwnProperty.call(n,t)),Gm=(e,t,n)=>r=>{if(typeof r!="string")return r;const[s,i,o,a]=r.match(_u);return{[e]:parseFloat(s),[t]:parseFloat(i),[n]:parseFloat(o),alpha:a!==void 0?parseFloat(a):1}},U1=e=>yt(0,255,e),$o={...ir,transform:e=>Math.round(U1(e))},on={test:Vu("rgb","red"),parse:Gm("red","green","blue"),transform:({red:e,green:t,blue:n,alpha:r=1})=>"rgba("+$o.transform(e)+", "+$o.transform(t)+", "+$o.transform(n)+", "+Dr(rs.transform(r))+")"};function z1(e){let t="",n="",r="",s="";return e.length>5?(t=e.substring(1,3),n=e.substring(3,5),r=e.substring(5,7),s=e.substring(7,9)):(t=e.substring(1,2),n=e.substring(2,3),r=e.substring(3,4),s=e.substring(4,5),t+=t,n+=n,r+=r,s+=s),{red:parseInt(t,16),green:parseInt(n,16),blue:parseInt(r,16),alpha:s?parseInt(s,16)/255:1}}const nl={test:Vu("#"),parse:z1,transform:on.transform},Fn={test:Vu("hsl","hue"),parse:Gm("hue","saturation","lightness"),transform:({hue:e,saturation:t,lightness:n,alpha:r=1})=>"hsla("+Math.round(e)+", "+st.transform(Dr(t))+", "+st.transform(Dr(n))+", "+Dr(rs.transform(r))+")"},pe={test:e=>on.test(e)||nl.test(e)||Fn.test(e),parse:e=>on.test(e)?on.parse(e):Fn.test(e)?Fn.parse(e):nl.parse(e),transform:e=>typeof e=="string"?e:e.hasOwnProperty("red")?on.transform(e):Fn.transform(e)},$1=/(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))/giu;function W1(e){var t,n;return isNaN(e)&&typeof e=="string"&&(((t=e.match(_u))===null||t===void 0?void 0:t.length)||0)+(((n=e.match($1))===null||n===void 0?void 0:n.length)||0)>0}const Xm="number",Qm="color",K1="var",H1="var(",kd="${}",G1=/var\s*\(\s*--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)|#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\)|-?(?:\d+(?:\.\d+)?|\.\d+)/giu;function is(e){const t=e.toString(),n=[],r={color:[],number:[],var:[]},s=[];let i=0;const a=t.replace(G1,l=>(pe.test(l)?(r.color.push(i),s.push(Qm),n.push(pe.parse(l))):l.startsWith(H1)?(r.var.push(i),s.push(K1),n.push(l)):(r.number.push(i),s.push(Xm),n.push(parseFloat(l))),++i,kd)).split(kd);return{values:n,split:a,indexes:r,types:s}}function Ym(e){return is(e).values}function Zm(e){const{split:t,types:n}=is(e),r=t.length;return s=>{let i="";for(let o=0;otypeof e=="number"?0:e;function Q1(e){const t=Ym(e);return Zm(e)(t.map(X1))}const zt={test:W1,parse:Ym,createTransformer:Zm,getAnimatableNone:Q1},Y1=new Set(["brightness","contrast","saturate","opacity"]);function Z1(e){const[t,n]=e.slice(0,-1).split("(");if(t==="drop-shadow")return e;const[r]=n.match(_u)||[];if(!r)return e;const s=n.replace(r,"");let i=Y1.has(t)?1:0;return r!==n&&(i*=100),t+"("+i+s+")"}const J1=/\b([a-z-]*)\(.*?\)/gu,rl={...zt,getAnimatableNone:e=>{const t=e.match(J1);return t?t.map(Z1).join(" "):e}},q1={...Su,color:pe,backgroundColor:pe,outlineColor:pe,fill:pe,stroke:pe,borderColor:pe,borderTopColor:pe,borderRightColor:pe,borderBottomColor:pe,borderLeftColor:pe,filter:rl,WebkitFilter:rl},Ou=e=>q1[e];function Jm(e,t){let n=Ou(e);return n!==rl&&(n=zt),n.getAnimatableNone?n.getAnimatableNone(t):void 0}const ew=new Set(["auto","none","0"]);function tw(e,t,n){let r=0,s;for(;re===ir||e===R,Pd=(e,t)=>parseFloat(e.split(", ")[t]),Td=(e,t)=>(n,{transform:r})=>{if(r==="none"||!r)return 0;const s=r.match(/^matrix3d\((.+)\)$/u);if(s)return Pd(s[1],t);{const i=r.match(/^matrix\((.+)\)$/u);return i?Pd(i[1],e):0}},nw=new Set(["x","y","z"]),rw=sr.filter(e=>!nw.has(e));function sw(e){const t=[];return rw.forEach(n=>{const r=e.getValue(n);r!==void 0&&(t.push([n,r.get()]),r.set(n.startsWith("scale")?1:0))}),t}const er={width:({x:e},{paddingLeft:t="0",paddingRight:n="0"})=>e.max-e.min-parseFloat(t)-parseFloat(n),height:({y:e},{paddingTop:t="0",paddingBottom:n="0"})=>e.max-e.min-parseFloat(t)-parseFloat(n),top:(e,{top:t})=>parseFloat(t),left:(e,{left:t})=>parseFloat(t),bottom:({y:e},{top:t})=>parseFloat(t)+(e.max-e.min),right:({x:e},{left:t})=>parseFloat(t)+(e.max-e.min),x:Td(4,13),y:Td(5,14)};er.translateX=er.x;er.translateY=er.y;const un=new Set;let sl=!1,il=!1;function qm(){if(il){const e=Array.from(un).filter(r=>r.needsMeasurement),t=new Set(e.map(r=>r.element)),n=new Map;t.forEach(r=>{const s=sw(r);s.length&&(n.set(r,s),r.render())}),e.forEach(r=>r.measureInitialState()),t.forEach(r=>{r.render();const s=n.get(r);s&&s.forEach(([i,o])=>{var a;(a=r.getValue(i))===null||a===void 0||a.set(o)})}),e.forEach(r=>r.measureEndState()),e.forEach(r=>{r.suspendedScrollY!==void 0&&window.scrollTo(0,r.suspendedScrollY)})}il=!1,sl=!1,un.forEach(e=>e.complete()),un.clear()}function eg(){un.forEach(e=>{e.readKeyframes(),e.needsMeasurement&&(il=!0)})}function iw(){eg(),qm()}class Iu{constructor(t,n,r,s,i,o=!1){this.isComplete=!1,this.isAsync=!1,this.needsMeasurement=!1,this.isScheduled=!1,this.unresolvedKeyframes=[...t],this.onComplete=n,this.name=r,this.motionValue=s,this.element=i,this.isAsync=o}scheduleResolve(){this.isScheduled=!0,this.isAsync?(un.add(this),sl||(sl=!0,z.read(eg),z.resolveKeyframes(qm))):(this.readKeyframes(),this.complete())}readKeyframes(){const{unresolvedKeyframes:t,name:n,element:r,motionValue:s}=this;for(let i=0;i/^-?(?:\d+(?:\.\d+)?|\.\d+)$/u.test(e),ow=/^var\(--(?:([\w-]+)|([\w-]+), ?([a-zA-Z\d ()%#.,-]+))\)/u;function aw(e){const t=ow.exec(e);if(!t)return[,];const[,n,r,s]=t;return[`--${n??r}`,s]}function ng(e,t,n=1){const[r,s]=aw(e);if(!r)return;const i=window.getComputedStyle(t).getPropertyValue(r);if(i){const o=i.trim();return tg(o)?parseFloat(o):o}return wu(s)?ng(s,t,n+1):s}const rg=e=>t=>t.test(e),lw={test:e=>e==="auto",parse:e=>e},sg=[ir,R,st,bt,Zx,Yx,lw],Ed=e=>sg.find(rg(e));class ig extends Iu{constructor(t,n,r,s,i){super(t,n,r,s,i,!0)}readKeyframes(){const{unresolvedKeyframes:t,element:n,name:r}=this;if(!n||!n.current)return;super.readKeyframes();for(let l=0;l{n.getValue(l).set(u)}),this.resolveNoneKeyframes()}}const jd=(e,t)=>t==="zIndex"?!1:!!(typeof e=="number"||Array.isArray(e)||typeof e=="string"&&(zt.test(e)||e==="0")&&!e.startsWith("url("));function uw(e){const t=e[0];if(e.length===1)return!0;for(let n=0;ne!==null;function co(e,{repeat:t,repeatType:n="loop"},r){const s=e.filter(dw),i=t&&n!=="loop"&&t%2===1?0:s.length-1;return!i||r===void 0?s[i]:r}const fw=40;class og{constructor({autoplay:t=!0,delay:n=0,type:r="keyframes",repeat:s=0,repeatDelay:i=0,repeatType:o="loop",...a}){this.isStopped=!1,this.hasAttemptedResolve=!1,this.createdAt=it.now(),this.options={autoplay:t,delay:n,type:r,repeat:s,repeatDelay:i,repeatType:o,...a},this.updateFinishedPromise()}calcStartTime(){return this.resolvedAt?this.resolvedAt-this.createdAt>fw?this.resolvedAt:this.createdAt:this.createdAt}get resolved(){return!this._resolved&&!this.hasAttemptedResolve&&iw(),this._resolved}onKeyframesResolved(t,n){this.resolvedAt=it.now(),this.hasAttemptedResolve=!0;const{name:r,type:s,velocity:i,delay:o,onComplete:a,onUpdate:l,isGenerator:u}=this.options;if(!u&&!cw(t,r,s,i))if(o)this.options.duration=0;else{l&&l(co(t,this.options,n)),a&&a(),this.resolveFinishedPromise();return}const c=this.initPlayback(t,n);c!==!1&&(this._resolved={keyframes:t,finalKeyframe:n,...c},this.onPostResolved())}onPostResolved(){}then(t,n){return this.currentFinishedPromise.then(t,n)}flatten(){this.options.type="keyframes",this.options.ease="linear"}updateFinishedPromise(){this.currentFinishedPromise=new Promise(t=>{this.resolveFinishedPromise=t})}}const K=(e,t,n)=>e+(t-e)*n;function Wo(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*6*n:n<1/2?t:n<2/3?e+(t-e)*(2/3-n)*6:e}function hw({hue:e,saturation:t,lightness:n,alpha:r}){e/=360,t/=100,n/=100;let s=0,i=0,o=0;if(!t)s=i=o=n;else{const a=n<.5?n*(1+t):n+t-n*t,l=2*n-a;s=Wo(l,a,e+1/3),i=Wo(l,a,e),o=Wo(l,a,e-1/3)}return{red:Math.round(s*255),green:Math.round(i*255),blue:Math.round(o*255),alpha:r}}function Mi(e,t){return n=>n>0?t:e}const Ko=(e,t,n)=>{const r=e*e,s=n*(t*t-r)+r;return s<0?0:Math.sqrt(s)},pw=[nl,on,Fn],mw=e=>pw.find(t=>t.test(e));function Nd(e){const t=mw(e);if(!t)return!1;let n=t.parse(e);return t===Fn&&(n=hw(n)),n}const Ad=(e,t)=>{const n=Nd(e),r=Nd(t);if(!n||!r)return Mi(e,t);const s={...n};return i=>(s.red=Ko(n.red,r.red,i),s.green=Ko(n.green,r.green,i),s.blue=Ko(n.blue,r.blue,i),s.alpha=K(n.alpha,r.alpha,i),on.transform(s))},gw=(e,t)=>n=>t(e(n)),gs=(...e)=>e.reduce(gw),ol=new Set(["none","hidden"]);function yw(e,t){return ol.has(e)?n=>n<=0?e:t:n=>n>=1?t:e}function vw(e,t){return n=>K(e,t,n)}function Bu(e){return typeof e=="number"?vw:typeof e=="string"?wu(e)?Mi:pe.test(e)?Ad:Sw:Array.isArray(e)?ag:typeof e=="object"?pe.test(e)?Ad:xw:Mi}function ag(e,t){const n=[...e],r=n.length,s=e.map((i,o)=>Bu(i)(i,t[o]));return i=>{for(let o=0;o{for(const i in r)n[i]=r[i](s);return n}}function ww(e,t){var n;const r=[],s={color:0,var:0,number:0};for(let i=0;i{const n=zt.createTransformer(t),r=is(e),s=is(t);return r.indexes.var.length===s.indexes.var.length&&r.indexes.color.length===s.indexes.color.length&&r.indexes.number.length>=s.indexes.number.length?ol.has(e)&&!s.values.length||ol.has(t)&&!r.values.length?yw(e,t):gs(ag(ww(r,s),s.values),n):Mi(e,t)};function lg(e,t,n){return typeof e=="number"&&typeof t=="number"&&typeof n=="number"?K(e,t,n):Bu(e)(e,t)}const bw=5;function ug(e,t,n){const r=Math.max(t-bw,0);return _m(n-e(r),t-r)}const X={stiffness:100,damping:10,mass:1,velocity:0,duration:800,bounce:.3,visualDuration:.3,restSpeed:{granular:.01,default:2},restDelta:{granular:.005,default:.5},minDuration:.01,maxDuration:10,minDamping:.05,maxDamping:1},Ho=.001;function kw({duration:e=X.duration,bounce:t=X.bounce,velocity:n=X.velocity,mass:r=X.mass}){let s,i,o=1-t;o=yt(X.minDamping,X.maxDamping,o),e=yt(X.minDuration,X.maxDuration,ft(e)),o<1?(s=u=>{const c=u*o,f=c*e,h=c-n,g=al(u,o),v=Math.exp(-f);return Ho-h/g*v},i=u=>{const f=u*o*e,h=f*n+n,g=Math.pow(o,2)*Math.pow(u,2)*e,v=Math.exp(-f),w=al(Math.pow(u,2),o);return(-s(u)+Ho>0?-1:1)*((h-g)*v)/w}):(s=u=>{const c=Math.exp(-u*e),f=(u-n)*e+1;return-Ho+c*f},i=u=>{const c=Math.exp(-u*e),f=(n-u)*(e*e);return c*f});const a=5/e,l=Pw(s,i,a);if(e=dt(e),isNaN(l))return{stiffness:X.stiffness,damping:X.damping,duration:e};{const u=Math.pow(l,2)*r;return{stiffness:u,damping:o*2*Math.sqrt(r*u),duration:e}}}const Cw=12;function Pw(e,t,n){let r=n;for(let s=1;se[n]!==void 0)}function jw(e){let t={velocity:X.velocity,stiffness:X.stiffness,damping:X.damping,mass:X.mass,isResolvedFromDuration:!1,...e};if(!Rd(e,Ew)&&Rd(e,Tw))if(e.visualDuration){const n=e.visualDuration,r=2*Math.PI/(n*1.2),s=r*r,i=2*yt(.05,1,1-(e.bounce||0))*Math.sqrt(s);t={...t,mass:X.mass,stiffness:s,damping:i}}else{const n=kw(e);t={...t,...n,mass:X.mass},t.isResolvedFromDuration=!0}return t}function cg(e=X.visualDuration,t=X.bounce){const n=typeof e!="object"?{visualDuration:e,keyframes:[0,1],bounce:t}:e;let{restSpeed:r,restDelta:s}=n;const i=n.keyframes[0],o=n.keyframes[n.keyframes.length-1],a={done:!1,value:i},{stiffness:l,damping:u,mass:c,duration:f,velocity:h,isResolvedFromDuration:g}=jw({...n,velocity:-ft(n.velocity||0)}),v=h||0,w=u/(2*Math.sqrt(l*c)),S=o-i,m=ft(Math.sqrt(l/c)),p=Math.abs(S)<5;r||(r=p?X.restSpeed.granular:X.restSpeed.default),s||(s=p?X.restDelta.granular:X.restDelta.default);let y;if(w<1){const k=al(m,w);y=C=>{const E=Math.exp(-w*m*C);return o-E*((v+w*m*S)/k*Math.sin(k*C)+S*Math.cos(k*C))}}else if(w===1)y=k=>o-Math.exp(-m*k)*(S+(v+m*S)*k);else{const k=m*Math.sqrt(w*w-1);y=C=>{const E=Math.exp(-w*m*C),P=Math.min(k*C,300);return o-E*((v+w*m*S)*Math.sinh(P)+k*S*Math.cosh(P))/k}}const b={calculatedDuration:g&&f||null,next:k=>{const C=y(k);if(g)a.done=k>=f;else{let E=0;w<1&&(E=k===0?dt(v):ug(y,k,C));const P=Math.abs(E)<=r,F=Math.abs(o-C)<=s;a.done=P&&F}return a.value=a.done?o:C,a},toString:()=>{const k=Math.min(jm(b),qa),C=Nm(E=>b.next(k*E).value,k,30);return k+"ms "+C}};return b}function Ld({keyframes:e,velocity:t=0,power:n=.8,timeConstant:r=325,bounceDamping:s=10,bounceStiffness:i=500,modifyTarget:o,min:a,max:l,restDelta:u=.5,restSpeed:c}){const f=e[0],h={done:!1,value:f},g=P=>a!==void 0&&Pl,v=P=>a===void 0?l:l===void 0||Math.abs(a-P)-w*Math.exp(-P/r),y=P=>m+p(P),b=P=>{const F=p(P),A=y(P);h.done=Math.abs(F)<=u,h.value=h.done?m:A};let k,C;const E=P=>{g(h.value)&&(k=P,C=cg({keyframes:[h.value,v(h.value)],velocity:ug(y,P,h.value),damping:s,stiffness:i,restDelta:u,restSpeed:c}))};return E(0),{calculatedDuration:null,next:P=>{let F=!1;return!C&&k===void 0&&(F=!0,b(P),E(P)),k!==void 0&&P>=k?C.next(P-k):(!F&&b(P),h)}}}const Nw=ms(.42,0,1,1),Aw=ms(0,0,.58,1),dg=ms(.42,0,.58,1),Rw=e=>Array.isArray(e)&&typeof e[0]!="number",Lw={linear:Ae,easeIn:Nw,easeInOut:dg,easeOut:Aw,circIn:Mu,circInOut:Km,circOut:Wm,backIn:Fu,backInOut:zm,backOut:Um,anticipate:$m},Dd=e=>{if(Nu(e)){lm(e.length===4);const[t,n,r,s]=e;return ms(t,n,r,s)}else if(typeof e=="string")return Lw[e];return e};function Dw(e,t,n){const r=[],s=n||lg,i=e.length-1;for(let o=0;ot[0];if(i===2&&t[0]===t[1])return()=>t[1];const o=e[0]===e[1];e[0]>e[i-1]&&(e=[...e].reverse(),t=[...t].reverse());const a=Dw(t,r,s),l=a.length,u=c=>{if(o&&c1)for(;fu(yt(e[0],e[i-1],c)):u}function Mw(e,t){const n=e[e.length-1];for(let r=1;r<=t;r++){const s=Jn(0,t,r);e.push(K(n,1,s))}}function _w(e){const t=[0];return Mw(t,e.length-1),t}function Vw(e,t){return e.map(n=>n*t)}function Ow(e,t){return e.map(()=>t||dg).splice(0,e.length-1)}function _i({duration:e=300,keyframes:t,times:n,ease:r="easeInOut"}){const s=Rw(r)?r.map(Dd):Dd(r),i={done:!1,value:t[0]},o=Vw(n&&n.length===t.length?n:_w(t),e),a=Fw(o,t,{ease:Array.isArray(s)?s:Ow(t,s)});return{calculatedDuration:e,next:l=>(i.value=a(l),i.done=l>=e,i)}}const Iw=e=>{const t=({timestamp:n})=>e(n);return{start:()=>z.update(t,!0),stop:()=>Ut(t),now:()=>ue.isProcessing?ue.timestamp:it.now()}},Bw={decay:Ld,inertia:Ld,tween:_i,keyframes:_i,spring:cg},Uw=e=>e/100;class Uu extends og{constructor(t){super(t),this.holdTime=null,this.cancelTime=null,this.currentTime=0,this.playbackSpeed=1,this.pendingPlayState="running",this.startTime=null,this.state="idle",this.stop=()=>{if(this.resolver.cancel(),this.isStopped=!0,this.state==="idle")return;this.teardown();const{onStop:l}=this.options;l&&l()};const{name:n,motionValue:r,element:s,keyframes:i}=this.options,o=(s==null?void 0:s.KeyframeResolver)||Iu,a=(l,u)=>this.onKeyframesResolved(l,u);this.resolver=new o(i,a,n,r,s),this.resolver.scheduleResolve()}flatten(){super.flatten(),this._resolved&&Object.assign(this._resolved,this.initPlayback(this._resolved.keyframes))}initPlayback(t){const{type:n="keyframes",repeat:r=0,repeatDelay:s=0,repeatType:i,velocity:o=0}=this.options,a=ju(n)?n:Bw[n]||_i;let l,u;a!==_i&&typeof t[0]!="number"&&(l=gs(Uw,lg(t[0],t[1])),t=[0,100]);const c=a({...this.options,keyframes:t});i==="mirror"&&(u=a({...this.options,keyframes:[...t].reverse(),velocity:-o})),c.calculatedDuration===null&&(c.calculatedDuration=jm(c));const{calculatedDuration:f}=c,h=f+s,g=h*(r+1)-s;return{generator:c,mirroredGenerator:u,mapPercentToKeyframes:l,calculatedDuration:f,resolvedDuration:h,totalDuration:g}}onPostResolved(){const{autoplay:t=!0}=this.options;this.play(),this.pendingPlayState==="paused"||!t?this.pause():this.state=this.pendingPlayState}tick(t,n=!1){const{resolved:r}=this;if(!r){const{keyframes:P}=this.options;return{done:!0,value:P[P.length-1]}}const{finalKeyframe:s,generator:i,mirroredGenerator:o,mapPercentToKeyframes:a,keyframes:l,calculatedDuration:u,totalDuration:c,resolvedDuration:f}=r;if(this.startTime===null)return i.next(0);const{delay:h,repeat:g,repeatType:v,repeatDelay:w,onUpdate:S}=this.options;this.speed>0?this.startTime=Math.min(this.startTime,t):this.speed<0&&(this.startTime=Math.min(t-c/this.speed,this.startTime)),n?this.currentTime=t:this.holdTime!==null?this.currentTime=this.holdTime:this.currentTime=Math.round(t-this.startTime)*this.speed;const m=this.currentTime-h*(this.speed>=0?1:-1),p=this.speed>=0?m<0:m>c;this.currentTime=Math.max(m,0),this.state==="finished"&&this.holdTime===null&&(this.currentTime=c);let y=this.currentTime,b=i;if(g){const P=Math.min(this.currentTime,c)/f;let F=Math.floor(P),A=P%1;!A&&P>=1&&(A=1),A===1&&F--,F=Math.min(F,g+1),!!(F%2)&&(v==="reverse"?(A=1-A,w&&(A-=w/f)):v==="mirror"&&(b=o)),y=yt(0,1,A)*f}const k=p?{done:!1,value:l[0]}:b.next(y);a&&(k.value=a(k.value));let{done:C}=k;!p&&u!==null&&(C=this.speed>=0?this.currentTime>=c:this.currentTime<=0);const E=this.holdTime===null&&(this.state==="finished"||this.state==="running"&&C);return E&&s!==void 0&&(k.value=co(l,this.options,s)),S&&S(k.value),E&&this.finish(),k}get duration(){const{resolved:t}=this;return t?ft(t.calculatedDuration):0}get time(){return ft(this.currentTime)}set time(t){t=dt(t),this.currentTime=t,this.holdTime!==null||this.speed===0?this.holdTime=t:this.driver&&(this.startTime=this.driver.now()-t/this.speed)}get speed(){return this.playbackSpeed}set speed(t){const n=this.playbackSpeed!==t;this.playbackSpeed=t,n&&(this.time=ft(this.currentTime))}play(){if(this.resolver.isScheduled||this.resolver.resume(),!this._resolved){this.pendingPlayState="running";return}if(this.isStopped)return;const{driver:t=Iw,onPlay:n,startTime:r}=this.options;this.driver||(this.driver=t(i=>this.tick(i))),n&&n();const s=this.driver.now();this.holdTime!==null?this.startTime=s-this.holdTime:this.startTime?this.state==="finished"&&(this.startTime=s):this.startTime=r??this.calcStartTime(),this.state==="finished"&&this.updateFinishedPromise(),this.cancelTime=this.startTime,this.holdTime=null,this.state="running",this.driver.start()}pause(){var t;if(!this._resolved){this.pendingPlayState="paused";return}this.state="paused",this.holdTime=(t=this.currentTime)!==null&&t!==void 0?t:0}complete(){this.state!=="running"&&this.play(),this.pendingPlayState=this.state="finished",this.holdTime=null}finish(){this.teardown(),this.state="finished";const{onComplete:t}=this.options;t&&t()}cancel(){this.cancelTime!==null&&this.tick(this.cancelTime),this.teardown(),this.updateFinishedPromise()}teardown(){this.state="idle",this.stopDriver(),this.resolveFinishedPromise(),this.updateFinishedPromise(),this.startTime=this.cancelTime=null,this.resolver.cancel()}stopDriver(){this.driver&&(this.driver.stop(),this.driver=void 0)}sample(t){return this.startTime=0,this.tick(t,!0)}}const zw=new Set(["opacity","clipPath","filter","transform"]);function $w(e,t,n,{delay:r=0,duration:s=300,repeat:i=0,repeatType:o="loop",ease:a="easeInOut",times:l}={}){const u={[t]:n};l&&(u.offset=l);const c=Rm(a,s);return Array.isArray(c)&&(u.easing=c),e.animate(u,{delay:r,duration:s,easing:Array.isArray(c)?"linear":c,fill:"both",iterations:i+1,direction:o==="reverse"?"alternate":"normal"})}const Ww=hu(()=>Object.hasOwnProperty.call(Element.prototype,"animate")),Vi=10,Kw=2e4;function Hw(e){return ju(e.type)||e.type==="spring"||!Am(e.ease)}function Gw(e,t){const n=new Uu({...t,keyframes:e,repeat:0,delay:0,isGenerator:!0});let r={done:!1,value:e[0]};const s=[];let i=0;for(;!r.done&&ithis.onKeyframesResolved(o,a),n,r,s),this.resolver.scheduleResolve()}initPlayback(t,n){let{duration:r=300,times:s,ease:i,type:o,motionValue:a,name:l,startTime:u}=this.options;if(!a.owner||!a.owner.current)return!1;if(typeof i=="string"&&Fi()&&Xw(i)&&(i=fg[i]),Hw(this.options)){const{onComplete:f,onUpdate:h,motionValue:g,element:v,...w}=this.options,S=Gw(t,w);t=S.keyframes,t.length===1&&(t[1]=t[0]),r=S.duration,s=S.times,i=S.ease,o="keyframes"}const c=$w(a.owner.current,l,t,{...this.options,duration:r,times:s,ease:i});return c.startTime=u??this.calcStartTime(),this.pendingTimeline?(vd(c,this.pendingTimeline),this.pendingTimeline=void 0):c.onfinish=()=>{const{onComplete:f}=this.options;a.set(co(t,this.options,n)),f&&f(),this.cancel(),this.resolveFinishedPromise()},{animation:c,duration:r,times:s,type:o,ease:i,keyframes:t}}get duration(){const{resolved:t}=this;if(!t)return 0;const{duration:n}=t;return ft(n)}get time(){const{resolved:t}=this;if(!t)return 0;const{animation:n}=t;return ft(n.currentTime||0)}set time(t){const{resolved:n}=this;if(!n)return;const{animation:r}=n;r.currentTime=dt(t)}get speed(){const{resolved:t}=this;if(!t)return 1;const{animation:n}=t;return n.playbackRate}set speed(t){const{resolved:n}=this;if(!n)return;const{animation:r}=n;r.playbackRate=t}get state(){const{resolved:t}=this;if(!t)return"idle";const{animation:n}=t;return n.playState}get startTime(){const{resolved:t}=this;if(!t)return null;const{animation:n}=t;return n.startTime}attachTimeline(t){if(!this._resolved)this.pendingTimeline=t;else{const{resolved:n}=this;if(!n)return Ae;const{animation:r}=n;vd(r,t)}return Ae}play(){if(this.isStopped)return;const{resolved:t}=this;if(!t)return;const{animation:n}=t;n.playState==="finished"&&this.updateFinishedPromise(),n.play()}pause(){const{resolved:t}=this;if(!t)return;const{animation:n}=t;n.pause()}stop(){if(this.resolver.cancel(),this.isStopped=!0,this.state==="idle")return;this.resolveFinishedPromise(),this.updateFinishedPromise();const{resolved:t}=this;if(!t)return;const{animation:n,keyframes:r,duration:s,type:i,ease:o,times:a}=t;if(n.playState==="idle"||n.playState==="finished")return;if(this.time){const{motionValue:u,onUpdate:c,onComplete:f,element:h,...g}=this.options,v=new Uu({...g,keyframes:r,duration:s,type:i,ease:o,times:a,isGenerator:!0}),w=dt(this.time);u.setWithVelocity(v.sample(w-Vi).value,v.sample(w).value,Vi)}const{onStop:l}=this.options;l&&l(),this.cancel()}complete(){const{resolved:t}=this;t&&t.animation.finish()}cancel(){const{resolved:t}=this;t&&t.animation.cancel()}static supports(t){const{motionValue:n,name:r,repeatDelay:s,repeatType:i,damping:o,type:a}=t;if(!n||!n.owner||!(n.owner.current instanceof HTMLElement))return!1;const{onUpdate:l,transformTemplate:u}=n.owner.getProps();return Ww()&&r&&zw.has(r)&&!l&&!u&&!s&&i!=="mirror"&&o!==0&&a!=="inertia"}}const Qw={type:"spring",stiffness:500,damping:25,restSpeed:10},Yw=e=>({type:"spring",stiffness:550,damping:e===0?2*Math.sqrt(550):30,restSpeed:10}),Zw={type:"keyframes",duration:.8},Jw={type:"keyframes",ease:[.25,.1,.35,1],duration:.3},qw=(e,{keyframes:t})=>t.length>2?Zw:xn.has(e)?e.startsWith("scale")?Yw(t[1]):Qw:Jw;function eS({when:e,delay:t,delayChildren:n,staggerChildren:r,staggerDirection:s,repeat:i,repeatType:o,repeatDelay:a,from:l,elapsed:u,...c}){return!!Object.keys(c).length}const zu=(e,t,n,r={},s,i)=>o=>{const a=Eu(r,e)||{},l=a.delay||r.delay||0;let{elapsed:u=0}=r;u=u-dt(l);let c={keyframes:Array.isArray(n)?n:[null,n],ease:"easeOut",velocity:t.getVelocity(),...a,delay:-u,onUpdate:h=>{t.set(h),a.onUpdate&&a.onUpdate(h)},onComplete:()=>{o(),a.onComplete&&a.onComplete()},name:e,motionValue:t,element:i?void 0:s};eS(a)||(c={...c,...qw(e,c)}),c.duration&&(c.duration=dt(c.duration)),c.repeatDelay&&(c.repeatDelay=dt(c.repeatDelay)),c.from!==void 0&&(c.keyframes[0]=c.from);let f=!1;if((c.type===!1||c.duration===0&&!c.repeatDelay)&&(c.duration=0,c.delay===0&&(f=!0)),f&&!i&&t.get()!==void 0){const h=co(c.keyframes,a);if(h!==void 0)return z.update(()=>{c.onUpdate(h),c.onComplete()}),new x1([])}return!i&&Fd.supports(c)?new Fd(c):new Uu(c)};function tS({protectedKeys:e,needsAnimating:t},n){const r=e.hasOwnProperty(n)&&t[n]!==!0;return t[n]=!1,r}function hg(e,t,{delay:n=0,transitionOverride:r,type:s}={}){var i;let{transition:o=e.getDefaultTransition(),transitionEnd:a,...l}=t;r&&(o=r);const u=[],c=s&&e.animationState&&e.animationState.getState()[s];for(const f in l){const h=e.getValue(f,(i=e.latestValues[f])!==null&&i!==void 0?i:null),g=l[f];if(g===void 0||c&&tS(c,f))continue;const v={delay:n,...Eu(o||{},f)};let w=!1;if(window.MotionHandoffAnimation){const m=Vm(e);if(m){const p=window.MotionHandoffAnimation(m,f,z);p!==null&&(v.startTime=p,w=!0)}}tl(e,f),h.start(zu(f,h,g,e.shouldReduceMotion&&Mm.has(f)?{type:!1}:v,e,w));const S=h.animation;S&&u.push(S)}return a&&Promise.all(u).then(()=>{z.update(()=>{a&&D1(e,a)})}),u}function ll(e,t,n={}){var r;const s=uo(e,t,n.type==="exit"?(r=e.presenceContext)===null||r===void 0?void 0:r.custom:void 0);let{transition:i=e.getDefaultTransition()||{}}=s||{};n.transitionOverride&&(i=n.transitionOverride);const o=s?()=>Promise.all(hg(e,s,n)):()=>Promise.resolve(),a=e.variantChildren&&e.variantChildren.size?(u=0)=>{const{delayChildren:c=0,staggerChildren:f,staggerDirection:h}=i;return nS(e,t,c+u,f,h,n)}:()=>Promise.resolve(),{when:l}=i;if(l){const[u,c]=l==="beforeChildren"?[o,a]:[a,o];return u().then(()=>c())}else return Promise.all([o(),a(n.delay)])}function nS(e,t,n=0,r=0,s=1,i){const o=[],a=(e.variantChildren.size-1)*r,l=s===1?(u=0)=>u*r:(u=0)=>a-u*r;return Array.from(e.variantChildren).sort(rS).forEach((u,c)=>{u.notify("AnimationStart",t),o.push(ll(u,t,{...i,delay:n+l(c)}).then(()=>u.notify("AnimationComplete",t)))}),Promise.all(o)}function rS(e,t){return e.sortNodePosition(t)}function sS(e,t,n={}){e.notify("AnimationStart",t);let r;if(Array.isArray(t)){const s=t.map(i=>ll(e,i,n));r=Promise.all(s)}else if(typeof t=="string")r=ll(e,t,n);else{const s=typeof t=="function"?uo(e,t,n.custom):t;r=Promise.all(hg(e,s,n))}return r.then(()=>{e.notify("AnimationComplete",t)})}const iS=mu.length;function pg(e){if(!e)return;if(!e.isControllingVariants){const n=e.parent?pg(e.parent)||{}:{};return e.props.initial!==void 0&&(n.initial=e.props.initial),n}const t={};for(let n=0;nPromise.all(t.map(({animation:n,options:r})=>sS(e,n,r)))}function uS(e){let t=lS(e),n=Md(),r=!0;const s=l=>(u,c)=>{var f;const h=uo(e,c,l==="exit"?(f=e.presenceContext)===null||f===void 0?void 0:f.custom:void 0);if(h){const{transition:g,transitionEnd:v,...w}=h;u={...u,...w,...v}}return u};function i(l){t=l(e)}function o(l){const{props:u}=e,c=pg(e.parent)||{},f=[],h=new Set;let g={},v=1/0;for(let S=0;Sv&&b,F=!1;const A=Array.isArray(y)?y:[y];let ee=A.reduce(s(m),{});k===!1&&(ee={});const{prevResolvedValues:wt={}}=p,Xt={...wt,...ee},or=ne=>{P=!0,h.has(ne)&&(F=!0,h.delete(ne)),p.needsAnimating[ne]=!0;const j=e.getValue(ne);j&&(j.liveStyle=!1)};for(const ne in Xt){const j=ee[ne],L=wt[ne];if(g.hasOwnProperty(ne))continue;let D=!1;Ja(j)&&Ja(L)?D=!Em(j,L):D=j!==L,D?j!=null?or(ne):h.add(ne):j!==void 0&&h.has(ne)?or(ne):p.protectedKeys[ne]=!0}p.prevProp=y,p.prevResolvedValues=ee,p.isActive&&(g={...g,...ee}),r&&e.blockInitialAnimation&&(P=!1),P&&(!(C&&E)||F)&&f.push(...A.map(ne=>({animation:ne,options:{type:m}})))}if(h.size){const S={};h.forEach(m=>{const p=e.getBaseTarget(m),y=e.getValue(m);y&&(y.liveStyle=!0),S[m]=p??null}),f.push({animation:S})}let w=!!f.length;return r&&(u.initial===!1||u.initial===u.animate)&&!e.manuallyAnimateOnMount&&(w=!1),r=!1,w?t(f):Promise.resolve()}function a(l,u){var c;if(n[l].isActive===u)return Promise.resolve();(c=e.variantChildren)===null||c===void 0||c.forEach(h=>{var g;return(g=h.animationState)===null||g===void 0?void 0:g.setActive(l,u)}),n[l].isActive=u;const f=o(l);for(const h in n)n[h].protectedKeys={};return f}return{animateChanges:o,setActive:a,setAnimateFunction:i,getState:()=>n,reset:()=>{n=Md(),r=!0}}}function cS(e,t){return typeof t=="string"?t!==e:Array.isArray(t)?!Em(t,e):!1}function Zt(e=!1){return{isActive:e,protectedKeys:{},needsAnimating:{},prevResolvedValues:{}}}function Md(){return{animate:Zt(!0),whileInView:Zt(),whileHover:Zt(),whileTap:Zt(),whileDrag:Zt(),whileFocus:Zt(),exit:Zt()}}class Gt{constructor(t){this.isMounted=!1,this.node=t}update(){}}class dS extends Gt{constructor(t){super(t),t.animationState||(t.animationState=uS(t))}updateAnimationControlsSubscription(){const{animate:t}=this.node.getProps();ao(t)&&(this.unmountControls=t.subscribe(this.node))}mount(){this.updateAnimationControlsSubscription()}update(){const{animate:t}=this.node.getProps(),{animate:n}=this.node.prevProps||{};t!==n&&this.updateAnimationControlsSubscription()}unmount(){var t;this.node.animationState.reset(),(t=this.unmountControls)===null||t===void 0||t.call(this)}}let fS=0;class hS extends Gt{constructor(){super(...arguments),this.id=fS++}update(){if(!this.node.presenceContext)return;const{isPresent:t,onExitComplete:n}=this.node.presenceContext,{isPresent:r}=this.node.prevPresenceContext||{};if(!this.node.animationState||t===r)return;const s=this.node.animationState.setActive("exit",!t);n&&!t&&s.then(()=>n(this.id))}mount(){const{register:t}=this.node.presenceContext||{};t&&(this.unmount=t(this.id))}unmount(){}}const pS={animation:{Feature:dS},exit:{Feature:hS}};function os(e,t,n,r={passive:!0}){return e.addEventListener(t,n,r),()=>e.removeEventListener(t,n)}function ys(e){return{point:{x:e.pageX,y:e.pageY}}}const mS=e=>t=>Au(t)&&e(t,ys(t));function Fr(e,t,n,r){return os(e,t,mS(n),r)}const _d=(e,t)=>Math.abs(e-t);function gS(e,t){const n=_d(e.x,t.x),r=_d(e.y,t.y);return Math.sqrt(n**2+r**2)}class mg{constructor(t,n,{transformPagePoint:r,contextWindow:s,dragSnapToOrigin:i=!1}={}){if(this.startEvent=null,this.lastMoveEvent=null,this.lastMoveEventInfo=null,this.handlers={},this.contextWindow=window,this.updatePoint=()=>{if(!(this.lastMoveEvent&&this.lastMoveEventInfo))return;const f=Xo(this.lastMoveEventInfo,this.history),h=this.startEvent!==null,g=gS(f.offset,{x:0,y:0})>=3;if(!h&&!g)return;const{point:v}=f,{timestamp:w}=ue;this.history.push({...v,timestamp:w});const{onStart:S,onMove:m}=this.handlers;h||(S&&S(this.lastMoveEvent,f),this.startEvent=this.lastMoveEvent),m&&m(this.lastMoveEvent,f)},this.handlePointerMove=(f,h)=>{this.lastMoveEvent=f,this.lastMoveEventInfo=Go(h,this.transformPagePoint),z.update(this.updatePoint,!0)},this.handlePointerUp=(f,h)=>{this.end();const{onEnd:g,onSessionEnd:v,resumeAnimation:w}=this.handlers;if(this.dragSnapToOrigin&&w&&w(),!(this.lastMoveEvent&&this.lastMoveEventInfo))return;const S=Xo(f.type==="pointercancel"?this.lastMoveEventInfo:Go(h,this.transformPagePoint),this.history);this.startEvent&&g&&g(f,S),v&&v(f,S)},!Au(t))return;this.dragSnapToOrigin=i,this.handlers=n,this.transformPagePoint=r,this.contextWindow=s||window;const o=ys(t),a=Go(o,this.transformPagePoint),{point:l}=a,{timestamp:u}=ue;this.history=[{...l,timestamp:u}];const{onSessionStart:c}=n;c&&c(t,Xo(a,this.history)),this.removeListeners=gs(Fr(this.contextWindow,"pointermove",this.handlePointerMove),Fr(this.contextWindow,"pointerup",this.handlePointerUp),Fr(this.contextWindow,"pointercancel",this.handlePointerUp))}updateHandlers(t){this.handlers=t}end(){this.removeListeners&&this.removeListeners(),Ut(this.updatePoint)}}function Go(e,t){return t?{point:t(e.point)}:e}function Vd(e,t){return{x:e.x-t.x,y:e.y-t.y}}function Xo({point:e},t){return{point:e,delta:Vd(e,gg(t)),offset:Vd(e,yS(t)),velocity:vS(t,.1)}}function yS(e){return e[0]}function gg(e){return e[e.length-1]}function vS(e,t){if(e.length<2)return{x:0,y:0};let n=e.length-1,r=null;const s=gg(e);for(;n>=0&&(r=e[n],!(s.timestamp-r.timestamp>dt(t)));)n--;if(!r)return{x:0,y:0};const i=ft(s.timestamp-r.timestamp);if(i===0)return{x:0,y:0};const o={x:(s.x-r.x)/i,y:(s.y-r.y)/i};return o.x===1/0&&(o.x=0),o.y===1/0&&(o.y=0),o}const yg=1e-4,xS=1-yg,wS=1+yg,vg=.01,SS=0-vg,bS=0+vg;function Le(e){return e.max-e.min}function kS(e,t,n){return Math.abs(e-t)<=n}function Od(e,t,n,r=.5){e.origin=r,e.originPoint=K(t.min,t.max,e.origin),e.scale=Le(n)/Le(t),e.translate=K(n.min,n.max,e.origin)-e.originPoint,(e.scale>=xS&&e.scale<=wS||isNaN(e.scale))&&(e.scale=1),(e.translate>=SS&&e.translate<=bS||isNaN(e.translate))&&(e.translate=0)}function Mr(e,t,n,r){Od(e.x,t.x,n.x,r?r.originX:void 0),Od(e.y,t.y,n.y,r?r.originY:void 0)}function Id(e,t,n){e.min=n.min+t.min,e.max=e.min+Le(t)}function CS(e,t,n){Id(e.x,t.x,n.x),Id(e.y,t.y,n.y)}function Bd(e,t,n){e.min=t.min-n.min,e.max=e.min+Le(t)}function _r(e,t,n){Bd(e.x,t.x,n.x),Bd(e.y,t.y,n.y)}function PS(e,{min:t,max:n},r){return t!==void 0&&en&&(e=r?K(n,e,r.max):Math.min(e,n)),e}function Ud(e,t,n){return{min:t!==void 0?e.min+t:void 0,max:n!==void 0?e.max+n-(e.max-e.min):void 0}}function TS(e,{top:t,left:n,bottom:r,right:s}){return{x:Ud(e.x,n,s),y:Ud(e.y,t,r)}}function zd(e,t){let n=t.min-e.min,r=t.max-e.max;return t.max-t.minr?n=Jn(t.min,t.max-r,e.min):r>s&&(n=Jn(e.min,e.max-s,t.min)),yt(0,1,n)}function NS(e,t){const n={};return t.min!==void 0&&(n.min=t.min-e.min),t.max!==void 0&&(n.max=t.max-e.min),n}const ul=.35;function AS(e=ul){return e===!1?e=0:e===!0&&(e=ul),{x:$d(e,"left","right"),y:$d(e,"top","bottom")}}function $d(e,t,n){return{min:Wd(e,t),max:Wd(e,n)}}function Wd(e,t){return typeof e=="number"?e:e[t]||0}const Kd=()=>({translate:0,scale:1,origin:0,originPoint:0}),Mn=()=>({x:Kd(),y:Kd()}),Hd=()=>({min:0,max:0}),J=()=>({x:Hd(),y:Hd()});function Ve(e){return[e("x"),e("y")]}function xg({top:e,left:t,right:n,bottom:r}){return{x:{min:t,max:n},y:{min:e,max:r}}}function RS({x:e,y:t}){return{top:t.min,right:e.max,bottom:t.max,left:e.min}}function LS(e,t){if(!t)return e;const n=t({x:e.left,y:e.top}),r=t({x:e.right,y:e.bottom});return{top:n.y,left:n.x,bottom:r.y,right:r.x}}function Qo(e){return e===void 0||e===1}function cl({scale:e,scaleX:t,scaleY:n}){return!Qo(e)||!Qo(t)||!Qo(n)}function en(e){return cl(e)||wg(e)||e.z||e.rotate||e.rotateX||e.rotateY||e.skewX||e.skewY}function wg(e){return Gd(e.x)||Gd(e.y)}function Gd(e){return e&&e!=="0%"}function Oi(e,t,n){const r=e-n,s=t*r;return n+s}function Xd(e,t,n,r,s){return s!==void 0&&(e=Oi(e,s,r)),Oi(e,n,r)+t}function dl(e,t=0,n=1,r,s){e.min=Xd(e.min,t,n,r,s),e.max=Xd(e.max,t,n,r,s)}function Sg(e,{x:t,y:n}){dl(e.x,t.translate,t.scale,t.originPoint),dl(e.y,n.translate,n.scale,n.originPoint)}const Qd=.999999999999,Yd=1.0000000000001;function DS(e,t,n,r=!1){const s=n.length;if(!s)return;t.x=t.y=1;let i,o;for(let a=0;aQd&&(t.x=1),t.yQd&&(t.y=1)}function _n(e,t){e.min=e.min+t,e.max=e.max+t}function Zd(e,t,n,r,s=.5){const i=K(e.min,e.max,s);dl(e,t,n,i,r)}function Vn(e,t){Zd(e.x,t.x,t.scaleX,t.scale,t.originX),Zd(e.y,t.y,t.scaleY,t.scale,t.originY)}function bg(e,t){return xg(LS(e.getBoundingClientRect(),t))}function FS(e,t,n){const r=bg(e,n),{scroll:s}=t;return s&&(_n(r.x,s.offset.x),_n(r.y,s.offset.y)),r}const kg=({current:e})=>e?e.ownerDocument.defaultView:null,MS=new WeakMap;class _S{constructor(t){this.openDragLock=null,this.isDragging=!1,this.currentDirection=null,this.originPoint={x:0,y:0},this.constraints=!1,this.hasMutatedConstraints=!1,this.elastic=J(),this.visualElement=t}start(t,{snapToCursor:n=!1}={}){const{presenceContext:r}=this.visualElement;if(r&&r.isPresent===!1)return;const s=c=>{const{dragSnapToOrigin:f}=this.getProps();f?this.pauseAnimation():this.stopAnimation(),n&&this.snapToCursor(ys(c).point)},i=(c,f)=>{const{drag:h,dragPropagation:g,onDragStart:v}=this.getProps();if(h&&!g&&(this.openDragLock&&this.openDragLock(),this.openDragLock=j1(h),!this.openDragLock))return;this.isDragging=!0,this.currentDirection=null,this.resolveConstraints(),this.visualElement.projection&&(this.visualElement.projection.isAnimationBlocked=!0,this.visualElement.projection.target=void 0),Ve(S=>{let m=this.getAxisMotionValue(S).get()||0;if(st.test(m)){const{projection:p}=this.visualElement;if(p&&p.layout){const y=p.layout.layoutBox[S];y&&(m=Le(y)*(parseFloat(m)/100))}}this.originPoint[S]=m}),v&&z.postRender(()=>v(c,f)),tl(this.visualElement,"transform");const{animationState:w}=this.visualElement;w&&w.setActive("whileDrag",!0)},o=(c,f)=>{const{dragPropagation:h,dragDirectionLock:g,onDirectionLock:v,onDrag:w}=this.getProps();if(!h&&!this.openDragLock)return;const{offset:S}=f;if(g&&this.currentDirection===null){this.currentDirection=VS(S),this.currentDirection!==null&&v&&v(this.currentDirection);return}this.updateAxis("x",f.point,S),this.updateAxis("y",f.point,S),this.visualElement.render(),w&&w(c,f)},a=(c,f)=>this.stop(c,f),l=()=>Ve(c=>{var f;return this.getAnimationState(c)==="paused"&&((f=this.getAxisMotionValue(c).animation)===null||f===void 0?void 0:f.play())}),{dragSnapToOrigin:u}=this.getProps();this.panSession=new mg(t,{onSessionStart:s,onStart:i,onMove:o,onSessionEnd:a,resumeAnimation:l},{transformPagePoint:this.visualElement.getTransformPagePoint(),dragSnapToOrigin:u,contextWindow:kg(this.visualElement)})}stop(t,n){const r=this.isDragging;if(this.cancel(),!r)return;const{velocity:s}=n;this.startAnimation(s);const{onDragEnd:i}=this.getProps();i&&z.postRender(()=>i(t,n))}cancel(){this.isDragging=!1;const{projection:t,animationState:n}=this.visualElement;t&&(t.isAnimationBlocked=!1),this.panSession&&this.panSession.end(),this.panSession=void 0;const{dragPropagation:r}=this.getProps();!r&&this.openDragLock&&(this.openDragLock(),this.openDragLock=null),n&&n.setActive("whileDrag",!1)}updateAxis(t,n,r){const{drag:s}=this.getProps();if(!r||!Ws(t,s,this.currentDirection))return;const i=this.getAxisMotionValue(t);let o=this.originPoint[t]+r[t];this.constraints&&this.constraints[t]&&(o=PS(o,this.constraints[t],this.elastic[t])),i.set(o)}resolveConstraints(){var t;const{dragConstraints:n,dragElastic:r}=this.getProps(),s=this.visualElement.projection&&!this.visualElement.projection.layout?this.visualElement.projection.measure(!1):(t=this.visualElement.projection)===null||t===void 0?void 0:t.layout,i=this.constraints;n&&Dn(n)?this.constraints||(this.constraints=this.resolveRefConstraints()):n&&s?this.constraints=TS(s.layoutBox,n):this.constraints=!1,this.elastic=AS(r),i!==this.constraints&&s&&this.constraints&&!this.hasMutatedConstraints&&Ve(o=>{this.constraints!==!1&&this.getAxisMotionValue(o)&&(this.constraints[o]=NS(s.layoutBox[o],this.constraints[o]))})}resolveRefConstraints(){const{dragConstraints:t,onMeasureDragConstraints:n}=this.getProps();if(!t||!Dn(t))return!1;const r=t.current,{projection:s}=this.visualElement;if(!s||!s.layout)return!1;const i=FS(r,s.root,this.visualElement.getTransformPagePoint());let o=ES(s.layout.layoutBox,i);if(n){const a=n(RS(o));this.hasMutatedConstraints=!!a,a&&(o=xg(a))}return o}startAnimation(t){const{drag:n,dragMomentum:r,dragElastic:s,dragTransition:i,dragSnapToOrigin:o,onDragTransitionEnd:a}=this.getProps(),l=this.constraints||{},u=Ve(c=>{if(!Ws(c,n,this.currentDirection))return;let f=l&&l[c]||{};o&&(f={min:0,max:0});const h=s?200:1e6,g=s?40:1e7,v={type:"inertia",velocity:r?t[c]:0,bounceStiffness:h,bounceDamping:g,timeConstant:750,restDelta:1,restSpeed:10,...i,...f};return this.startAxisValueAnimation(c,v)});return Promise.all(u).then(a)}startAxisValueAnimation(t,n){const r=this.getAxisMotionValue(t);return tl(this.visualElement,t),r.start(zu(t,r,0,n,this.visualElement,!1))}stopAnimation(){Ve(t=>this.getAxisMotionValue(t).stop())}pauseAnimation(){Ve(t=>{var n;return(n=this.getAxisMotionValue(t).animation)===null||n===void 0?void 0:n.pause()})}getAnimationState(t){var n;return(n=this.getAxisMotionValue(t).animation)===null||n===void 0?void 0:n.state}getAxisMotionValue(t){const n=`_drag${t.toUpperCase()}`,r=this.visualElement.getProps(),s=r[n];return s||this.visualElement.getValue(t,(r.initial?r.initial[t]:void 0)||0)}snapToCursor(t){Ve(n=>{const{drag:r}=this.getProps();if(!Ws(n,r,this.currentDirection))return;const{projection:s}=this.visualElement,i=this.getAxisMotionValue(n);if(s&&s.layout){const{min:o,max:a}=s.layout.layoutBox[n];i.set(t[n]-K(o,a,.5))}})}scalePositionWithinConstraints(){if(!this.visualElement.current)return;const{drag:t,dragConstraints:n}=this.getProps(),{projection:r}=this.visualElement;if(!Dn(n)||!r||!this.constraints)return;this.stopAnimation();const s={x:0,y:0};Ve(o=>{const a=this.getAxisMotionValue(o);if(a&&this.constraints!==!1){const l=a.get();s[o]=jS({min:l,max:l},this.constraints[o])}});const{transformTemplate:i}=this.visualElement.getProps();this.visualElement.current.style.transform=i?i({},""):"none",r.root&&r.root.updateScroll(),r.updateLayout(),this.resolveConstraints(),Ve(o=>{if(!Ws(o,t,null))return;const a=this.getAxisMotionValue(o),{min:l,max:u}=this.constraints[o];a.set(K(l,u,s[o]))})}addListeners(){if(!this.visualElement.current)return;MS.set(this.visualElement,this);const t=this.visualElement.current,n=Fr(t,"pointerdown",l=>{const{drag:u,dragListener:c=!0}=this.getProps();u&&c&&this.start(l)}),r=()=>{const{dragConstraints:l}=this.getProps();Dn(l)&&l.current&&(this.constraints=this.resolveRefConstraints())},{projection:s}=this.visualElement,i=s.addEventListener("measure",r);s&&!s.layout&&(s.root&&s.root.updateScroll(),s.updateLayout()),z.read(r);const o=os(window,"resize",()=>this.scalePositionWithinConstraints()),a=s.addEventListener("didUpdate",({delta:l,hasLayoutChanged:u})=>{this.isDragging&&u&&(Ve(c=>{const f=this.getAxisMotionValue(c);f&&(this.originPoint[c]+=l[c].translate,f.set(f.get()+l[c].translate))}),this.visualElement.render())});return()=>{o(),n(),i(),a&&a()}}getProps(){const t=this.visualElement.getProps(),{drag:n=!1,dragDirectionLock:r=!1,dragPropagation:s=!1,dragConstraints:i=!1,dragElastic:o=ul,dragMomentum:a=!0}=t;return{...t,drag:n,dragDirectionLock:r,dragPropagation:s,dragConstraints:i,dragElastic:o,dragMomentum:a}}}function Ws(e,t,n){return(t===!0||t===e)&&(n===null||n===e)}function VS(e,t=10){let n=null;return Math.abs(e.y)>t?n="y":Math.abs(e.x)>t&&(n="x"),n}class OS extends Gt{constructor(t){super(t),this.removeGroupControls=Ae,this.removeListeners=Ae,this.controls=new _S(t)}mount(){const{dragControls:t}=this.node.getProps();t&&(this.removeGroupControls=t.subscribe(this.controls)),this.removeListeners=this.controls.addListeners()||Ae}unmount(){this.removeGroupControls(),this.removeListeners()}}const Jd=e=>(t,n)=>{e&&z.postRender(()=>e(t,n))};class IS extends Gt{constructor(){super(...arguments),this.removePointerDownListener=Ae}onPointerDown(t){this.session=new mg(t,this.createPanHandlers(),{transformPagePoint:this.node.getTransformPagePoint(),contextWindow:kg(this.node)})}createPanHandlers(){const{onPanSessionStart:t,onPanStart:n,onPan:r,onPanEnd:s}=this.node.getProps();return{onSessionStart:Jd(t),onStart:Jd(n),onMove:r,onEnd:(i,o)=>{delete this.session,s&&z.postRender(()=>s(i,o))}}}mount(){this.removePointerDownListener=Fr(this.node.current,"pointerdown",t=>this.onPointerDown(t))}update(){this.session&&this.session.updateHandlers(this.createPanHandlers())}unmount(){this.removePointerDownListener(),this.session&&this.session.end()}}const ii={hasAnimatedSinceResize:!0,hasEverUpdated:!1};function qd(e,t){return t.max===t.min?0:e/(t.max-t.min)*100}const mr={correct:(e,t)=>{if(!t.target)return e;if(typeof e=="string")if(R.test(e))e=parseFloat(e);else return e;const n=qd(e,t.target.x),r=qd(e,t.target.y);return`${n}% ${r}%`}},BS={correct:(e,{treeScale:t,projectionDelta:n})=>{const r=e,s=zt.parse(e);if(s.length>5)return r;const i=zt.createTransformer(e),o=typeof s[0]!="number"?1:0,a=n.x.scale*t.x,l=n.y.scale*t.y;s[0+o]/=a,s[1+o]/=l;const u=K(a,l,.5);return typeof s[2+o]=="number"&&(s[2+o]/=u),typeof s[3+o]=="number"&&(s[3+o]/=u),i(s)}};class US extends x.Component{componentDidMount(){const{visualElement:t,layoutGroup:n,switchLayoutGroup:r,layoutId:s}=this.props,{projection:i}=t;a1(zS),i&&(n.group&&n.group.add(i),r&&r.register&&s&&r.register(i),i.root.didUpdate(),i.addEventListener("animationComplete",()=>{this.safeToRemove()}),i.setOptions({...i.options,onExitComplete:()=>this.safeToRemove()})),ii.hasEverUpdated=!0}getSnapshotBeforeUpdate(t){const{layoutDependency:n,visualElement:r,drag:s,isPresent:i}=this.props,o=r.projection;return o&&(o.isPresent=i,s||t.layoutDependency!==n||n===void 0?o.willUpdate():this.safeToRemove(),t.isPresent!==i&&(i?o.promote():o.relegate()||z.postRender(()=>{const a=o.getStack();(!a||!a.members.length)&&this.safeToRemove()}))),null}componentDidUpdate(){const{projection:t}=this.props.visualElement;t&&(t.root.didUpdate(),yu.postRender(()=>{!t.currentAnimation&&t.isLead()&&this.safeToRemove()}))}componentWillUnmount(){const{visualElement:t,layoutGroup:n,switchLayoutGroup:r}=this.props,{projection:s}=t;s&&(s.scheduleCheckAfterUnmount(),n&&n.group&&n.group.remove(s),r&&r.deregister&&r.deregister(s))}safeToRemove(){const{safeToRemove:t}=this.props;t&&t()}render(){return null}}function Cg(e){const[t,n]=im(),r=x.useContext(uu);return d.jsx(US,{...e,layoutGroup:r,switchLayoutGroup:x.useContext(pm),isPresent:t,safeToRemove:n})}const zS={borderRadius:{...mr,applyTo:["borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius"]},borderTopLeftRadius:mr,borderTopRightRadius:mr,borderBottomLeftRadius:mr,borderBottomRightRadius:mr,boxShadow:BS};function $S(e,t,n){const r=ge(e)?e:ss(e);return r.start(zu("",r,t,n)),r.animation}function WS(e){return e instanceof SVGElement&&e.tagName!=="svg"}const KS=(e,t)=>e.depth-t.depth;class HS{constructor(){this.children=[],this.isDirty=!1}add(t){Ru(this.children,t),this.isDirty=!0}remove(t){Lu(this.children,t),this.isDirty=!0}forEach(t){this.isDirty&&this.children.sort(KS),this.isDirty=!1,this.children.forEach(t)}}function GS(e,t){const n=it.now(),r=({timestamp:s})=>{const i=s-n;i>=t&&(Ut(r),e(i-t))};return z.read(r,!0),()=>Ut(r)}const Pg=["TopLeft","TopRight","BottomLeft","BottomRight"],XS=Pg.length,ef=e=>typeof e=="string"?parseFloat(e):e,tf=e=>typeof e=="number"||R.test(e);function QS(e,t,n,r,s,i){s?(e.opacity=K(0,n.opacity!==void 0?n.opacity:1,YS(r)),e.opacityExit=K(t.opacity!==void 0?t.opacity:1,0,ZS(r))):i&&(e.opacity=K(t.opacity!==void 0?t.opacity:1,n.opacity!==void 0?n.opacity:1,r));for(let o=0;ort?1:n(Jn(e,t,r))}function rf(e,t){e.min=t.min,e.max=t.max}function Me(e,t){rf(e.x,t.x),rf(e.y,t.y)}function sf(e,t){e.translate=t.translate,e.scale=t.scale,e.originPoint=t.originPoint,e.origin=t.origin}function of(e,t,n,r,s){return e-=t,e=Oi(e,1/n,r),s!==void 0&&(e=Oi(e,1/s,r)),e}function JS(e,t=0,n=1,r=.5,s,i=e,o=e){if(st.test(t)&&(t=parseFloat(t),t=K(o.min,o.max,t/100)-o.min),typeof t!="number")return;let a=K(i.min,i.max,r);e===i&&(a-=t),e.min=of(e.min,t,n,a,s),e.max=of(e.max,t,n,a,s)}function af(e,t,[n,r,s],i,o){JS(e,t[n],t[r],t[s],t.scale,i,o)}const qS=["x","scaleX","originX"],eb=["y","scaleY","originY"];function lf(e,t,n,r){af(e.x,t,qS,n?n.x:void 0,r?r.x:void 0),af(e.y,t,eb,n?n.y:void 0,r?r.y:void 0)}function uf(e){return e.translate===0&&e.scale===1}function Eg(e){return uf(e.x)&&uf(e.y)}function cf(e,t){return e.min===t.min&&e.max===t.max}function tb(e,t){return cf(e.x,t.x)&&cf(e.y,t.y)}function df(e,t){return Math.round(e.min)===Math.round(t.min)&&Math.round(e.max)===Math.round(t.max)}function jg(e,t){return df(e.x,t.x)&&df(e.y,t.y)}function ff(e){return Le(e.x)/Le(e.y)}function hf(e,t){return e.translate===t.translate&&e.scale===t.scale&&e.originPoint===t.originPoint}class nb{constructor(){this.members=[]}add(t){Ru(this.members,t),t.scheduleRender()}remove(t){if(Lu(this.members,t),t===this.prevLead&&(this.prevLead=void 0),t===this.lead){const n=this.members[this.members.length-1];n&&this.promote(n)}}relegate(t){const n=this.members.findIndex(s=>t===s);if(n===0)return!1;let r;for(let s=n;s>=0;s--){const i=this.members[s];if(i.isPresent!==!1){r=i;break}}return r?(this.promote(r),!0):!1}promote(t,n){const r=this.lead;if(t!==r&&(this.prevLead=r,this.lead=t,t.show(),r)){r.instance&&r.scheduleRender(),t.scheduleRender(),t.resumeFrom=r,n&&(t.resumeFrom.preserveOpacity=!0),r.snapshot&&(t.snapshot=r.snapshot,t.snapshot.latestValues=r.animationValues||r.latestValues),t.root&&t.root.isUpdating&&(t.isLayoutDirty=!0);const{crossfade:s}=t.options;s===!1&&r.hide()}}exitAnimationComplete(){this.members.forEach(t=>{const{options:n,resumingFrom:r}=t;n.onExitComplete&&n.onExitComplete(),r&&r.options.onExitComplete&&r.options.onExitComplete()})}scheduleRender(){this.members.forEach(t=>{t.instance&&t.scheduleRender(!1)})}removeLeadSnapshot(){this.lead&&this.lead.snapshot&&(this.lead.snapshot=void 0)}}function rb(e,t,n){let r="";const s=e.x.translate/t.x,i=e.y.translate/t.y,o=(n==null?void 0:n.z)||0;if((s||i||o)&&(r=`translate3d(${s}px, ${i}px, ${o}px) `),(t.x!==1||t.y!==1)&&(r+=`scale(${1/t.x}, ${1/t.y}) `),n){const{transformPerspective:u,rotate:c,rotateX:f,rotateY:h,skewX:g,skewY:v}=n;u&&(r=`perspective(${u}px) ${r}`),c&&(r+=`rotate(${c}deg) `),f&&(r+=`rotateX(${f}deg) `),h&&(r+=`rotateY(${h}deg) `),g&&(r+=`skewX(${g}deg) `),v&&(r+=`skewY(${v}deg) `)}const a=e.x.scale*t.x,l=e.y.scale*t.y;return(a!==1||l!==1)&&(r+=`scale(${a}, ${l})`),r||"none"}const tn={type:"projectionFrame",totalNodes:0,resolvedTargetDeltas:0,recalculatedProjection:0},br=typeof window<"u"&&window.MotionDebug!==void 0,Yo=["","X","Y","Z"],sb={visibility:"hidden"},pf=1e3;let ib=0;function Zo(e,t,n,r){const{latestValues:s}=t;s[e]&&(n[e]=s[e],t.setStaticValue(e,0),r&&(r[e]=0))}function Ng(e){if(e.hasCheckedOptimisedAppear=!0,e.root===e)return;const{visualElement:t}=e.options;if(!t)return;const n=Vm(t);if(window.MotionHasOptimisedAnimation(n,"transform")){const{layout:s,layoutId:i}=e.options;window.MotionCancelOptimisedAnimation(n,"transform",z,!(s||i))}const{parent:r}=e;r&&!r.hasCheckedOptimisedAppear&&Ng(r)}function Ag({attachResizeListener:e,defaultParent:t,measureScroll:n,checkIsScrollRoot:r,resetTransform:s}){return class{constructor(o={},a=t==null?void 0:t()){this.id=ib++,this.animationId=0,this.children=new Set,this.options={},this.isTreeAnimating=!1,this.isAnimationBlocked=!1,this.isLayoutDirty=!1,this.isProjectionDirty=!1,this.isSharedProjectionDirty=!1,this.isTransformDirty=!1,this.updateManuallyBlocked=!1,this.updateBlockedByResize=!1,this.isUpdating=!1,this.isSVG=!1,this.needsReset=!1,this.shouldResetTransform=!1,this.hasCheckedOptimisedAppear=!1,this.treeScale={x:1,y:1},this.eventHandlers=new Map,this.hasTreeAnimated=!1,this.updateScheduled=!1,this.scheduleUpdate=()=>this.update(),this.projectionUpdateScheduled=!1,this.checkUpdateFailed=()=>{this.isUpdating&&(this.isUpdating=!1,this.clearAllSnapshots())},this.updateProjection=()=>{this.projectionUpdateScheduled=!1,br&&(tn.totalNodes=tn.resolvedTargetDeltas=tn.recalculatedProjection=0),this.nodes.forEach(lb),this.nodes.forEach(hb),this.nodes.forEach(pb),this.nodes.forEach(ub),br&&window.MotionDebug.record(tn)},this.resolvedRelativeTargetAt=0,this.hasProjected=!1,this.isVisible=!0,this.animationProgress=0,this.sharedNodes=new Map,this.latestValues=o,this.root=a?a.root||a:this,this.path=a?[...a.path,a]:[],this.parent=a,this.depth=a?a.depth+1:0;for(let l=0;lthis.root.updateBlockedByResize=!1;e(o,()=>{this.root.updateBlockedByResize=!0,f&&f(),f=GS(h,250),ii.hasAnimatedSinceResize&&(ii.hasAnimatedSinceResize=!1,this.nodes.forEach(gf))})}l&&this.root.registerSharedNode(l,this),this.options.animate!==!1&&c&&(l||u)&&this.addEventListener("didUpdate",({delta:f,hasLayoutChanged:h,hasRelativeTargetChanged:g,layout:v})=>{if(this.isTreeAnimationBlocked()){this.target=void 0,this.relativeTarget=void 0;return}const w=this.options.transition||c.getDefaultTransition()||xb,{onLayoutAnimationStart:S,onLayoutAnimationComplete:m}=c.getProps(),p=!this.targetLayout||!jg(this.targetLayout,v)||g,y=!h&&g;if(this.options.layoutRoot||this.resumeFrom&&this.resumeFrom.instance||y||h&&(p||!this.currentAnimation)){this.resumeFrom&&(this.resumingFrom=this.resumeFrom,this.resumingFrom.resumingFrom=void 0),this.setAnimationOrigin(f,y);const b={...Eu(w,"layout"),onPlay:S,onComplete:m};(c.shouldReduceMotion||this.options.layoutRoot)&&(b.delay=0,b.type=!1),this.startAnimation(b)}else h||gf(this),this.isLead()&&this.options.onExitComplete&&this.options.onExitComplete();this.targetLayout=v})}unmount(){this.options.layoutId&&this.willUpdate(),this.root.nodes.remove(this);const o=this.getStack();o&&o.remove(this),this.parent&&this.parent.children.delete(this),this.instance=void 0,Ut(this.updateProjection)}blockUpdate(){this.updateManuallyBlocked=!0}unblockUpdate(){this.updateManuallyBlocked=!1}isUpdateBlocked(){return this.updateManuallyBlocked||this.updateBlockedByResize}isTreeAnimationBlocked(){return this.isAnimationBlocked||this.parent&&this.parent.isTreeAnimationBlocked()||!1}startUpdate(){this.isUpdateBlocked()||(this.isUpdating=!0,this.nodes&&this.nodes.forEach(mb),this.animationId++)}getTransformTemplate(){const{visualElement:o}=this.options;return o&&o.getProps().transformTemplate}willUpdate(o=!0){if(this.root.hasTreeAnimated=!0,this.root.isUpdateBlocked()){this.options.onExitComplete&&this.options.onExitComplete();return}if(window.MotionCancelOptimisedAnimation&&!this.hasCheckedOptimisedAppear&&Ng(this),!this.root.isUpdating&&this.root.startUpdate(),this.isLayoutDirty)return;this.isLayoutDirty=!0;for(let c=0;c{this.isLayoutDirty?this.root.didUpdate():this.root.checkUpdateFailed()})}updateSnapshot(){this.snapshot||!this.instance||(this.snapshot=this.measure())}updateLayout(){if(!this.instance||(this.updateScroll(),!(this.options.alwaysMeasureLayout&&this.isLead())&&!this.isLayoutDirty))return;if(this.resumeFrom&&!this.resumeFrom.instance)for(let l=0;l{const k=b/1e3;yf(f.x,o.x,k),yf(f.y,o.y,k),this.setTargetDelta(f),this.relativeTarget&&this.relativeTargetOrigin&&this.layout&&this.relativeParent&&this.relativeParent.layout&&(_r(h,this.layout.layoutBox,this.relativeParent.layout.layoutBox),yb(this.relativeTarget,this.relativeTargetOrigin,h,k),y&&tb(this.relativeTarget,y)&&(this.isProjectionDirty=!1),y||(y=J()),Me(y,this.relativeTarget)),w&&(this.animationValues=c,QS(c,u,this.latestValues,k,p,m)),this.root.scheduleUpdateProjection(),this.scheduleRender(),this.animationProgress=k},this.mixTargetDelta(this.options.layoutRoot?1e3:0)}startAnimation(o){this.notifyListeners("animationStart"),this.currentAnimation&&this.currentAnimation.stop(),this.resumingFrom&&this.resumingFrom.currentAnimation&&this.resumingFrom.currentAnimation.stop(),this.pendingAnimation&&(Ut(this.pendingAnimation),this.pendingAnimation=void 0),this.pendingAnimation=z.update(()=>{ii.hasAnimatedSinceResize=!0,this.currentAnimation=$S(0,pf,{...o,onUpdate:a=>{this.mixTargetDelta(a),o.onUpdate&&o.onUpdate(a)},onComplete:()=>{o.onComplete&&o.onComplete(),this.completeAnimation()}}),this.resumingFrom&&(this.resumingFrom.currentAnimation=this.currentAnimation),this.pendingAnimation=void 0})}completeAnimation(){this.resumingFrom&&(this.resumingFrom.currentAnimation=void 0,this.resumingFrom.preserveOpacity=void 0);const o=this.getStack();o&&o.exitAnimationComplete(),this.resumingFrom=this.currentAnimation=this.animationValues=void 0,this.notifyListeners("animationComplete")}finishAnimation(){this.currentAnimation&&(this.mixTargetDelta&&this.mixTargetDelta(pf),this.currentAnimation.stop()),this.completeAnimation()}applyTransformsToTarget(){const o=this.getLead();let{targetWithTransforms:a,target:l,layout:u,latestValues:c}=o;if(!(!a||!l||!u)){if(this!==o&&this.layout&&u&&Rg(this.options.animationType,this.layout.layoutBox,u.layoutBox)){l=this.target||J();const f=Le(this.layout.layoutBox.x);l.x.min=o.target.x.min,l.x.max=l.x.min+f;const h=Le(this.layout.layoutBox.y);l.y.min=o.target.y.min,l.y.max=l.y.min+h}Me(a,l),Vn(a,c),Mr(this.projectionDeltaWithTransform,this.layoutCorrected,a,c)}}registerSharedNode(o,a){this.sharedNodes.has(o)||this.sharedNodes.set(o,new nb),this.sharedNodes.get(o).add(a);const u=a.options.initialPromotionConfig;a.promote({transition:u?u.transition:void 0,preserveFollowOpacity:u&&u.shouldPreserveFollowOpacity?u.shouldPreserveFollowOpacity(a):void 0})}isLead(){const o=this.getStack();return o?o.lead===this:!0}getLead(){var o;const{layoutId:a}=this.options;return a?((o=this.getStack())===null||o===void 0?void 0:o.lead)||this:this}getPrevLead(){var o;const{layoutId:a}=this.options;return a?(o=this.getStack())===null||o===void 0?void 0:o.prevLead:void 0}getStack(){const{layoutId:o}=this.options;if(o)return this.root.sharedNodes.get(o)}promote({needsReset:o,transition:a,preserveFollowOpacity:l}={}){const u=this.getStack();u&&u.promote(this,l),o&&(this.projectionDelta=void 0,this.needsReset=!0),a&&this.setOptions({transition:a})}relegate(){const o=this.getStack();return o?o.relegate(this):!1}resetSkewAndRotation(){const{visualElement:o}=this.options;if(!o)return;let a=!1;const{latestValues:l}=o;if((l.z||l.rotate||l.rotateX||l.rotateY||l.rotateZ||l.skewX||l.skewY)&&(a=!0),!a)return;const u={};l.z&&Zo("z",o,u,this.animationValues);for(let c=0;c{var a;return(a=o.currentAnimation)===null||a===void 0?void 0:a.stop()}),this.root.nodes.forEach(mf),this.root.sharedNodes.clear()}}}function ob(e){e.updateLayout()}function ab(e){var t;const n=((t=e.resumeFrom)===null||t===void 0?void 0:t.snapshot)||e.snapshot;if(e.isLead()&&e.layout&&n&&e.hasListeners("didUpdate")){const{layoutBox:r,measuredBox:s}=e.layout,{animationType:i}=e.options,o=n.source!==e.layout.source;i==="size"?Ve(f=>{const h=o?n.measuredBox[f]:n.layoutBox[f],g=Le(h);h.min=r[f].min,h.max=h.min+g}):Rg(i,n.layoutBox,r)&&Ve(f=>{const h=o?n.measuredBox[f]:n.layoutBox[f],g=Le(r[f]);h.max=h.min+g,e.relativeTarget&&!e.currentAnimation&&(e.isProjectionDirty=!0,e.relativeTarget[f].max=e.relativeTarget[f].min+g)});const a=Mn();Mr(a,r,n.layoutBox);const l=Mn();o?Mr(l,e.applyTransform(s,!0),n.measuredBox):Mr(l,r,n.layoutBox);const u=!Eg(a);let c=!1;if(!e.resumeFrom){const f=e.getClosestProjectingParent();if(f&&!f.resumeFrom){const{snapshot:h,layout:g}=f;if(h&&g){const v=J();_r(v,n.layoutBox,h.layoutBox);const w=J();_r(w,r,g.layoutBox),jg(v,w)||(c=!0),f.options.layoutRoot&&(e.relativeTarget=w,e.relativeTargetOrigin=v,e.relativeParent=f)}}}e.notifyListeners("didUpdate",{layout:r,snapshot:n,delta:l,layoutDelta:a,hasLayoutChanged:u,hasRelativeTargetChanged:c})}else if(e.isLead()){const{onExitComplete:r}=e.options;r&&r()}e.options.transition=void 0}function lb(e){br&&tn.totalNodes++,e.parent&&(e.isProjecting()||(e.isProjectionDirty=e.parent.isProjectionDirty),e.isSharedProjectionDirty||(e.isSharedProjectionDirty=!!(e.isProjectionDirty||e.parent.isProjectionDirty||e.parent.isSharedProjectionDirty)),e.isTransformDirty||(e.isTransformDirty=e.parent.isTransformDirty))}function ub(e){e.isProjectionDirty=e.isSharedProjectionDirty=e.isTransformDirty=!1}function cb(e){e.clearSnapshot()}function mf(e){e.clearMeasurements()}function db(e){e.isLayoutDirty=!1}function fb(e){const{visualElement:t}=e.options;t&&t.getProps().onBeforeLayoutMeasure&&t.notify("BeforeLayoutMeasure"),e.resetTransform()}function gf(e){e.finishAnimation(),e.targetDelta=e.relativeTarget=e.target=void 0,e.isProjectionDirty=!0}function hb(e){e.resolveTargetDelta()}function pb(e){e.calcProjection()}function mb(e){e.resetSkewAndRotation()}function gb(e){e.removeLeadSnapshot()}function yf(e,t,n){e.translate=K(t.translate,0,n),e.scale=K(t.scale,1,n),e.origin=t.origin,e.originPoint=t.originPoint}function vf(e,t,n,r){e.min=K(t.min,n.min,r),e.max=K(t.max,n.max,r)}function yb(e,t,n,r){vf(e.x,t.x,n.x,r),vf(e.y,t.y,n.y,r)}function vb(e){return e.animationValues&&e.animationValues.opacityExit!==void 0}const xb={duration:.45,ease:[.4,0,.1,1]},xf=e=>typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().includes(e),wf=xf("applewebkit/")&&!xf("chrome/")?Math.round:Ae;function Sf(e){e.min=wf(e.min),e.max=wf(e.max)}function wb(e){Sf(e.x),Sf(e.y)}function Rg(e,t,n){return e==="position"||e==="preserve-aspect"&&!kS(ff(t),ff(n),.2)}function Sb(e){var t;return e!==e.root&&((t=e.scroll)===null||t===void 0?void 0:t.wasRoot)}const bb=Ag({attachResizeListener:(e,t)=>os(e,"resize",t),measureScroll:()=>({x:document.documentElement.scrollLeft||document.body.scrollLeft,y:document.documentElement.scrollTop||document.body.scrollTop}),checkIsScrollRoot:()=>!0}),Jo={current:void 0},Lg=Ag({measureScroll:e=>({x:e.scrollLeft,y:e.scrollTop}),defaultParent:()=>{if(!Jo.current){const e=new bb({});e.mount(window),e.setOptions({layoutScroll:!0}),Jo.current=e}return Jo.current},resetTransform:(e,t)=>{e.style.transform=t!==void 0?t:"none"},checkIsScrollRoot:e=>window.getComputedStyle(e).position==="fixed"}),kb={pan:{Feature:IS},drag:{Feature:OS,ProjectionNode:Lg,MeasureLayout:Cg}};function bf(e,t,n){const{props:r}=e;e.animationState&&r.whileHover&&e.animationState.setActive("whileHover",n==="Start");const s="onHover"+n,i=r[s];i&&z.postRender(()=>i(t,ys(t)))}class Cb extends Gt{mount(){const{current:t}=this.node;t&&(this.unmount=k1(t,n=>(bf(this.node,n,"Start"),r=>bf(this.node,r,"End"))))}unmount(){}}class Pb extends Gt{constructor(){super(...arguments),this.isActive=!1}onFocus(){let t=!1;try{t=this.node.current.matches(":focus-visible")}catch{t=!0}!t||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!0),this.isActive=!0)}onBlur(){!this.isActive||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!1),this.isActive=!1)}mount(){this.unmount=gs(os(this.node.current,"focus",()=>this.onFocus()),os(this.node.current,"blur",()=>this.onBlur()))}unmount(){}}function kf(e,t,n){const{props:r}=e;e.animationState&&r.whileTap&&e.animationState.setActive("whileTap",n==="Start");const s="onTap"+(n==="End"?"":n),i=r[s];i&&z.postRender(()=>i(t,ys(t)))}class Tb extends Gt{mount(){const{current:t}=this.node;t&&(this.unmount=E1(t,n=>(kf(this.node,n,"Start"),(r,{success:s})=>kf(this.node,r,s?"End":"Cancel")),{useGlobalTarget:this.node.props.globalTapTarget}))}unmount(){}}const fl=new WeakMap,qo=new WeakMap,Eb=e=>{const t=fl.get(e.target);t&&t(e)},jb=e=>{e.forEach(Eb)};function Nb({root:e,...t}){const n=e||document;qo.has(n)||qo.set(n,{});const r=qo.get(n),s=JSON.stringify(t);return r[s]||(r[s]=new IntersectionObserver(jb,{root:e,...t})),r[s]}function Ab(e,t,n){const r=Nb(t);return fl.set(e,n),r.observe(e),()=>{fl.delete(e),r.unobserve(e)}}const Rb={some:0,all:1};class Lb extends Gt{constructor(){super(...arguments),this.hasEnteredView=!1,this.isInView=!1}startObserver(){this.unmount();const{viewport:t={}}=this.node.getProps(),{root:n,margin:r,amount:s="some",once:i}=t,o={root:n?n.current:void 0,rootMargin:r,threshold:typeof s=="number"?s:Rb[s]},a=l=>{const{isIntersecting:u}=l;if(this.isInView===u||(this.isInView=u,i&&!u&&this.hasEnteredView))return;u&&(this.hasEnteredView=!0),this.node.animationState&&this.node.animationState.setActive("whileInView",u);const{onViewportEnter:c,onViewportLeave:f}=this.node.getProps(),h=u?c:f;h&&h(l)};return Ab(this.node.current,o,a)}mount(){this.startObserver()}update(){if(typeof IntersectionObserver>"u")return;const{props:t,prevProps:n}=this.node;["amount","margin","root"].some(Db(t,n))&&this.startObserver()}unmount(){}}function Db({viewport:e={}},{viewport:t={}}={}){return n=>e[n]!==t[n]}const Fb={inView:{Feature:Lb},tap:{Feature:Tb},focus:{Feature:Pb},hover:{Feature:Cb}},Mb={layout:{ProjectionNode:Lg,MeasureLayout:Cg}},hl={current:null},Dg={current:!1};function _b(){if(Dg.current=!0,!!fu)if(window.matchMedia){const e=window.matchMedia("(prefers-reduced-motion)"),t=()=>hl.current=e.matches;e.addListener(t),t()}else hl.current=!1}const Vb=[...sg,pe,zt],Ob=e=>Vb.find(rg(e)),Cf=new WeakMap;function Ib(e,t,n){for(const r in t){const s=t[r],i=n[r];if(ge(s))e.addValue(r,s);else if(ge(i))e.addValue(r,ss(s,{owner:e}));else if(i!==s)if(e.hasValue(r)){const o=e.getValue(r);o.liveStyle===!0?o.jump(s):o.hasAnimated||o.set(s)}else{const o=e.getStaticValue(r);e.addValue(r,ss(o!==void 0?o:s,{owner:e}))}}for(const r in n)t[r]===void 0&&e.removeValue(r);return t}const Pf=["AnimationStart","AnimationComplete","Update","BeforeLayoutMeasure","LayoutMeasure","LayoutAnimationStart","LayoutAnimationComplete"];class Bb{scrapeMotionValuesFromProps(t,n,r){return{}}constructor({parent:t,props:n,presenceContext:r,reducedMotionConfig:s,blockInitialAnimation:i,visualState:o},a={}){this.current=null,this.children=new Set,this.isVariantNode=!1,this.isControllingVariants=!1,this.shouldReduceMotion=null,this.values=new Map,this.KeyframeResolver=Iu,this.features={},this.valueSubscriptions=new Map,this.prevMotionValues={},this.events={},this.propEventSubscriptions={},this.notifyUpdate=()=>this.notify("Update",this.latestValues),this.render=()=>{this.current&&(this.triggerBuild(),this.renderInstance(this.current,this.renderState,this.props.style,this.projection))},this.renderScheduledAt=0,this.scheduleRender=()=>{const g=it.now();this.renderScheduledAtthis.bindToMotionValue(r,n)),Dg.current||_b(),this.shouldReduceMotion=this.reducedMotionConfig==="never"?!1:this.reducedMotionConfig==="always"?!0:hl.current,this.parent&&this.parent.children.add(this),this.update(this.props,this.presenceContext)}unmount(){Cf.delete(this.current),this.projection&&this.projection.unmount(),Ut(this.notifyUpdate),Ut(this.render),this.valueSubscriptions.forEach(t=>t()),this.valueSubscriptions.clear(),this.removeFromVariantTree&&this.removeFromVariantTree(),this.parent&&this.parent.children.delete(this);for(const t in this.events)this.events[t].clear();for(const t in this.features){const n=this.features[t];n&&(n.unmount(),n.isMounted=!1)}this.current=null}bindToMotionValue(t,n){this.valueSubscriptions.has(t)&&this.valueSubscriptions.get(t)();const r=xn.has(t),s=n.on("change",a=>{this.latestValues[t]=a,this.props.onUpdate&&z.preRender(this.notifyUpdate),r&&this.projection&&(this.projection.isTransformDirty=!0)}),i=n.on("renderRequest",this.scheduleRender);let o;window.MotionCheckAppearSync&&(o=window.MotionCheckAppearSync(this,t,n)),this.valueSubscriptions.set(t,()=>{s(),i(),o&&o(),n.owner&&n.stop()})}sortNodePosition(t){return!this.current||!this.sortInstanceNodePosition||this.type!==t.type?0:this.sortInstanceNodePosition(this.current,t.current)}updateFeatures(){let t="animation";for(t in qn){const n=qn[t];if(!n)continue;const{isEnabled:r,Feature:s}=n;if(!this.features[t]&&s&&r(this.props)&&(this.features[t]=new s(this)),this.features[t]){const i=this.features[t];i.isMounted?i.update():(i.mount(),i.isMounted=!0)}}}triggerBuild(){this.build(this.renderState,this.latestValues,this.props)}measureViewportBox(){return this.current?this.measureInstanceViewportBox(this.current,this.props):J()}getStaticValue(t){return this.latestValues[t]}setStaticValue(t,n){this.latestValues[t]=n}update(t,n){(t.transformTemplate||this.props.transformTemplate)&&this.scheduleRender(),this.prevProps=this.props,this.props=t,this.prevPresenceContext=this.presenceContext,this.presenceContext=n;for(let r=0;rn.variantChildren.delete(t)}addValue(t,n){const r=this.values.get(t);n!==r&&(r&&this.removeValue(t),this.bindToMotionValue(t,n),this.values.set(t,n),this.latestValues[t]=n.get())}removeValue(t){this.values.delete(t);const n=this.valueSubscriptions.get(t);n&&(n(),this.valueSubscriptions.delete(t)),delete this.latestValues[t],this.removeValueFromRenderState(t,this.renderState)}hasValue(t){return this.values.has(t)}getValue(t,n){if(this.props.values&&this.props.values[t])return this.props.values[t];let r=this.values.get(t);return r===void 0&&n!==void 0&&(r=ss(n===null?void 0:n,{owner:this}),this.addValue(t,r)),r}readValue(t,n){var r;let s=this.latestValues[t]!==void 0||!this.current?this.latestValues[t]:(r=this.getBaseTargetFromProps(this.props,t))!==null&&r!==void 0?r:this.readValueFromInstance(this.current,t,this.options);return s!=null&&(typeof s=="string"&&(tg(s)||Hm(s))?s=parseFloat(s):!Ob(s)&&zt.test(n)&&(s=Jm(t,n)),this.setBaseTarget(t,ge(s)?s.get():s)),ge(s)?s.get():s}setBaseTarget(t,n){this.baseTarget[t]=n}getBaseTarget(t){var n;const{initial:r}=this.props;let s;if(typeof r=="string"||typeof r=="object"){const o=xu(this.props,r,(n=this.presenceContext)===null||n===void 0?void 0:n.custom);o&&(s=o[t])}if(r&&s!==void 0)return s;const i=this.getBaseTargetFromProps(this.props,t);return i!==void 0&&!ge(i)?i:this.initialValues[t]!==void 0&&s===void 0?void 0:this.baseTarget[t]}on(t,n){return this.events[t]||(this.events[t]=new Du),this.events[t].add(n)}notify(t,...n){this.events[t]&&this.events[t].notify(...n)}}class Fg extends Bb{constructor(){super(...arguments),this.KeyframeResolver=ig}sortInstanceNodePosition(t,n){return t.compareDocumentPosition(n)&2?1:-1}getBaseTargetFromProps(t,n){return t.style?t.style[n]:void 0}removeValueFromRenderState(t,{vars:n,style:r}){delete n[t],delete r[t]}handleChildMotionValue(){this.childSubscription&&(this.childSubscription(),delete this.childSubscription);const{children:t}=this.props;ge(t)&&(this.childSubscription=t.on("change",n=>{this.current&&(this.current.textContent=`${n}`)}))}}function Ub(e){return window.getComputedStyle(e)}class zb extends Fg{constructor(){super(...arguments),this.type="html",this.renderInstance=Sm}readValueFromInstance(t,n){if(xn.has(n)){const r=Ou(n);return r&&r.default||0}else{const r=Ub(t),s=(vm(n)?r.getPropertyValue(n):r[n])||0;return typeof s=="string"?s.trim():s}}measureInstanceViewportBox(t,{transformPagePoint:n}){return bg(t,n)}build(t,n,r){bu(t,n,r.transformTemplate)}scrapeMotionValuesFromProps(t,n,r){return Tu(t,n,r)}}class $b extends Fg{constructor(){super(...arguments),this.type="svg",this.isSVGTag=!1,this.measureInstanceViewportBox=J}getBaseTargetFromProps(t,n){return t[n]}readValueFromInstance(t,n){if(xn.has(n)){const r=Ou(n);return r&&r.default||0}return n=bm.has(n)?n:gu(n),t.getAttribute(n)}scrapeMotionValuesFromProps(t,n,r){return Pm(t,n,r)}build(t,n,r){ku(t,n,this.isSVGTag,r.transformTemplate)}renderInstance(t,n,r,s){km(t,n,r,s)}mount(t){this.isSVGTag=Pu(t.tagName),super.mount(t)}}const Wb=(e,t)=>vu(e)?new $b(t):new zb(t,{allowProjection:e!==x.Fragment}),Kb=g1({...pS,...Fb,...kb,...Mb},Wb),O=Rx(Kb);function Mg(){return(localStorage.getItem("apiBase")||"").replace(/\/+$/,"")}function vs(e){const t=Mg(),n=e.startsWith("/")?e:`/${e}`;return t?`${t}${n}`:n}async function $u(e){const t=await fetch(vs(e));if(!t.ok)throw new Error(await t.text());return t.json()}async function vt(e,t){const n=await fetch(vs(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok)throw new Error(await n.text());return n.json()}const Hb=()=>{const e=Mg();if(e)try{const r=new URL(e.includes("://")?e:`http://${e}`);return`${r.protocol==="https:"?"wss:":"ws:"}//${r.host}/ws`}catch{}const t=window.location;return`${t.protocol==="https:"?"wss:":"ws:"}//${t.host}/ws`};function Gb(e){const[t,n]=x.useState(!1),r=x.useRef(e);return r.current=e,x.useEffect(()=>{let s=!1,i=0,o,a=null;const l=()=>{s||(a=new WebSocket(Hb()),a.onopen=()=>{i=0,n(!0),a==null||a.send("ping")},a.onclose=()=>{n(!1),i+=1,o=setTimeout(l,Math.min(8e3,500+i*400))},a.onerror=()=>a==null?void 0:a.close(),a.onmessage=u=>r.current(String(u.data)))};return l(),()=>{s=!0,clearTimeout(o),a==null||a.close()}},[]),t}const _g=x.createContext(null),Wu=5e3,Ku="pn532_browser_log_v1";function Xb(){try{const e=sessionStorage.getItem(Ku);if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?t.slice(-Wu):[]}catch{return[]}}function Qb(e){try{sessionStorage.setItem(Ku,JSON.stringify(e.slice(-Wu)))}catch{}}function Yb(e,t,n){if(typeof e=="object"&&e&&"present"in e&&e.present===!1){t(null),n(!1);return}n(!0),typeof e=="object"&&e&&"uid"in e&&t(e)}function Zb(e){if(!e||typeof e!="object")return!1;const t=e;return t.present===!1?!1:typeof t.uid=="string"&&t.uid.length>0}function Jb(e){return!e||typeof e!="object"?!1:e.event==="recorded"}function qb({children:e}){const[t,n]=x.useState(null),[r,s]=x.useState(!1),[i,o]=x.useState(()=>Xb()),[a,l]=x.useState(0),[u,c]=x.useState("tag"),f=x.useRef(0),h=x.useCallback(y=>{const b=Date.now();y==="tag"&&b-f.current<280||(f.current=b,c(y),l(k=>k+1))},[]),g=x.useCallback(y=>{try{const b=JSON.parse(y),k=b.channel||"unknown";o(C=>{const E=[...C,{t:Date.now(),channel:k,payload:b.payload}].slice(-Wu);return Qb(E),E}),k==="scan"?(Yb(b.payload,n,s),Zb(b.payload)&&h("tag")):k==="capture"&&Jb(b.payload)&&h("vault")}catch{}},[h]),v=Gb(g),w=x.useCallback((y,b)=>{if(!y){n(null),s(!1);return}b&&(n(b),s(!0),h("tag"))},[h]),S=x.useCallback(()=>{o([]),sessionStorage.removeItem(Ku)},[]),m=x.useCallback(()=>{const y=new Blob([JSON.stringify(i,null,2)],{type:"application/json"}),b=URL.createObjectURL(y),k=document.createElement("a");k.href=b,k.download=`pn532-browser-log-${Date.now()}.json`,k.click(),URL.revokeObjectURL(b)},[i]),p=x.useMemo(()=>({wsOk:v,lastTag:t,tagPresent:r,log:i,cashWave:a,cashVariant:u,clearBrowserLog:S,exportBrowserLog:m,applyScanPoll:w}),[v,t,r,i,a,u,S,m,w]);return d.jsx(_g.Provider,{value:p,children:e})}function xs(){const e=x.useContext(_g);if(!e)throw new Error("useNfcWs outside NfcWsProvider");return e}function e2(){const{log:e,exportBrowserLog:t,clearBrowserLog:n,wsOk:r}=xs();return d.jsxs("div",{className:"flash-log-bar relative z-40 mx-auto flex max-w-6xl flex-wrap items-center justify-between gap-2 overflow-hidden border-b border-bubble-accent/15 px-4 py-2.5 font-mono text-[10px] text-bubble-mint/80 sm:text-xs",children:[d.jsx("div",{className:"pointer-events-none absolute inset-0 overflow-hidden",children:d.jsx("div",{className:"absolute inset-y-0 left-0 w-1/3 bg-gradient-to-r from-bubble-accent/10 to-transparent animate-shimmerLine"})}),d.jsxs("div",{className:"relative flex min-w-0 flex-1 flex-wrap items-center gap-x-3 gap-y-1",children:[d.jsx("span",{className:"shrink-0 animate-pulse text-bubble-volt",children:"◆"}),d.jsxs("span",{className:"truncate",children:[d.jsx("span",{className:"text-bubble-accent/70",children:"BUF"})," ",d.jsx("span",{className:"text-glow-matrix font-bold text-bubble-mint",children:e.length}),d.jsx("span",{className:"text-bubble-mint/40",children:"_evt"})]}),d.jsx("span",{className:"hidden text-bubble-mint/20 sm:inline",children:"│"}),d.jsxs("span",{children:[d.jsx("span",{className:"text-bubble-accent/60",children:"WS"})," ",d.jsx("span",{className:r?"text-glow-matrix font-bold tracking-wide text-bubble-mint":"animate-pulse text-glow-rose font-semibold text-bubble-rose",children:r?"SYNC":"WAIT"})]})]}),d.jsxs("div",{className:"relative flex shrink-0 gap-2",children:[d.jsx("button",{type:"button",onClick:t,className:"btn-neon rounded-md border border-bubble-accent/50 bg-gradient-to-r from-bubble-accent/25 to-bubble-mint/15 px-3 py-1.5 text-[10px] font-bold uppercase tracking-wider text-bubble-accent sm:text-xs",children:"Exfil"}),d.jsx("button",{type:"button",onClick:n,className:"rounded-md border border-bubble-rose/40 bg-bubble-rose/10 px-3 py-1.5 text-[10px] font-bold uppercase tracking-wide text-bubble-rose transition hover:border-bubble-rose hover:bg-bubble-rose/20 sm:text-xs",children:"Purge"})]})]})}function t2(){return d.jsxs("div",{className:"pointer-events-none fixed inset-0 z-[2] overflow-hidden",children:[d.jsx("div",{className:"absolute -left-[20%] top-[10%] h-[min(70vh,520px)] w-[min(70vh,520px)] rounded-full bg-fuchsia-600/25 blur-[100px] animate-pulseGlow",style:{animationDelay:"0s"}}),d.jsx("div",{className:"absolute -right-[15%] bottom-[5%] h-[min(55vh,440px)] w-[min(55vh,440px)] rounded-full bg-cyan-400/20 blur-[90px] animate-pulseGlow",style:{animationDelay:"1.2s"}}),d.jsx("div",{className:"absolute left-[35%] top-[40%] h-[min(45vh,360px)] w-[min(45vh,360px)] -translate-x-1/2 -translate-y-1/2 rounded-full bg-emerald-400/15 blur-[80px] animate-floatSlow"}),d.jsx("div",{className:"absolute inset-0 bg-[radial-gradient(ellipse_at_center,transparent_0%,rgba(2,4,8,0.75)_100%)]"})]})}const Tf=16,n2=7;function r2(){var e;try{const t=window.AudioContext||window.webkitAudioContext;if(!t)return;const n=new t,r=n.createGain();r.gain.value=.11,r.connect(n.destination);const s=(c,f,h)=>{const g=n.createOscillator(),v=n.createGain();g.type="sine",g.frequency.setValueAtTime(c,f),v.gain.setValueAtTime(0,f),v.gain.linearRampToValueAtTime(1,f+.02),v.gain.exponentialRampToValueAtTime(.01,f+h),g.connect(v),v.connect(r),g.start(f),g.stop(f+h+.05)},i=n.currentTime;s(523.25,i,.11),s(659.25,i+.055,.13),s(783.99,i+.1,.16),s(1046.5,i+.14,.2);const o=n.createBufferSource(),a=n.createBuffer(1,n.sampleRate*.07,n.sampleRate),l=a.getChannelData(0);for(let c=0;cvoid n.close(),700)}catch{}}function s2(){const{cashWave:e,cashVariant:t,lastTag:n}=xs(),[r,s]=x.useState(!1),[i,o]=x.useState(0);return x.useEffect(()=>{if(e===0)return;o(e),s(!0),r2();const a=window.setTimeout(()=>s(!1),1650);return()=>window.clearTimeout(a)},[e]),d.jsx("div",{className:"pointer-events-none fixed left-2 top-[4.25rem] z-[55] sm:left-4 sm:top-[4.5rem] md:top-[5.25rem]",children:d.jsx(am,{mode:"wait",children:r?d.jsxs(O.div,{className:"relative flex flex-col items-start",initial:{opacity:0},animate:{opacity:1},exit:{opacity:0,scale:.92,filter:"blur(4px)"},transition:{duration:.4},children:[d.jsx(O.div,{className:"absolute -left-8 -top-8 h-40 w-40 rounded-full bg-gradient-to-br from-amber-400/45 via-yellow-200/30 to-bubble-mint/35 blur-2xl",initial:{scale:.2,opacity:0},animate:{scale:[.2,1.35,1],opacity:[0,1,.7]},transition:{duration:.5,ease:[.22,1,.36,1]}}),Array.from({length:Tf}).map((a,l)=>{const u=l/Tf*Math.PI*2,c=56+l%4*10;return d.jsx(O.span,{className:"absolute left-8 top-9 h-2 w-2 rounded-full bg-gradient-to-br from-yellow-100 to-amber-500 shadow-[0_0_12px_rgba(250,204,21,1)]",initial:{x:0,y:0,opacity:0,scale:0},animate:{x:Math.cos(u)*c,y:Math.sin(u)*c,opacity:[0,1,0],scale:[0,1.3,.3]},transition:{duration:.8,delay:l*.018,ease:"easeOut"}},`s-${l}`)}),Array.from({length:n2}).map((a,l)=>d.jsx(O.span,{className:"absolute left-8 top-8 text-xl sm:text-2xl",initial:{x:0,y:0,opacity:0,rotate:-30,scale:0},animate:{x:(l%2===0?1:-1)*(36+l*12),y:-32-l*11,opacity:[0,1,0],rotate:l*35,scale:[0,1.15,.85]},transition:{duration:.9,delay:.04+l*.035,ease:[.22,1,.36,1]},children:"🪙"},`c-${l}`)),d.jsxs(O.div,{className:"relative flex h-[4.75rem] w-[4.75rem] items-center justify-center sm:h-[5.5rem] sm:w-[5.5rem]",initial:{scale:0,rotate:-40},animate:{scale:[0,1.3,.92,1.06,1],rotate:[-40,12,-6,3,0]},transition:{duration:.7,ease:[.34,1.56,.64,1]},children:[d.jsx(O.div,{className:"absolute inset-0 rounded-2xl border-2 border-yellow-200/90",animate:{boxShadow:["0 0 25px rgba(250,204,21,0.55), inset 0 0 22px rgba(254,240,138,0.2)","0 0 50px rgba(0,255,157,0.5), inset 0 0 28px rgba(0,229,255,0.15)","0 0 28px rgba(250,204,21,0.6), inset 0 0 18px rgba(254,240,138,0.25)"]},transition:{duration:1.1,repeat:2}}),d.jsxs("svg",{viewBox:"0 0 100 100",className:"relative z-[1] h-[72%] w-[72%] drop-shadow-[0_0_14px_rgba(250,204,21,0.9)]","aria-hidden":!0,children:[d.jsxs("defs",{children:[d.jsxs("linearGradient",{id:"cashGold",x1:"0%",y1:"0%",x2:"100%",y2:"100%",children:[d.jsx("stop",{offset:"0%",stopColor:"#fef9c3"}),d.jsx("stop",{offset:"40%",stopColor:"#facc15"}),d.jsx("stop",{offset:"100%",stopColor:"#a16207"})]}),d.jsxs("filter",{id:"cashGlow",x:"-50%",y:"-50%",width:"200%",height:"200%",children:[d.jsx("feGaussianBlur",{stdDeviation:"1.2",result:"b"}),d.jsxs("feMerge",{children:[d.jsx("feMergeNode",{in:"b"}),d.jsx("feMergeNode",{in:"SourceGraphic"})]})]})]}),d.jsx("circle",{cx:"50",cy:"50",r:"44",fill:"url(#cashGold)",filter:"url(#cashGlow)"}),d.jsx("circle",{cx:"50",cy:"50",r:"40",fill:"none",stroke:"#422006",strokeOpacity:"0.28",strokeWidth:"2"}),d.jsx("text",{x:"50",y:"64",textAnchor:"middle",fill:"#713f12",fontSize:"54",fontWeight:"700",fontFamily:"Audiowide, Orbitron, system-ui, sans-serif",children:"$"})]}),d.jsx(O.div,{className:"pointer-events-none absolute inset-0 overflow-hidden rounded-2xl",initial:!1,children:d.jsx(O.div,{className:"absolute inset-y-2 w-2/5 bg-gradient-to-r from-transparent via-white/60 to-transparent skew-x-[-18deg]",initial:{left:"-40%"},animate:{left:"140%"},transition:{duration:.55,delay:.12,ease:"easeInOut"}})})]}),d.jsxs(O.div,{className:"relative -mt-0.5 max-w-[12rem] pl-0.5",initial:{opacity:0,y:10},animate:{opacity:1,y:0},transition:{delay:.12,type:"spring",stiffness:320,damping:22},children:[d.jsx(O.p,{className:"font-display text-[10px] tracking-[0.42em] text-yellow-100 sm:text-[11px]",animate:{textShadow:["0 0 10px rgba(250,204,21,0.95)","0 0 22px rgba(0,255,157,0.75)","0 0 12px rgba(250,204,21,0.9)"]},transition:{duration:.75,repeat:3},children:t==="vault"?"VAULT · LOCKED":"CHA-CHING · HIT"}),n!=null&&n.uid?d.jsx(O.p,{className:"mt-1 truncate font-mono text-[10px] font-bold tracking-[0.15em] text-bubble-mint sm:text-xs",initial:{opacity:0,x:-6},animate:{opacity:1,x:0},transition:{delay:.22},children:n.uid}):null]})]},i):null})})}const Vg=x.createContext(()=>{});function i2({children:e}){const[t,n]=x.useState([]),r=x.useCallback((i,o="info")=>{const a=Date.now();n(l=>[...l,{id:a,msg:i,kind:o}]),setTimeout(()=>n(l=>l.filter(u=>u.id!==a)),4200)},[]),s=x.useMemo(()=>r,[r]);return d.jsxs(Vg.Provider,{value:s,children:[e,d.jsx("div",{className:"pointer-events-none fixed bottom-5 right-5 z-[60] flex max-w-sm flex-col gap-3",children:d.jsx(am,{children:t.map(i=>d.jsxs(O.div,{initial:{opacity:0,x:40,rotate:-2,scale:.92},animate:{opacity:1,x:0,rotate:0,scale:1},exit:{opacity:0,x:20,scale:.9},transition:{type:"spring",stiffness:380,damping:26},className:`pointer-events-auto relative overflow-hidden border-2 px-5 py-3.5 font-mono text-xs backdrop-blur-md ${i.kind==="err"?"border-bubble-rose bg-bubble-950/95 text-bubble-rose shadow-glowRose":"border-bubble-mint bg-bubble-900/95 text-bubble-mint shadow-glow"} `,children:[d.jsx("div",{className:`pointer-events-none absolute inset-0 opacity-30 ${i.kind==="err"?"bg-gradient-to-r from-bubble-rose/20 to-transparent":"bg-gradient-to-r from-bubble-accent/20 to-bubble-mint/10"}`}),d.jsx("span",{className:"relative mr-2 font-black opacity-80",children:i.kind==="err"?"!!":"»"}),d.jsx("span",{className:"relative",children:i.msg})]},i.id))})})]})}function Je(){return x.useContext(Vg)}function o2(e){const t=e.replace(/\s/g,"");if(t.length!==32)return null;const n=new Uint8Array(16);for(let u=0;u<16;u++)n[u]=parseInt(t.slice(u*2,u*2+2),16);const r=n[6],s=n[7],i=n[8],o=r>>4&1|s>>0&2|i>>0&4,a=r>>5&1|s>>1&2|i>>1&4,l=r>>6&1|s>>2&2|i>>2&4;return{c1:o,c2:a,c3:l}}function Og(e){switch(e){case 8:return"Ultralight family";case 9:return"Mini / Classic";case 24:return"Classic 1K";case 25:return"Classic 4K";default:return`SAK 0x${e.toString(16).toUpperCase()}`}}function Ig(e){var n;const t=e.replace(/\s/g,"");return t.length%2!==0?e:((n=t.match(/.{2}/g))==null?void 0:n.join(":"))??t}function a2(e){switch(e){case 1:return"Classic-style (MIFARE)";case 2:return"Type 2 / Ultralight-style";default:return"Unknown (check SAK/ATQA)"}}function l2(e){const t=[];return e.uidLen===4?t.push("4-byte UID — single cascade level (CL1)."):e.uidLen===7?t.push("7-byte UID — double cascade (CL1 + CL2) typical for 7B tags."):e.uidLen===10&&t.push("10-byte UID — triple cascade path."),e.sak===8&&t.push("SAK 0x08 — often Ultralight / Type 2; use page read/write for user memory."),(e.sak===24||e.sak===25)&&t.push("MIFARE Classic — authenticate per sector trailer, then block read/write."),(e.atqa===68||e.atqa===17408)&&t.push("ATQA 0x4400 pattern — very common Type A inventory response."),t}function u2(e){return e.map(t=>(Number(t)&255).toString(16).toUpperCase().padStart(2,"0")).join(" ")}function c2({className:e=""}){return d.jsx("div",{className:`relative ${e}`.trim(),children:d.jsxs("svg",{viewBox:"0 0 400 220",className:"h-auto w-full max-w-md text-bubble-mint/90","aria-hidden":!0,children:[d.jsxs("defs",{children:[d.jsxs("linearGradient",{id:"g1",x1:"0%",y1:"0%",x2:"100%",y2:"100%",children:[d.jsx("stop",{offset:"0%",stopColor:"currentColor",stopOpacity:"0.9"}),d.jsx("stop",{offset:"100%",stopColor:"#00e5ff",stopOpacity:"0.35"})]}),d.jsxs("filter",{id:"glow",children:[d.jsx("feGaussianBlur",{stdDeviation:"2",result:"b"}),d.jsxs("feMerge",{children:[d.jsx("feMergeNode",{in:"b"}),d.jsx("feMergeNode",{in:"SourceGraphic"})]})]})]}),[0,1,2,3].map(t=>d.jsx("ellipse",{cx:"200",cy:"110",rx:40+t*38,ry:28+t*26,fill:"none",stroke:"currentColor",strokeWidth:"0.6",strokeOpacity:.22-t*.04,className:"origin-center animate-[spin_32s_linear_infinite]",style:{transformOrigin:"200px 110px",animationDelay:`${t*2}s`}},t)),d.jsx("g",{filter:"url(#glow)",children:d.jsx("path",{d:"M200 110 L360 110 A160 80 0 0 1 200 190 Z",fill:"url(#g1)",fillOpacity:"0.12",className:"origin-center animate-[spin_6s_linear_infinite]",style:{transformOrigin:"200px 110px"}})}),d.jsx("circle",{cx:"200",cy:"110",r:"36",fill:"none",stroke:"currentColor",strokeWidth:"1.2",opacity:"0.5"}),d.jsx("circle",{cx:"200",cy:"110",r:"22",fill:"none",stroke:"#00e5ff",strokeWidth:"0.8",opacity:"0.45"}),d.jsx("circle",{cx:"200",cy:"110",r:"8",fill:"currentColor",opacity:"0.35"}),Array.from({length:12}).map((t,n)=>{const r=n/12*Math.PI*2,s=200+Math.cos(r)*118,i=110+Math.sin(r)*78;return d.jsx("rect",{x:s-1,y:i-1,width:"2",height:"2",fill:"currentColor",opacity:.15+n%3*.08,className:"animate-pulse",style:{animationDelay:`${n*.15}s`}},n)}),d.jsx("text",{x:"200",y:"205",textAnchor:"middle",className:"fill-bubble-mint/40 font-mono text-[9px] tracking-[0.35em]",children:"13.56MHZ"})]})})}function d2(){const e=Je(),{lastTag:t,applyScanPoll:n}=xs(),[r,s]=x.useState(null),[i,o]=x.useState(!0),a=()=>{$u("/api/status").then(s).catch(()=>e("Status unreachable","err"))};x.useEffect(()=>{a();const c=setInterval(a,3e3);return()=>clearInterval(c)},[e]),x.useEffect(()=>{r&&typeof r.scanning=="boolean"&&o(r.scanning)},[r]);const l=async()=>{try{await vt("/api/nfc/scan",{enable:!i}),o(!i),e(i?"Continuous scan off":"Continuous scan on")}catch(c){e(String(c),"err")}},u=async()=>{try{const c=await vt("/api/nfc/poll",{});c.present&&c.tag?(n(!0,c.tag),e(`Tag ${c.tag.uid}`)):(n(!1),e("No tag"))}catch(c){e(String(c),"err")}};return d.jsxs("div",{className:"space-y-8",children:[d.jsxs(O.div,{initial:{opacity:0,y:16},animate:{opacity:1,y:0},transition:{duration:.5,ease:[.22,1,.36,1]},className:"glass relative overflow-hidden p-6 md:p-10",children:[d.jsx("div",{className:"pointer-events-none absolute inset-0 bg-[conic-gradient(from_180deg_at_50%_120%,rgba(0,229,255,0.08),transparent_40%,rgba(255,42,109,0.06),transparent_70%)]"}),d.jsxs("div",{className:"relative grid gap-8 lg:grid-cols-[1fr_min(320px,40%)] lg:items-center",children:[d.jsxs("div",{children:[d.jsx("p",{className:"font-mono text-[10px] font-bold tracking-[0.4em] text-bubble-accent/80",children:"COMMAND_LAYER"}),d.jsxs("h1",{className:"font-display mt-2 text-3xl font-normal tracking-wide text-glow-matrix md:text-5xl",children:["NFC ",d.jsx("span",{className:"text-bubble-accent",children:"CONTROL"})]}),d.jsx("p",{className:"mt-3 max-w-xl text-sm leading-relaxed text-slate-400",children:"Full-time scan out of the box. Fat RF retries. Browser log + device session export — crank it from your phone."}),(r==null?void 0:r.session)&&(r.session.deepCapture||r.session.usedBytes>0)&&d.jsxs(O.div,{initial:{opacity:0,scale:.98},animate:{opacity:1,scale:1},className:"mt-5 flex flex-wrap items-center gap-3 rounded-xl border border-bubble-accent/40 bg-gradient-to-r from-bubble-accent/15 to-bubble-mint/10 px-4 py-3 text-sm shadow-glowCyan",children:[d.jsxs("span",{className:"font-mono text-bubble-mint",children:["RAM ",r.session.usedBytes,"/",r.session.maxBytes,r.session.full?" · LOCKED":""]}),d.jsx(sm,{to:"/capture",className:"btn-neon rounded-lg bg-bubble-mint/20 px-3 py-1 text-xs font-bold text-bubble-mint",children:"Read-all →"})]}),d.jsxs("div",{className:"mt-8 flex flex-wrap gap-3",children:[d.jsx(O.button,{type:"button",whileHover:{scale:1.04},whileTap:{scale:.98},onClick:u,className:"btn-neon rounded-xl bg-gradient-to-r from-bubble-accent via-cyan-400 to-bubble-mint px-6 py-3 text-sm font-black uppercase tracking-wider text-bubble-950 shadow-neonBtn",children:"Poll tag"}),d.jsx(O.button,{type:"button",whileHover:{scale:1.03},whileTap:{scale:.98},onClick:l,className:`rounded-xl border-2 px-6 py-3 text-sm font-bold uppercase tracking-wide transition ${i?"border-bubble-mint/70 bg-bubble-mint/15 text-glow-matrix text-bubble-mint shadow-glow":"border-white/20 bg-black/30 text-slate-400 hover:border-bubble-accent/50 hover:text-bubble-accent"}`,children:i?"Stop scan":"Start scan"})]})]}),d.jsx("div",{className:"relative flex justify-center lg:justify-end",children:d.jsx("div",{className:"relative w-full max-w-[280px] opacity-90 drop-shadow-[0_0_40px_rgba(0,229,255,0.35)]",children:d.jsx(c2,{})})})]})]}),d.jsxs("div",{className:"grid gap-5 md:grid-cols-2",children:[d.jsxs(O.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},transition:{delay:.08},className:"glass p-6",children:[d.jsx("h2",{className:"font-display text-lg font-normal text-bubble-accent text-glow-cyan",children:"Device stack"}),r?d.jsxs("ul",{className:"mt-4 space-y-3 font-mono text-sm text-slate-300",children:[d.jsxs("li",{className:"flex justify-between border-b border-white/5 pb-2",children:[d.jsx("span",{className:"text-slate-500",children:"uptime"}),d.jsxs("span",{className:"text-bubble-mint",children:[(r.uptimeMs/1e3).toFixed(1),"s"]})]}),d.jsxs("li",{className:"flex justify-between border-b border-white/5 pb-2",children:[d.jsx("span",{className:"text-slate-500",children:"heap"}),d.jsx("span",{className:"text-white",children:r.freeHeap})]}),d.jsxs("li",{className:"flex justify-between",children:[d.jsx("span",{className:"text-slate-500",children:"PN532"}),d.jsx("span",{className:"text-bubble-accent",children:r.pn532?`IC${r.pn532.ic} v${r.pn532.fwHi}.${r.pn532.fwLo}`:"n/a"})]})]}):d.jsx("p",{className:"mt-4 animate-pulse font-mono text-sm text-bubble-accent/60",children:"Pulling status…"})]}),d.jsxs(O.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},transition:{delay:.14},className:"glass p-6",children:[d.jsx("h2",{className:"font-display text-lg font-normal text-bubble-rose/90 text-glow-rose",children:"Live tag"}),t?d.jsxs("div",{className:"mt-4 space-y-4 rounded-xl border border-bubble-mint/25 bg-black/35 p-4 shadow-glow",children:[d.jsxs("div",{children:[d.jsx("p",{className:"text-[10px] font-mono uppercase tracking-widest text-bubble-mint/50",children:"UID"}),d.jsx("div",{className:"font-mono text-xl font-bold tracking-[0.15em] text-glow-matrix text-bubble-mint md:text-2xl",children:Ig(t.uid)}),d.jsxs("p",{className:"mt-1 font-mono text-[11px] text-slate-500",children:["raw ",t.uid," · ",t.uidLen," byte",t.uidLen===1?"":"s"]})]}),d.jsxs("div",{className:"grid gap-3 border-t border-white/5 pt-3 font-mono text-[11px] text-slate-300 sm:grid-cols-2",children:[d.jsxs("div",{children:[d.jsx("span",{className:"text-slate-500",children:"ATQA"})," ",d.jsxs("span",{className:"text-bubble-accent",children:["0x",(t.atqaHex??t.atqa.toString(16).toUpperCase().padStart(4,"0")).slice(-4)]}),d.jsxs("span",{className:"ml-2 text-slate-500",children:["(",t.atqa,")"]})]}),d.jsxs("div",{children:[d.jsx("span",{className:"text-slate-500",children:"SAK"})," ",d.jsxs("span",{className:"text-bubble-accent",children:["0x",(t.sakHex??t.sak.toString(16).toUpperCase().padStart(2,"0")).slice(-2)]}),d.jsxs("span",{className:"ml-1 text-slate-400",children:["— ",Og(t.sak)]})]}),d.jsxs("div",{className:"sm:col-span-2",children:[d.jsx("span",{className:"text-slate-500",children:"Guess"})," ",d.jsx("span",{className:"text-bubble-mint",children:t.typeGuess??a2(t.typeHint)}),d.jsxs("span",{className:"ml-2 text-slate-600",children:["· hint ",t.typeHint]})]})]}),t.pn532GeneralStatus&&t.pn532GeneralStatus.length>0&&d.jsxs("div",{className:"rounded-lg border border-bubble-accent/20 bg-black/40 p-3",children:[d.jsx("p",{className:"text-[10px] font-mono uppercase tracking-widest text-bubble-accent/70",children:"PN532 general status"}),d.jsx("p",{className:"mt-2 break-all font-mono text-[10px] leading-relaxed text-slate-400",children:u2(t.pn532GeneralStatus)}),d.jsx("p",{className:"mt-2 text-[10px] text-slate-600",children:"Raw bytes from the chip right after this inventory (error flags, last command, tag count — see NXP PN532 user manual)."})]}),d.jsx("ul",{className:"space-y-1 border-t border-white/5 pt-3 text-[11px] leading-relaxed text-slate-500",children:l2(t).map((c,f)=>d.jsxs("li",{className:"flex gap-2",children:[d.jsx("span",{className:"text-bubble-mint/40",children:"▸"}),d.jsx("span",{children:c})]},f))})]}):d.jsx("p",{className:"mt-6 font-mono text-sm text-bubble-mint/40",children:"Listening on the field…"})]})]})]})}function f2(){const e=Je(),[t,n]=x.useState("FFFFFFFFFFFF"),[r,s]=x.useState(!1),[i,o]=x.useState(0),[a,l]=x.useState(""),[u,c]=x.useState(""),f=async()=>{try{const v=await vt("/api/mifare/read-block",{block:i,key:t,keyB:r});v.data?(l(v.data),e("Read OK")):e(v.error||"failed","err")}catch(v){e(String(v),"err")}},h=async()=>{try{const v=await vt("/api/ul/read-page",{page:i});v.data&&(l(v.data+" (UL page)"),e("UL read OK"))}catch(v){e(String(v),"err")}},g=u?o2(u):null;return d.jsxs("div",{className:"space-y-6",children:[d.jsxs("div",{className:"glass p-6",children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Read / analyze"}),d.jsx("p",{className:"mt-2 text-sm text-slate-400",children:"Authenticate with a known key, dump a block, paste a sector trailer to decode access bits."}),d.jsxs("div",{className:"mt-6 grid gap-4 md:grid-cols-2",children:[d.jsxs("label",{className:"block space-y-2 text-sm",children:["Key (12 hex)",d.jsx("input",{value:t,onChange:v=>n(v.target.value),className:"w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2 font-mono text-bubble-mint outline-none ring-bubble-accent/40 focus:ring-2"})]}),d.jsxs("label",{className:"flex items-end gap-3 text-sm",children:[d.jsx("input",{type:"checkbox",checked:r,onChange:v=>s(v.target.checked)})," Key B"]}),d.jsxs("label",{className:"block space-y-2 text-sm",children:["Block / page",d.jsx("input",{type:"number",value:i,onChange:v=>o(Number(v.target.value)),className:"w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2 outline-none ring-bubble-accent/40 focus:ring-2"})]})]}),d.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[d.jsx("button",{type:"button",onClick:f,className:"rounded-2xl bg-bubble-accent/90 px-4 py-2 font-semibold text-white",children:"MIFARE read block"}),d.jsx("button",{type:"button",onClick:h,className:"rounded-2xl border border-white/15 px-4 py-2",children:"Ultralight read page"})]}),a&&d.jsx("pre",{className:"mt-4 overflow-auto rounded-2xl border border-white/10 bg-black/30 p-4 font-mono text-sm",children:a})]}),d.jsxs("div",{className:"glass p-6",children:[d.jsx("h2",{className:"font-display text-lg font-semibold",children:"Sector trailer playground"}),d.jsxs("label",{className:"mt-4 block text-sm",children:["16-byte trailer (32 hex) — bytes 6–8 are access bytes",d.jsx("textarea",{value:u,onChange:v=>c(v.target.value),rows:3,className:"mt-2 w-full rounded-2xl border border-white/10 bg-black/25 p-3 font-mono text-xs outline-none focus:ring-2 focus:ring-bubble-accent/40"})]}),g&&d.jsxs("div",{className:"mt-4 rounded-2xl border border-bubble-mint/30 bg-bubble-mint/5 p-4 text-sm",children:["Parsed C1–C3 nibble pattern: ",g.c1," ",g.c2," ",g.c3," (see NXP MIFARE docs for truth tables)"]}),d.jsxs("p",{className:"mt-4 text-xs text-slate-500",children:["SAK hints: common values for labeling only — ",Og(24)," etc."]})]})]})}const ws="Lab-only synthetic data and well-known defaults. Edit bytes freely to validate parsers, checksums, and emulate/raw paths — never treat these as real tags.",Ef=[{id:"get-fw",title:"GetFirmwareVersion (0x02)",hex:"02",detail:"Expect PN532 firmware major/minor in response payload."},{id:"get-status",title:"GetGeneralStatus (0x04)",hex:"04",detail:"Chip + RF status snapshot; useful sanity check after a stuck session."},{id:"in-list-a",title:"InListPassiveTarget — 106 kbps, 1 target",hex:"4A0100",detail:"Poll one ISO14443-A target at 106 kbps (maxTg=1, BrTy=0)."}],jf=[{id:"tg-stub",title:"TgInitAsTarget — opcode only (shell)",hex:"8C",detail:"Minimal placeholder; real target mode needs a full parameter block per NXP UM0701. Extend with NFCID, FeliCa params, etc."},{id:"tg-type-a-sketch",title:"TgInitAsTarget — Type A sketch (synthetic NFCID3T)",hex:"8C000012DEADBEEF00000000000000000000000000000000000000000000000000",detail:"Synthetic 0x8C prefix + padded fake ID — not guaranteed to satisfy any reader; use as a byte-editing template only."}],h2="DEADBEEF2208040000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF078069FFFFFFFFFFFF",p2="04112233445566172233445566172233445566172233445566172233",m2="0310D1010C55046578616D706C652E636F6DFE",pl=[{id:"mifare-block0",title:"MIFARE Classic — block 0 (16 B, synthetic UID+BCC)",hex:"DEADBEEF220804000000000000000000",byteLength:16,sha256Hex:"6f13f064d70ec33b7ace5842011d66aff3852baa4ab7c0a85aa66d113c7189fe",detail:"Fake 4-byte UID (DE:AD:BE:EF wire order as stored), BCC = XOR(UID), rest filler. Pair with key FFFFFFFFFFFF on a writable tag only."},{id:"mifare-sector0",title:"MIFARE Classic — sector 0 dump (64 B)",hex:h2,byteLength:64,sha256Hex:"11095df4db11e4271f40234533db45de35c4ca69f04e231e3fa47f38181e0168",detail:"Four blocks: manufacturer/UID, empty, empty, default trailer (Key A/B FFFFFFFFFFFF, access FF078069). Edit block 1–2 payload and re-hash to validate your pipeline."},{id:"ntag-pages",title:"NTAG-style — pages 0–6 (28 B)",hex:p2,byteLength:28,sha256Hex:"8ffd95e646b2deb218dabd72e35c7a1938725e07332d8ed7df4f2a2656e590a0",detail:"Synthetic UID/internal/lock placeholders — not copied from a physical tag."},{id:"ndef-uri-tlv",title:"NDEF TLV — URI https://example.com/",hex:m2,byteLength:19,sha256Hex:"81197b6cd6e40a3f62f56f0c0f3f449c63a956919d04c5b5317895ad4328fa14",detail:"Type 2 TLV (0x03) + short NDEF Well-Known URI record; append to user memory after static pages in real layouts."}],g2=["FFFFFFFFFFFF","A0A1A2A3A4A5","D3F7D3F7D3F7","000000000000","B0B1B2B3B4B5","AABBCCDDEEFF","4D3A99C351DD","1A982C7E459A","714C5C886E97","587EE5F9350F","A0478CC39091","26940B21FFF5","E4410EF8ED2D"],y2=pl.map(e=>({name:`LAB // ${e.title}`,hex:e.hex,note:e.detail}));function fo({mode:e,onApplyHex:t,onPickBinary:n,className:r=""}){const[s,i]=x.useState(0),o=()=>i(a=>a+1);return e==="raw"?d.jsx("div",{className:`flex flex-wrap items-center gap-2 ${r}`,children:d.jsxs("select",{defaultValue:"","aria-label":"Load PN532 lab command",className:"max-w-full rounded-xl border border-bubble-mint/25 bg-black/40 px-3 py-2 font-mono text-xs text-bubble-mint/90",onChange:a=>{const l=a.target.value;if(!l)return;const u=Ef.find(c=>c.id===l);u&&t(u.hex),o()},children:[d.jsx("option",{value:"",children:"Lab: PN532 command bytes…"}),Ef.map(a=>d.jsx("option",{value:a.id,children:a.title},a.id))]},s)}):e==="emulate"?d.jsx("div",{className:`flex flex-wrap items-center gap-2 ${r}`,children:d.jsxs("select",{defaultValue:"","aria-label":"Load emulate lab frame",className:"max-w-full rounded-xl border border-bubble-mint/25 bg-black/40 px-3 py-2 font-mono text-xs text-bubble-mint/90",onChange:a=>{const l=a.target.value;if(!l)return;const u=jf.find(c=>c.id===l);u&&t(u.hex),o()},children:[d.jsx("option",{value:"",children:"Lab: emulate / TgInit…"}),jf.map(a=>d.jsx("option",{value:a.id,children:a.title},a.id))]},s)}):d.jsx("div",{className:`space-y-2 ${r}`,children:d.jsxs("select",{defaultValue:"","aria-label":"Load synthetic card blob",className:"w-full max-w-full rounded-xl border border-bubble-mint/25 bg-black/40 px-3 py-2 font-mono text-xs text-bubble-mint/90",onChange:a=>{const l=a.target.value;if(!l)return;const u=pl.find(c=>c.id===l);u&&(t(u.hex),n==null||n(u)),o()},children:[d.jsx("option",{value:"",children:"Lab: synthetic card / NDEF blob…"}),pl.map(a=>d.jsxs("option",{value:a.id,children:[a.title," (",a.byteLength," B)"]},a.id))]},s)})}function v2(){const e=Je(),{lastTag:t}=xs(),[n,r]=x.useState("FFFFFFFFFFFF"),[s,i]=x.useState(!1),[o,a]=x.useState(4),[l,u]=x.useState("00000000000000000000000000000000"),[c,f]=x.useState(null),[h,g]=x.useState(4),[v,w]=x.useState("00000000"),S=async()=>{if(confirm("Write will modify tag memory. Continue?"))try{await vt("/api/mifare/write-block",{block:o,key:n,keyB:s,data:l}),e("Write OK")}catch(p){e(String(p),"err")}},m=async()=>{if(confirm("Ultralight page write — can brick OTP/lock bytes if misused. Continue?"))try{await vt("/api/ul/write-page",{page:h,data:v.replace(/\s/g,"")}),e("UL page write OK")}catch(p){e(String(p),"err")}};return d.jsxs("div",{className:"glass space-y-6 p-6",children:[d.jsxs("div",{children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Write / clone helpers"}),d.jsx("p",{className:"mt-2 text-sm text-slate-400",children:"Block editor for MIFARE Classic. Read blocks on the Read tab, adjust hex here, then write with a key that unlocks the sector."}),t&&d.jsxs("p",{className:"mt-2 rounded-lg border border-bubble-mint/20 bg-bubble-mint/5 px-3 py-2 font-mono text-xs text-bubble-mint",children:["Field: ",d.jsx("span",{className:"text-white",children:Ig(t.uid)})," ·"," ",t.typeGuess??`hint ${t.typeHint}`]}),d.jsx("p",{className:"mt-2 text-[11px] leading-relaxed text-slate-500",children:ws}),d.jsx(fo,{mode:"binary",className:"mt-3",onApplyHex:p=>{const y=p.replace(/\s/g,"");y.length<=32?u(y):(u(y.slice(0,32)),e("First 16 bytes of lab blob loaded into block editor","info"))},onPickBinary:f}),c&&d.jsxs("p",{className:"mt-2 font-mono text-[10px] text-bubble-accent/90",children:["Canonical SHA-256 (",c.byteLength," B): ",c.sha256Hex," — changes after any edit"]})]}),d.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[d.jsxs("label",{className:"text-sm",children:["Key (12 hex)",d.jsx("input",{value:n,onChange:p=>r(p.target.value),className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2 font-mono"})]}),d.jsxs("label",{className:"flex items-end gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:s,onChange:p=>i(p.target.checked)})," Key B"]}),d.jsxs("label",{className:"text-sm",children:["Block",d.jsx("input",{type:"number",value:o,onChange:p=>a(Number(p.target.value)),className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2"})]})]}),d.jsxs("label",{className:"block text-sm",children:["16 bytes (32 hex)",d.jsx("textarea",{value:l,onChange:p=>u(p.target.value),rows:4,className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 p-3 font-mono text-sm"})]}),d.jsx("button",{type:"button",onClick:S,className:"rounded-2xl bg-gradient-to-r from-bubble-rose to-orange-400 px-6 py-3 font-bold text-white shadow-glow",children:"Write block"}),d.jsxs("div",{className:"border-t border-white/10 pt-8",children:[d.jsx("h2",{className:"font-display text-lg font-bold text-bubble-accent",children:"Ultralight / NTAG page write"}),d.jsx("p",{className:"mt-2 text-sm text-slate-400",children:"4 bytes per page (8 hex). Keep tag on the coil. Avoid lock / config pages unless you mean it."}),d.jsxs("div",{className:"mt-4 grid gap-4 md:grid-cols-2",children:[d.jsxs("label",{className:"text-sm",children:["Page",d.jsx("input",{type:"number",value:h,onChange:p=>g(Number(p.target.value)),className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2"})]}),d.jsxs("label",{className:"text-sm",children:["Data (8 hex)",d.jsx("input",{value:v,onChange:p=>w(p.target.value),className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2 font-mono"})]})]}),d.jsx("button",{type:"button",onClick:m,className:"mt-4 rounded-2xl border border-bubble-accent/50 bg-bubble-accent/20 px-6 py-3 font-bold text-bubble-accent",children:"Write UL page"})]})]})}const Nf="pn532_saved_tags_v1";function x2(){const e=Je(),[t,n]=x.useState([]),[r,s]=x.useState("My tag"),[i,o]=x.useState(""),[a,l]=x.useState(null);x.useEffect(()=>{try{const g=localStorage.getItem(Nf);n(g?JSON.parse(g):[])}catch{n([])}},[]);const u=g=>{localStorage.setItem(Nf,JSON.stringify(g)),n(g)},c=()=>{if(!i.trim()){e("Paste hex first","err");return}const v={id:`${Date.now()}-${Math.random().toString(16).slice(2)}`,name:r,hex:i.replace(/\s/g,""),ts:Date.now()};u([v,...t]),e("Saved")},f=g=>u(t.filter(v=>v.id!==g)),h=()=>{const g=new Set(t.map(S=>S.name)),v=Date.now(),w=y2.filter(S=>!g.has(S.name)).map((S,m)=>({id:`lab-seed-${v}-${m}`,name:S.name,hex:S.hex,ts:v}));if(!w.length){e("Lab catalog already in library","info");return}u([...w,...t]),e(`Seeded ${w.length} lab record(s)`)};return d.jsxs("div",{className:"glass space-y-6 p-6",children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Saved tag library"}),d.jsx("p",{className:"text-sm text-slate-400",children:"Local browser storage — export by copy/paste."}),d.jsx("p",{className:"text-[11px] leading-relaxed text-slate-500",children:ws}),d.jsx("div",{className:"flex flex-wrap gap-2",children:d.jsx("button",{type:"button",onClick:h,className:"rounded-2xl border border-bubble-mint/30 bg-bubble-mint/10 px-4 py-2 font-mono text-xs font-semibold text-bubble-mint",children:"Seed all lab samples"})}),d.jsx(fo,{mode:"binary",onApplyHex:g=>o(g.replace(/\s/g,"")),onPickBinary:l}),a&&d.jsxs("div",{className:"rounded-xl border border-bubble-accent/25 bg-black/30 p-3 font-mono text-[10px] text-bubble-accent/90",children:[d.jsx("div",{className:"text-bubble-mint/70",children:"Expected SHA-256 (canonical blob, pre-edit)"}),d.jsx("div",{className:"break-all",children:a.sha256Hex})]}),d.jsxs("div",{className:"grid gap-3 md:grid-cols-2",children:[d.jsx("input",{value:r,onChange:g=>s(g.target.value),placeholder:"Label",className:"rounded-2xl border border-white/10 bg-black/25 px-4 py-2"}),d.jsx("button",{type:"button",onClick:c,className:"rounded-2xl bg-bubble-accent px-4 py-2 font-semibold",children:"Save current hex"})]}),d.jsx("textarea",{value:i,onChange:g=>o(g.target.value),placeholder:"Hex dump",rows:5,className:"w-full rounded-2xl border border-white/10 bg-black/25 p-3 font-mono text-xs"}),d.jsx("ul",{className:"space-y-3",children:t.map(g=>d.jsxs("li",{className:"rounded-2xl border border-white/10 bg-black/20 p-4",children:[d.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[d.jsxs("div",{children:[d.jsx("div",{className:"font-display font-semibold",children:g.name}),d.jsx("div",{className:"text-xs text-slate-500",children:new Date(g.ts).toLocaleString()})]}),d.jsx("button",{type:"button",onClick:()=>f(g.id),className:"text-rose-300",children:"Remove"})]}),d.jsx("pre",{className:"mt-2 max-h-32 overflow-auto text-xs text-bubble-mint/90",children:g.hex}),d.jsx("button",{type:"button",onClick:()=>{navigator.clipboard.writeText(g.hex),e("Copied")},className:"mt-2 text-sm text-slate-300 underline",children:"Copy hex"})]},g.id))})]})}const w2=["FFFFFFFFFFFF","A0A1A2A3A4A5","D3F7D3F7D3F7","000000000000"],Af="pn532_key_dict_v1";function S2(){const e=Je(),[t,n]=x.useState([]),[r,s]=x.useState("");x.useEffect(()=>{const u=localStorage.getItem(Af);n(u?JSON.parse(u):[...w2])},[]);const i=u=>{localStorage.setItem(Af,JSON.stringify(u)),n(u)},o=()=>{const u=[...t];let c=0;for(const f of g2)u.includes(f)||(u.push(f),c++);if(!c){e("Lab key corpus already merged","info");return}i(u),e(`Added ${c} public lab key(s)`)},a=()=>{const u=sessionStorage.getItem("pn532_keylab_import");if(!(u!=null&&u.trim())){e("Key Lab has nothing staged","info");return}const c=u.split(/\r?\n/).map(g=>g.replace(/\s/g,"").toUpperCase()).filter(g=>g.length===12);if(!c.length){e("No valid 12-hex keys in stash","err");return}const f=[...t];let h=0;for(const g of c)f.includes(g)||(f.push(g),h++);i(f),sessionStorage.removeItem("pn532_keylab_import"),e(h?`Merged ${h} key(s) from Key Lab`:"Keys already in list")},l=()=>{const u=r.replace(/\s/g,"").toUpperCase();if(u.length!==12){e("12 hex chars required","err");return}t.includes(u)?e("Already in dictionary"):(i([u,...t]),e("Key added")),s("")};return d.jsxs("div",{className:"glass space-y-6 p-6",children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Key manager"}),d.jsx("p",{className:"text-sm text-slate-400",children:"Dictionary for manual trials (not a cloud rainbow table). Keys stay in your browser."}),d.jsx("p",{className:"text-[11px] leading-relaxed text-slate-500",children:ws}),d.jsxs("div",{className:"flex flex-wrap gap-2",children:[d.jsx("button",{type:"button",onClick:o,className:"btn-neon rounded-xl border border-bubble-mint/40 bg-bubble-mint/10 px-4 py-2 font-mono text-xs font-bold text-bubble-mint",children:"Merge lab corpus"}),d.jsx("button",{type:"button",onClick:a,className:"rounded-xl border border-bubble-accent/45 bg-bubble-accent/10 px-4 py-2 font-mono text-xs font-bold text-bubble-accent",children:"Import Key Lab stash"})]}),d.jsxs("div",{className:"flex gap-2",children:[d.jsx("input",{value:r,onChange:u=>s(u.target.value),placeholder:"New key",className:"flex-1 rounded-2xl border border-white/10 bg-black/25 px-4 py-2 font-mono"}),d.jsx("button",{type:"button",className:"rounded-2xl bg-bubble-accent px-4 py-2 font-semibold",onClick:l,children:"Add"})]}),d.jsx("ul",{className:"space-y-2",children:t.map(u=>d.jsxs("li",{className:"flex items-center justify-between rounded-2xl border border-white/10 bg-black/20 px-4 py-2 font-mono text-sm",children:[u,d.jsx("button",{type:"button",className:"text-rose-300",onClick:()=>i(t.filter(c=>c!==u)),children:"×"})]},u))})]})}function b2(){const e=Je(),[t,n]=x.useState("4A0100"),[r,s]=x.useState([]),[i,o]=x.useState(""),a=c=>s(f=>[new Date().toLocaleTimeString()+" "+c,...f].slice(0,80)),l=async()=>{try{const c=await vt("/api/raw/pn532",{frame:t});a(`TX ${t}`),a(`RX ${c.response||c.error||"?"}`),c.response&&e("Frame OK")}catch(c){a(`ERR ${String(c)}`),e(String(c),"err")}},u=async()=>{try{const c=await $u("/api/pn532/general-status");o(JSON.stringify(c.raw??c,null,2)),e("Fetched PN532 status")}catch(c){e(String(c),"err")}};return d.jsxs("div",{className:"glass space-y-6 p-6",children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Advanced / raw PN532"}),d.jsxs("p",{className:"text-sm text-slate-400",children:["Send command bytes (without PN532 frame wrapper). Example: ",d.jsx("code",{children:"4A0100"})," lists one Type A passive target at 106 kbps."]}),d.jsx("p",{className:"text-[11px] leading-relaxed text-slate-500",children:ws}),d.jsx(fo,{mode:"raw",onApplyHex:c=>n(c)}),d.jsxs("div",{className:"flex flex-wrap gap-2",children:[d.jsx("input",{value:t,onChange:c=>n(c.target.value),className:"min-w-[16rem] flex-1 rounded-2xl border border-white/10 bg-black/25 px-4 py-2 font-mono text-sm"}),d.jsx("button",{type:"button",onClick:l,className:"rounded-2xl bg-bubble-accent px-4 py-2 font-semibold",children:"Send"}),d.jsx("button",{type:"button",onClick:u,className:"rounded-2xl border border-white/15 px-4 py-2",children:"General status"})]}),d.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[d.jsxs("div",{children:[d.jsx("h2",{className:"text-sm font-semibold text-slate-300",children:"Log"}),d.jsx("pre",{className:"mt-2 max-h-80 overflow-auto rounded-2xl border border-white/10 bg-black/30 p-3 text-xs",children:r.join(` + `),()=>{document.head.removeChild(c)}},[t]),d.jsx(wx,{isPresent:t,childRef:r,sizeRef:s,children:x.cloneElement(e,{ref:r})})}const bx=({children:e,initial:t,isPresent:n,onExitComplete:r,custom:s,presenceAffectsLayout:i,mode:o})=>{const a=cu(kx),l=x.useId(),u=x.useCallback(f=>{a.set(f,!0);for(const h of a.values())if(!h)return;r&&r()},[a,r]),c=x.useMemo(()=>({id:l,initial:t,isPresent:n,custom:s,onExitComplete:u,register:f=>(a.set(f,!1),()=>a.delete(f))}),i?[Math.random(),u]:[n,u]);return x.useMemo(()=>{a.forEach((f,h)=>a.set(h,!1))},[n]),x.useEffect(()=>{!n&&!a.size&&r&&r()},[n]),o==="popLayout"&&(e=d.jsx(Sx,{isPresent:n,children:e})),d.jsx(io.Provider,{value:c,children:e})};function kx(){return new Map}function im(e=!0){const t=x.useContext(io);if(t===null)return[!0,null];const{isPresent:n,onExitComplete:r,register:s}=t,i=x.useId();x.useEffect(()=>{e&&s(i)},[e]);const o=x.useCallback(()=>e&&r&&r(i),[i,r,e]);return!n&&r?[!1,o]:[!0]}const Us=e=>e.key||"";function cd(e){const t=[];return x.Children.forEach(e,n=>{x.isValidElement(n)&&t.push(n)}),t}const fu=typeof window<"u",om=fu?x.useLayoutEffect:x.useEffect,am=({children:e,custom:t,initial:n=!0,onExitComplete:r,presenceAffectsLayout:s=!0,mode:i="sync",propagate:o=!1})=>{const[a,l]=im(o),u=x.useMemo(()=>cd(e),[e]),c=o&&!a?[]:u.map(Us),f=x.useRef(!0),h=x.useRef(u),g=cu(()=>new Map),[v,w]=x.useState(u),[S,m]=x.useState(u);om(()=>{f.current=!1,h.current=u;for(let b=0;b{const k=Us(b),C=o&&!a?!1:u===S||c.includes(k),E=()=>{if(g.has(k))g.set(k,!0);else return;let P=!0;g.forEach(F=>{F||(P=!1)}),P&&(y==null||y(),m(h.current),o&&(l==null||l()),r&&r())};return d.jsx(bx,{isPresent:C,initial:!f.current||n?void 0:!1,custom:C?void 0:t,presenceAffectsLayout:s,mode:i,onExitComplete:C?void 0:E,children:b},k)})})},Ae=e=>e;let lm=Ae;function hu(e){let t;return()=>(t===void 0&&(t=e()),t)}const Jn=(e,t,n)=>{const r=t-e;return r===0?1:(n-e)/r},dt=e=>e*1e3,ft=e=>e/1e3,Cx={useManualTiming:!1};function Px(e){let t=new Set,n=new Set,r=!1,s=!1;const i=new WeakSet;let o={delta:0,timestamp:0,isProcessing:!1};function a(u){i.has(u)&&(l.schedule(u),e()),u(o)}const l={schedule:(u,c=!1,f=!1)=>{const g=f&&r?t:n;return c&&i.add(u),g.has(u)||g.add(u),u},cancel:u=>{n.delete(u),i.delete(u)},process:u=>{if(o=u,r){s=!0;return}r=!0,[t,n]=[n,t],t.forEach(a),t.clear(),r=!1,s&&(s=!1,l.process(u))}};return l}const zs=["read","resolveKeyframes","update","preRender","render","postRender"],Tx=40;function um(e,t){let n=!1,r=!0;const s={delta:0,timestamp:0,isProcessing:!1},i=()=>n=!0,o=zs.reduce((m,p)=>(m[p]=Px(i),m),{}),{read:a,resolveKeyframes:l,update:u,preRender:c,render:f,postRender:h}=o,g=()=>{const m=performance.now();n=!1,s.delta=r?1e3/60:Math.max(Math.min(m-s.timestamp,Tx),1),s.timestamp=m,s.isProcessing=!0,a.process(s),l.process(s),u.process(s),c.process(s),f.process(s),h.process(s),s.isProcessing=!1,n&&t&&(r=!1,e(g))},v=()=>{n=!0,r=!0,s.isProcessing||e(g)};return{schedule:zs.reduce((m,p)=>{const y=o[p];return m[p]=(b,k=!1,C=!1)=>(n||v(),y.schedule(b,k,C)),m},{}),cancel:m=>{for(let p=0;pdd[e].some(n=>!!t[n])};function Ex(e){for(const t in e)qn[t]={...qn[t],...e[t]}}const jx=new Set(["animate","exit","variants","initial","style","values","variants","transition","transformTemplate","custom","inherit","onBeforeLayoutMeasure","onAnimationStart","onAnimationComplete","onUpdate","onDragStart","onDrag","onDragEnd","onMeasureDragConstraints","onDirectionLock","onDragTransitionEnd","_dragX","_dragY","onHoverStart","onHoverEnd","onViewportEnter","onViewportLeave","globalTapTarget","ignoreStrict","viewport"]);function Li(e){return e.startsWith("while")||e.startsWith("drag")&&e!=="draggable"||e.startsWith("layout")||e.startsWith("onTap")||e.startsWith("onPan")||e.startsWith("onLayout")||jx.has(e)}let dm=e=>!Li(e);function Nx(e){e&&(dm=t=>t.startsWith("on")?!Li(t):e(t))}try{Nx(require("@emotion/is-prop-valid").default)}catch{}function Ax(e,t,n){const r={};for(const s in e)s==="values"&&typeof e.values=="object"||(dm(s)||n===!0&&Li(s)||!t&&!Li(s)||e.draggable&&s.startsWith("onDrag"))&&(r[s]=e[s]);return r}function Rx(e){if(typeof Proxy>"u")return e;const t=new Map,n=(...r)=>e(...r);return new Proxy(n,{get:(r,s)=>s==="create"?e:(t.has(s)||t.set(s,e(s)),t.get(s))})}const oo=x.createContext({});function ns(e){return typeof e=="string"||Array.isArray(e)}function ao(e){return e!==null&&typeof e=="object"&&typeof e.start=="function"}const pu=["animate","whileInView","whileFocus","whileHover","whileTap","whileDrag","exit"],mu=["initial",...pu];function lo(e){return ao(e.animate)||mu.some(t=>ns(e[t]))}function fm(e){return!!(lo(e)||e.variants)}function Lx(e,t){if(lo(e)){const{initial:n,animate:r}=e;return{initial:n===!1||ns(n)?n:void 0,animate:ns(r)?r:void 0}}return e.inherit!==!1?t:{}}function Dx(e){const{initial:t,animate:n}=Lx(e,x.useContext(oo));return x.useMemo(()=>({initial:t,animate:n}),[fd(t),fd(n)])}function fd(e){return Array.isArray(e)?e.join(" "):e}const Fx=Symbol.for("motionComponentSymbol");function Dn(e){return e&&typeof e=="object"&&Object.prototype.hasOwnProperty.call(e,"current")}function Mx(e,t,n){return x.useCallback(r=>{r&&e.onMount&&e.onMount(r),t&&(r?t.mount(r):t.unmount()),n&&(typeof n=="function"?n(r):Dn(n)&&(n.current=r))},[t])}const gu=e=>e.replace(/([a-z])([A-Z])/gu,"$1-$2").toLowerCase(),_x="framerAppearId",hm="data-"+gu(_x),{schedule:yu}=um(queueMicrotask,!1),pm=x.createContext({});function Vx(e,t,n,r,s){var i,o;const{visualElement:a}=x.useContext(oo),l=x.useContext(cm),u=x.useContext(io),c=x.useContext(du).reducedMotion,f=x.useRef(null);r=r||l.renderer,!f.current&&r&&(f.current=r(e,{visualState:t,parent:a,props:n,presenceContext:u,blockInitialAnimation:u?u.initial===!1:!1,reducedMotionConfig:c}));const h=f.current,g=x.useContext(pm);h&&!h.projection&&s&&(h.type==="html"||h.type==="svg")&&Ox(f.current,n,s,g);const v=x.useRef(!1);x.useInsertionEffect(()=>{h&&v.current&&h.update(n,u)});const w=n[hm],S=x.useRef(!!w&&!(!((i=window.MotionHandoffIsComplete)===null||i===void 0)&&i.call(window,w))&&((o=window.MotionHasOptimisedAnimation)===null||o===void 0?void 0:o.call(window,w)));return om(()=>{h&&(v.current=!0,window.MotionIsMounted=!0,h.updateFeatures(),yu.render(h.render),S.current&&h.animationState&&h.animationState.animateChanges())}),x.useEffect(()=>{h&&(!S.current&&h.animationState&&h.animationState.animateChanges(),S.current&&(queueMicrotask(()=>{var m;(m=window.MotionHandoffMarkAsComplete)===null||m===void 0||m.call(window,w)}),S.current=!1))}),h}function Ox(e,t,n,r){const{layoutId:s,layout:i,drag:o,dragConstraints:a,layoutScroll:l,layoutRoot:u}=t;e.projection=new n(e.latestValues,t["data-framer-portal-id"]?void 0:mm(e.parent)),e.projection.setOptions({layoutId:s,layout:i,alwaysMeasureLayout:!!o||a&&Dn(a),visualElement:e,animationType:typeof i=="string"?i:"both",initialPromotionConfig:r,layoutScroll:l,layoutRoot:u})}function mm(e){if(e)return e.options.allowProjection!==!1?e.projection:mm(e.parent)}function Ix({preloadedFeatures:e,createVisualElement:t,useRender:n,useVisualState:r,Component:s}){var i,o;e&&Ex(e);function a(u,c){let f;const h={...x.useContext(du),...u,layoutId:Bx(u)},{isStatic:g}=h,v=Dx(u),w=r(u,g);if(!g&&fu){Ux();const S=zx(h);f=S.MeasureLayout,v.visualElement=Vx(s,w,h,t,S.ProjectionNode)}return d.jsxs(oo.Provider,{value:v,children:[f&&v.visualElement?d.jsx(f,{visualElement:v.visualElement,...h}):null,n(s,u,Mx(w,v.visualElement,c),w,g,v.visualElement)]})}a.displayName=`motion.${typeof s=="string"?s:`create(${(o=(i=s.displayName)!==null&&i!==void 0?i:s.name)!==null&&o!==void 0?o:""})`}`;const l=x.forwardRef(a);return l[Fx]=s,l}function Bx({layoutId:e}){const t=x.useContext(uu).id;return t&&e!==void 0?t+"-"+e:e}function Ux(e,t){x.useContext(cm).strict}function zx(e){const{drag:t,layout:n}=qn;if(!t&&!n)return{};const r={...t,...n};return{MeasureLayout:t!=null&&t.isEnabled(e)||n!=null&&n.isEnabled(e)?r.MeasureLayout:void 0,ProjectionNode:r.ProjectionNode}}const $x=["animate","circle","defs","desc","ellipse","g","image","line","filter","marker","mask","metadata","path","pattern","polygon","polyline","rect","stop","switch","symbol","svg","text","tspan","use","view"];function vu(e){return typeof e!="string"||e.includes("-")?!1:!!($x.indexOf(e)>-1||/[A-Z]/u.test(e))}function hd(e){const t=[{},{}];return e==null||e.values.forEach((n,r)=>{t[0][r]=n.get(),t[1][r]=n.getVelocity()}),t}function xu(e,t,n,r){if(typeof t=="function"){const[s,i]=hd(r);t=t(n!==void 0?n:e.custom,s,i)}if(typeof t=="string"&&(t=e.variants&&e.variants[t]),typeof t=="function"){const[s,i]=hd(r);t=t(n!==void 0?n:e.custom,s,i)}return t}const Ja=e=>Array.isArray(e),Wx=e=>!!(e&&typeof e=="object"&&e.mix&&e.toValue),Kx=e=>Ja(e)?e[e.length-1]||0:e,ge=e=>!!(e&&e.getVelocity);function ri(e){const t=ge(e)?e.get():e;return Wx(t)?t.toValue():t}function Hx({scrapeMotionValuesFromProps:e,createRenderState:t,onUpdate:n},r,s,i){const o={latestValues:Gx(r,s,i,e),renderState:t()};return n&&(o.onMount=a=>n({props:r,current:a,...o}),o.onUpdate=a=>n(a)),o}const gm=e=>(t,n)=>{const r=x.useContext(oo),s=x.useContext(io),i=()=>Hx(e,t,r,s);return n?i():cu(i)};function Gx(e,t,n,r){const s={},i=r(e,{});for(const h in i)s[h]=ri(i[h]);let{initial:o,animate:a}=e;const l=lo(e),u=fm(e);t&&u&&!l&&e.inherit!==!1&&(o===void 0&&(o=t.initial),a===void 0&&(a=t.animate));let c=n?n.initial===!1:!1;c=c||o===!1;const f=c?a:o;if(f&&typeof f!="boolean"&&!ao(f)){const h=Array.isArray(f)?f:[f];for(let g=0;gt=>typeof t=="string"&&t.startsWith(e),vm=ym("--"),Xx=ym("var(--"),wu=e=>Xx(e)?Qx.test(e.split("/*")[0].trim()):!1,Qx=/var\(--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)$/iu,xm=(e,t)=>t&&typeof e=="number"?t.transform(e):e,yt=(e,t,n)=>n>t?t:ntypeof e=="number",parse:parseFloat,transform:e=>e},rs={...ir,transform:e=>yt(0,1,e)},$s={...ir,default:1},ps=e=>({test:t=>typeof t=="string"&&t.endsWith(e)&&t.split(" ").length===1,parse:parseFloat,transform:t=>`${t}${e}`}),bt=ps("deg"),st=ps("%"),R=ps("px"),Yx=ps("vh"),Zx=ps("vw"),pd={...st,parse:e=>st.parse(e)/100,transform:e=>st.transform(e*100)},Jx={borderWidth:R,borderTopWidth:R,borderRightWidth:R,borderBottomWidth:R,borderLeftWidth:R,borderRadius:R,radius:R,borderTopLeftRadius:R,borderTopRightRadius:R,borderBottomRightRadius:R,borderBottomLeftRadius:R,width:R,maxWidth:R,height:R,maxHeight:R,top:R,right:R,bottom:R,left:R,padding:R,paddingTop:R,paddingRight:R,paddingBottom:R,paddingLeft:R,margin:R,marginTop:R,marginRight:R,marginBottom:R,marginLeft:R,backgroundPositionX:R,backgroundPositionY:R},qx={rotate:bt,rotateX:bt,rotateY:bt,rotateZ:bt,scale:$s,scaleX:$s,scaleY:$s,scaleZ:$s,skew:bt,skewX:bt,skewY:bt,distance:R,translateX:R,translateY:R,translateZ:R,x:R,y:R,z:R,perspective:R,transformPerspective:R,opacity:rs,originX:pd,originY:pd,originZ:R},md={...ir,transform:Math.round},Su={...Jx,...qx,zIndex:md,size:R,fillOpacity:rs,strokeOpacity:rs,numOctaves:md},e1={x:"translateX",y:"translateY",z:"translateZ",transformPerspective:"perspective"},t1=sr.length;function n1(e,t,n){let r="",s=!0;for(let i=0;i({style:{},transform:{},transformOrigin:{},vars:{}}),wm=()=>({...Cu(),attrs:{}}),Pu=e=>typeof e=="string"&&e.toLowerCase()==="svg";function Sm(e,{style:t,vars:n},r,s){Object.assign(e.style,t,s&&s.getProjectionStyles(r));for(const i in n)e.style.setProperty(i,n[i])}const bm=new Set(["baseFrequency","diffuseConstant","kernelMatrix","kernelUnitLength","keySplines","keyTimes","limitingConeAngle","markerHeight","markerWidth","numOctaves","targetX","targetY","surfaceScale","specularConstant","specularExponent","stdDeviation","tableValues","viewBox","gradientTransform","pathLength","startOffset","textLength","lengthAdjust"]);function km(e,t,n,r){Sm(e,t,void 0,r);for(const s in t.attrs)e.setAttribute(bm.has(s)?s:gu(s),t.attrs[s])}const Di={};function a1(e){Object.assign(Di,e)}function Cm(e,{layout:t,layoutId:n}){return xn.has(e)||e.startsWith("origin")||(t||n!==void 0)&&(!!Di[e]||e==="opacity")}function Tu(e,t,n){var r;const{style:s}=e,i={};for(const o in s)(ge(s[o])||t.style&&ge(t.style[o])||Cm(o,e)||((r=n==null?void 0:n.getValue(o))===null||r===void 0?void 0:r.liveStyle)!==void 0)&&(i[o]=s[o]);return i}function Pm(e,t,n){const r=Tu(e,t,n);for(const s in e)if(ge(e[s])||ge(t[s])){const i=sr.indexOf(s)!==-1?"attr"+s.charAt(0).toUpperCase()+s.substring(1):s;r[i]=e[s]}return r}function l1(e,t){try{t.dimensions=typeof e.getBBox=="function"?e.getBBox():e.getBoundingClientRect()}catch{t.dimensions={x:0,y:0,width:0,height:0}}}const yd=["x","y","width","height","cx","cy","r"],u1={useVisualState:gm({scrapeMotionValuesFromProps:Pm,createRenderState:wm,onUpdate:({props:e,prevProps:t,current:n,renderState:r,latestValues:s})=>{if(!n)return;let i=!!e.drag;if(!i){for(const a in s)if(xn.has(a)){i=!0;break}}if(!i)return;let o=!t;if(t)for(let a=0;a{l1(n,r),z.render(()=>{ku(r,s,Pu(n.tagName),e.transformTemplate),km(n,r)})})}})},c1={useVisualState:gm({scrapeMotionValuesFromProps:Tu,createRenderState:Cu})};function Tm(e,t,n){for(const r in t)!ge(t[r])&&!Cm(r,n)&&(e[r]=t[r])}function d1({transformTemplate:e},t){return x.useMemo(()=>{const n=Cu();return bu(n,t,e),Object.assign({},n.vars,n.style)},[t])}function f1(e,t){const n=e.style||{},r={};return Tm(r,n,e),Object.assign(r,d1(e,t)),r}function h1(e,t){const n={},r=f1(e,t);return e.drag&&e.dragListener!==!1&&(n.draggable=!1,r.userSelect=r.WebkitUserSelect=r.WebkitTouchCallout="none",r.touchAction=e.drag===!0?"none":`pan-${e.drag==="x"?"y":"x"}`),e.tabIndex===void 0&&(e.onTap||e.onTapStart||e.whileTap)&&(n.tabIndex=0),n.style=r,n}function p1(e,t,n,r){const s=x.useMemo(()=>{const i=wm();return ku(i,t,Pu(r),e.transformTemplate),{...i.attrs,style:{...i.style}}},[t]);if(e.style){const i={};Tm(i,e.style,e),s.style={...i,...s.style}}return s}function m1(e=!1){return(n,r,s,{latestValues:i},o)=>{const l=(vu(n)?p1:h1)(r,i,o,n),u=Ax(r,typeof n=="string",e),c=n!==x.Fragment?{...u,...l,ref:s}:{},{children:f}=r,h=x.useMemo(()=>ge(f)?f.get():f,[f]);return x.createElement(n,{...c,children:h})}}function g1(e,t){return function(r,{forwardMotionProps:s}={forwardMotionProps:!1}){const o={...vu(r)?u1:c1,preloadedFeatures:e,useRender:m1(s),createVisualElement:t,Component:r};return Ix(o)}}function Em(e,t){if(!Array.isArray(t))return!1;const n=t.length;if(n!==e.length)return!1;for(let r=0;rwindow.ScrollTimeline!==void 0);class v1{constructor(t){this.stop=()=>this.runAll("stop"),this.animations=t.filter(Boolean)}get finished(){return Promise.all(this.animations.map(t=>"finished"in t?t.finished:t))}getAll(t){return this.animations[0][t]}setAll(t,n){for(let r=0;r{if(y1()&&s.attachTimeline)return s.attachTimeline(t);if(typeof n=="function")return n(s)});return()=>{r.forEach((s,i)=>{s&&s(),this.animations[i].stop()})}}get time(){return this.getAll("time")}set time(t){this.setAll("time",t)}get speed(){return this.getAll("speed")}set speed(t){this.setAll("speed",t)}get startTime(){return this.getAll("startTime")}get duration(){let t=0;for(let n=0;nn[t]())}flatten(){this.runAll("flatten")}play(){this.runAll("play")}pause(){this.runAll("pause")}cancel(){this.runAll("cancel")}complete(){this.runAll("complete")}}class x1 extends v1{then(t,n){return Promise.all(this.animations).then(t).catch(n)}}function Eu(e,t){return e?e[t]||e.default||e:void 0}const qa=2e4;function jm(e){let t=0;const n=50;let r=e.next(t);for(;!r.done&&t=qa?1/0:t}function ju(e){return typeof e=="function"}function vd(e,t){e.timeline=t,e.onfinish=null}const Nu=e=>Array.isArray(e)&&typeof e[0]=="number",w1={linearEasing:void 0};function S1(e,t){const n=hu(e);return()=>{var r;return(r=w1[t])!==null&&r!==void 0?r:n()}}const Fi=S1(()=>{try{document.createElement("div").animate({opacity:0},{easing:"linear(0, 1)"})}catch{return!1}return!0},"linearEasing"),Nm=(e,t,n=10)=>{let r="";const s=Math.max(Math.round(t/n),2);for(let i=0;i`cubic-bezier(${e}, ${t}, ${n}, ${r})`,el={linear:"linear",ease:"ease",easeIn:"ease-in",easeOut:"ease-out",easeInOut:"ease-in-out",circIn:wr([0,.65,.55,1]),circOut:wr([.55,0,1,.45]),backIn:wr([.31,.01,.66,-.59]),backOut:wr([.33,1.53,.69,.99])};function Rm(e,t){if(e)return typeof e=="function"&&Fi()?Nm(e,t):Nu(e)?wr(e):Array.isArray(e)?e.map(n=>Rm(n,t)||el.easeOut):el[e]}const Ke={x:!1,y:!1};function Lm(){return Ke.x||Ke.y}function b1(e,t,n){var r;if(e instanceof Element)return[e];if(typeof e=="string"){let s=document;const i=(r=void 0)!==null&&r!==void 0?r:s.querySelectorAll(e);return i?Array.from(i):[]}return Array.from(e)}function Dm(e,t){const n=b1(e),r=new AbortController,s={passive:!0,...t,signal:r.signal};return[n,s,()=>r.abort()]}function xd(e){return t=>{t.pointerType==="touch"||Lm()||e(t)}}function k1(e,t,n={}){const[r,s,i]=Dm(e,n),o=xd(a=>{const{target:l}=a,u=t(a);if(typeof u!="function"||!l)return;const c=xd(f=>{u(f),l.removeEventListener("pointerleave",c)});l.addEventListener("pointerleave",c,s)});return r.forEach(a=>{a.addEventListener("pointerenter",o,s)}),i}const Fm=(e,t)=>t?e===t?!0:Fm(e,t.parentElement):!1,Au=e=>e.pointerType==="mouse"?typeof e.button!="number"||e.button<=0:e.isPrimary!==!1,C1=new Set(["BUTTON","INPUT","SELECT","TEXTAREA","A"]);function P1(e){return C1.has(e.tagName)||e.tabIndex!==-1}const Sr=new WeakSet;function wd(e){return t=>{t.key==="Enter"&&e(t)}}function zo(e,t){e.dispatchEvent(new PointerEvent("pointer"+t,{isPrimary:!0,bubbles:!0}))}const T1=(e,t)=>{const n=e.currentTarget;if(!n)return;const r=wd(()=>{if(Sr.has(n))return;zo(n,"down");const s=wd(()=>{zo(n,"up")}),i=()=>zo(n,"cancel");n.addEventListener("keyup",s,t),n.addEventListener("blur",i,t)});n.addEventListener("keydown",r,t),n.addEventListener("blur",()=>n.removeEventListener("keydown",r),t)};function Sd(e){return Au(e)&&!Lm()}function E1(e,t,n={}){const[r,s,i]=Dm(e,n),o=a=>{const l=a.currentTarget;if(!Sd(a)||Sr.has(l))return;Sr.add(l);const u=t(a),c=(g,v)=>{window.removeEventListener("pointerup",f),window.removeEventListener("pointercancel",h),!(!Sd(g)||!Sr.has(l))&&(Sr.delete(l),typeof u=="function"&&u(g,{success:v}))},f=g=>{c(g,n.useGlobalTarget||Fm(l,g.target))},h=g=>{c(g,!1)};window.addEventListener("pointerup",f,s),window.addEventListener("pointercancel",h,s)};return r.forEach(a=>{!P1(a)&&a.getAttribute("tabindex")===null&&(a.tabIndex=0),(n.useGlobalTarget?window:a).addEventListener("pointerdown",o,s),a.addEventListener("focus",u=>T1(u,s),s)}),i}function j1(e){return e==="x"||e==="y"?Ke[e]?null:(Ke[e]=!0,()=>{Ke[e]=!1}):Ke.x||Ke.y?null:(Ke.x=Ke.y=!0,()=>{Ke.x=Ke.y=!1})}const Mm=new Set(["width","height","top","left","right","bottom",...sr]);let si;function N1(){si=void 0}const it={now:()=>(si===void 0&&it.set(ue.isProcessing||Cx.useManualTiming?ue.timestamp:performance.now()),si),set:e=>{si=e,queueMicrotask(N1)}};function Ru(e,t){e.indexOf(t)===-1&&e.push(t)}function Lu(e,t){const n=e.indexOf(t);n>-1&&e.splice(n,1)}class Du{constructor(){this.subscriptions=[]}add(t){return Ru(this.subscriptions,t),()=>Lu(this.subscriptions,t)}notify(t,n,r){const s=this.subscriptions.length;if(s)if(s===1)this.subscriptions[0](t,n,r);else for(let i=0;i!isNaN(parseFloat(e));class R1{constructor(t,n={}){this.version="11.18.2",this.canTrackVelocity=null,this.events={},this.updateAndNotify=(r,s=!0)=>{const i=it.now();this.updatedAt!==i&&this.setPrevFrameValue(),this.prev=this.current,this.setCurrent(r),this.current!==this.prev&&this.events.change&&this.events.change.notify(this.current),s&&this.events.renderRequest&&this.events.renderRequest.notify(this.current)},this.hasAnimated=!1,this.setCurrent(t),this.owner=n.owner}setCurrent(t){this.current=t,this.updatedAt=it.now(),this.canTrackVelocity===null&&t!==void 0&&(this.canTrackVelocity=A1(this.current))}setPrevFrameValue(t=this.current){this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt}onChange(t){return this.on("change",t)}on(t,n){this.events[t]||(this.events[t]=new Du);const r=this.events[t].add(n);return t==="change"?()=>{r(),z.read(()=>{this.events.change.getSize()||this.stop()})}:r}clearListeners(){for(const t in this.events)this.events[t].clear()}attach(t,n){this.passiveEffect=t,this.stopPassiveEffect=n}set(t,n=!0){!n||!this.passiveEffect?this.updateAndNotify(t,n):this.passiveEffect(t,this.updateAndNotify)}setWithVelocity(t,n,r){this.set(n),this.prev=void 0,this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt-r}jump(t,n=!0){this.updateAndNotify(t),this.prev=t,this.prevUpdatedAt=this.prevFrameValue=void 0,n&&this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}get(){return this.current}getPrevious(){return this.prev}getVelocity(){const t=it.now();if(!this.canTrackVelocity||this.prevFrameValue===void 0||t-this.updatedAt>bd)return 0;const n=Math.min(this.updatedAt-this.prevUpdatedAt,bd);return _m(parseFloat(this.current)-parseFloat(this.prevFrameValue),n)}start(t){return this.stop(),new Promise(n=>{this.hasAnimated=!0,this.animation=t(n),this.events.animationStart&&this.events.animationStart.notify()}).then(()=>{this.events.animationComplete&&this.events.animationComplete.notify(),this.clearAnimation()})}stop(){this.animation&&(this.animation.stop(),this.events.animationCancel&&this.events.animationCancel.notify()),this.clearAnimation()}isAnimating(){return!!this.animation}clearAnimation(){delete this.animation}destroy(){this.clearListeners(),this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}}function ss(e,t){return new R1(e,t)}function L1(e,t,n){e.hasValue(t)?e.getValue(t).set(n):e.addValue(t,ss(n))}function D1(e,t){const n=uo(e,t);let{transitionEnd:r={},transition:s={},...i}=n||{};i={...i,...r};for(const o in i){const a=Kx(i[o]);L1(e,o,a)}}function F1(e){return!!(ge(e)&&e.add)}function tl(e,t){const n=e.getValue("willChange");if(F1(n))return n.add(t)}function Vm(e){return e.props[hm]}const Om=(e,t,n)=>(((1-3*n+3*t)*e+(3*n-6*t))*e+3*t)*e,M1=1e-7,_1=12;function V1(e,t,n,r,s){let i,o,a=0;do o=t+(n-t)/2,i=Om(o,r,s)-e,i>0?n=o:t=o;while(Math.abs(i)>M1&&++a<_1);return o}function ms(e,t,n,r){if(e===t&&n===r)return Ae;const s=i=>V1(i,0,1,e,n);return i=>i===0||i===1?i:Om(s(i),t,r)}const Im=e=>t=>t<=.5?e(2*t)/2:(2-e(2*(1-t)))/2,Bm=e=>t=>1-e(1-t),Um=ms(.33,1.53,.69,.99),Fu=Bm(Um),zm=Im(Fu),$m=e=>(e*=2)<1?.5*Fu(e):.5*(2-Math.pow(2,-10*(e-1))),Mu=e=>1-Math.sin(Math.acos(e)),Wm=Bm(Mu),Km=Im(Mu),Hm=e=>/^0[^.\s]+$/u.test(e);function O1(e){return typeof e=="number"?e===0:e!==null?e==="none"||e==="0"||Hm(e):!0}const Dr=e=>Math.round(e*1e5)/1e5,_u=/-?(?:\d+(?:\.\d+)?|\.\d+)/gu;function I1(e){return e==null}const B1=/^(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))$/iu,Vu=(e,t)=>n=>!!(typeof n=="string"&&B1.test(n)&&n.startsWith(e)||t&&!I1(n)&&Object.prototype.hasOwnProperty.call(n,t)),Gm=(e,t,n)=>r=>{if(typeof r!="string")return r;const[s,i,o,a]=r.match(_u);return{[e]:parseFloat(s),[t]:parseFloat(i),[n]:parseFloat(o),alpha:a!==void 0?parseFloat(a):1}},U1=e=>yt(0,255,e),$o={...ir,transform:e=>Math.round(U1(e))},on={test:Vu("rgb","red"),parse:Gm("red","green","blue"),transform:({red:e,green:t,blue:n,alpha:r=1})=>"rgba("+$o.transform(e)+", "+$o.transform(t)+", "+$o.transform(n)+", "+Dr(rs.transform(r))+")"};function z1(e){let t="",n="",r="",s="";return e.length>5?(t=e.substring(1,3),n=e.substring(3,5),r=e.substring(5,7),s=e.substring(7,9)):(t=e.substring(1,2),n=e.substring(2,3),r=e.substring(3,4),s=e.substring(4,5),t+=t,n+=n,r+=r,s+=s),{red:parseInt(t,16),green:parseInt(n,16),blue:parseInt(r,16),alpha:s?parseInt(s,16)/255:1}}const nl={test:Vu("#"),parse:z1,transform:on.transform},Fn={test:Vu("hsl","hue"),parse:Gm("hue","saturation","lightness"),transform:({hue:e,saturation:t,lightness:n,alpha:r=1})=>"hsla("+Math.round(e)+", "+st.transform(Dr(t))+", "+st.transform(Dr(n))+", "+Dr(rs.transform(r))+")"},pe={test:e=>on.test(e)||nl.test(e)||Fn.test(e),parse:e=>on.test(e)?on.parse(e):Fn.test(e)?Fn.parse(e):nl.parse(e),transform:e=>typeof e=="string"?e:e.hasOwnProperty("red")?on.transform(e):Fn.transform(e)},$1=/(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))/giu;function W1(e){var t,n;return isNaN(e)&&typeof e=="string"&&(((t=e.match(_u))===null||t===void 0?void 0:t.length)||0)+(((n=e.match($1))===null||n===void 0?void 0:n.length)||0)>0}const Xm="number",Qm="color",K1="var",H1="var(",kd="${}",G1=/var\s*\(\s*--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)|#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\)|-?(?:\d+(?:\.\d+)?|\.\d+)/giu;function is(e){const t=e.toString(),n=[],r={color:[],number:[],var:[]},s=[];let i=0;const a=t.replace(G1,l=>(pe.test(l)?(r.color.push(i),s.push(Qm),n.push(pe.parse(l))):l.startsWith(H1)?(r.var.push(i),s.push(K1),n.push(l)):(r.number.push(i),s.push(Xm),n.push(parseFloat(l))),++i,kd)).split(kd);return{values:n,split:a,indexes:r,types:s}}function Ym(e){return is(e).values}function Zm(e){const{split:t,types:n}=is(e),r=t.length;return s=>{let i="";for(let o=0;otypeof e=="number"?0:e;function Q1(e){const t=Ym(e);return Zm(e)(t.map(X1))}const zt={test:W1,parse:Ym,createTransformer:Zm,getAnimatableNone:Q1},Y1=new Set(["brightness","contrast","saturate","opacity"]);function Z1(e){const[t,n]=e.slice(0,-1).split("(");if(t==="drop-shadow")return e;const[r]=n.match(_u)||[];if(!r)return e;const s=n.replace(r,"");let i=Y1.has(t)?1:0;return r!==n&&(i*=100),t+"("+i+s+")"}const J1=/\b([a-z-]*)\(.*?\)/gu,rl={...zt,getAnimatableNone:e=>{const t=e.match(J1);return t?t.map(Z1).join(" "):e}},q1={...Su,color:pe,backgroundColor:pe,outlineColor:pe,fill:pe,stroke:pe,borderColor:pe,borderTopColor:pe,borderRightColor:pe,borderBottomColor:pe,borderLeftColor:pe,filter:rl,WebkitFilter:rl},Ou=e=>q1[e];function Jm(e,t){let n=Ou(e);return n!==rl&&(n=zt),n.getAnimatableNone?n.getAnimatableNone(t):void 0}const ew=new Set(["auto","none","0"]);function tw(e,t,n){let r=0,s;for(;re===ir||e===R,Pd=(e,t)=>parseFloat(e.split(", ")[t]),Td=(e,t)=>(n,{transform:r})=>{if(r==="none"||!r)return 0;const s=r.match(/^matrix3d\((.+)\)$/u);if(s)return Pd(s[1],t);{const i=r.match(/^matrix\((.+)\)$/u);return i?Pd(i[1],e):0}},nw=new Set(["x","y","z"]),rw=sr.filter(e=>!nw.has(e));function sw(e){const t=[];return rw.forEach(n=>{const r=e.getValue(n);r!==void 0&&(t.push([n,r.get()]),r.set(n.startsWith("scale")?1:0))}),t}const er={width:({x:e},{paddingLeft:t="0",paddingRight:n="0"})=>e.max-e.min-parseFloat(t)-parseFloat(n),height:({y:e},{paddingTop:t="0",paddingBottom:n="0"})=>e.max-e.min-parseFloat(t)-parseFloat(n),top:(e,{top:t})=>parseFloat(t),left:(e,{left:t})=>parseFloat(t),bottom:({y:e},{top:t})=>parseFloat(t)+(e.max-e.min),right:({x:e},{left:t})=>parseFloat(t)+(e.max-e.min),x:Td(4,13),y:Td(5,14)};er.translateX=er.x;er.translateY=er.y;const un=new Set;let sl=!1,il=!1;function qm(){if(il){const e=Array.from(un).filter(r=>r.needsMeasurement),t=new Set(e.map(r=>r.element)),n=new Map;t.forEach(r=>{const s=sw(r);s.length&&(n.set(r,s),r.render())}),e.forEach(r=>r.measureInitialState()),t.forEach(r=>{r.render();const s=n.get(r);s&&s.forEach(([i,o])=>{var a;(a=r.getValue(i))===null||a===void 0||a.set(o)})}),e.forEach(r=>r.measureEndState()),e.forEach(r=>{r.suspendedScrollY!==void 0&&window.scrollTo(0,r.suspendedScrollY)})}il=!1,sl=!1,un.forEach(e=>e.complete()),un.clear()}function eg(){un.forEach(e=>{e.readKeyframes(),e.needsMeasurement&&(il=!0)})}function iw(){eg(),qm()}class Iu{constructor(t,n,r,s,i,o=!1){this.isComplete=!1,this.isAsync=!1,this.needsMeasurement=!1,this.isScheduled=!1,this.unresolvedKeyframes=[...t],this.onComplete=n,this.name=r,this.motionValue=s,this.element=i,this.isAsync=o}scheduleResolve(){this.isScheduled=!0,this.isAsync?(un.add(this),sl||(sl=!0,z.read(eg),z.resolveKeyframes(qm))):(this.readKeyframes(),this.complete())}readKeyframes(){const{unresolvedKeyframes:t,name:n,element:r,motionValue:s}=this;for(let i=0;i/^-?(?:\d+(?:\.\d+)?|\.\d+)$/u.test(e),ow=/^var\(--(?:([\w-]+)|([\w-]+), ?([a-zA-Z\d ()%#.,-]+))\)/u;function aw(e){const t=ow.exec(e);if(!t)return[,];const[,n,r,s]=t;return[`--${n??r}`,s]}function ng(e,t,n=1){const[r,s]=aw(e);if(!r)return;const i=window.getComputedStyle(t).getPropertyValue(r);if(i){const o=i.trim();return tg(o)?parseFloat(o):o}return wu(s)?ng(s,t,n+1):s}const rg=e=>t=>t.test(e),lw={test:e=>e==="auto",parse:e=>e},sg=[ir,R,st,bt,Zx,Yx,lw],Ed=e=>sg.find(rg(e));class ig extends Iu{constructor(t,n,r,s,i){super(t,n,r,s,i,!0)}readKeyframes(){const{unresolvedKeyframes:t,element:n,name:r}=this;if(!n||!n.current)return;super.readKeyframes();for(let l=0;l{n.getValue(l).set(u)}),this.resolveNoneKeyframes()}}const jd=(e,t)=>t==="zIndex"?!1:!!(typeof e=="number"||Array.isArray(e)||typeof e=="string"&&(zt.test(e)||e==="0")&&!e.startsWith("url("));function uw(e){const t=e[0];if(e.length===1)return!0;for(let n=0;ne!==null;function co(e,{repeat:t,repeatType:n="loop"},r){const s=e.filter(dw),i=t&&n!=="loop"&&t%2===1?0:s.length-1;return!i||r===void 0?s[i]:r}const fw=40;class og{constructor({autoplay:t=!0,delay:n=0,type:r="keyframes",repeat:s=0,repeatDelay:i=0,repeatType:o="loop",...a}){this.isStopped=!1,this.hasAttemptedResolve=!1,this.createdAt=it.now(),this.options={autoplay:t,delay:n,type:r,repeat:s,repeatDelay:i,repeatType:o,...a},this.updateFinishedPromise()}calcStartTime(){return this.resolvedAt?this.resolvedAt-this.createdAt>fw?this.resolvedAt:this.createdAt:this.createdAt}get resolved(){return!this._resolved&&!this.hasAttemptedResolve&&iw(),this._resolved}onKeyframesResolved(t,n){this.resolvedAt=it.now(),this.hasAttemptedResolve=!0;const{name:r,type:s,velocity:i,delay:o,onComplete:a,onUpdate:l,isGenerator:u}=this.options;if(!u&&!cw(t,r,s,i))if(o)this.options.duration=0;else{l&&l(co(t,this.options,n)),a&&a(),this.resolveFinishedPromise();return}const c=this.initPlayback(t,n);c!==!1&&(this._resolved={keyframes:t,finalKeyframe:n,...c},this.onPostResolved())}onPostResolved(){}then(t,n){return this.currentFinishedPromise.then(t,n)}flatten(){this.options.type="keyframes",this.options.ease="linear"}updateFinishedPromise(){this.currentFinishedPromise=new Promise(t=>{this.resolveFinishedPromise=t})}}const K=(e,t,n)=>e+(t-e)*n;function Wo(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*6*n:n<1/2?t:n<2/3?e+(t-e)*(2/3-n)*6:e}function hw({hue:e,saturation:t,lightness:n,alpha:r}){e/=360,t/=100,n/=100;let s=0,i=0,o=0;if(!t)s=i=o=n;else{const a=n<.5?n*(1+t):n+t-n*t,l=2*n-a;s=Wo(l,a,e+1/3),i=Wo(l,a,e),o=Wo(l,a,e-1/3)}return{red:Math.round(s*255),green:Math.round(i*255),blue:Math.round(o*255),alpha:r}}function Mi(e,t){return n=>n>0?t:e}const Ko=(e,t,n)=>{const r=e*e,s=n*(t*t-r)+r;return s<0?0:Math.sqrt(s)},pw=[nl,on,Fn],mw=e=>pw.find(t=>t.test(e));function Nd(e){const t=mw(e);if(!t)return!1;let n=t.parse(e);return t===Fn&&(n=hw(n)),n}const Ad=(e,t)=>{const n=Nd(e),r=Nd(t);if(!n||!r)return Mi(e,t);const s={...n};return i=>(s.red=Ko(n.red,r.red,i),s.green=Ko(n.green,r.green,i),s.blue=Ko(n.blue,r.blue,i),s.alpha=K(n.alpha,r.alpha,i),on.transform(s))},gw=(e,t)=>n=>t(e(n)),gs=(...e)=>e.reduce(gw),ol=new Set(["none","hidden"]);function yw(e,t){return ol.has(e)?n=>n<=0?e:t:n=>n>=1?t:e}function vw(e,t){return n=>K(e,t,n)}function Bu(e){return typeof e=="number"?vw:typeof e=="string"?wu(e)?Mi:pe.test(e)?Ad:Sw:Array.isArray(e)?ag:typeof e=="object"?pe.test(e)?Ad:xw:Mi}function ag(e,t){const n=[...e],r=n.length,s=e.map((i,o)=>Bu(i)(i,t[o]));return i=>{for(let o=0;o{for(const i in r)n[i]=r[i](s);return n}}function ww(e,t){var n;const r=[],s={color:0,var:0,number:0};for(let i=0;i{const n=zt.createTransformer(t),r=is(e),s=is(t);return r.indexes.var.length===s.indexes.var.length&&r.indexes.color.length===s.indexes.color.length&&r.indexes.number.length>=s.indexes.number.length?ol.has(e)&&!s.values.length||ol.has(t)&&!r.values.length?yw(e,t):gs(ag(ww(r,s),s.values),n):Mi(e,t)};function lg(e,t,n){return typeof e=="number"&&typeof t=="number"&&typeof n=="number"?K(e,t,n):Bu(e)(e,t)}const bw=5;function ug(e,t,n){const r=Math.max(t-bw,0);return _m(n-e(r),t-r)}const X={stiffness:100,damping:10,mass:1,velocity:0,duration:800,bounce:.3,visualDuration:.3,restSpeed:{granular:.01,default:2},restDelta:{granular:.005,default:.5},minDuration:.01,maxDuration:10,minDamping:.05,maxDamping:1},Ho=.001;function kw({duration:e=X.duration,bounce:t=X.bounce,velocity:n=X.velocity,mass:r=X.mass}){let s,i,o=1-t;o=yt(X.minDamping,X.maxDamping,o),e=yt(X.minDuration,X.maxDuration,ft(e)),o<1?(s=u=>{const c=u*o,f=c*e,h=c-n,g=al(u,o),v=Math.exp(-f);return Ho-h/g*v},i=u=>{const f=u*o*e,h=f*n+n,g=Math.pow(o,2)*Math.pow(u,2)*e,v=Math.exp(-f),w=al(Math.pow(u,2),o);return(-s(u)+Ho>0?-1:1)*((h-g)*v)/w}):(s=u=>{const c=Math.exp(-u*e),f=(u-n)*e+1;return-Ho+c*f},i=u=>{const c=Math.exp(-u*e),f=(n-u)*(e*e);return c*f});const a=5/e,l=Pw(s,i,a);if(e=dt(e),isNaN(l))return{stiffness:X.stiffness,damping:X.damping,duration:e};{const u=Math.pow(l,2)*r;return{stiffness:u,damping:o*2*Math.sqrt(r*u),duration:e}}}const Cw=12;function Pw(e,t,n){let r=n;for(let s=1;se[n]!==void 0)}function jw(e){let t={velocity:X.velocity,stiffness:X.stiffness,damping:X.damping,mass:X.mass,isResolvedFromDuration:!1,...e};if(!Rd(e,Ew)&&Rd(e,Tw))if(e.visualDuration){const n=e.visualDuration,r=2*Math.PI/(n*1.2),s=r*r,i=2*yt(.05,1,1-(e.bounce||0))*Math.sqrt(s);t={...t,mass:X.mass,stiffness:s,damping:i}}else{const n=kw(e);t={...t,...n,mass:X.mass},t.isResolvedFromDuration=!0}return t}function cg(e=X.visualDuration,t=X.bounce){const n=typeof e!="object"?{visualDuration:e,keyframes:[0,1],bounce:t}:e;let{restSpeed:r,restDelta:s}=n;const i=n.keyframes[0],o=n.keyframes[n.keyframes.length-1],a={done:!1,value:i},{stiffness:l,damping:u,mass:c,duration:f,velocity:h,isResolvedFromDuration:g}=jw({...n,velocity:-ft(n.velocity||0)}),v=h||0,w=u/(2*Math.sqrt(l*c)),S=o-i,m=ft(Math.sqrt(l/c)),p=Math.abs(S)<5;r||(r=p?X.restSpeed.granular:X.restSpeed.default),s||(s=p?X.restDelta.granular:X.restDelta.default);let y;if(w<1){const k=al(m,w);y=C=>{const E=Math.exp(-w*m*C);return o-E*((v+w*m*S)/k*Math.sin(k*C)+S*Math.cos(k*C))}}else if(w===1)y=k=>o-Math.exp(-m*k)*(S+(v+m*S)*k);else{const k=m*Math.sqrt(w*w-1);y=C=>{const E=Math.exp(-w*m*C),P=Math.min(k*C,300);return o-E*((v+w*m*S)*Math.sinh(P)+k*S*Math.cosh(P))/k}}const b={calculatedDuration:g&&f||null,next:k=>{const C=y(k);if(g)a.done=k>=f;else{let E=0;w<1&&(E=k===0?dt(v):ug(y,k,C));const P=Math.abs(E)<=r,F=Math.abs(o-C)<=s;a.done=P&&F}return a.value=a.done?o:C,a},toString:()=>{const k=Math.min(jm(b),qa),C=Nm(E=>b.next(k*E).value,k,30);return k+"ms "+C}};return b}function Ld({keyframes:e,velocity:t=0,power:n=.8,timeConstant:r=325,bounceDamping:s=10,bounceStiffness:i=500,modifyTarget:o,min:a,max:l,restDelta:u=.5,restSpeed:c}){const f=e[0],h={done:!1,value:f},g=P=>a!==void 0&&Pl,v=P=>a===void 0?l:l===void 0||Math.abs(a-P)-w*Math.exp(-P/r),y=P=>m+p(P),b=P=>{const F=p(P),A=y(P);h.done=Math.abs(F)<=u,h.value=h.done?m:A};let k,C;const E=P=>{g(h.value)&&(k=P,C=cg({keyframes:[h.value,v(h.value)],velocity:ug(y,P,h.value),damping:s,stiffness:i,restDelta:u,restSpeed:c}))};return E(0),{calculatedDuration:null,next:P=>{let F=!1;return!C&&k===void 0&&(F=!0,b(P),E(P)),k!==void 0&&P>=k?C.next(P-k):(!F&&b(P),h)}}}const Nw=ms(.42,0,1,1),Aw=ms(0,0,.58,1),dg=ms(.42,0,.58,1),Rw=e=>Array.isArray(e)&&typeof e[0]!="number",Lw={linear:Ae,easeIn:Nw,easeInOut:dg,easeOut:Aw,circIn:Mu,circInOut:Km,circOut:Wm,backIn:Fu,backInOut:zm,backOut:Um,anticipate:$m},Dd=e=>{if(Nu(e)){lm(e.length===4);const[t,n,r,s]=e;return ms(t,n,r,s)}else if(typeof e=="string")return Lw[e];return e};function Dw(e,t,n){const r=[],s=n||lg,i=e.length-1;for(let o=0;ot[0];if(i===2&&t[0]===t[1])return()=>t[1];const o=e[0]===e[1];e[0]>e[i-1]&&(e=[...e].reverse(),t=[...t].reverse());const a=Dw(t,r,s),l=a.length,u=c=>{if(o&&c1)for(;fu(yt(e[0],e[i-1],c)):u}function Mw(e,t){const n=e[e.length-1];for(let r=1;r<=t;r++){const s=Jn(0,t,r);e.push(K(n,1,s))}}function _w(e){const t=[0];return Mw(t,e.length-1),t}function Vw(e,t){return e.map(n=>n*t)}function Ow(e,t){return e.map(()=>t||dg).splice(0,e.length-1)}function _i({duration:e=300,keyframes:t,times:n,ease:r="easeInOut"}){const s=Rw(r)?r.map(Dd):Dd(r),i={done:!1,value:t[0]},o=Vw(n&&n.length===t.length?n:_w(t),e),a=Fw(o,t,{ease:Array.isArray(s)?s:Ow(t,s)});return{calculatedDuration:e,next:l=>(i.value=a(l),i.done=l>=e,i)}}const Iw=e=>{const t=({timestamp:n})=>e(n);return{start:()=>z.update(t,!0),stop:()=>Ut(t),now:()=>ue.isProcessing?ue.timestamp:it.now()}},Bw={decay:Ld,inertia:Ld,tween:_i,keyframes:_i,spring:cg},Uw=e=>e/100;class Uu extends og{constructor(t){super(t),this.holdTime=null,this.cancelTime=null,this.currentTime=0,this.playbackSpeed=1,this.pendingPlayState="running",this.startTime=null,this.state="idle",this.stop=()=>{if(this.resolver.cancel(),this.isStopped=!0,this.state==="idle")return;this.teardown();const{onStop:l}=this.options;l&&l()};const{name:n,motionValue:r,element:s,keyframes:i}=this.options,o=(s==null?void 0:s.KeyframeResolver)||Iu,a=(l,u)=>this.onKeyframesResolved(l,u);this.resolver=new o(i,a,n,r,s),this.resolver.scheduleResolve()}flatten(){super.flatten(),this._resolved&&Object.assign(this._resolved,this.initPlayback(this._resolved.keyframes))}initPlayback(t){const{type:n="keyframes",repeat:r=0,repeatDelay:s=0,repeatType:i,velocity:o=0}=this.options,a=ju(n)?n:Bw[n]||_i;let l,u;a!==_i&&typeof t[0]!="number"&&(l=gs(Uw,lg(t[0],t[1])),t=[0,100]);const c=a({...this.options,keyframes:t});i==="mirror"&&(u=a({...this.options,keyframes:[...t].reverse(),velocity:-o})),c.calculatedDuration===null&&(c.calculatedDuration=jm(c));const{calculatedDuration:f}=c,h=f+s,g=h*(r+1)-s;return{generator:c,mirroredGenerator:u,mapPercentToKeyframes:l,calculatedDuration:f,resolvedDuration:h,totalDuration:g}}onPostResolved(){const{autoplay:t=!0}=this.options;this.play(),this.pendingPlayState==="paused"||!t?this.pause():this.state=this.pendingPlayState}tick(t,n=!1){const{resolved:r}=this;if(!r){const{keyframes:P}=this.options;return{done:!0,value:P[P.length-1]}}const{finalKeyframe:s,generator:i,mirroredGenerator:o,mapPercentToKeyframes:a,keyframes:l,calculatedDuration:u,totalDuration:c,resolvedDuration:f}=r;if(this.startTime===null)return i.next(0);const{delay:h,repeat:g,repeatType:v,repeatDelay:w,onUpdate:S}=this.options;this.speed>0?this.startTime=Math.min(this.startTime,t):this.speed<0&&(this.startTime=Math.min(t-c/this.speed,this.startTime)),n?this.currentTime=t:this.holdTime!==null?this.currentTime=this.holdTime:this.currentTime=Math.round(t-this.startTime)*this.speed;const m=this.currentTime-h*(this.speed>=0?1:-1),p=this.speed>=0?m<0:m>c;this.currentTime=Math.max(m,0),this.state==="finished"&&this.holdTime===null&&(this.currentTime=c);let y=this.currentTime,b=i;if(g){const P=Math.min(this.currentTime,c)/f;let F=Math.floor(P),A=P%1;!A&&P>=1&&(A=1),A===1&&F--,F=Math.min(F,g+1),!!(F%2)&&(v==="reverse"?(A=1-A,w&&(A-=w/f)):v==="mirror"&&(b=o)),y=yt(0,1,A)*f}const k=p?{done:!1,value:l[0]}:b.next(y);a&&(k.value=a(k.value));let{done:C}=k;!p&&u!==null&&(C=this.speed>=0?this.currentTime>=c:this.currentTime<=0);const E=this.holdTime===null&&(this.state==="finished"||this.state==="running"&&C);return E&&s!==void 0&&(k.value=co(l,this.options,s)),S&&S(k.value),E&&this.finish(),k}get duration(){const{resolved:t}=this;return t?ft(t.calculatedDuration):0}get time(){return ft(this.currentTime)}set time(t){t=dt(t),this.currentTime=t,this.holdTime!==null||this.speed===0?this.holdTime=t:this.driver&&(this.startTime=this.driver.now()-t/this.speed)}get speed(){return this.playbackSpeed}set speed(t){const n=this.playbackSpeed!==t;this.playbackSpeed=t,n&&(this.time=ft(this.currentTime))}play(){if(this.resolver.isScheduled||this.resolver.resume(),!this._resolved){this.pendingPlayState="running";return}if(this.isStopped)return;const{driver:t=Iw,onPlay:n,startTime:r}=this.options;this.driver||(this.driver=t(i=>this.tick(i))),n&&n();const s=this.driver.now();this.holdTime!==null?this.startTime=s-this.holdTime:this.startTime?this.state==="finished"&&(this.startTime=s):this.startTime=r??this.calcStartTime(),this.state==="finished"&&this.updateFinishedPromise(),this.cancelTime=this.startTime,this.holdTime=null,this.state="running",this.driver.start()}pause(){var t;if(!this._resolved){this.pendingPlayState="paused";return}this.state="paused",this.holdTime=(t=this.currentTime)!==null&&t!==void 0?t:0}complete(){this.state!=="running"&&this.play(),this.pendingPlayState=this.state="finished",this.holdTime=null}finish(){this.teardown(),this.state="finished";const{onComplete:t}=this.options;t&&t()}cancel(){this.cancelTime!==null&&this.tick(this.cancelTime),this.teardown(),this.updateFinishedPromise()}teardown(){this.state="idle",this.stopDriver(),this.resolveFinishedPromise(),this.updateFinishedPromise(),this.startTime=this.cancelTime=null,this.resolver.cancel()}stopDriver(){this.driver&&(this.driver.stop(),this.driver=void 0)}sample(t){return this.startTime=0,this.tick(t,!0)}}const zw=new Set(["opacity","clipPath","filter","transform"]);function $w(e,t,n,{delay:r=0,duration:s=300,repeat:i=0,repeatType:o="loop",ease:a="easeInOut",times:l}={}){const u={[t]:n};l&&(u.offset=l);const c=Rm(a,s);return Array.isArray(c)&&(u.easing=c),e.animate(u,{delay:r,duration:s,easing:Array.isArray(c)?"linear":c,fill:"both",iterations:i+1,direction:o==="reverse"?"alternate":"normal"})}const Ww=hu(()=>Object.hasOwnProperty.call(Element.prototype,"animate")),Vi=10,Kw=2e4;function Hw(e){return ju(e.type)||e.type==="spring"||!Am(e.ease)}function Gw(e,t){const n=new Uu({...t,keyframes:e,repeat:0,delay:0,isGenerator:!0});let r={done:!1,value:e[0]};const s=[];let i=0;for(;!r.done&&ithis.onKeyframesResolved(o,a),n,r,s),this.resolver.scheduleResolve()}initPlayback(t,n){let{duration:r=300,times:s,ease:i,type:o,motionValue:a,name:l,startTime:u}=this.options;if(!a.owner||!a.owner.current)return!1;if(typeof i=="string"&&Fi()&&Xw(i)&&(i=fg[i]),Hw(this.options)){const{onComplete:f,onUpdate:h,motionValue:g,element:v,...w}=this.options,S=Gw(t,w);t=S.keyframes,t.length===1&&(t[1]=t[0]),r=S.duration,s=S.times,i=S.ease,o="keyframes"}const c=$w(a.owner.current,l,t,{...this.options,duration:r,times:s,ease:i});return c.startTime=u??this.calcStartTime(),this.pendingTimeline?(vd(c,this.pendingTimeline),this.pendingTimeline=void 0):c.onfinish=()=>{const{onComplete:f}=this.options;a.set(co(t,this.options,n)),f&&f(),this.cancel(),this.resolveFinishedPromise()},{animation:c,duration:r,times:s,type:o,ease:i,keyframes:t}}get duration(){const{resolved:t}=this;if(!t)return 0;const{duration:n}=t;return ft(n)}get time(){const{resolved:t}=this;if(!t)return 0;const{animation:n}=t;return ft(n.currentTime||0)}set time(t){const{resolved:n}=this;if(!n)return;const{animation:r}=n;r.currentTime=dt(t)}get speed(){const{resolved:t}=this;if(!t)return 1;const{animation:n}=t;return n.playbackRate}set speed(t){const{resolved:n}=this;if(!n)return;const{animation:r}=n;r.playbackRate=t}get state(){const{resolved:t}=this;if(!t)return"idle";const{animation:n}=t;return n.playState}get startTime(){const{resolved:t}=this;if(!t)return null;const{animation:n}=t;return n.startTime}attachTimeline(t){if(!this._resolved)this.pendingTimeline=t;else{const{resolved:n}=this;if(!n)return Ae;const{animation:r}=n;vd(r,t)}return Ae}play(){if(this.isStopped)return;const{resolved:t}=this;if(!t)return;const{animation:n}=t;n.playState==="finished"&&this.updateFinishedPromise(),n.play()}pause(){const{resolved:t}=this;if(!t)return;const{animation:n}=t;n.pause()}stop(){if(this.resolver.cancel(),this.isStopped=!0,this.state==="idle")return;this.resolveFinishedPromise(),this.updateFinishedPromise();const{resolved:t}=this;if(!t)return;const{animation:n,keyframes:r,duration:s,type:i,ease:o,times:a}=t;if(n.playState==="idle"||n.playState==="finished")return;if(this.time){const{motionValue:u,onUpdate:c,onComplete:f,element:h,...g}=this.options,v=new Uu({...g,keyframes:r,duration:s,type:i,ease:o,times:a,isGenerator:!0}),w=dt(this.time);u.setWithVelocity(v.sample(w-Vi).value,v.sample(w).value,Vi)}const{onStop:l}=this.options;l&&l(),this.cancel()}complete(){const{resolved:t}=this;t&&t.animation.finish()}cancel(){const{resolved:t}=this;t&&t.animation.cancel()}static supports(t){const{motionValue:n,name:r,repeatDelay:s,repeatType:i,damping:o,type:a}=t;if(!n||!n.owner||!(n.owner.current instanceof HTMLElement))return!1;const{onUpdate:l,transformTemplate:u}=n.owner.getProps();return Ww()&&r&&zw.has(r)&&!l&&!u&&!s&&i!=="mirror"&&o!==0&&a!=="inertia"}}const Qw={type:"spring",stiffness:500,damping:25,restSpeed:10},Yw=e=>({type:"spring",stiffness:550,damping:e===0?2*Math.sqrt(550):30,restSpeed:10}),Zw={type:"keyframes",duration:.8},Jw={type:"keyframes",ease:[.25,.1,.35,1],duration:.3},qw=(e,{keyframes:t})=>t.length>2?Zw:xn.has(e)?e.startsWith("scale")?Yw(t[1]):Qw:Jw;function eS({when:e,delay:t,delayChildren:n,staggerChildren:r,staggerDirection:s,repeat:i,repeatType:o,repeatDelay:a,from:l,elapsed:u,...c}){return!!Object.keys(c).length}const zu=(e,t,n,r={},s,i)=>o=>{const a=Eu(r,e)||{},l=a.delay||r.delay||0;let{elapsed:u=0}=r;u=u-dt(l);let c={keyframes:Array.isArray(n)?n:[null,n],ease:"easeOut",velocity:t.getVelocity(),...a,delay:-u,onUpdate:h=>{t.set(h),a.onUpdate&&a.onUpdate(h)},onComplete:()=>{o(),a.onComplete&&a.onComplete()},name:e,motionValue:t,element:i?void 0:s};eS(a)||(c={...c,...qw(e,c)}),c.duration&&(c.duration=dt(c.duration)),c.repeatDelay&&(c.repeatDelay=dt(c.repeatDelay)),c.from!==void 0&&(c.keyframes[0]=c.from);let f=!1;if((c.type===!1||c.duration===0&&!c.repeatDelay)&&(c.duration=0,c.delay===0&&(f=!0)),f&&!i&&t.get()!==void 0){const h=co(c.keyframes,a);if(h!==void 0)return z.update(()=>{c.onUpdate(h),c.onComplete()}),new x1([])}return!i&&Fd.supports(c)?new Fd(c):new Uu(c)};function tS({protectedKeys:e,needsAnimating:t},n){const r=e.hasOwnProperty(n)&&t[n]!==!0;return t[n]=!1,r}function hg(e,t,{delay:n=0,transitionOverride:r,type:s}={}){var i;let{transition:o=e.getDefaultTransition(),transitionEnd:a,...l}=t;r&&(o=r);const u=[],c=s&&e.animationState&&e.animationState.getState()[s];for(const f in l){const h=e.getValue(f,(i=e.latestValues[f])!==null&&i!==void 0?i:null),g=l[f];if(g===void 0||c&&tS(c,f))continue;const v={delay:n,...Eu(o||{},f)};let w=!1;if(window.MotionHandoffAnimation){const m=Vm(e);if(m){const p=window.MotionHandoffAnimation(m,f,z);p!==null&&(v.startTime=p,w=!0)}}tl(e,f),h.start(zu(f,h,g,e.shouldReduceMotion&&Mm.has(f)?{type:!1}:v,e,w));const S=h.animation;S&&u.push(S)}return a&&Promise.all(u).then(()=>{z.update(()=>{a&&D1(e,a)})}),u}function ll(e,t,n={}){var r;const s=uo(e,t,n.type==="exit"?(r=e.presenceContext)===null||r===void 0?void 0:r.custom:void 0);let{transition:i=e.getDefaultTransition()||{}}=s||{};n.transitionOverride&&(i=n.transitionOverride);const o=s?()=>Promise.all(hg(e,s,n)):()=>Promise.resolve(),a=e.variantChildren&&e.variantChildren.size?(u=0)=>{const{delayChildren:c=0,staggerChildren:f,staggerDirection:h}=i;return nS(e,t,c+u,f,h,n)}:()=>Promise.resolve(),{when:l}=i;if(l){const[u,c]=l==="beforeChildren"?[o,a]:[a,o];return u().then(()=>c())}else return Promise.all([o(),a(n.delay)])}function nS(e,t,n=0,r=0,s=1,i){const o=[],a=(e.variantChildren.size-1)*r,l=s===1?(u=0)=>u*r:(u=0)=>a-u*r;return Array.from(e.variantChildren).sort(rS).forEach((u,c)=>{u.notify("AnimationStart",t),o.push(ll(u,t,{...i,delay:n+l(c)}).then(()=>u.notify("AnimationComplete",t)))}),Promise.all(o)}function rS(e,t){return e.sortNodePosition(t)}function sS(e,t,n={}){e.notify("AnimationStart",t);let r;if(Array.isArray(t)){const s=t.map(i=>ll(e,i,n));r=Promise.all(s)}else if(typeof t=="string")r=ll(e,t,n);else{const s=typeof t=="function"?uo(e,t,n.custom):t;r=Promise.all(hg(e,s,n))}return r.then(()=>{e.notify("AnimationComplete",t)})}const iS=mu.length;function pg(e){if(!e)return;if(!e.isControllingVariants){const n=e.parent?pg(e.parent)||{}:{};return e.props.initial!==void 0&&(n.initial=e.props.initial),n}const t={};for(let n=0;nPromise.all(t.map(({animation:n,options:r})=>sS(e,n,r)))}function uS(e){let t=lS(e),n=Md(),r=!0;const s=l=>(u,c)=>{var f;const h=uo(e,c,l==="exit"?(f=e.presenceContext)===null||f===void 0?void 0:f.custom:void 0);if(h){const{transition:g,transitionEnd:v,...w}=h;u={...u,...w,...v}}return u};function i(l){t=l(e)}function o(l){const{props:u}=e,c=pg(e.parent)||{},f=[],h=new Set;let g={},v=1/0;for(let S=0;Sv&&b,F=!1;const A=Array.isArray(y)?y:[y];let ee=A.reduce(s(m),{});k===!1&&(ee={});const{prevResolvedValues:wt={}}=p,Xt={...wt,...ee},or=ne=>{P=!0,h.has(ne)&&(F=!0,h.delete(ne)),p.needsAnimating[ne]=!0;const j=e.getValue(ne);j&&(j.liveStyle=!1)};for(const ne in Xt){const j=ee[ne],L=wt[ne];if(g.hasOwnProperty(ne))continue;let D=!1;Ja(j)&&Ja(L)?D=!Em(j,L):D=j!==L,D?j!=null?or(ne):h.add(ne):j!==void 0&&h.has(ne)?or(ne):p.protectedKeys[ne]=!0}p.prevProp=y,p.prevResolvedValues=ee,p.isActive&&(g={...g,...ee}),r&&e.blockInitialAnimation&&(P=!1),P&&(!(C&&E)||F)&&f.push(...A.map(ne=>({animation:ne,options:{type:m}})))}if(h.size){const S={};h.forEach(m=>{const p=e.getBaseTarget(m),y=e.getValue(m);y&&(y.liveStyle=!0),S[m]=p??null}),f.push({animation:S})}let w=!!f.length;return r&&(u.initial===!1||u.initial===u.animate)&&!e.manuallyAnimateOnMount&&(w=!1),r=!1,w?t(f):Promise.resolve()}function a(l,u){var c;if(n[l].isActive===u)return Promise.resolve();(c=e.variantChildren)===null||c===void 0||c.forEach(h=>{var g;return(g=h.animationState)===null||g===void 0?void 0:g.setActive(l,u)}),n[l].isActive=u;const f=o(l);for(const h in n)n[h].protectedKeys={};return f}return{animateChanges:o,setActive:a,setAnimateFunction:i,getState:()=>n,reset:()=>{n=Md(),r=!0}}}function cS(e,t){return typeof t=="string"?t!==e:Array.isArray(t)?!Em(t,e):!1}function Zt(e=!1){return{isActive:e,protectedKeys:{},needsAnimating:{},prevResolvedValues:{}}}function Md(){return{animate:Zt(!0),whileInView:Zt(),whileHover:Zt(),whileTap:Zt(),whileDrag:Zt(),whileFocus:Zt(),exit:Zt()}}class Gt{constructor(t){this.isMounted=!1,this.node=t}update(){}}class dS extends Gt{constructor(t){super(t),t.animationState||(t.animationState=uS(t))}updateAnimationControlsSubscription(){const{animate:t}=this.node.getProps();ao(t)&&(this.unmountControls=t.subscribe(this.node))}mount(){this.updateAnimationControlsSubscription()}update(){const{animate:t}=this.node.getProps(),{animate:n}=this.node.prevProps||{};t!==n&&this.updateAnimationControlsSubscription()}unmount(){var t;this.node.animationState.reset(),(t=this.unmountControls)===null||t===void 0||t.call(this)}}let fS=0;class hS extends Gt{constructor(){super(...arguments),this.id=fS++}update(){if(!this.node.presenceContext)return;const{isPresent:t,onExitComplete:n}=this.node.presenceContext,{isPresent:r}=this.node.prevPresenceContext||{};if(!this.node.animationState||t===r)return;const s=this.node.animationState.setActive("exit",!t);n&&!t&&s.then(()=>n(this.id))}mount(){const{register:t}=this.node.presenceContext||{};t&&(this.unmount=t(this.id))}unmount(){}}const pS={animation:{Feature:dS},exit:{Feature:hS}};function os(e,t,n,r={passive:!0}){return e.addEventListener(t,n,r),()=>e.removeEventListener(t,n)}function ys(e){return{point:{x:e.pageX,y:e.pageY}}}const mS=e=>t=>Au(t)&&e(t,ys(t));function Fr(e,t,n,r){return os(e,t,mS(n),r)}const _d=(e,t)=>Math.abs(e-t);function gS(e,t){const n=_d(e.x,t.x),r=_d(e.y,t.y);return Math.sqrt(n**2+r**2)}class mg{constructor(t,n,{transformPagePoint:r,contextWindow:s,dragSnapToOrigin:i=!1}={}){if(this.startEvent=null,this.lastMoveEvent=null,this.lastMoveEventInfo=null,this.handlers={},this.contextWindow=window,this.updatePoint=()=>{if(!(this.lastMoveEvent&&this.lastMoveEventInfo))return;const f=Xo(this.lastMoveEventInfo,this.history),h=this.startEvent!==null,g=gS(f.offset,{x:0,y:0})>=3;if(!h&&!g)return;const{point:v}=f,{timestamp:w}=ue;this.history.push({...v,timestamp:w});const{onStart:S,onMove:m}=this.handlers;h||(S&&S(this.lastMoveEvent,f),this.startEvent=this.lastMoveEvent),m&&m(this.lastMoveEvent,f)},this.handlePointerMove=(f,h)=>{this.lastMoveEvent=f,this.lastMoveEventInfo=Go(h,this.transformPagePoint),z.update(this.updatePoint,!0)},this.handlePointerUp=(f,h)=>{this.end();const{onEnd:g,onSessionEnd:v,resumeAnimation:w}=this.handlers;if(this.dragSnapToOrigin&&w&&w(),!(this.lastMoveEvent&&this.lastMoveEventInfo))return;const S=Xo(f.type==="pointercancel"?this.lastMoveEventInfo:Go(h,this.transformPagePoint),this.history);this.startEvent&&g&&g(f,S),v&&v(f,S)},!Au(t))return;this.dragSnapToOrigin=i,this.handlers=n,this.transformPagePoint=r,this.contextWindow=s||window;const o=ys(t),a=Go(o,this.transformPagePoint),{point:l}=a,{timestamp:u}=ue;this.history=[{...l,timestamp:u}];const{onSessionStart:c}=n;c&&c(t,Xo(a,this.history)),this.removeListeners=gs(Fr(this.contextWindow,"pointermove",this.handlePointerMove),Fr(this.contextWindow,"pointerup",this.handlePointerUp),Fr(this.contextWindow,"pointercancel",this.handlePointerUp))}updateHandlers(t){this.handlers=t}end(){this.removeListeners&&this.removeListeners(),Ut(this.updatePoint)}}function Go(e,t){return t?{point:t(e.point)}:e}function Vd(e,t){return{x:e.x-t.x,y:e.y-t.y}}function Xo({point:e},t){return{point:e,delta:Vd(e,gg(t)),offset:Vd(e,yS(t)),velocity:vS(t,.1)}}function yS(e){return e[0]}function gg(e){return e[e.length-1]}function vS(e,t){if(e.length<2)return{x:0,y:0};let n=e.length-1,r=null;const s=gg(e);for(;n>=0&&(r=e[n],!(s.timestamp-r.timestamp>dt(t)));)n--;if(!r)return{x:0,y:0};const i=ft(s.timestamp-r.timestamp);if(i===0)return{x:0,y:0};const o={x:(s.x-r.x)/i,y:(s.y-r.y)/i};return o.x===1/0&&(o.x=0),o.y===1/0&&(o.y=0),o}const yg=1e-4,xS=1-yg,wS=1+yg,vg=.01,SS=0-vg,bS=0+vg;function Le(e){return e.max-e.min}function kS(e,t,n){return Math.abs(e-t)<=n}function Od(e,t,n,r=.5){e.origin=r,e.originPoint=K(t.min,t.max,e.origin),e.scale=Le(n)/Le(t),e.translate=K(n.min,n.max,e.origin)-e.originPoint,(e.scale>=xS&&e.scale<=wS||isNaN(e.scale))&&(e.scale=1),(e.translate>=SS&&e.translate<=bS||isNaN(e.translate))&&(e.translate=0)}function Mr(e,t,n,r){Od(e.x,t.x,n.x,r?r.originX:void 0),Od(e.y,t.y,n.y,r?r.originY:void 0)}function Id(e,t,n){e.min=n.min+t.min,e.max=e.min+Le(t)}function CS(e,t,n){Id(e.x,t.x,n.x),Id(e.y,t.y,n.y)}function Bd(e,t,n){e.min=t.min-n.min,e.max=e.min+Le(t)}function _r(e,t,n){Bd(e.x,t.x,n.x),Bd(e.y,t.y,n.y)}function PS(e,{min:t,max:n},r){return t!==void 0&&en&&(e=r?K(n,e,r.max):Math.min(e,n)),e}function Ud(e,t,n){return{min:t!==void 0?e.min+t:void 0,max:n!==void 0?e.max+n-(e.max-e.min):void 0}}function TS(e,{top:t,left:n,bottom:r,right:s}){return{x:Ud(e.x,n,s),y:Ud(e.y,t,r)}}function zd(e,t){let n=t.min-e.min,r=t.max-e.max;return t.max-t.minr?n=Jn(t.min,t.max-r,e.min):r>s&&(n=Jn(e.min,e.max-s,t.min)),yt(0,1,n)}function NS(e,t){const n={};return t.min!==void 0&&(n.min=t.min-e.min),t.max!==void 0&&(n.max=t.max-e.min),n}const ul=.35;function AS(e=ul){return e===!1?e=0:e===!0&&(e=ul),{x:$d(e,"left","right"),y:$d(e,"top","bottom")}}function $d(e,t,n){return{min:Wd(e,t),max:Wd(e,n)}}function Wd(e,t){return typeof e=="number"?e:e[t]||0}const Kd=()=>({translate:0,scale:1,origin:0,originPoint:0}),Mn=()=>({x:Kd(),y:Kd()}),Hd=()=>({min:0,max:0}),J=()=>({x:Hd(),y:Hd()});function Ve(e){return[e("x"),e("y")]}function xg({top:e,left:t,right:n,bottom:r}){return{x:{min:t,max:n},y:{min:e,max:r}}}function RS({x:e,y:t}){return{top:t.min,right:e.max,bottom:t.max,left:e.min}}function LS(e,t){if(!t)return e;const n=t({x:e.left,y:e.top}),r=t({x:e.right,y:e.bottom});return{top:n.y,left:n.x,bottom:r.y,right:r.x}}function Qo(e){return e===void 0||e===1}function cl({scale:e,scaleX:t,scaleY:n}){return!Qo(e)||!Qo(t)||!Qo(n)}function en(e){return cl(e)||wg(e)||e.z||e.rotate||e.rotateX||e.rotateY||e.skewX||e.skewY}function wg(e){return Gd(e.x)||Gd(e.y)}function Gd(e){return e&&e!=="0%"}function Oi(e,t,n){const r=e-n,s=t*r;return n+s}function Xd(e,t,n,r,s){return s!==void 0&&(e=Oi(e,s,r)),Oi(e,n,r)+t}function dl(e,t=0,n=1,r,s){e.min=Xd(e.min,t,n,r,s),e.max=Xd(e.max,t,n,r,s)}function Sg(e,{x:t,y:n}){dl(e.x,t.translate,t.scale,t.originPoint),dl(e.y,n.translate,n.scale,n.originPoint)}const Qd=.999999999999,Yd=1.0000000000001;function DS(e,t,n,r=!1){const s=n.length;if(!s)return;t.x=t.y=1;let i,o;for(let a=0;aQd&&(t.x=1),t.yQd&&(t.y=1)}function _n(e,t){e.min=e.min+t,e.max=e.max+t}function Zd(e,t,n,r,s=.5){const i=K(e.min,e.max,s);dl(e,t,n,i,r)}function Vn(e,t){Zd(e.x,t.x,t.scaleX,t.scale,t.originX),Zd(e.y,t.y,t.scaleY,t.scale,t.originY)}function bg(e,t){return xg(LS(e.getBoundingClientRect(),t))}function FS(e,t,n){const r=bg(e,n),{scroll:s}=t;return s&&(_n(r.x,s.offset.x),_n(r.y,s.offset.y)),r}const kg=({current:e})=>e?e.ownerDocument.defaultView:null,MS=new WeakMap;class _S{constructor(t){this.openDragLock=null,this.isDragging=!1,this.currentDirection=null,this.originPoint={x:0,y:0},this.constraints=!1,this.hasMutatedConstraints=!1,this.elastic=J(),this.visualElement=t}start(t,{snapToCursor:n=!1}={}){const{presenceContext:r}=this.visualElement;if(r&&r.isPresent===!1)return;const s=c=>{const{dragSnapToOrigin:f}=this.getProps();f?this.pauseAnimation():this.stopAnimation(),n&&this.snapToCursor(ys(c).point)},i=(c,f)=>{const{drag:h,dragPropagation:g,onDragStart:v}=this.getProps();if(h&&!g&&(this.openDragLock&&this.openDragLock(),this.openDragLock=j1(h),!this.openDragLock))return;this.isDragging=!0,this.currentDirection=null,this.resolveConstraints(),this.visualElement.projection&&(this.visualElement.projection.isAnimationBlocked=!0,this.visualElement.projection.target=void 0),Ve(S=>{let m=this.getAxisMotionValue(S).get()||0;if(st.test(m)){const{projection:p}=this.visualElement;if(p&&p.layout){const y=p.layout.layoutBox[S];y&&(m=Le(y)*(parseFloat(m)/100))}}this.originPoint[S]=m}),v&&z.postRender(()=>v(c,f)),tl(this.visualElement,"transform");const{animationState:w}=this.visualElement;w&&w.setActive("whileDrag",!0)},o=(c,f)=>{const{dragPropagation:h,dragDirectionLock:g,onDirectionLock:v,onDrag:w}=this.getProps();if(!h&&!this.openDragLock)return;const{offset:S}=f;if(g&&this.currentDirection===null){this.currentDirection=VS(S),this.currentDirection!==null&&v&&v(this.currentDirection);return}this.updateAxis("x",f.point,S),this.updateAxis("y",f.point,S),this.visualElement.render(),w&&w(c,f)},a=(c,f)=>this.stop(c,f),l=()=>Ve(c=>{var f;return this.getAnimationState(c)==="paused"&&((f=this.getAxisMotionValue(c).animation)===null||f===void 0?void 0:f.play())}),{dragSnapToOrigin:u}=this.getProps();this.panSession=new mg(t,{onSessionStart:s,onStart:i,onMove:o,onSessionEnd:a,resumeAnimation:l},{transformPagePoint:this.visualElement.getTransformPagePoint(),dragSnapToOrigin:u,contextWindow:kg(this.visualElement)})}stop(t,n){const r=this.isDragging;if(this.cancel(),!r)return;const{velocity:s}=n;this.startAnimation(s);const{onDragEnd:i}=this.getProps();i&&z.postRender(()=>i(t,n))}cancel(){this.isDragging=!1;const{projection:t,animationState:n}=this.visualElement;t&&(t.isAnimationBlocked=!1),this.panSession&&this.panSession.end(),this.panSession=void 0;const{dragPropagation:r}=this.getProps();!r&&this.openDragLock&&(this.openDragLock(),this.openDragLock=null),n&&n.setActive("whileDrag",!1)}updateAxis(t,n,r){const{drag:s}=this.getProps();if(!r||!Ws(t,s,this.currentDirection))return;const i=this.getAxisMotionValue(t);let o=this.originPoint[t]+r[t];this.constraints&&this.constraints[t]&&(o=PS(o,this.constraints[t],this.elastic[t])),i.set(o)}resolveConstraints(){var t;const{dragConstraints:n,dragElastic:r}=this.getProps(),s=this.visualElement.projection&&!this.visualElement.projection.layout?this.visualElement.projection.measure(!1):(t=this.visualElement.projection)===null||t===void 0?void 0:t.layout,i=this.constraints;n&&Dn(n)?this.constraints||(this.constraints=this.resolveRefConstraints()):n&&s?this.constraints=TS(s.layoutBox,n):this.constraints=!1,this.elastic=AS(r),i!==this.constraints&&s&&this.constraints&&!this.hasMutatedConstraints&&Ve(o=>{this.constraints!==!1&&this.getAxisMotionValue(o)&&(this.constraints[o]=NS(s.layoutBox[o],this.constraints[o]))})}resolveRefConstraints(){const{dragConstraints:t,onMeasureDragConstraints:n}=this.getProps();if(!t||!Dn(t))return!1;const r=t.current,{projection:s}=this.visualElement;if(!s||!s.layout)return!1;const i=FS(r,s.root,this.visualElement.getTransformPagePoint());let o=ES(s.layout.layoutBox,i);if(n){const a=n(RS(o));this.hasMutatedConstraints=!!a,a&&(o=xg(a))}return o}startAnimation(t){const{drag:n,dragMomentum:r,dragElastic:s,dragTransition:i,dragSnapToOrigin:o,onDragTransitionEnd:a}=this.getProps(),l=this.constraints||{},u=Ve(c=>{if(!Ws(c,n,this.currentDirection))return;let f=l&&l[c]||{};o&&(f={min:0,max:0});const h=s?200:1e6,g=s?40:1e7,v={type:"inertia",velocity:r?t[c]:0,bounceStiffness:h,bounceDamping:g,timeConstant:750,restDelta:1,restSpeed:10,...i,...f};return this.startAxisValueAnimation(c,v)});return Promise.all(u).then(a)}startAxisValueAnimation(t,n){const r=this.getAxisMotionValue(t);return tl(this.visualElement,t),r.start(zu(t,r,0,n,this.visualElement,!1))}stopAnimation(){Ve(t=>this.getAxisMotionValue(t).stop())}pauseAnimation(){Ve(t=>{var n;return(n=this.getAxisMotionValue(t).animation)===null||n===void 0?void 0:n.pause()})}getAnimationState(t){var n;return(n=this.getAxisMotionValue(t).animation)===null||n===void 0?void 0:n.state}getAxisMotionValue(t){const n=`_drag${t.toUpperCase()}`,r=this.visualElement.getProps(),s=r[n];return s||this.visualElement.getValue(t,(r.initial?r.initial[t]:void 0)||0)}snapToCursor(t){Ve(n=>{const{drag:r}=this.getProps();if(!Ws(n,r,this.currentDirection))return;const{projection:s}=this.visualElement,i=this.getAxisMotionValue(n);if(s&&s.layout){const{min:o,max:a}=s.layout.layoutBox[n];i.set(t[n]-K(o,a,.5))}})}scalePositionWithinConstraints(){if(!this.visualElement.current)return;const{drag:t,dragConstraints:n}=this.getProps(),{projection:r}=this.visualElement;if(!Dn(n)||!r||!this.constraints)return;this.stopAnimation();const s={x:0,y:0};Ve(o=>{const a=this.getAxisMotionValue(o);if(a&&this.constraints!==!1){const l=a.get();s[o]=jS({min:l,max:l},this.constraints[o])}});const{transformTemplate:i}=this.visualElement.getProps();this.visualElement.current.style.transform=i?i({},""):"none",r.root&&r.root.updateScroll(),r.updateLayout(),this.resolveConstraints(),Ve(o=>{if(!Ws(o,t,null))return;const a=this.getAxisMotionValue(o),{min:l,max:u}=this.constraints[o];a.set(K(l,u,s[o]))})}addListeners(){if(!this.visualElement.current)return;MS.set(this.visualElement,this);const t=this.visualElement.current,n=Fr(t,"pointerdown",l=>{const{drag:u,dragListener:c=!0}=this.getProps();u&&c&&this.start(l)}),r=()=>{const{dragConstraints:l}=this.getProps();Dn(l)&&l.current&&(this.constraints=this.resolveRefConstraints())},{projection:s}=this.visualElement,i=s.addEventListener("measure",r);s&&!s.layout&&(s.root&&s.root.updateScroll(),s.updateLayout()),z.read(r);const o=os(window,"resize",()=>this.scalePositionWithinConstraints()),a=s.addEventListener("didUpdate",({delta:l,hasLayoutChanged:u})=>{this.isDragging&&u&&(Ve(c=>{const f=this.getAxisMotionValue(c);f&&(this.originPoint[c]+=l[c].translate,f.set(f.get()+l[c].translate))}),this.visualElement.render())});return()=>{o(),n(),i(),a&&a()}}getProps(){const t=this.visualElement.getProps(),{drag:n=!1,dragDirectionLock:r=!1,dragPropagation:s=!1,dragConstraints:i=!1,dragElastic:o=ul,dragMomentum:a=!0}=t;return{...t,drag:n,dragDirectionLock:r,dragPropagation:s,dragConstraints:i,dragElastic:o,dragMomentum:a}}}function Ws(e,t,n){return(t===!0||t===e)&&(n===null||n===e)}function VS(e,t=10){let n=null;return Math.abs(e.y)>t?n="y":Math.abs(e.x)>t&&(n="x"),n}class OS extends Gt{constructor(t){super(t),this.removeGroupControls=Ae,this.removeListeners=Ae,this.controls=new _S(t)}mount(){const{dragControls:t}=this.node.getProps();t&&(this.removeGroupControls=t.subscribe(this.controls)),this.removeListeners=this.controls.addListeners()||Ae}unmount(){this.removeGroupControls(),this.removeListeners()}}const Jd=e=>(t,n)=>{e&&z.postRender(()=>e(t,n))};class IS extends Gt{constructor(){super(...arguments),this.removePointerDownListener=Ae}onPointerDown(t){this.session=new mg(t,this.createPanHandlers(),{transformPagePoint:this.node.getTransformPagePoint(),contextWindow:kg(this.node)})}createPanHandlers(){const{onPanSessionStart:t,onPanStart:n,onPan:r,onPanEnd:s}=this.node.getProps();return{onSessionStart:Jd(t),onStart:Jd(n),onMove:r,onEnd:(i,o)=>{delete this.session,s&&z.postRender(()=>s(i,o))}}}mount(){this.removePointerDownListener=Fr(this.node.current,"pointerdown",t=>this.onPointerDown(t))}update(){this.session&&this.session.updateHandlers(this.createPanHandlers())}unmount(){this.removePointerDownListener(),this.session&&this.session.end()}}const ii={hasAnimatedSinceResize:!0,hasEverUpdated:!1};function qd(e,t){return t.max===t.min?0:e/(t.max-t.min)*100}const mr={correct:(e,t)=>{if(!t.target)return e;if(typeof e=="string")if(R.test(e))e=parseFloat(e);else return e;const n=qd(e,t.target.x),r=qd(e,t.target.y);return`${n}% ${r}%`}},BS={correct:(e,{treeScale:t,projectionDelta:n})=>{const r=e,s=zt.parse(e);if(s.length>5)return r;const i=zt.createTransformer(e),o=typeof s[0]!="number"?1:0,a=n.x.scale*t.x,l=n.y.scale*t.y;s[0+o]/=a,s[1+o]/=l;const u=K(a,l,.5);return typeof s[2+o]=="number"&&(s[2+o]/=u),typeof s[3+o]=="number"&&(s[3+o]/=u),i(s)}};class US extends x.Component{componentDidMount(){const{visualElement:t,layoutGroup:n,switchLayoutGroup:r,layoutId:s}=this.props,{projection:i}=t;a1(zS),i&&(n.group&&n.group.add(i),r&&r.register&&s&&r.register(i),i.root.didUpdate(),i.addEventListener("animationComplete",()=>{this.safeToRemove()}),i.setOptions({...i.options,onExitComplete:()=>this.safeToRemove()})),ii.hasEverUpdated=!0}getSnapshotBeforeUpdate(t){const{layoutDependency:n,visualElement:r,drag:s,isPresent:i}=this.props,o=r.projection;return o&&(o.isPresent=i,s||t.layoutDependency!==n||n===void 0?o.willUpdate():this.safeToRemove(),t.isPresent!==i&&(i?o.promote():o.relegate()||z.postRender(()=>{const a=o.getStack();(!a||!a.members.length)&&this.safeToRemove()}))),null}componentDidUpdate(){const{projection:t}=this.props.visualElement;t&&(t.root.didUpdate(),yu.postRender(()=>{!t.currentAnimation&&t.isLead()&&this.safeToRemove()}))}componentWillUnmount(){const{visualElement:t,layoutGroup:n,switchLayoutGroup:r}=this.props,{projection:s}=t;s&&(s.scheduleCheckAfterUnmount(),n&&n.group&&n.group.remove(s),r&&r.deregister&&r.deregister(s))}safeToRemove(){const{safeToRemove:t}=this.props;t&&t()}render(){return null}}function Cg(e){const[t,n]=im(),r=x.useContext(uu);return d.jsx(US,{...e,layoutGroup:r,switchLayoutGroup:x.useContext(pm),isPresent:t,safeToRemove:n})}const zS={borderRadius:{...mr,applyTo:["borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius"]},borderTopLeftRadius:mr,borderTopRightRadius:mr,borderBottomLeftRadius:mr,borderBottomRightRadius:mr,boxShadow:BS};function $S(e,t,n){const r=ge(e)?e:ss(e);return r.start(zu("",r,t,n)),r.animation}function WS(e){return e instanceof SVGElement&&e.tagName!=="svg"}const KS=(e,t)=>e.depth-t.depth;class HS{constructor(){this.children=[],this.isDirty=!1}add(t){Ru(this.children,t),this.isDirty=!0}remove(t){Lu(this.children,t),this.isDirty=!0}forEach(t){this.isDirty&&this.children.sort(KS),this.isDirty=!1,this.children.forEach(t)}}function GS(e,t){const n=it.now(),r=({timestamp:s})=>{const i=s-n;i>=t&&(Ut(r),e(i-t))};return z.read(r,!0),()=>Ut(r)}const Pg=["TopLeft","TopRight","BottomLeft","BottomRight"],XS=Pg.length,ef=e=>typeof e=="string"?parseFloat(e):e,tf=e=>typeof e=="number"||R.test(e);function QS(e,t,n,r,s,i){s?(e.opacity=K(0,n.opacity!==void 0?n.opacity:1,YS(r)),e.opacityExit=K(t.opacity!==void 0?t.opacity:1,0,ZS(r))):i&&(e.opacity=K(t.opacity!==void 0?t.opacity:1,n.opacity!==void 0?n.opacity:1,r));for(let o=0;ort?1:n(Jn(e,t,r))}function rf(e,t){e.min=t.min,e.max=t.max}function Me(e,t){rf(e.x,t.x),rf(e.y,t.y)}function sf(e,t){e.translate=t.translate,e.scale=t.scale,e.originPoint=t.originPoint,e.origin=t.origin}function of(e,t,n,r,s){return e-=t,e=Oi(e,1/n,r),s!==void 0&&(e=Oi(e,1/s,r)),e}function JS(e,t=0,n=1,r=.5,s,i=e,o=e){if(st.test(t)&&(t=parseFloat(t),t=K(o.min,o.max,t/100)-o.min),typeof t!="number")return;let a=K(i.min,i.max,r);e===i&&(a-=t),e.min=of(e.min,t,n,a,s),e.max=of(e.max,t,n,a,s)}function af(e,t,[n,r,s],i,o){JS(e,t[n],t[r],t[s],t.scale,i,o)}const qS=["x","scaleX","originX"],eb=["y","scaleY","originY"];function lf(e,t,n,r){af(e.x,t,qS,n?n.x:void 0,r?r.x:void 0),af(e.y,t,eb,n?n.y:void 0,r?r.y:void 0)}function uf(e){return e.translate===0&&e.scale===1}function Eg(e){return uf(e.x)&&uf(e.y)}function cf(e,t){return e.min===t.min&&e.max===t.max}function tb(e,t){return cf(e.x,t.x)&&cf(e.y,t.y)}function df(e,t){return Math.round(e.min)===Math.round(t.min)&&Math.round(e.max)===Math.round(t.max)}function jg(e,t){return df(e.x,t.x)&&df(e.y,t.y)}function ff(e){return Le(e.x)/Le(e.y)}function hf(e,t){return e.translate===t.translate&&e.scale===t.scale&&e.originPoint===t.originPoint}class nb{constructor(){this.members=[]}add(t){Ru(this.members,t),t.scheduleRender()}remove(t){if(Lu(this.members,t),t===this.prevLead&&(this.prevLead=void 0),t===this.lead){const n=this.members[this.members.length-1];n&&this.promote(n)}}relegate(t){const n=this.members.findIndex(s=>t===s);if(n===0)return!1;let r;for(let s=n;s>=0;s--){const i=this.members[s];if(i.isPresent!==!1){r=i;break}}return r?(this.promote(r),!0):!1}promote(t,n){const r=this.lead;if(t!==r&&(this.prevLead=r,this.lead=t,t.show(),r)){r.instance&&r.scheduleRender(),t.scheduleRender(),t.resumeFrom=r,n&&(t.resumeFrom.preserveOpacity=!0),r.snapshot&&(t.snapshot=r.snapshot,t.snapshot.latestValues=r.animationValues||r.latestValues),t.root&&t.root.isUpdating&&(t.isLayoutDirty=!0);const{crossfade:s}=t.options;s===!1&&r.hide()}}exitAnimationComplete(){this.members.forEach(t=>{const{options:n,resumingFrom:r}=t;n.onExitComplete&&n.onExitComplete(),r&&r.options.onExitComplete&&r.options.onExitComplete()})}scheduleRender(){this.members.forEach(t=>{t.instance&&t.scheduleRender(!1)})}removeLeadSnapshot(){this.lead&&this.lead.snapshot&&(this.lead.snapshot=void 0)}}function rb(e,t,n){let r="";const s=e.x.translate/t.x,i=e.y.translate/t.y,o=(n==null?void 0:n.z)||0;if((s||i||o)&&(r=`translate3d(${s}px, ${i}px, ${o}px) `),(t.x!==1||t.y!==1)&&(r+=`scale(${1/t.x}, ${1/t.y}) `),n){const{transformPerspective:u,rotate:c,rotateX:f,rotateY:h,skewX:g,skewY:v}=n;u&&(r=`perspective(${u}px) ${r}`),c&&(r+=`rotate(${c}deg) `),f&&(r+=`rotateX(${f}deg) `),h&&(r+=`rotateY(${h}deg) `),g&&(r+=`skewX(${g}deg) `),v&&(r+=`skewY(${v}deg) `)}const a=e.x.scale*t.x,l=e.y.scale*t.y;return(a!==1||l!==1)&&(r+=`scale(${a}, ${l})`),r||"none"}const tn={type:"projectionFrame",totalNodes:0,resolvedTargetDeltas:0,recalculatedProjection:0},br=typeof window<"u"&&window.MotionDebug!==void 0,Yo=["","X","Y","Z"],sb={visibility:"hidden"},pf=1e3;let ib=0;function Zo(e,t,n,r){const{latestValues:s}=t;s[e]&&(n[e]=s[e],t.setStaticValue(e,0),r&&(r[e]=0))}function Ng(e){if(e.hasCheckedOptimisedAppear=!0,e.root===e)return;const{visualElement:t}=e.options;if(!t)return;const n=Vm(t);if(window.MotionHasOptimisedAnimation(n,"transform")){const{layout:s,layoutId:i}=e.options;window.MotionCancelOptimisedAnimation(n,"transform",z,!(s||i))}const{parent:r}=e;r&&!r.hasCheckedOptimisedAppear&&Ng(r)}function Ag({attachResizeListener:e,defaultParent:t,measureScroll:n,checkIsScrollRoot:r,resetTransform:s}){return class{constructor(o={},a=t==null?void 0:t()){this.id=ib++,this.animationId=0,this.children=new Set,this.options={},this.isTreeAnimating=!1,this.isAnimationBlocked=!1,this.isLayoutDirty=!1,this.isProjectionDirty=!1,this.isSharedProjectionDirty=!1,this.isTransformDirty=!1,this.updateManuallyBlocked=!1,this.updateBlockedByResize=!1,this.isUpdating=!1,this.isSVG=!1,this.needsReset=!1,this.shouldResetTransform=!1,this.hasCheckedOptimisedAppear=!1,this.treeScale={x:1,y:1},this.eventHandlers=new Map,this.hasTreeAnimated=!1,this.updateScheduled=!1,this.scheduleUpdate=()=>this.update(),this.projectionUpdateScheduled=!1,this.checkUpdateFailed=()=>{this.isUpdating&&(this.isUpdating=!1,this.clearAllSnapshots())},this.updateProjection=()=>{this.projectionUpdateScheduled=!1,br&&(tn.totalNodes=tn.resolvedTargetDeltas=tn.recalculatedProjection=0),this.nodes.forEach(lb),this.nodes.forEach(hb),this.nodes.forEach(pb),this.nodes.forEach(ub),br&&window.MotionDebug.record(tn)},this.resolvedRelativeTargetAt=0,this.hasProjected=!1,this.isVisible=!0,this.animationProgress=0,this.sharedNodes=new Map,this.latestValues=o,this.root=a?a.root||a:this,this.path=a?[...a.path,a]:[],this.parent=a,this.depth=a?a.depth+1:0;for(let l=0;lthis.root.updateBlockedByResize=!1;e(o,()=>{this.root.updateBlockedByResize=!0,f&&f(),f=GS(h,250),ii.hasAnimatedSinceResize&&(ii.hasAnimatedSinceResize=!1,this.nodes.forEach(gf))})}l&&this.root.registerSharedNode(l,this),this.options.animate!==!1&&c&&(l||u)&&this.addEventListener("didUpdate",({delta:f,hasLayoutChanged:h,hasRelativeTargetChanged:g,layout:v})=>{if(this.isTreeAnimationBlocked()){this.target=void 0,this.relativeTarget=void 0;return}const w=this.options.transition||c.getDefaultTransition()||xb,{onLayoutAnimationStart:S,onLayoutAnimationComplete:m}=c.getProps(),p=!this.targetLayout||!jg(this.targetLayout,v)||g,y=!h&&g;if(this.options.layoutRoot||this.resumeFrom&&this.resumeFrom.instance||y||h&&(p||!this.currentAnimation)){this.resumeFrom&&(this.resumingFrom=this.resumeFrom,this.resumingFrom.resumingFrom=void 0),this.setAnimationOrigin(f,y);const b={...Eu(w,"layout"),onPlay:S,onComplete:m};(c.shouldReduceMotion||this.options.layoutRoot)&&(b.delay=0,b.type=!1),this.startAnimation(b)}else h||gf(this),this.isLead()&&this.options.onExitComplete&&this.options.onExitComplete();this.targetLayout=v})}unmount(){this.options.layoutId&&this.willUpdate(),this.root.nodes.remove(this);const o=this.getStack();o&&o.remove(this),this.parent&&this.parent.children.delete(this),this.instance=void 0,Ut(this.updateProjection)}blockUpdate(){this.updateManuallyBlocked=!0}unblockUpdate(){this.updateManuallyBlocked=!1}isUpdateBlocked(){return this.updateManuallyBlocked||this.updateBlockedByResize}isTreeAnimationBlocked(){return this.isAnimationBlocked||this.parent&&this.parent.isTreeAnimationBlocked()||!1}startUpdate(){this.isUpdateBlocked()||(this.isUpdating=!0,this.nodes&&this.nodes.forEach(mb),this.animationId++)}getTransformTemplate(){const{visualElement:o}=this.options;return o&&o.getProps().transformTemplate}willUpdate(o=!0){if(this.root.hasTreeAnimated=!0,this.root.isUpdateBlocked()){this.options.onExitComplete&&this.options.onExitComplete();return}if(window.MotionCancelOptimisedAnimation&&!this.hasCheckedOptimisedAppear&&Ng(this),!this.root.isUpdating&&this.root.startUpdate(),this.isLayoutDirty)return;this.isLayoutDirty=!0;for(let c=0;c{this.isLayoutDirty?this.root.didUpdate():this.root.checkUpdateFailed()})}updateSnapshot(){this.snapshot||!this.instance||(this.snapshot=this.measure())}updateLayout(){if(!this.instance||(this.updateScroll(),!(this.options.alwaysMeasureLayout&&this.isLead())&&!this.isLayoutDirty))return;if(this.resumeFrom&&!this.resumeFrom.instance)for(let l=0;l{const k=b/1e3;yf(f.x,o.x,k),yf(f.y,o.y,k),this.setTargetDelta(f),this.relativeTarget&&this.relativeTargetOrigin&&this.layout&&this.relativeParent&&this.relativeParent.layout&&(_r(h,this.layout.layoutBox,this.relativeParent.layout.layoutBox),yb(this.relativeTarget,this.relativeTargetOrigin,h,k),y&&tb(this.relativeTarget,y)&&(this.isProjectionDirty=!1),y||(y=J()),Me(y,this.relativeTarget)),w&&(this.animationValues=c,QS(c,u,this.latestValues,k,p,m)),this.root.scheduleUpdateProjection(),this.scheduleRender(),this.animationProgress=k},this.mixTargetDelta(this.options.layoutRoot?1e3:0)}startAnimation(o){this.notifyListeners("animationStart"),this.currentAnimation&&this.currentAnimation.stop(),this.resumingFrom&&this.resumingFrom.currentAnimation&&this.resumingFrom.currentAnimation.stop(),this.pendingAnimation&&(Ut(this.pendingAnimation),this.pendingAnimation=void 0),this.pendingAnimation=z.update(()=>{ii.hasAnimatedSinceResize=!0,this.currentAnimation=$S(0,pf,{...o,onUpdate:a=>{this.mixTargetDelta(a),o.onUpdate&&o.onUpdate(a)},onComplete:()=>{o.onComplete&&o.onComplete(),this.completeAnimation()}}),this.resumingFrom&&(this.resumingFrom.currentAnimation=this.currentAnimation),this.pendingAnimation=void 0})}completeAnimation(){this.resumingFrom&&(this.resumingFrom.currentAnimation=void 0,this.resumingFrom.preserveOpacity=void 0);const o=this.getStack();o&&o.exitAnimationComplete(),this.resumingFrom=this.currentAnimation=this.animationValues=void 0,this.notifyListeners("animationComplete")}finishAnimation(){this.currentAnimation&&(this.mixTargetDelta&&this.mixTargetDelta(pf),this.currentAnimation.stop()),this.completeAnimation()}applyTransformsToTarget(){const o=this.getLead();let{targetWithTransforms:a,target:l,layout:u,latestValues:c}=o;if(!(!a||!l||!u)){if(this!==o&&this.layout&&u&&Rg(this.options.animationType,this.layout.layoutBox,u.layoutBox)){l=this.target||J();const f=Le(this.layout.layoutBox.x);l.x.min=o.target.x.min,l.x.max=l.x.min+f;const h=Le(this.layout.layoutBox.y);l.y.min=o.target.y.min,l.y.max=l.y.min+h}Me(a,l),Vn(a,c),Mr(this.projectionDeltaWithTransform,this.layoutCorrected,a,c)}}registerSharedNode(o,a){this.sharedNodes.has(o)||this.sharedNodes.set(o,new nb),this.sharedNodes.get(o).add(a);const u=a.options.initialPromotionConfig;a.promote({transition:u?u.transition:void 0,preserveFollowOpacity:u&&u.shouldPreserveFollowOpacity?u.shouldPreserveFollowOpacity(a):void 0})}isLead(){const o=this.getStack();return o?o.lead===this:!0}getLead(){var o;const{layoutId:a}=this.options;return a?((o=this.getStack())===null||o===void 0?void 0:o.lead)||this:this}getPrevLead(){var o;const{layoutId:a}=this.options;return a?(o=this.getStack())===null||o===void 0?void 0:o.prevLead:void 0}getStack(){const{layoutId:o}=this.options;if(o)return this.root.sharedNodes.get(o)}promote({needsReset:o,transition:a,preserveFollowOpacity:l}={}){const u=this.getStack();u&&u.promote(this,l),o&&(this.projectionDelta=void 0,this.needsReset=!0),a&&this.setOptions({transition:a})}relegate(){const o=this.getStack();return o?o.relegate(this):!1}resetSkewAndRotation(){const{visualElement:o}=this.options;if(!o)return;let a=!1;const{latestValues:l}=o;if((l.z||l.rotate||l.rotateX||l.rotateY||l.rotateZ||l.skewX||l.skewY)&&(a=!0),!a)return;const u={};l.z&&Zo("z",o,u,this.animationValues);for(let c=0;c{var a;return(a=o.currentAnimation)===null||a===void 0?void 0:a.stop()}),this.root.nodes.forEach(mf),this.root.sharedNodes.clear()}}}function ob(e){e.updateLayout()}function ab(e){var t;const n=((t=e.resumeFrom)===null||t===void 0?void 0:t.snapshot)||e.snapshot;if(e.isLead()&&e.layout&&n&&e.hasListeners("didUpdate")){const{layoutBox:r,measuredBox:s}=e.layout,{animationType:i}=e.options,o=n.source!==e.layout.source;i==="size"?Ve(f=>{const h=o?n.measuredBox[f]:n.layoutBox[f],g=Le(h);h.min=r[f].min,h.max=h.min+g}):Rg(i,n.layoutBox,r)&&Ve(f=>{const h=o?n.measuredBox[f]:n.layoutBox[f],g=Le(r[f]);h.max=h.min+g,e.relativeTarget&&!e.currentAnimation&&(e.isProjectionDirty=!0,e.relativeTarget[f].max=e.relativeTarget[f].min+g)});const a=Mn();Mr(a,r,n.layoutBox);const l=Mn();o?Mr(l,e.applyTransform(s,!0),n.measuredBox):Mr(l,r,n.layoutBox);const u=!Eg(a);let c=!1;if(!e.resumeFrom){const f=e.getClosestProjectingParent();if(f&&!f.resumeFrom){const{snapshot:h,layout:g}=f;if(h&&g){const v=J();_r(v,n.layoutBox,h.layoutBox);const w=J();_r(w,r,g.layoutBox),jg(v,w)||(c=!0),f.options.layoutRoot&&(e.relativeTarget=w,e.relativeTargetOrigin=v,e.relativeParent=f)}}}e.notifyListeners("didUpdate",{layout:r,snapshot:n,delta:l,layoutDelta:a,hasLayoutChanged:u,hasRelativeTargetChanged:c})}else if(e.isLead()){const{onExitComplete:r}=e.options;r&&r()}e.options.transition=void 0}function lb(e){br&&tn.totalNodes++,e.parent&&(e.isProjecting()||(e.isProjectionDirty=e.parent.isProjectionDirty),e.isSharedProjectionDirty||(e.isSharedProjectionDirty=!!(e.isProjectionDirty||e.parent.isProjectionDirty||e.parent.isSharedProjectionDirty)),e.isTransformDirty||(e.isTransformDirty=e.parent.isTransformDirty))}function ub(e){e.isProjectionDirty=e.isSharedProjectionDirty=e.isTransformDirty=!1}function cb(e){e.clearSnapshot()}function mf(e){e.clearMeasurements()}function db(e){e.isLayoutDirty=!1}function fb(e){const{visualElement:t}=e.options;t&&t.getProps().onBeforeLayoutMeasure&&t.notify("BeforeLayoutMeasure"),e.resetTransform()}function gf(e){e.finishAnimation(),e.targetDelta=e.relativeTarget=e.target=void 0,e.isProjectionDirty=!0}function hb(e){e.resolveTargetDelta()}function pb(e){e.calcProjection()}function mb(e){e.resetSkewAndRotation()}function gb(e){e.removeLeadSnapshot()}function yf(e,t,n){e.translate=K(t.translate,0,n),e.scale=K(t.scale,1,n),e.origin=t.origin,e.originPoint=t.originPoint}function vf(e,t,n,r){e.min=K(t.min,n.min,r),e.max=K(t.max,n.max,r)}function yb(e,t,n,r){vf(e.x,t.x,n.x,r),vf(e.y,t.y,n.y,r)}function vb(e){return e.animationValues&&e.animationValues.opacityExit!==void 0}const xb={duration:.45,ease:[.4,0,.1,1]},xf=e=>typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().includes(e),wf=xf("applewebkit/")&&!xf("chrome/")?Math.round:Ae;function Sf(e){e.min=wf(e.min),e.max=wf(e.max)}function wb(e){Sf(e.x),Sf(e.y)}function Rg(e,t,n){return e==="position"||e==="preserve-aspect"&&!kS(ff(t),ff(n),.2)}function Sb(e){var t;return e!==e.root&&((t=e.scroll)===null||t===void 0?void 0:t.wasRoot)}const bb=Ag({attachResizeListener:(e,t)=>os(e,"resize",t),measureScroll:()=>({x:document.documentElement.scrollLeft||document.body.scrollLeft,y:document.documentElement.scrollTop||document.body.scrollTop}),checkIsScrollRoot:()=>!0}),Jo={current:void 0},Lg=Ag({measureScroll:e=>({x:e.scrollLeft,y:e.scrollTop}),defaultParent:()=>{if(!Jo.current){const e=new bb({});e.mount(window),e.setOptions({layoutScroll:!0}),Jo.current=e}return Jo.current},resetTransform:(e,t)=>{e.style.transform=t!==void 0?t:"none"},checkIsScrollRoot:e=>window.getComputedStyle(e).position==="fixed"}),kb={pan:{Feature:IS},drag:{Feature:OS,ProjectionNode:Lg,MeasureLayout:Cg}};function bf(e,t,n){const{props:r}=e;e.animationState&&r.whileHover&&e.animationState.setActive("whileHover",n==="Start");const s="onHover"+n,i=r[s];i&&z.postRender(()=>i(t,ys(t)))}class Cb extends Gt{mount(){const{current:t}=this.node;t&&(this.unmount=k1(t,n=>(bf(this.node,n,"Start"),r=>bf(this.node,r,"End"))))}unmount(){}}class Pb extends Gt{constructor(){super(...arguments),this.isActive=!1}onFocus(){let t=!1;try{t=this.node.current.matches(":focus-visible")}catch{t=!0}!t||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!0),this.isActive=!0)}onBlur(){!this.isActive||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!1),this.isActive=!1)}mount(){this.unmount=gs(os(this.node.current,"focus",()=>this.onFocus()),os(this.node.current,"blur",()=>this.onBlur()))}unmount(){}}function kf(e,t,n){const{props:r}=e;e.animationState&&r.whileTap&&e.animationState.setActive("whileTap",n==="Start");const s="onTap"+(n==="End"?"":n),i=r[s];i&&z.postRender(()=>i(t,ys(t)))}class Tb extends Gt{mount(){const{current:t}=this.node;t&&(this.unmount=E1(t,n=>(kf(this.node,n,"Start"),(r,{success:s})=>kf(this.node,r,s?"End":"Cancel")),{useGlobalTarget:this.node.props.globalTapTarget}))}unmount(){}}const fl=new WeakMap,qo=new WeakMap,Eb=e=>{const t=fl.get(e.target);t&&t(e)},jb=e=>{e.forEach(Eb)};function Nb({root:e,...t}){const n=e||document;qo.has(n)||qo.set(n,{});const r=qo.get(n),s=JSON.stringify(t);return r[s]||(r[s]=new IntersectionObserver(jb,{root:e,...t})),r[s]}function Ab(e,t,n){const r=Nb(t);return fl.set(e,n),r.observe(e),()=>{fl.delete(e),r.unobserve(e)}}const Rb={some:0,all:1};class Lb extends Gt{constructor(){super(...arguments),this.hasEnteredView=!1,this.isInView=!1}startObserver(){this.unmount();const{viewport:t={}}=this.node.getProps(),{root:n,margin:r,amount:s="some",once:i}=t,o={root:n?n.current:void 0,rootMargin:r,threshold:typeof s=="number"?s:Rb[s]},a=l=>{const{isIntersecting:u}=l;if(this.isInView===u||(this.isInView=u,i&&!u&&this.hasEnteredView))return;u&&(this.hasEnteredView=!0),this.node.animationState&&this.node.animationState.setActive("whileInView",u);const{onViewportEnter:c,onViewportLeave:f}=this.node.getProps(),h=u?c:f;h&&h(l)};return Ab(this.node.current,o,a)}mount(){this.startObserver()}update(){if(typeof IntersectionObserver>"u")return;const{props:t,prevProps:n}=this.node;["amount","margin","root"].some(Db(t,n))&&this.startObserver()}unmount(){}}function Db({viewport:e={}},{viewport:t={}}={}){return n=>e[n]!==t[n]}const Fb={inView:{Feature:Lb},tap:{Feature:Tb},focus:{Feature:Pb},hover:{Feature:Cb}},Mb={layout:{ProjectionNode:Lg,MeasureLayout:Cg}},hl={current:null},Dg={current:!1};function _b(){if(Dg.current=!0,!!fu)if(window.matchMedia){const e=window.matchMedia("(prefers-reduced-motion)"),t=()=>hl.current=e.matches;e.addListener(t),t()}else hl.current=!1}const Vb=[...sg,pe,zt],Ob=e=>Vb.find(rg(e)),Cf=new WeakMap;function Ib(e,t,n){for(const r in t){const s=t[r],i=n[r];if(ge(s))e.addValue(r,s);else if(ge(i))e.addValue(r,ss(s,{owner:e}));else if(i!==s)if(e.hasValue(r)){const o=e.getValue(r);o.liveStyle===!0?o.jump(s):o.hasAnimated||o.set(s)}else{const o=e.getStaticValue(r);e.addValue(r,ss(o!==void 0?o:s,{owner:e}))}}for(const r in n)t[r]===void 0&&e.removeValue(r);return t}const Pf=["AnimationStart","AnimationComplete","Update","BeforeLayoutMeasure","LayoutMeasure","LayoutAnimationStart","LayoutAnimationComplete"];class Bb{scrapeMotionValuesFromProps(t,n,r){return{}}constructor({parent:t,props:n,presenceContext:r,reducedMotionConfig:s,blockInitialAnimation:i,visualState:o},a={}){this.current=null,this.children=new Set,this.isVariantNode=!1,this.isControllingVariants=!1,this.shouldReduceMotion=null,this.values=new Map,this.KeyframeResolver=Iu,this.features={},this.valueSubscriptions=new Map,this.prevMotionValues={},this.events={},this.propEventSubscriptions={},this.notifyUpdate=()=>this.notify("Update",this.latestValues),this.render=()=>{this.current&&(this.triggerBuild(),this.renderInstance(this.current,this.renderState,this.props.style,this.projection))},this.renderScheduledAt=0,this.scheduleRender=()=>{const g=it.now();this.renderScheduledAtthis.bindToMotionValue(r,n)),Dg.current||_b(),this.shouldReduceMotion=this.reducedMotionConfig==="never"?!1:this.reducedMotionConfig==="always"?!0:hl.current,this.parent&&this.parent.children.add(this),this.update(this.props,this.presenceContext)}unmount(){Cf.delete(this.current),this.projection&&this.projection.unmount(),Ut(this.notifyUpdate),Ut(this.render),this.valueSubscriptions.forEach(t=>t()),this.valueSubscriptions.clear(),this.removeFromVariantTree&&this.removeFromVariantTree(),this.parent&&this.parent.children.delete(this);for(const t in this.events)this.events[t].clear();for(const t in this.features){const n=this.features[t];n&&(n.unmount(),n.isMounted=!1)}this.current=null}bindToMotionValue(t,n){this.valueSubscriptions.has(t)&&this.valueSubscriptions.get(t)();const r=xn.has(t),s=n.on("change",a=>{this.latestValues[t]=a,this.props.onUpdate&&z.preRender(this.notifyUpdate),r&&this.projection&&(this.projection.isTransformDirty=!0)}),i=n.on("renderRequest",this.scheduleRender);let o;window.MotionCheckAppearSync&&(o=window.MotionCheckAppearSync(this,t,n)),this.valueSubscriptions.set(t,()=>{s(),i(),o&&o(),n.owner&&n.stop()})}sortNodePosition(t){return!this.current||!this.sortInstanceNodePosition||this.type!==t.type?0:this.sortInstanceNodePosition(this.current,t.current)}updateFeatures(){let t="animation";for(t in qn){const n=qn[t];if(!n)continue;const{isEnabled:r,Feature:s}=n;if(!this.features[t]&&s&&r(this.props)&&(this.features[t]=new s(this)),this.features[t]){const i=this.features[t];i.isMounted?i.update():(i.mount(),i.isMounted=!0)}}}triggerBuild(){this.build(this.renderState,this.latestValues,this.props)}measureViewportBox(){return this.current?this.measureInstanceViewportBox(this.current,this.props):J()}getStaticValue(t){return this.latestValues[t]}setStaticValue(t,n){this.latestValues[t]=n}update(t,n){(t.transformTemplate||this.props.transformTemplate)&&this.scheduleRender(),this.prevProps=this.props,this.props=t,this.prevPresenceContext=this.presenceContext,this.presenceContext=n;for(let r=0;rn.variantChildren.delete(t)}addValue(t,n){const r=this.values.get(t);n!==r&&(r&&this.removeValue(t),this.bindToMotionValue(t,n),this.values.set(t,n),this.latestValues[t]=n.get())}removeValue(t){this.values.delete(t);const n=this.valueSubscriptions.get(t);n&&(n(),this.valueSubscriptions.delete(t)),delete this.latestValues[t],this.removeValueFromRenderState(t,this.renderState)}hasValue(t){return this.values.has(t)}getValue(t,n){if(this.props.values&&this.props.values[t])return this.props.values[t];let r=this.values.get(t);return r===void 0&&n!==void 0&&(r=ss(n===null?void 0:n,{owner:this}),this.addValue(t,r)),r}readValue(t,n){var r;let s=this.latestValues[t]!==void 0||!this.current?this.latestValues[t]:(r=this.getBaseTargetFromProps(this.props,t))!==null&&r!==void 0?r:this.readValueFromInstance(this.current,t,this.options);return s!=null&&(typeof s=="string"&&(tg(s)||Hm(s))?s=parseFloat(s):!Ob(s)&&zt.test(n)&&(s=Jm(t,n)),this.setBaseTarget(t,ge(s)?s.get():s)),ge(s)?s.get():s}setBaseTarget(t,n){this.baseTarget[t]=n}getBaseTarget(t){var n;const{initial:r}=this.props;let s;if(typeof r=="string"||typeof r=="object"){const o=xu(this.props,r,(n=this.presenceContext)===null||n===void 0?void 0:n.custom);o&&(s=o[t])}if(r&&s!==void 0)return s;const i=this.getBaseTargetFromProps(this.props,t);return i!==void 0&&!ge(i)?i:this.initialValues[t]!==void 0&&s===void 0?void 0:this.baseTarget[t]}on(t,n){return this.events[t]||(this.events[t]=new Du),this.events[t].add(n)}notify(t,...n){this.events[t]&&this.events[t].notify(...n)}}class Fg extends Bb{constructor(){super(...arguments),this.KeyframeResolver=ig}sortInstanceNodePosition(t,n){return t.compareDocumentPosition(n)&2?1:-1}getBaseTargetFromProps(t,n){return t.style?t.style[n]:void 0}removeValueFromRenderState(t,{vars:n,style:r}){delete n[t],delete r[t]}handleChildMotionValue(){this.childSubscription&&(this.childSubscription(),delete this.childSubscription);const{children:t}=this.props;ge(t)&&(this.childSubscription=t.on("change",n=>{this.current&&(this.current.textContent=`${n}`)}))}}function Ub(e){return window.getComputedStyle(e)}class zb extends Fg{constructor(){super(...arguments),this.type="html",this.renderInstance=Sm}readValueFromInstance(t,n){if(xn.has(n)){const r=Ou(n);return r&&r.default||0}else{const r=Ub(t),s=(vm(n)?r.getPropertyValue(n):r[n])||0;return typeof s=="string"?s.trim():s}}measureInstanceViewportBox(t,{transformPagePoint:n}){return bg(t,n)}build(t,n,r){bu(t,n,r.transformTemplate)}scrapeMotionValuesFromProps(t,n,r){return Tu(t,n,r)}}class $b extends Fg{constructor(){super(...arguments),this.type="svg",this.isSVGTag=!1,this.measureInstanceViewportBox=J}getBaseTargetFromProps(t,n){return t[n]}readValueFromInstance(t,n){if(xn.has(n)){const r=Ou(n);return r&&r.default||0}return n=bm.has(n)?n:gu(n),t.getAttribute(n)}scrapeMotionValuesFromProps(t,n,r){return Pm(t,n,r)}build(t,n,r){ku(t,n,this.isSVGTag,r.transformTemplate)}renderInstance(t,n,r,s){km(t,n,r,s)}mount(t){this.isSVGTag=Pu(t.tagName),super.mount(t)}}const Wb=(e,t)=>vu(e)?new $b(t):new zb(t,{allowProjection:e!==x.Fragment}),Kb=g1({...pS,...Fb,...kb,...Mb},Wb),O=Rx(Kb);function Mg(){return(localStorage.getItem("apiBase")||"").replace(/\/+$/,"")}function vs(e){const t=Mg(),n=e.startsWith("/")?e:`/${e}`;return t?`${t}${n}`:n}async function $u(e){const t=await fetch(vs(e));if(!t.ok)throw new Error(await t.text());return t.json()}async function vt(e,t){const n=await fetch(vs(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok)throw new Error(await n.text());return n.json()}const Hb=()=>{const e=Mg();if(e)try{const r=new URL(e.includes("://")?e:`http://${e}`);return`${r.protocol==="https:"?"wss:":"ws:"}//${r.host}/ws`}catch{}const t=window.location;return`${t.protocol==="https:"?"wss:":"ws:"}//${t.host}/ws`};function Gb(e){const[t,n]=x.useState(!1),r=x.useRef(e);return r.current=e,x.useEffect(()=>{let s=!1,i=0,o,a=null;const l=()=>{s||(a=new WebSocket(Hb()),a.onopen=()=>{i=0,n(!0),a==null||a.send("ping")},a.onclose=()=>{n(!1),i+=1,o=setTimeout(l,Math.min(8e3,500+i*400))},a.onerror=()=>a==null?void 0:a.close(),a.onmessage=u=>r.current(String(u.data)))};return l(),()=>{s=!0,clearTimeout(o),a==null||a.close()}},[]),t}const _g=x.createContext(null),Wu=5e3,Ku="pn532_browser_log_v1";function Xb(){try{const e=sessionStorage.getItem(Ku);if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?t.slice(-Wu):[]}catch{return[]}}function Qb(e){try{sessionStorage.setItem(Ku,JSON.stringify(e.slice(-Wu)))}catch{}}function Yb(e,t,n){if(typeof e=="object"&&e&&"present"in e&&e.present===!1){t(null),n(!1);return}n(!0),typeof e=="object"&&e&&"uid"in e&&t(e)}function Zb(e){if(!e||typeof e!="object")return!1;const t=e;return t.present===!1?!1:typeof t.uid=="string"&&t.uid.length>0}function Jb(e){return!e||typeof e!="object"?!1:e.event==="recorded"}function qb({children:e}){const[t,n]=x.useState(null),[r,s]=x.useState(!1),[i,o]=x.useState(()=>Xb()),[a,l]=x.useState(0),[u,c]=x.useState("tag"),f=x.useRef(0),h=x.useCallback(y=>{const b=Date.now();y==="tag"&&b-f.current<280||(f.current=b,c(y),l(k=>k+1))},[]),g=x.useCallback(y=>{try{const b=JSON.parse(y),k=b.channel||"unknown";o(C=>{const E=[...C,{t:Date.now(),channel:k,payload:b.payload}].slice(-Wu);return Qb(E),E}),k==="scan"?(Yb(b.payload,n,s),Zb(b.payload)&&h("tag")):k==="capture"&&Jb(b.payload)&&h("vault")}catch{}},[h]),v=Gb(g),w=x.useCallback((y,b)=>{if(!y){n(null),s(!1);return}b&&(n(b),s(!0),h("tag"))},[h]),S=x.useCallback(()=>{o([]),sessionStorage.removeItem(Ku)},[]),m=x.useCallback(()=>{const y=new Blob([JSON.stringify(i,null,2)],{type:"application/json"}),b=URL.createObjectURL(y),k=document.createElement("a");k.href=b,k.download=`pn532-browser-log-${Date.now()}.json`,k.click(),URL.revokeObjectURL(b)},[i]),p=x.useMemo(()=>({wsOk:v,lastTag:t,tagPresent:r,log:i,cashWave:a,cashVariant:u,clearBrowserLog:S,exportBrowserLog:m,applyScanPoll:w}),[v,t,r,i,a,u,S,m,w]);return d.jsx(_g.Provider,{value:p,children:e})}function xs(){const e=x.useContext(_g);if(!e)throw new Error("useNfcWs outside NfcWsProvider");return e}function e2(){const{log:e,exportBrowserLog:t,clearBrowserLog:n,wsOk:r}=xs();return d.jsxs("div",{className:"flash-log-bar relative z-40 mx-auto flex max-w-6xl flex-wrap items-center justify-between gap-2 overflow-hidden border-b border-bubble-accent/15 px-4 py-2.5 font-mono text-[10px] text-bubble-mint/80 sm:text-xs",children:[d.jsx("div",{className:"pointer-events-none absolute inset-0 overflow-hidden",children:d.jsx("div",{className:"absolute inset-y-0 left-0 w-1/3 bg-gradient-to-r from-bubble-accent/10 to-transparent animate-shimmerLine"})}),d.jsxs("div",{className:"relative flex min-w-0 flex-1 flex-wrap items-center gap-x-3 gap-y-1",children:[d.jsx("span",{className:"shrink-0 animate-pulse text-bubble-volt",children:"◆"}),d.jsxs("span",{className:"truncate",children:[d.jsx("span",{className:"text-bubble-accent/70",children:"BUF"})," ",d.jsx("span",{className:"text-glow-matrix font-bold text-bubble-mint",children:e.length}),d.jsx("span",{className:"text-bubble-mint/40",children:"_evt"})]}),d.jsx("span",{className:"hidden text-bubble-mint/20 sm:inline",children:"│"}),d.jsxs("span",{children:[d.jsx("span",{className:"text-bubble-accent/60",children:"WS"})," ",d.jsx("span",{className:r?"text-glow-matrix font-bold tracking-wide text-bubble-mint":"animate-pulse text-glow-rose font-semibold text-bubble-rose",children:r?"SYNC":"WAIT"})]})]}),d.jsxs("div",{className:"relative flex shrink-0 gap-2",children:[d.jsx("button",{type:"button",onClick:t,className:"btn-neon rounded-md border border-bubble-accent/50 bg-gradient-to-r from-bubble-accent/25 to-bubble-mint/15 px-3 py-1.5 text-[10px] font-bold uppercase tracking-wider text-bubble-accent sm:text-xs",children:"Exfil"}),d.jsx("button",{type:"button",onClick:n,className:"rounded-md border border-bubble-rose/40 bg-bubble-rose/10 px-3 py-1.5 text-[10px] font-bold uppercase tracking-wide text-bubble-rose transition hover:border-bubble-rose hover:bg-bubble-rose/20 sm:text-xs",children:"Purge"})]})]})}function t2(){return d.jsxs("div",{className:"pointer-events-none fixed inset-0 z-[2] overflow-hidden",children:[d.jsx("div",{className:"absolute -left-[20%] top-[10%] h-[min(70vh,520px)] w-[min(70vh,520px)] rounded-full bg-fuchsia-600/25 blur-[100px] animate-pulseGlow",style:{animationDelay:"0s"}}),d.jsx("div",{className:"absolute -right-[15%] bottom-[5%] h-[min(55vh,440px)] w-[min(55vh,440px)] rounded-full bg-cyan-400/20 blur-[90px] animate-pulseGlow",style:{animationDelay:"1.2s"}}),d.jsx("div",{className:"absolute left-[35%] top-[40%] h-[min(45vh,360px)] w-[min(45vh,360px)] -translate-x-1/2 -translate-y-1/2 rounded-full bg-emerald-400/15 blur-[80px] animate-floatSlow"}),d.jsx("div",{className:"absolute inset-0 bg-[radial-gradient(ellipse_at_center,transparent_0%,rgba(2,4,8,0.75)_100%)]"})]})}const Tf=16,n2=7;function r2(){var e;try{const t=window.AudioContext||window.webkitAudioContext;if(!t)return;const n=new t,r=n.createGain();r.gain.value=.11,r.connect(n.destination);const s=(c,f,h)=>{const g=n.createOscillator(),v=n.createGain();g.type="sine",g.frequency.setValueAtTime(c,f),v.gain.setValueAtTime(0,f),v.gain.linearRampToValueAtTime(1,f+.02),v.gain.exponentialRampToValueAtTime(.01,f+h),g.connect(v),v.connect(r),g.start(f),g.stop(f+h+.05)},i=n.currentTime;s(523.25,i,.11),s(659.25,i+.055,.13),s(783.99,i+.1,.16),s(1046.5,i+.14,.2);const o=n.createBufferSource(),a=n.createBuffer(1,n.sampleRate*.07,n.sampleRate),l=a.getChannelData(0);for(let c=0;cvoid n.close(),700)}catch{}}function s2(){const{cashWave:e,cashVariant:t,lastTag:n}=xs(),[r,s]=x.useState(!1),[i,o]=x.useState(0);return x.useEffect(()=>{if(e===0)return;o(e),s(!0),r2();const a=window.setTimeout(()=>s(!1),1650);return()=>window.clearTimeout(a)},[e]),d.jsx("div",{className:"pointer-events-none fixed left-2 top-[4.25rem] z-[55] sm:left-4 sm:top-[4.5rem] md:top-[5.25rem]",children:d.jsx(am,{mode:"wait",children:r?d.jsxs(O.div,{className:"relative flex flex-col items-start",initial:{opacity:0},animate:{opacity:1},exit:{opacity:0,scale:.92,filter:"blur(4px)"},transition:{duration:.4},children:[d.jsx(O.div,{className:"absolute -left-8 -top-8 h-40 w-40 rounded-full bg-gradient-to-br from-amber-400/45 via-yellow-200/30 to-bubble-mint/35 blur-2xl",initial:{scale:.2,opacity:0},animate:{scale:[.2,1.35,1],opacity:[0,1,.7]},transition:{duration:.5,ease:[.22,1,.36,1]}}),Array.from({length:Tf}).map((a,l)=>{const u=l/Tf*Math.PI*2,c=56+l%4*10;return d.jsx(O.span,{className:"absolute left-8 top-9 h-2 w-2 rounded-full bg-gradient-to-br from-yellow-100 to-amber-500 shadow-[0_0_12px_rgba(250,204,21,1)]",initial:{x:0,y:0,opacity:0,scale:0},animate:{x:Math.cos(u)*c,y:Math.sin(u)*c,opacity:[0,1,0],scale:[0,1.3,.3]},transition:{duration:.8,delay:l*.018,ease:"easeOut"}},`s-${l}`)}),Array.from({length:n2}).map((a,l)=>d.jsx(O.span,{className:"absolute left-8 top-8 text-xl sm:text-2xl",initial:{x:0,y:0,opacity:0,rotate:-30,scale:0},animate:{x:(l%2===0?1:-1)*(36+l*12),y:-32-l*11,opacity:[0,1,0],rotate:l*35,scale:[0,1.15,.85]},transition:{duration:.9,delay:.04+l*.035,ease:[.22,1,.36,1]},children:"🪙"},`c-${l}`)),d.jsxs(O.div,{className:"relative flex h-[4.75rem] w-[4.75rem] items-center justify-center sm:h-[5.5rem] sm:w-[5.5rem]",initial:{scale:0,rotate:-40},animate:{scale:[0,1.3,.92,1.06,1],rotate:[-40,12,-6,3,0]},transition:{duration:.7,ease:[.34,1.56,.64,1]},children:[d.jsx(O.div,{className:"absolute inset-0 rounded-2xl border-2 border-yellow-200/90",animate:{boxShadow:["0 0 25px rgba(250,204,21,0.55), inset 0 0 22px rgba(254,240,138,0.2)","0 0 50px rgba(0,255,157,0.5), inset 0 0 28px rgba(0,229,255,0.15)","0 0 28px rgba(250,204,21,0.6), inset 0 0 18px rgba(254,240,138,0.25)"]},transition:{duration:1.1,repeat:2}}),d.jsxs("svg",{viewBox:"0 0 100 100",className:"relative z-[1] h-[72%] w-[72%] drop-shadow-[0_0_14px_rgba(250,204,21,0.9)]","aria-hidden":!0,children:[d.jsxs("defs",{children:[d.jsxs("linearGradient",{id:"cashGold",x1:"0%",y1:"0%",x2:"100%",y2:"100%",children:[d.jsx("stop",{offset:"0%",stopColor:"#fef9c3"}),d.jsx("stop",{offset:"40%",stopColor:"#facc15"}),d.jsx("stop",{offset:"100%",stopColor:"#a16207"})]}),d.jsxs("filter",{id:"cashGlow",x:"-50%",y:"-50%",width:"200%",height:"200%",children:[d.jsx("feGaussianBlur",{stdDeviation:"1.2",result:"b"}),d.jsxs("feMerge",{children:[d.jsx("feMergeNode",{in:"b"}),d.jsx("feMergeNode",{in:"SourceGraphic"})]})]})]}),d.jsx("circle",{cx:"50",cy:"50",r:"44",fill:"url(#cashGold)",filter:"url(#cashGlow)"}),d.jsx("circle",{cx:"50",cy:"50",r:"40",fill:"none",stroke:"#422006",strokeOpacity:"0.28",strokeWidth:"2"}),d.jsx("text",{x:"50",y:"64",textAnchor:"middle",fill:"#713f12",fontSize:"54",fontWeight:"700",fontFamily:"Audiowide, Orbitron, system-ui, sans-serif",children:"$"})]}),d.jsx(O.div,{className:"pointer-events-none absolute inset-0 overflow-hidden rounded-2xl",initial:!1,children:d.jsx(O.div,{className:"absolute inset-y-2 w-2/5 bg-gradient-to-r from-transparent via-white/60 to-transparent skew-x-[-18deg]",initial:{left:"-40%"},animate:{left:"140%"},transition:{duration:.55,delay:.12,ease:"easeInOut"}})})]}),d.jsxs(O.div,{className:"relative -mt-0.5 max-w-[12rem] pl-0.5",initial:{opacity:0,y:10},animate:{opacity:1,y:0},transition:{delay:.12,type:"spring",stiffness:320,damping:22},children:[d.jsx(O.p,{className:"font-display text-[10px] tracking-[0.42em] text-yellow-100 sm:text-[11px]",animate:{textShadow:["0 0 10px rgba(250,204,21,0.95)","0 0 22px rgba(0,255,157,0.75)","0 0 12px rgba(250,204,21,0.9)"]},transition:{duration:.75,repeat:3},children:t==="vault"?"VAULT · LOCKED":"CHA-CHING · HIT"}),n!=null&&n.uid?d.jsx(O.p,{className:"mt-1 truncate font-mono text-[10px] font-bold tracking-[0.15em] text-bubble-mint sm:text-xs",initial:{opacity:0,x:-6},animate:{opacity:1,x:0},transition:{delay:.22},children:n.uid}):null]})]},i):null})})}const Vg=x.createContext(()=>{});function i2({children:e}){const[t,n]=x.useState([]),r=x.useCallback((i,o="info")=>{const a=Date.now();n(l=>[...l,{id:a,msg:i,kind:o}]),setTimeout(()=>n(l=>l.filter(u=>u.id!==a)),4200)},[]),s=x.useMemo(()=>r,[r]);return d.jsxs(Vg.Provider,{value:s,children:[e,d.jsx("div",{className:"pointer-events-none fixed bottom-5 right-5 z-[60] flex max-w-sm flex-col gap-3",children:d.jsx(am,{children:t.map(i=>d.jsxs(O.div,{initial:{opacity:0,x:40,rotate:-2,scale:.92},animate:{opacity:1,x:0,rotate:0,scale:1},exit:{opacity:0,x:20,scale:.9},transition:{type:"spring",stiffness:380,damping:26},className:`pointer-events-auto relative overflow-hidden border-2 px-5 py-3.5 font-mono text-xs backdrop-blur-md ${i.kind==="err"?"border-bubble-rose bg-bubble-950/95 text-bubble-rose shadow-glowRose":"border-bubble-mint bg-bubble-900/95 text-bubble-mint shadow-glow"} `,children:[d.jsx("div",{className:`pointer-events-none absolute inset-0 opacity-30 ${i.kind==="err"?"bg-gradient-to-r from-bubble-rose/20 to-transparent":"bg-gradient-to-r from-bubble-accent/20 to-bubble-mint/10"}`}),d.jsx("span",{className:"relative mr-2 font-black opacity-80",children:i.kind==="err"?"!!":"»"}),d.jsx("span",{className:"relative",children:i.msg})]},i.id))})})]})}function Je(){return x.useContext(Vg)}function o2(e){const t=e.replace(/\s/g,"");if(t.length!==32)return null;const n=new Uint8Array(16);for(let u=0;u<16;u++)n[u]=parseInt(t.slice(u*2,u*2+2),16);const r=n[6],s=n[7],i=n[8],o=r>>4&1|s>>0&2|i>>0&4,a=r>>5&1|s>>1&2|i>>1&4,l=r>>6&1|s>>2&2|i>>2&4;return{c1:o,c2:a,c3:l}}function Og(e){switch(e){case 0:return"Ultralight / NTAG / Type 2";case 8:return"MIFARE Classic 1K";case 9:return"MIFARE Mini";case 24:return"MIFARE Classic 4K";default:return`SAK 0x${e.toString(16).toUpperCase()}`}}function Ig(e){var n;const t=e.replace(/\s/g,"");return t.length%2!==0?e:((n=t.match(/.{2}/g))==null?void 0:n.join(":"))??t}function a2(e){switch(e){case 1:return"Classic-style (MIFARE)";case 2:return"Type 2 / Ultralight-style";default:return"Unknown (check SAK/ATQA)"}}function l2(e){const t=[];return e.uidLen===4?t.push("4-byte UID — single cascade level (CL1)."):e.uidLen===7?t.push("7-byte UID — double cascade (CL1 + CL2) typical for 7B tags."):e.uidLen===10&&t.push("10-byte UID — triple cascade path."),e.sak===0&&t.push("SAK 0x00 — typical Type 2 / Ultralight-style path; use page read/write."),(e.sak===8||e.sak===9||e.sak===24)&&t.push("MIFARE Classic family — authenticate per sector trailer, then block read/write."),(e.atqa===1024||e.atqa===17408)&&t.push("ATQA 0x0400/0x4400 class — common Type A / MIFARE inventory shapes."),t}function u2(e){return e.map(t=>(Number(t)&255).toString(16).toUpperCase().padStart(2,"0")).join(" ")}function c2({className:e=""}){return d.jsx("div",{className:`relative ${e}`.trim(),children:d.jsxs("svg",{viewBox:"0 0 400 220",className:"h-auto w-full max-w-md text-bubble-mint/90","aria-hidden":!0,children:[d.jsxs("defs",{children:[d.jsxs("linearGradient",{id:"g1",x1:"0%",y1:"0%",x2:"100%",y2:"100%",children:[d.jsx("stop",{offset:"0%",stopColor:"currentColor",stopOpacity:"0.9"}),d.jsx("stop",{offset:"100%",stopColor:"#00e5ff",stopOpacity:"0.35"})]}),d.jsxs("filter",{id:"glow",children:[d.jsx("feGaussianBlur",{stdDeviation:"2",result:"b"}),d.jsxs("feMerge",{children:[d.jsx("feMergeNode",{in:"b"}),d.jsx("feMergeNode",{in:"SourceGraphic"})]})]})]}),[0,1,2,3].map(t=>d.jsx("ellipse",{cx:"200",cy:"110",rx:40+t*38,ry:28+t*26,fill:"none",stroke:"currentColor",strokeWidth:"0.6",strokeOpacity:.22-t*.04,className:"origin-center animate-[spin_32s_linear_infinite]",style:{transformOrigin:"200px 110px",animationDelay:`${t*2}s`}},t)),d.jsx("g",{filter:"url(#glow)",children:d.jsx("path",{d:"M200 110 L360 110 A160 80 0 0 1 200 190 Z",fill:"url(#g1)",fillOpacity:"0.12",className:"origin-center animate-[spin_6s_linear_infinite]",style:{transformOrigin:"200px 110px"}})}),d.jsx("circle",{cx:"200",cy:"110",r:"36",fill:"none",stroke:"currentColor",strokeWidth:"1.2",opacity:"0.5"}),d.jsx("circle",{cx:"200",cy:"110",r:"22",fill:"none",stroke:"#00e5ff",strokeWidth:"0.8",opacity:"0.45"}),d.jsx("circle",{cx:"200",cy:"110",r:"8",fill:"currentColor",opacity:"0.35"}),Array.from({length:12}).map((t,n)=>{const r=n/12*Math.PI*2,s=200+Math.cos(r)*118,i=110+Math.sin(r)*78;return d.jsx("rect",{x:s-1,y:i-1,width:"2",height:"2",fill:"currentColor",opacity:.15+n%3*.08,className:"animate-pulse",style:{animationDelay:`${n*.15}s`}},n)}),d.jsx("text",{x:"200",y:"205",textAnchor:"middle",className:"fill-bubble-mint/40 font-mono text-[9px] tracking-[0.35em]",children:"13.56MHZ"})]})})}function d2(){const e=Je(),{lastTag:t,applyScanPoll:n}=xs(),[r,s]=x.useState(null),[i,o]=x.useState(!0),a=()=>{$u("/api/status").then(s).catch(()=>e("Status unreachable","err"))};x.useEffect(()=>{a();const c=setInterval(a,3e3);return()=>clearInterval(c)},[e]),x.useEffect(()=>{r&&typeof r.scanning=="boolean"&&o(r.scanning)},[r]);const l=async()=>{try{await vt("/api/nfc/scan",{enable:!i}),o(!i),e(i?"Continuous scan off":"Continuous scan on")}catch(c){e(String(c),"err")}},u=async()=>{try{const c=await vt("/api/nfc/poll",{});c.present&&c.tag?(n(!0,c.tag),e(`Tag ${c.tag.uid}`)):(n(!1),e("No tag"))}catch(c){e(String(c),"err")}};return d.jsxs("div",{className:"space-y-8",children:[d.jsxs(O.div,{initial:{opacity:0,y:16},animate:{opacity:1,y:0},transition:{duration:.5,ease:[.22,1,.36,1]},className:"glass relative overflow-hidden p-6 md:p-10",children:[d.jsx("div",{className:"pointer-events-none absolute inset-0 bg-[conic-gradient(from_180deg_at_50%_120%,rgba(0,229,255,0.08),transparent_40%,rgba(255,42,109,0.06),transparent_70%)]"}),d.jsxs("div",{className:"relative grid gap-8 lg:grid-cols-[1fr_min(320px,40%)] lg:items-center",children:[d.jsxs("div",{children:[d.jsx("p",{className:"font-mono text-[10px] font-bold tracking-[0.4em] text-bubble-accent/80",children:"COMMAND_LAYER"}),d.jsxs("h1",{className:"font-display mt-2 text-3xl font-normal tracking-wide text-glow-matrix md:text-5xl",children:["NFC ",d.jsx("span",{className:"text-bubble-accent",children:"CONTROL"})]}),d.jsx("p",{className:"mt-3 max-w-xl text-sm leading-relaxed text-slate-400",children:"Full-time scan out of the box. Fat RF retries. Browser log + device session export — crank it from your phone."}),(r==null?void 0:r.session)&&(r.session.deepCapture||r.session.usedBytes>0)&&d.jsxs(O.div,{initial:{opacity:0,scale:.98},animate:{opacity:1,scale:1},className:"mt-5 flex flex-wrap items-center gap-3 rounded-xl border border-bubble-accent/40 bg-gradient-to-r from-bubble-accent/15 to-bubble-mint/10 px-4 py-3 text-sm shadow-glowCyan",children:[d.jsxs("span",{className:"font-mono text-bubble-mint",children:["RAM ",r.session.usedBytes,"/",r.session.maxBytes,r.session.full?" · LOCKED":""]}),d.jsx(sm,{to:"/capture",className:"btn-neon rounded-lg bg-bubble-mint/20 px-3 py-1 text-xs font-bold text-bubble-mint",children:"Read-all →"})]}),d.jsxs("div",{className:"mt-8 flex flex-wrap gap-3",children:[d.jsx(O.button,{type:"button",whileHover:{scale:1.04},whileTap:{scale:.98},onClick:u,className:"btn-neon rounded-xl bg-gradient-to-r from-bubble-accent via-cyan-400 to-bubble-mint px-6 py-3 text-sm font-black uppercase tracking-wider text-bubble-950 shadow-neonBtn",children:"Poll tag"}),d.jsx(O.button,{type:"button",whileHover:{scale:1.03},whileTap:{scale:.98},onClick:l,className:`rounded-xl border-2 px-6 py-3 text-sm font-bold uppercase tracking-wide transition ${i?"border-bubble-mint/70 bg-bubble-mint/15 text-glow-matrix text-bubble-mint shadow-glow":"border-white/20 bg-black/30 text-slate-400 hover:border-bubble-accent/50 hover:text-bubble-accent"}`,children:i?"Stop scan":"Start scan"})]})]}),d.jsx("div",{className:"relative flex justify-center lg:justify-end",children:d.jsx("div",{className:"relative w-full max-w-[280px] opacity-90 drop-shadow-[0_0_40px_rgba(0,229,255,0.35)]",children:d.jsx(c2,{})})})]})]}),d.jsxs("div",{className:"grid gap-5 md:grid-cols-2",children:[d.jsxs(O.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},transition:{delay:.08},className:"glass p-6",children:[d.jsx("h2",{className:"font-display text-lg font-normal text-bubble-accent text-glow-cyan",children:"Device stack"}),r?d.jsxs("ul",{className:"mt-4 space-y-3 font-mono text-sm text-slate-300",children:[d.jsxs("li",{className:"flex justify-between border-b border-white/5 pb-2",children:[d.jsx("span",{className:"text-slate-500",children:"uptime"}),d.jsxs("span",{className:"text-bubble-mint",children:[(r.uptimeMs/1e3).toFixed(1),"s"]})]}),d.jsxs("li",{className:"flex justify-between border-b border-white/5 pb-2",children:[d.jsx("span",{className:"text-slate-500",children:"heap"}),d.jsx("span",{className:"text-white",children:r.freeHeap})]}),d.jsxs("li",{className:"flex justify-between",children:[d.jsx("span",{className:"text-slate-500",children:"PN532"}),d.jsx("span",{className:"text-bubble-accent",children:r.pn532?`IC${r.pn532.ic} v${r.pn532.fwHi}.${r.pn532.fwLo}`:"n/a"})]})]}):d.jsx("p",{className:"mt-4 animate-pulse font-mono text-sm text-bubble-accent/60",children:"Pulling status…"})]}),d.jsxs(O.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},transition:{delay:.14},className:"glass p-6",children:[d.jsx("h2",{className:"font-display text-lg font-normal text-bubble-rose/90 text-glow-rose",children:"Live tag"}),t?d.jsxs("div",{className:"mt-4 space-y-4 rounded-xl border border-bubble-mint/25 bg-black/35 p-4 shadow-glow",children:[d.jsxs("div",{children:[d.jsx("p",{className:"text-[10px] font-mono uppercase tracking-widest text-bubble-mint/50",children:"UID"}),d.jsx("div",{className:"font-mono text-xl font-bold tracking-[0.15em] text-glow-matrix text-bubble-mint md:text-2xl",children:Ig(t.uid)}),d.jsxs("p",{className:"mt-1 font-mono text-[11px] text-slate-500",children:["raw ",t.uid," · ",t.uidLen," byte",t.uidLen===1?"":"s"]})]}),d.jsxs("div",{className:"grid gap-3 border-t border-white/5 pt-3 font-mono text-[11px] text-slate-300 sm:grid-cols-2",children:[d.jsxs("div",{children:[d.jsx("span",{className:"text-slate-500",children:"ATQA"})," ",d.jsxs("span",{className:"text-bubble-accent",children:["0x",(t.atqaHex??t.atqa.toString(16).toUpperCase().padStart(4,"0")).slice(-4)]}),d.jsxs("span",{className:"ml-2 text-slate-500",children:["(",t.atqa,")"]})]}),d.jsxs("div",{children:[d.jsx("span",{className:"text-slate-500",children:"SAK"})," ",d.jsxs("span",{className:"text-bubble-accent",children:["0x",(t.sakHex??t.sak.toString(16).toUpperCase().padStart(2,"0")).slice(-2)]}),d.jsxs("span",{className:"ml-1 text-slate-400",children:["— ",Og(t.sak)]})]}),d.jsxs("div",{className:"sm:col-span-2",children:[d.jsx("span",{className:"text-slate-500",children:"Guess"})," ",d.jsx("span",{className:"text-bubble-mint",children:t.typeGuess??a2(t.typeHint)}),d.jsxs("span",{className:"ml-2 text-slate-600",children:["· hint ",t.typeHint]})]})]}),t.pn532GeneralStatus&&t.pn532GeneralStatus.length>0&&d.jsxs("div",{className:"rounded-lg border border-bubble-accent/20 bg-black/40 p-3",children:[d.jsx("p",{className:"text-[10px] font-mono uppercase tracking-widest text-bubble-accent/70",children:"PN532 general status"}),d.jsx("p",{className:"mt-2 break-all font-mono text-[10px] leading-relaxed text-slate-400",children:u2(t.pn532GeneralStatus)}),d.jsx("p",{className:"mt-2 text-[10px] text-slate-600",children:"Raw bytes from the chip right after this inventory (error flags, last command, tag count — see NXP PN532 user manual)."})]}),d.jsx("ul",{className:"space-y-1 border-t border-white/5 pt-3 text-[11px] leading-relaxed text-slate-500",children:l2(t).map((c,f)=>d.jsxs("li",{className:"flex gap-2",children:[d.jsx("span",{className:"text-bubble-mint/40",children:"▸"}),d.jsx("span",{children:c})]},f))})]}):d.jsx("p",{className:"mt-6 font-mono text-sm text-bubble-mint/40",children:"Listening on the field…"})]})]})]})}function f2(){const e=Je(),[t,n]=x.useState("FFFFFFFFFFFF"),[r,s]=x.useState(!1),[i,o]=x.useState(0),[a,l]=x.useState(""),[u,c]=x.useState(""),f=async()=>{try{const v=await vt("/api/mifare/read-block",{block:i,key:t,keyB:r});v.data?(l(v.data),e("Read OK")):e(v.error||"failed","err")}catch(v){e(String(v),"err")}},h=async()=>{try{const v=await vt("/api/ul/read-page",{page:i});v.data&&(l(v.data+" (UL page)"),e("UL read OK"))}catch(v){e(String(v),"err")}},g=u?o2(u):null;return d.jsxs("div",{className:"space-y-6",children:[d.jsxs("div",{className:"glass p-6",children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Read / analyze"}),d.jsx("p",{className:"mt-2 text-sm text-slate-400",children:"Authenticate with a known key, dump a block, paste a sector trailer to decode access bits."}),d.jsxs("div",{className:"mt-6 grid gap-4 md:grid-cols-2",children:[d.jsxs("label",{className:"block space-y-2 text-sm",children:["Key (12 hex)",d.jsx("input",{value:t,onChange:v=>n(v.target.value),className:"w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2 font-mono text-bubble-mint outline-none ring-bubble-accent/40 focus:ring-2"})]}),d.jsxs("label",{className:"flex items-end gap-3 text-sm",children:[d.jsx("input",{type:"checkbox",checked:r,onChange:v=>s(v.target.checked)})," Key B"]}),d.jsxs("label",{className:"block space-y-2 text-sm",children:["Block / page",d.jsx("input",{type:"number",value:i,onChange:v=>o(Number(v.target.value)),className:"w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2 outline-none ring-bubble-accent/40 focus:ring-2"})]})]}),d.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[d.jsx("button",{type:"button",onClick:f,className:"rounded-2xl bg-bubble-accent/90 px-4 py-2 font-semibold text-white",children:"MIFARE read block"}),d.jsx("button",{type:"button",onClick:h,className:"rounded-2xl border border-white/15 px-4 py-2",children:"Ultralight read page"})]}),a&&d.jsx("pre",{className:"mt-4 overflow-auto rounded-2xl border border-white/10 bg-black/30 p-4 font-mono text-sm",children:a})]}),d.jsxs("div",{className:"glass p-6",children:[d.jsx("h2",{className:"font-display text-lg font-semibold",children:"Sector trailer playground"}),d.jsxs("label",{className:"mt-4 block text-sm",children:["16-byte trailer (32 hex) — bytes 6–8 are access bytes",d.jsx("textarea",{value:u,onChange:v=>c(v.target.value),rows:3,className:"mt-2 w-full rounded-2xl border border-white/10 bg-black/25 p-3 font-mono text-xs outline-none focus:ring-2 focus:ring-bubble-accent/40"})]}),g&&d.jsxs("div",{className:"mt-4 rounded-2xl border border-bubble-mint/30 bg-bubble-mint/5 p-4 text-sm",children:["Parsed C1–C3 nibble pattern: ",g.c1," ",g.c2," ",g.c3," (see NXP MIFARE docs for truth tables)"]}),d.jsxs("p",{className:"mt-4 text-xs text-slate-500",children:["SAK hints: common values for labeling only — ",Og(24)," etc."]})]})]})}const ws="Lab-only synthetic data and well-known defaults. Edit bytes freely to validate parsers, checksums, and emulate/raw paths — never treat these as real tags.",Ef=[{id:"get-fw",title:"GetFirmwareVersion (0x02)",hex:"02",detail:"Expect PN532 firmware major/minor in response payload."},{id:"get-status",title:"GetGeneralStatus (0x04)",hex:"04",detail:"Chip + RF status snapshot; useful sanity check after a stuck session."},{id:"in-list-a",title:"InListPassiveTarget — 106 kbps, 1 target",hex:"4A0100",detail:"Poll one ISO14443-A target at 106 kbps (maxTg=1, BrTy=0)."}],jf=[{id:"tg-stub",title:"TgInitAsTarget — opcode only (shell)",hex:"8C",detail:"Minimal placeholder; real target mode needs a full parameter block per NXP UM0701. Extend with NFCID, FeliCa params, etc."},{id:"tg-type-a-sketch",title:"TgInitAsTarget — Type A sketch (synthetic NFCID3T)",hex:"8C000012DEADBEEF00000000000000000000000000000000000000000000000000",detail:"Synthetic 0x8C prefix + padded fake ID — not guaranteed to satisfy any reader; use as a byte-editing template only."}],h2="DEADBEEF2208040000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF078069FFFFFFFFFFFF",p2="04112233445566172233445566172233445566172233445566172233",m2="0310D1010C55046578616D706C652E636F6DFE",pl=[{id:"mifare-block0",title:"MIFARE Classic — block 0 (16 B, synthetic UID+BCC)",hex:"DEADBEEF220804000000000000000000",byteLength:16,sha256Hex:"6f13f064d70ec33b7ace5842011d66aff3852baa4ab7c0a85aa66d113c7189fe",detail:"Fake 4-byte UID (DE:AD:BE:EF wire order as stored), BCC = XOR(UID), rest filler. Pair with key FFFFFFFFFFFF on a writable tag only."},{id:"mifare-sector0",title:"MIFARE Classic — sector 0 dump (64 B)",hex:h2,byteLength:64,sha256Hex:"11095df4db11e4271f40234533db45de35c4ca69f04e231e3fa47f38181e0168",detail:"Four blocks: manufacturer/UID, empty, empty, default trailer (Key A/B FFFFFFFFFFFF, access FF078069). Edit block 1–2 payload and re-hash to validate your pipeline."},{id:"ntag-pages",title:"NTAG-style — pages 0–6 (28 B)",hex:p2,byteLength:28,sha256Hex:"8ffd95e646b2deb218dabd72e35c7a1938725e07332d8ed7df4f2a2656e590a0",detail:"Synthetic UID/internal/lock placeholders — not copied from a physical tag."},{id:"ndef-uri-tlv",title:"NDEF TLV — URI https://example.com/",hex:m2,byteLength:19,sha256Hex:"81197b6cd6e40a3f62f56f0c0f3f449c63a956919d04c5b5317895ad4328fa14",detail:"Type 2 TLV (0x03) + short NDEF Well-Known URI record; append to user memory after static pages in real layouts."}],g2=["FFFFFFFFFFFF","A0A1A2A3A4A5","D3F7D3F7D3F7","000000000000","B0B1B2B3B4B5","AABBCCDDEEFF","4D3A99C351DD","1A982C7E459A","714C5C886E97","587EE5F9350F","A0478CC39091","26940B21FFF5","E4410EF8ED2D"],y2=pl.map(e=>({name:`LAB // ${e.title}`,hex:e.hex,note:e.detail}));function fo({mode:e,onApplyHex:t,onPickBinary:n,className:r=""}){const[s,i]=x.useState(0),o=()=>i(a=>a+1);return e==="raw"?d.jsx("div",{className:`flex flex-wrap items-center gap-2 ${r}`,children:d.jsxs("select",{defaultValue:"","aria-label":"Load PN532 lab command",className:"max-w-full rounded-xl border border-bubble-mint/25 bg-black/40 px-3 py-2 font-mono text-xs text-bubble-mint/90",onChange:a=>{const l=a.target.value;if(!l)return;const u=Ef.find(c=>c.id===l);u&&t(u.hex),o()},children:[d.jsx("option",{value:"",children:"Lab: PN532 command bytes…"}),Ef.map(a=>d.jsx("option",{value:a.id,children:a.title},a.id))]},s)}):e==="emulate"?d.jsx("div",{className:`flex flex-wrap items-center gap-2 ${r}`,children:d.jsxs("select",{defaultValue:"","aria-label":"Load emulate lab frame",className:"max-w-full rounded-xl border border-bubble-mint/25 bg-black/40 px-3 py-2 font-mono text-xs text-bubble-mint/90",onChange:a=>{const l=a.target.value;if(!l)return;const u=jf.find(c=>c.id===l);u&&t(u.hex),o()},children:[d.jsx("option",{value:"",children:"Lab: emulate / TgInit…"}),jf.map(a=>d.jsx("option",{value:a.id,children:a.title},a.id))]},s)}):d.jsx("div",{className:`space-y-2 ${r}`,children:d.jsxs("select",{defaultValue:"","aria-label":"Load synthetic card blob",className:"w-full max-w-full rounded-xl border border-bubble-mint/25 bg-black/40 px-3 py-2 font-mono text-xs text-bubble-mint/90",onChange:a=>{const l=a.target.value;if(!l)return;const u=pl.find(c=>c.id===l);u&&(t(u.hex),n==null||n(u)),o()},children:[d.jsx("option",{value:"",children:"Lab: synthetic card / NDEF blob…"}),pl.map(a=>d.jsxs("option",{value:a.id,children:[a.title," (",a.byteLength," B)"]},a.id))]},s)})}function v2(){const e=Je(),{lastTag:t}=xs(),[n,r]=x.useState("FFFFFFFFFFFF"),[s,i]=x.useState(!1),[o,a]=x.useState(4),[l,u]=x.useState("00000000000000000000000000000000"),[c,f]=x.useState(null),[h,g]=x.useState(4),[v,w]=x.useState("00000000"),S=async()=>{const p=n.replace(/\s/g,""),y=l.replace(/\s/g,"");if(p.length!==12||!/^[0-9A-Fa-f]+$/.test(p)){e("Key must be exactly 12 hex digits","err");return}if(y.length!==32||!/^[0-9A-Fa-f]+$/.test(y)){e("Block data must be exactly 32 hex digits (16 bytes)","err");return}if(!Number.isInteger(o)||o<0||o>255){e("Block must be an integer 0–255","err");return}if(confirm("Write will modify tag memory. Continue?"))try{await vt("/api/mifare/write-block",{block:o,key:p,keyB:s,data:y}),e("Write OK")}catch(b){e(String(b),"err")}},m=async()=>{const p=v.replace(/\s/g,"");if(p.length!==8||!/^[0-9A-Fa-f]+$/.test(p)){e("UL data must be exactly 8 hex digits (4 bytes)","err");return}if(confirm("Ultralight page write — can brick OTP/lock bytes if misused. Continue?"))try{await vt("/api/ul/write-page",{page:h,data:p}),e("UL page write OK")}catch(y){e(String(y),"err")}};return d.jsxs("div",{className:"glass space-y-6 p-6",children:[d.jsxs("div",{children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Write / clone helpers"}),d.jsx("p",{className:"mt-2 text-sm text-slate-400",children:"Block editor for MIFARE Classic. Read blocks on the Read tab, adjust hex here, then write with a key that unlocks the sector."}),t&&d.jsxs("p",{className:"mt-2 rounded-lg border border-bubble-mint/20 bg-bubble-mint/5 px-3 py-2 font-mono text-xs text-bubble-mint",children:["Field: ",d.jsx("span",{className:"text-white",children:Ig(t.uid)})," ·"," ",t.typeGuess??`hint ${t.typeHint}`]}),d.jsx("p",{className:"mt-2 text-[11px] leading-relaxed text-slate-500",children:ws}),d.jsx(fo,{mode:"binary",className:"mt-3",onApplyHex:p=>{const y=p.replace(/\s/g,"");y.length<=32?u(y):(u(y.slice(0,32)),e("First 16 bytes of lab blob loaded into block editor","info"))},onPickBinary:f}),c&&d.jsxs("p",{className:"mt-2 font-mono text-[10px] text-bubble-accent/90",children:["Canonical SHA-256 (",c.byteLength," B): ",c.sha256Hex," — changes after any edit"]})]}),d.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[d.jsxs("label",{className:"text-sm",children:["Key (12 hex)",d.jsx("input",{value:n,onChange:p=>r(p.target.value),className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2 font-mono"})]}),d.jsxs("label",{className:"flex items-end gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:s,onChange:p=>i(p.target.checked)})," Key B"]}),d.jsxs("label",{className:"text-sm",children:["Block",d.jsx("input",{type:"number",value:o,onChange:p=>a(Number(p.target.value)),className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2"})]})]}),d.jsxs("label",{className:"block text-sm",children:["16 bytes (32 hex)",d.jsx("textarea",{value:l,onChange:p=>u(p.target.value),rows:4,className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 p-3 font-mono text-sm"})]}),d.jsx("button",{type:"button",onClick:S,className:"rounded-2xl bg-gradient-to-r from-bubble-rose to-orange-400 px-6 py-3 font-bold text-white shadow-glow",children:"Write block"}),d.jsxs("div",{className:"border-t border-white/10 pt-8",children:[d.jsx("h2",{className:"font-display text-lg font-bold text-bubble-accent",children:"Ultralight / NTAG page write"}),d.jsx("p",{className:"mt-2 text-sm text-slate-400",children:"4 bytes per page (8 hex). Keep tag on the coil. Avoid lock / config pages unless you mean it."}),d.jsxs("div",{className:"mt-4 grid gap-4 md:grid-cols-2",children:[d.jsxs("label",{className:"text-sm",children:["Page",d.jsx("input",{type:"number",value:h,onChange:p=>g(Number(p.target.value)),className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2"})]}),d.jsxs("label",{className:"text-sm",children:["Data (8 hex)",d.jsx("input",{value:v,onChange:p=>w(p.target.value),className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2 font-mono"})]})]}),d.jsx("button",{type:"button",onClick:m,className:"mt-4 rounded-2xl border border-bubble-accent/50 bg-bubble-accent/20 px-6 py-3 font-bold text-bubble-accent",children:"Write UL page"})]})]})}const Nf="pn532_saved_tags_v1";function x2(){const e=Je(),[t,n]=x.useState([]),[r,s]=x.useState("My tag"),[i,o]=x.useState(""),[a,l]=x.useState(null);x.useEffect(()=>{try{const g=localStorage.getItem(Nf);n(g?JSON.parse(g):[])}catch{n([])}},[]);const u=g=>{localStorage.setItem(Nf,JSON.stringify(g)),n(g)},c=()=>{if(!i.trim()){e("Paste hex first","err");return}const v={id:`${Date.now()}-${Math.random().toString(16).slice(2)}`,name:r,hex:i.replace(/\s/g,""),ts:Date.now()};u([v,...t]),e("Saved")},f=g=>u(t.filter(v=>v.id!==g)),h=()=>{const g=new Set(t.map(S=>S.name)),v=Date.now(),w=y2.filter(S=>!g.has(S.name)).map((S,m)=>({id:`lab-seed-${v}-${m}`,name:S.name,hex:S.hex,ts:v}));if(!w.length){e("Lab catalog already in library","info");return}u([...w,...t]),e(`Seeded ${w.length} lab record(s)`)};return d.jsxs("div",{className:"glass space-y-6 p-6",children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Saved tag library"}),d.jsx("p",{className:"text-sm text-slate-400",children:"Local browser storage — export by copy/paste."}),d.jsx("p",{className:"text-[11px] leading-relaxed text-slate-500",children:ws}),d.jsx("div",{className:"flex flex-wrap gap-2",children:d.jsx("button",{type:"button",onClick:h,className:"rounded-2xl border border-bubble-mint/30 bg-bubble-mint/10 px-4 py-2 font-mono text-xs font-semibold text-bubble-mint",children:"Seed all lab samples"})}),d.jsx(fo,{mode:"binary",onApplyHex:g=>o(g.replace(/\s/g,"")),onPickBinary:l}),a&&d.jsxs("div",{className:"rounded-xl border border-bubble-accent/25 bg-black/30 p-3 font-mono text-[10px] text-bubble-accent/90",children:[d.jsx("div",{className:"text-bubble-mint/70",children:"Expected SHA-256 (canonical blob, pre-edit)"}),d.jsx("div",{className:"break-all",children:a.sha256Hex})]}),d.jsxs("div",{className:"grid gap-3 md:grid-cols-2",children:[d.jsx("input",{value:r,onChange:g=>s(g.target.value),placeholder:"Label",className:"rounded-2xl border border-white/10 bg-black/25 px-4 py-2"}),d.jsx("button",{type:"button",onClick:c,className:"rounded-2xl bg-bubble-accent px-4 py-2 font-semibold",children:"Save current hex"})]}),d.jsx("textarea",{value:i,onChange:g=>o(g.target.value),placeholder:"Hex dump",rows:5,className:"w-full rounded-2xl border border-white/10 bg-black/25 p-3 font-mono text-xs"}),d.jsx("ul",{className:"space-y-3",children:t.map(g=>d.jsxs("li",{className:"rounded-2xl border border-white/10 bg-black/20 p-4",children:[d.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[d.jsxs("div",{children:[d.jsx("div",{className:"font-display font-semibold",children:g.name}),d.jsx("div",{className:"text-xs text-slate-500",children:new Date(g.ts).toLocaleString()})]}),d.jsx("button",{type:"button",onClick:()=>f(g.id),className:"text-rose-300",children:"Remove"})]}),d.jsx("pre",{className:"mt-2 max-h-32 overflow-auto text-xs text-bubble-mint/90",children:g.hex}),d.jsx("button",{type:"button",onClick:()=>{navigator.clipboard.writeText(g.hex),e("Copied")},className:"mt-2 text-sm text-slate-300 underline",children:"Copy hex"})]},g.id))})]})}const w2=["FFFFFFFFFFFF","A0A1A2A3A4A5","D3F7D3F7D3F7","000000000000"],Af="pn532_key_dict_v1";function S2(){const e=Je(),[t,n]=x.useState([]),[r,s]=x.useState("");x.useEffect(()=>{const u=localStorage.getItem(Af);n(u?JSON.parse(u):[...w2])},[]);const i=u=>{localStorage.setItem(Af,JSON.stringify(u)),n(u)},o=()=>{const u=[...t];let c=0;for(const f of g2)u.includes(f)||(u.push(f),c++);if(!c){e("Lab key corpus already merged","info");return}i(u),e(`Added ${c} public lab key(s)`)},a=()=>{const u=sessionStorage.getItem("pn532_keylab_import");if(!(u!=null&&u.trim())){e("Key Lab has nothing staged","info");return}const c=u.split(/\r?\n/).map(g=>g.replace(/\s/g,"").toUpperCase()).filter(g=>g.length===12);if(!c.length){e("No valid 12-hex keys in stash","err");return}const f=[...t];let h=0;for(const g of c)f.includes(g)||(f.push(g),h++);i(f),sessionStorage.removeItem("pn532_keylab_import"),e(h?`Merged ${h} key(s) from Key Lab`:"Keys already in list")},l=()=>{const u=r.replace(/\s/g,"").toUpperCase();if(u.length!==12){e("12 hex chars required","err");return}t.includes(u)?e("Already in dictionary"):(i([u,...t]),e("Key added")),s("")};return d.jsxs("div",{className:"glass space-y-6 p-6",children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Key manager"}),d.jsx("p",{className:"text-sm text-slate-400",children:"Dictionary for manual trials (not a cloud rainbow table). Keys stay in your browser."}),d.jsx("p",{className:"text-[11px] leading-relaxed text-slate-500",children:ws}),d.jsxs("div",{className:"flex flex-wrap gap-2",children:[d.jsx("button",{type:"button",onClick:o,className:"btn-neon rounded-xl border border-bubble-mint/40 bg-bubble-mint/10 px-4 py-2 font-mono text-xs font-bold text-bubble-mint",children:"Merge lab corpus"}),d.jsx("button",{type:"button",onClick:a,className:"rounded-xl border border-bubble-accent/45 bg-bubble-accent/10 px-4 py-2 font-mono text-xs font-bold text-bubble-accent",children:"Import Key Lab stash"})]}),d.jsxs("div",{className:"flex gap-2",children:[d.jsx("input",{value:r,onChange:u=>s(u.target.value),placeholder:"New key",className:"flex-1 rounded-2xl border border-white/10 bg-black/25 px-4 py-2 font-mono"}),d.jsx("button",{type:"button",className:"rounded-2xl bg-bubble-accent px-4 py-2 font-semibold",onClick:l,children:"Add"})]}),d.jsx("ul",{className:"space-y-2",children:t.map(u=>d.jsxs("li",{className:"flex items-center justify-between rounded-2xl border border-white/10 bg-black/20 px-4 py-2 font-mono text-sm",children:[u,d.jsx("button",{type:"button",className:"text-rose-300",onClick:()=>i(t.filter(c=>c!==u)),children:"×"})]},u))})]})}function b2(){const e=Je(),[t,n]=x.useState("4A0100"),[r,s]=x.useState([]),[i,o]=x.useState(""),a=c=>s(f=>[new Date().toLocaleTimeString()+" "+c,...f].slice(0,80)),l=async()=>{try{const c=await vt("/api/raw/pn532",{frame:t});a(`TX ${t}`),a(`RX ${c.response||c.error||"?"}`),c.response&&e("Frame OK")}catch(c){a(`ERR ${String(c)}`),e(String(c),"err")}},u=async()=>{try{const c=await $u("/api/pn532/general-status");o(JSON.stringify(c.raw??c,null,2)),e("Fetched PN532 status")}catch(c){e(String(c),"err")}};return d.jsxs("div",{className:"glass space-y-6 p-6",children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Advanced / raw PN532"}),d.jsxs("p",{className:"text-sm text-slate-400",children:["Send command bytes (without PN532 frame wrapper). Example: ",d.jsx("code",{children:"4A0100"})," lists one Type A passive target at 106 kbps."]}),d.jsx("p",{className:"text-[11px] leading-relaxed text-slate-500",children:ws}),d.jsx(fo,{mode:"raw",onApplyHex:c=>n(c)}),d.jsxs("div",{className:"flex flex-wrap gap-2",children:[d.jsx("input",{value:t,onChange:c=>n(c.target.value),className:"min-w-[16rem] flex-1 rounded-2xl border border-white/10 bg-black/25 px-4 py-2 font-mono text-sm"}),d.jsx("button",{type:"button",onClick:l,className:"rounded-2xl bg-bubble-accent px-4 py-2 font-semibold",children:"Send"}),d.jsx("button",{type:"button",onClick:u,className:"rounded-2xl border border-white/15 px-4 py-2",children:"General status"})]}),d.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[d.jsxs("div",{children:[d.jsx("h2",{className:"text-sm font-semibold text-slate-300",children:"Log"}),d.jsx("pre",{className:"mt-2 max-h-80 overflow-auto rounded-2xl border border-white/10 bg-black/30 p-3 text-xs",children:r.join(` `)})]}),d.jsxs("div",{children:[d.jsx("h2",{className:"text-sm font-semibold text-slate-300",children:"PN532 status snapshot"}),d.jsx("pre",{className:"mt-2 max-h-80 overflow-auto rounded-2xl border border-white/10 bg-black/30 p-3 text-xs",children:i||"—"})]})]})]})}function k2(){const e=Je(),[t,n]=x.useState(""),[r,s]=x.useState(!1);x.useEffect(()=>{n(localStorage.getItem("apiBase")||""),s(document.documentElement.classList.contains("light"))},[]);const i=()=>{localStorage.setItem("apiBase",t),e("Saved API base — reload for WS")},o=()=>{const a=!r;s(a),document.documentElement.classList.toggle("light",a),document.documentElement.classList.toggle("dark",!a),localStorage.setItem("theme",a?"light":"dark"),e(a?"Light":"Dark")};return d.jsxs("div",{className:"glass max-w-xl space-y-6 p-6",children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Settings"}),d.jsxs("label",{className:"block text-sm",children:["API base (empty = same host)",d.jsx("input",{value:t,onChange:a=>n(a.target.value),className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2",placeholder:"http://192.168.4.1"})]}),d.jsx("button",{type:"button",onClick:i,className:"rounded-2xl bg-bubble-accent px-4 py-2 font-semibold",children:"Save"}),d.jsxs("div",{className:"flex items-center justify-between rounded-2xl border border-white/10 bg-black/20 px-4 py-3",children:[d.jsx("span",{className:"text-sm",children:"Theme"}),d.jsx("button",{type:"button",onClick:o,className:"rounded-full border border-white/15 px-4 py-1 text-sm",children:r?"Switch to dark":"Switch to light"})]}),d.jsxs("p",{className:"text-xs text-slate-500",children:["Firmware opens a ",d.jsx("strong",{children:"password-free"})," SoftAP named ",d.jsx("strong",{children:"PN532-Toolkit"})," (lab default). mDNS: ",d.jsx("code",{children:"pn532tool.local"})]})]})}function C2(){const e=Je(),{log:t}=xs(),[n,r]=x.useState(null),s=x.useCallback(()=>{$u("/api/status").then(r).catch(()=>{})},[]);x.useEffect(()=>{s();const f=setInterval(s,2e3);return()=>clearInterval(f)},[s]),x.useEffect(()=>{s()},[t.length,s]);const i=(()=>{const f=[...t].reverse().find(h=>h.channel==="capture");return f?typeof f.payload=="object"?JSON.stringify(f.payload):String(f.payload):""})(),o=n==null?void 0:n.session,a=o?Math.min(100,o.usedBytes/Math.max(1,o.maxBytes)*100):0,l=async f=>{try{await vt("/api/session/deep",{enable:f}),e(f?"Passive read-all on (live scan on by default at boot)":"Passive read-all off"),s()}catch(h){e(String(h),"err")}},u=async()=>{try{await vt("/api/session/clear",{}),e("Buffer cleared — scanning can resume"),s()}catch(f){e(String(f),"err")}},c=async()=>{try{const f=await fetch(vs("/api/session/export"));if(!f.ok)throw new Error(await f.text());const h=await f.blob(),g=URL.createObjectURL(h),v=document.createElement("a");v.href=g,v.download=`pn532-deep-capture-${Date.now()}.ndjson`,v.click(),URL.revokeObjectURL(g),e("Download started — check your Downloads folder")}catch(f){e(String(f),"err")}};return d.jsxs("div",{className:"space-y-6",children:[d.jsxs(O.div,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},className:"glass relative overflow-hidden p-8",children:[d.jsx("div",{className:"pointer-events-none absolute -left-20 top-0 h-48 w-48 rounded-full bg-bubble-mint/20 blur-3xl"}),d.jsx("h1",{className:"font-display text-3xl font-bold md:text-4xl",children:"Passive read-all mode"}),d.jsx("p",{className:"mt-1 text-sm font-medium text-bubble-mint/90",children:"Same feature as “deep capture” — fully controlled from this screen."}),d.jsxs("p",{className:"mt-3 max-w-2xl text-slate-300",children:["Turn it on below and keep ",d.jsx("strong",{children:"live scan"})," running (on by default at boot). Each"," ",d.jsx("strong",{children:"new tag"})," in the field is read ",d.jsx("strong",{children:"passively"}),": no per-block clicks — the firmware pulls ",d.jsx("strong",{children:"all data it can"})," (PN532 status + Classic sector/block dump with default keys, or Ultralight/NTAG page sweep). Results queue in ",d.jsx("strong",{children:"device RAM"}),"; when full, polling pauses until you ",d.jsx("strong",{children:"download"})," and ",d.jsx("strong",{children:"clear"}),"."]})]}),d.jsxs("div",{className:"glass p-6",children:[d.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-4",children:[d.jsxs("div",{children:[d.jsx("h2",{className:"font-display text-lg font-semibold",children:"Read-all session buffer"}),d.jsxs("p",{className:"text-sm text-slate-400",children:[(o==null?void 0:o.lines)??0," full dumps · ",(o==null?void 0:o.usedBytes)??0," / ",(o==null?void 0:o.maxBytes)??"—"," bytes RAM"]})]}),d.jsxs("div",{className:"flex flex-wrap gap-2",children:[d.jsx("button",{type:"button",onClick:()=>l(!((o==null?void 0:o.deepCapture)??!1)),className:`rounded-2xl px-4 py-2 font-semibold ${o!=null&&o.deepCapture?"bg-bubble-mint/20 text-bubble-mint ring-2 ring-bubble-mint/40":"border border-white/15 bg-white/5"}`,children:o!=null&&o.deepCapture?"Passive read-all ON":"Enable passive read-all"}),d.jsx("button",{type:"button",onClick:c,className:"rounded-2xl bg-gradient-to-r from-bubble-accent to-indigo-400 px-4 py-2 font-bold text-white shadow-glow",children:"Download NDJSON"}),d.jsx("button",{type:"button",onClick:u,className:"rounded-2xl border border-white/20 px-4 py-2",children:"Clear buffer"})]})]}),d.jsx("div",{className:"mt-6 h-4 overflow-hidden rounded-full bg-black/40",children:d.jsx(O.div,{className:"h-full rounded-full bg-gradient-to-r from-bubble-accent to-bubble-mint",initial:!1,animate:{width:`${a}%`},transition:{type:"spring",stiffness:120,damping:20}})}),(o==null?void 0:o.full)&&d.jsxs("div",{className:"mt-6 rounded-2xl border-2 border-bubble-rose/50 bg-bubble-rose/10 p-4 text-center",children:[d.jsx("p",{className:"font-display text-lg font-bold text-bubble-rose",children:"Buffer full — reader paused"}),d.jsxs("p",{className:"mt-1 text-sm text-slate-300",children:["Tap ",d.jsx("strong",{children:"Download NDJSON"})," to pull every card profile to your phone, then"," ",d.jsx("strong",{children:"Clear buffer"})," to resume field scans."]})]}),(o==null?void 0:o.deepCapture)&&n&&!n.scanning&&d.jsxs("p",{className:"mt-4 rounded-2xl border border-amber-500/30 bg-amber-500/10 p-3 text-sm text-amber-100",children:["Firmware normally has ",d.jsx("strong",{children:"Live scan"})," on at boot. If you turned it off, enable it on the Dashboard."]}),i&&d.jsxs("pre",{className:"mt-4 max-h-40 overflow-auto rounded-2xl border border-white/10 bg-black/30 p-3 text-xs text-slate-300",children:["Last capture event: ",i]})]})]})}function P2(){const e=Je(),[t,n]=x.useState("classic1k"),[r,s]=x.useState(!0),[i,o]=x.useState(`FFFFFFFFFFFF A0A1A2A3A4A5 D3F7D3F7D3F7`),[a,l]=x.useState(!1),[u,c]=x.useState(""),f=async()=>{l(!0),c("");try{const h=i.split(/\r?\n/).map(S=>S.replace(/\s/g,"").toUpperCase()).filter(S=>S.length===12),g={readerType:t,variations:r,keysHex:h},v=await fetch(vs("/api/mifare/dictionary-attack"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(g)}),w=await v.text();if(!v.ok)throw new Error(w);try{const S=JSON.parse(w);c(JSON.stringify(S,null,2))}catch{c(w)}e("Dictionary pass finished")}catch(h){e(String(h),"err")}finally{l(!1)}};return d.jsxs("div",{className:"glass space-y-6 p-6",children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Dictionary attack"}),d.jsxs("p",{className:"text-sm text-slate-400",children:["Select card family, optionally enable ",d.jsx("strong",{children:"bounded variations"})," (XOR / low-nibble tweaks per key). Firmware tries a ",d.jsx("strong",{children:"built-in community list"})," (Proxmark3 / MCT-style defaults) plus your lines below. This is ",d.jsx("strong",{children:"not"})," a full 2⁴⁸ exhaustive search — only keys you and the community already know. Hold a ",d.jsx("strong",{children:"MIFARE Classic"})," on the coil."," ",d.jsx("a",{className:"text-bubble-mint underline",href:"https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/mfc_default_keys.dic",target:"_blank",rel:"noreferrer",children:"More keys online"}),"."]}),d.jsxs("label",{className:"block text-sm",children:["Reader / map",d.jsxs("select",{value:t,onChange:h=>n(h.target.value),className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2",children:[d.jsx("option",{value:"classic1k",children:"MIFARE Classic 1K (sectors 0–15)"}),d.jsx("option",{value:"classic4k",children:"MIFARE Classic 4K (sectors 0–39, proper 4/16-block geometry)"})]})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:r,onChange:h=>s(h.target.checked)}),"Variations (extra tries per key — slower, wider net)"]}),d.jsxs("label",{className:"block text-sm",children:["Extra keys (one 12-hex key per line, merged after built-in list)",d.jsx("textarea",{value:i,onChange:h=>o(h.target.value),rows:6,className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 p-3 font-mono text-xs"})]}),d.jsx("button",{type:"button",disabled:a,onClick:f,className:"rounded-2xl bg-gradient-to-r from-bubble-rose to-orange-500 px-6 py-3 font-bold text-white disabled:opacity-50",children:a?"Running…":"Run dictionary attack"}),u&&d.jsx("pre",{className:"max-h-96 overflow-auto rounded-2xl border border-white/10 bg-black/40 p-4 text-xs text-bubble-mint",children:u})]})}function T2(){const e=Je(),[t,n]=x.useState("8C"),[r,s]=x.useState(""),[i,o]=x.useState(!1),a=async()=>{o(!0),s("");try{const l=await fetch(vs("/api/nfc/emulate-raw"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({hex:t.replace(/\s/g,"")})}),u=await l.text();if(!l.ok)throw new Error(u);try{s(JSON.stringify(JSON.parse(u),null,2))}catch{s(u)}e("PN532 emulation command sent")}catch(l){e(String(l),"err")}finally{o(!1)}};return d.jsxs("div",{className:"glass space-y-6 p-6",children:[d.jsx("h1",{className:"font-display text-2xl font-bold",children:"Card emulation (PN532 target mode)"}),d.jsxs("p",{className:"text-sm text-slate-400",children:["Sends ",d.jsx("code",{className:"text-bubble-mint",children:"TgInitAsTarget"})," (0x8C) and following bytes as one PN532 payload. Real card emulation depends on UID length, timing, and reader behavior — this is an"," ",d.jsx("strong",{children:"expert / experimental"})," path. Build the byte sequence from NXP UM0701 or community examples. Wrong frames can leave the RF stack busy; power-cycle if the field acts stuck."]}),d.jsx("p",{className:"text-[11px] leading-relaxed text-slate-500",children:ws}),d.jsx(fo,{mode:"emulate",onApplyHex:l=>n(l)}),d.jsxs("label",{className:"block text-sm",children:["Command + parameters (hex, no spaces required)",d.jsx("textarea",{value:t,onChange:l=>n(l.target.value),rows:4,className:"mt-1 w-full rounded-2xl border border-white/10 bg-black/25 p-3 font-mono text-xs"})]}),d.jsx("button",{type:"button",disabled:i,onClick:a,className:"rounded-2xl bg-bubble-accent px-6 py-2 font-semibold text-white disabled:opacity-50",children:i?"Sending…":"Send emulate frame"}),r&&d.jsx("pre",{className:"max-h-80 overflow-auto rounded-2xl border border-white/10 bg-black/40 p-4 text-xs text-slate-200",children:r})]})}function Rf({title:e,badge:t,children:n,className:r=""}){return d.jsxs(O.div,{initial:{opacity:0,y:12},whileInView:{opacity:1,y:0},viewport:{once:!0,margin:"-40px"},transition:{duration:.4,ease:[.22,1,.36,1]},className:`glass panel-edge relative overflow-hidden p-6 ${r}`.trim(),children:[d.jsx("div",{className:"pointer-events-none absolute -right-20 -top-20 h-40 w-40 rounded-full bg-bubble-accent/10 blur-3xl"}),d.jsx("div",{className:"pointer-events-none absolute -bottom-16 -left-16 h-36 w-36 rounded-full bg-bubble-rose/10 blur-3xl"}),d.jsx("div",{className:"pointer-events-none absolute inset-0 bg-gradient-to-br from-bubble-accent/[0.06] via-transparent to-bubble-mint/[0.07]"}),d.jsxs("div",{className:"relative",children:[d.jsxs("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-2",children:[d.jsx("h2",{className:"font-display text-lg font-normal tracking-wide text-bubble-mint text-glow-matrix",children:e}),t?d.jsx(O.span,{animate:{boxShadow:["0 0 12px rgba(0,229,255,0.3)","0 0 22px rgba(0,255,157,0.45)","0 0 12px rgba(0,229,255,0.3)"]},transition:{duration:2.2,repeat:1/0},className:"rounded-full border border-bubble-accent/50 bg-bubble-accent/15 px-2.5 py-0.5 font-mono text-[10px] uppercase tracking-widest text-bubble-accent",children:t}):null]}),n]})]})}function ea(e){const t=e.replace(/\s/g,"");if(t.length!==12)return null;const n=[];for(let r=0;r<12;r+=2){const s=parseInt(t.slice(r,r+2),16);if(Number.isNaN(s))return null;n.push(s)}return n}function kr(e){return e.map(t=>t.toString(16).toUpperCase().padStart(2,"0")).join("")}function E2(e){const t=e.length,n=new Set,r=[];for(let s=0;s<1<{const S=ea(t),m=ea(r),p=ea(i);return!S||!m?null:a&&p?[S,m,p]:[S,m]},[t,r,i,a]),h=x.useMemo(()=>f?E2(f):[],[f]),g=x.useMemo(()=>j2(u),[u]),v=()=>{const S=h.map(m=>kr(m)).join(` diff --git a/firmware/data/index.html b/firmware/data/index.html index 187f12f..0c62328 100644 --- a/firmware/data/index.html +++ b/firmware/data/index.html @@ -11,7 +11,7 @@ href="https://fonts.googleapis.com/css2?family=Audiowide&family=JetBrains+Mono:ital,wght@0,400;0,600;0,700;1,400&family=Orbitron:wght@500;600;700;800&display=swap" rel="stylesheet" /> - + diff --git a/firmware/dependencies.lock b/firmware/dependencies.lock new file mode 100644 index 0000000..5699b64 --- /dev/null +++ b/firmware/dependencies.lock @@ -0,0 +1,31 @@ +dependencies: + espressif/led_strip: + component_hash: 28c6509a727ef74925b372ed404772aeedf11cce10b78c3f69b3c66799095e2d + dependencies: + - name: idf + require: private + version: '>=4.4' + source: + registry_url: https://components.espressif.com/ + type: service + version: 2.5.5 + espressif/mdns: + component_hash: 1ebe3bd675bb9d1c58f52bc0b609b32f74e572b01c328f9e61282040c775495c + dependencies: + - name: idf + require: private + version: '>=5.0' + source: + registry_url: https://components.espressif.com/ + type: service + version: 1.11.0 + idf: + source: + type: idf + version: 5.3.5 +direct_dependencies: +- espressif/led_strip +- espressif/mdns +manifest_hash: 846f5d4c8f94373f8485b56cff23f9fbea0309ded1992f9236f5f5ef877a4d37 +target: esp32s3 +version: 2.0.0 diff --git a/firmware/flash.sh b/firmware/flash.sh index c3ffc71..0f5ab7d 100755 --- a/firmware/flash.sh +++ b/firmware/flash.sh @@ -1,12 +1,11 @@ #!/usr/bin/env bash -# Flash PN532 toolkit. Requires ESP-IDF 5.x in PATH (run export.sh first). +# Compatibility wrapper around the repo-root launcher. set -euo pipefail ROOT="$(cd "$(dirname "$0")" && pwd)" -PORT="${ESPPORT:-${1:-/dev/cu.usbserial-A5069RR4}}" -cd "$ROOT" -if ! command -v idf.py >/dev/null 2>&1; then - echo "idf.py not found. Source your ESP-IDF export.sh, then re-run:" >&2 - echo " ESPPORT=$PORT $0" >&2 - exit 1 +PORT="${ESPPORT:-${1:-}}" + +if [ -n "$PORT" ]; then + exec "$ROOT/../start-firmware.sh" --port "$PORT" --flash-only fi -idf.py -p "$PORT" flash + +exec "$ROOT/../start-firmware.sh" --flash-only diff --git a/firmware/main/idf_component.yml b/firmware/main/idf_component.yml index 4917680..3174fe0 100644 --- a/firmware/main/idf_component.yml +++ b/firmware/main/idf_component.yml @@ -1,3 +1,4 @@ ## IDF Component Manager — addressable RGB (DevKitC-1) dependencies: espressif/led_strip: "^2.5.5" + espressif/mdns: "^1.10.1" diff --git a/firmware/sdkconfig.defaults b/firmware/sdkconfig.defaults index 237ab76..ec202f9 100644 --- a/firmware/sdkconfig.defaults +++ b/firmware/sdkconfig.defaults @@ -9,7 +9,7 @@ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y # CONFIG_SPIRAM_MODE_OCT=y # CONFIG_SPIRAM_SPEED_80M=y -CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_UART_DEFAULT=y CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 CONFIG_FREERTOS_HZ=1000 @@ -18,7 +18,6 @@ CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024 CONFIG_HTTPD_MAX_URI_LEN=512 CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y -CONFIG_LWIP_LOCAL_IP4_TTL=64 CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10 CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32 diff --git a/start-firmware.sh b/start-firmware.sh new file mode 100755 index 0000000..b85cda0 --- /dev/null +++ b/start-firmware.sh @@ -0,0 +1,274 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +FW_DIR="$ROOT/firmware" +WEB_DIR="$ROOT/web" + +ESP_IDF_REF="${ESP_IDF_REF:-release/v5.3}" +ESP_IDF_DIR="${ESP_IDF_DIR:-$HOME/.pn532-toolkit/esp-idf}" +ESP_IDF_REPO="${ESP_IDF_REPO:-https://github.com/espressif/esp-idf.git}" +IDF_TOOLS_PATH="${IDF_TOOLS_PATH:-$HOME/.pn532-toolkit/espressif}" +PORT="${ESPPORT:-}" + +BUILD_WEB=1 +FLASH=1 +FLASH_ONLY=0 +MONITOR=0 +MENUCONFIG=0 +CLEAN=0 +SKIP_HOST_DEPS=0 + +log() { + printf '[pn532] %s\n' "$*" +} + +fail() { + printf '[pn532] ERROR: %s\n' "$*" >&2 + exit 1 +} + +have() { + command -v "$1" >/dev/null 2>&1 +} + +usage() { + cat </dev/null 2>&1 || true + if ! have idf.py; then + log "Installing ESP-IDF tools for esp32s3" + (cd "$ESP_IDF_DIR" && ./install.sh esp32s3) + # shellcheck disable=SC1090 + . "$ESP_IDF_DIR/export.sh" >/dev/null + fi + + have idf.py || fail "idf.py is still unavailable after sourcing ESP-IDF" +} + +build_web_assets() { + [ "$BUILD_WEB" -eq 1 ] || return 0 + + have npm || fail "npm is required to build the embedded web UI" + if [ ! -d "$WEB_DIR/node_modules" ]; then + log "Installing web dependencies" + (cd "$WEB_DIR" && npm ci) + fi + + log "Building web UI into firmware/data" + (cd "$WEB_DIR" && npm run build:fw) +} + +cleanup_partial_build_dir() { + local build_dir="$FW_DIR/build" + + if [ -d "$build_dir" ] && [ ! -f "$build_dir/CMakeCache.txt" ]; then + log "Removing partial firmware/build left by an interrupted or failed configure" + rm -rf "$build_dir" + fi +} + +prepare_target() { + cd "$FW_DIR" + cleanup_partial_build_dir + + if [ ! -f sdkconfig ] || ! grep -q '^CONFIG_IDF_TARGET="esp32s3"$' sdkconfig; then + log "Configuring firmware target: esp32s3" + idf.py set-target esp32s3 + fi + + if [ "$MENUCONFIG" -eq 1 ]; then + log "Opening menuconfig" + idf.py menuconfig + fi + + if [ "$CLEAN" -eq 1 ]; then + log "Cleaning previous build" + idf.py fullclean + fi +} + +run_firmware_flow() { + cd "$FW_DIR" + + local -a cmd=(idf.py) + if [ -n "$PORT" ]; then + cmd+=(-p "$PORT") + fi + + if [ "$FLASH" -eq 0 ]; then + log "Building firmware only" + "${cmd[@]}" build + return 0 + fi + + if [ -z "$PORT" ]; then + PORT="$(detect_port || true)" + fi + [ -n "$PORT" ] || fail "No ESP32 serial port detected. Plug the device in or pass --port." + + cmd=(idf.py -p "$PORT") + if [ "$FLASH_ONLY" -eq 1 ] && [ "$MONITOR" -eq 1 ]; then + log "Flashing existing build and opening monitor on $PORT" + "${cmd[@]}" flash monitor + elif [ "$FLASH_ONLY" -eq 1 ]; then + log "Flashing existing build on $PORT" + "${cmd[@]}" flash + log "Flash complete. Join Wi-Fi SSID PN532-Toolkit and open http://192.168.4.1" + elif [ "$MONITOR" -eq 1 ]; then + log "Building, flashing, and opening monitor on $PORT" + "${cmd[@]}" build flash monitor + else + log "Building and flashing on $PORT" + "${cmd[@]}" build flash + log "Flash complete. Join Wi-Fi SSID PN532-Toolkit and open http://192.168.4.1" + fi +} + +while [ "$#" -gt 0 ]; do + case "$1" in + --port) + [ "$#" -ge 2 ] || fail "--port requires a value" + PORT="$2" + shift 2 + ;; + --build-only) + FLASH=0 + shift + ;; + --flash-only) + BUILD_WEB=0 + FLASH_ONLY=1 + shift + ;; + --monitor) + MONITOR=1 + shift + ;; + --menuconfig) + MENUCONFIG=1 + shift + ;; + --no-web) + BUILD_WEB=0 + shift + ;; + --clean) + CLEAN=1 + shift + ;; + --skip-host-deps) + SKIP_HOST_DEPS=1 + shift + ;; + --help|-h) + usage + exit 0 + ;; + *) + fail "Unknown option: $1" + ;; + esac +done + +ensure_host_deps +load_idf_env +build_web_assets +prepare_target +run_firmware_flow diff --git a/web/src/nfcUtils.ts b/web/src/nfcUtils.ts index d7c8993..da72f83 100644 --- a/web/src/nfcUtils.ts +++ b/web/src/nfcUtils.ts @@ -26,14 +26,14 @@ export function parseTrailerAccess(hex16: string): AccessBits | null { export function sakLabel(sak: number): string { switch (sak) { + case 0x00: + return "Ultralight / NTAG / Type 2"; case 0x08: - return "Ultralight family"; + return "MIFARE Classic 1K"; case 0x09: - return "Mini / Classic"; + return "MIFARE Mini"; case 0x18: - return "Classic 1K"; - case 0x19: - return "Classic 4K"; + return "MIFARE Classic 4K"; default: return `SAK 0x${sak.toString(16).toUpperCase()}`; } @@ -68,14 +68,15 @@ export function scanCheatLines(tag: { uidLen: number; atqa: number; sak: number } else if (tag.uidLen === 10) { lines.push("10-byte UID — triple cascade path."); } - if (tag.sak === 0x08) { - lines.push("SAK 0x08 — often Ultralight / Type 2; use page read/write for user memory."); + if (tag.sak === 0x00) { + lines.push("SAK 0x00 — typical Type 2 / Ultralight-style path; use page read/write."); } - if (tag.sak === 0x18 || tag.sak === 0x19) { - lines.push("MIFARE Classic — authenticate per sector trailer, then block read/write."); + if (tag.sak === 0x08 || tag.sak === 0x09 || tag.sak === 0x18) { + lines.push("MIFARE Classic family — authenticate per sector trailer, then block read/write."); } - if (tag.atqa === 0x0044 || tag.atqa === 0x4400) { - lines.push("ATQA 0x4400 pattern — very common Type A inventory response."); + /* Firmware stores ATQA as (resp[3]<<8)|resp[4]; e.g. 04 00 → 0x0400. */ + if (tag.atqa === 0x0400 || tag.atqa === 0x4400) { + lines.push("ATQA 0x0400/0x4400 class — common Type A / MIFARE inventory shapes."); } return lines; } diff --git a/web/src/pages/WriteClone.tsx b/web/src/pages/WriteClone.tsx index 0ab4ede..96b497f 100644 --- a/web/src/pages/WriteClone.tsx +++ b/web/src/pages/WriteClone.tsx @@ -19,11 +19,25 @@ export default function WriteClone() { const [ulData, setUlData] = useState("00000000"); const write = async () => { + const cleanKey = key.replace(/\s/g, ""); + const cleanData = data.replace(/\s/g, ""); + if (cleanKey.length !== 12 || !/^[0-9A-Fa-f]+$/.test(cleanKey)) { + toast("Key must be exactly 12 hex digits", "err"); + return; + } + if (cleanData.length !== 32 || !/^[0-9A-Fa-f]+$/.test(cleanData)) { + toast("Block data must be exactly 32 hex digits (16 bytes)", "err"); + return; + } + if (!Number.isInteger(block) || block < 0 || block > 255) { + toast("Block must be an integer 0–255", "err"); + return; + } if (!confirm("Write will modify tag memory. Continue?")) { return; } try { - await apiPost("/api/mifare/write-block", { block, key, keyB, data }); + await apiPost("/api/mifare/write-block", { block, key: cleanKey, keyB, data: cleanData }); toast("Write OK"); } catch (e) { toast(String(e), "err"); @@ -31,11 +45,16 @@ export default function WriteClone() { }; const writeUl = async () => { + const h = ulData.replace(/\s/g, ""); + if (h.length !== 8 || !/^[0-9A-Fa-f]+$/.test(h)) { + toast("UL data must be exactly 8 hex digits (4 bytes)", "err"); + return; + } if (!confirm("Ultralight page write — can brick OTP/lock bytes if misused. Continue?")) { return; } try { - await apiPost("/api/ul/write-page", { page: ulPage, data: ulData.replace(/\s/g, "") }); + await apiPost("/api/ul/write-page", { page: ulPage, data: h }); toast("UL page write OK"); } catch (e) { toast(String(e), "err");