diff --git a/MeshMapper_WebClient.code-workspace b/MeshMapper_WebClient.code-workspace deleted file mode 100644 index ef9f5d2..0000000 --- a/MeshMapper_WebClient.code-workspace +++ /dev/null @@ -1,7 +0,0 @@ -{ - "folders": [ - { - "path": "." - } - ] -} \ No newline at end of file diff --git a/README.md b/README.md index a700e70..73a8472 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MeshCore GOME WarDriver -[![Version](https://img.shields.io/badge/version-1.8.0-blue.svg)](https://github.com/MrAlders0n/MeshCore-GOME-WarDriver/releases/tag/v1.8.0) +[![Version](https://img.shields.io/badge/version-1.8.4-blue.svg)](https://github.com/MrAlders0n/MeshCore-GOME-WarDriver/releases/tag/v1.8.4) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Platform](https://img.shields.io/badge/platform-Android%20%7C%20iOS-orange.svg)](#platform-support) diff --git a/content/tailwind-in.css b/content/tailwind-in.css index a461c50..76fcadc 100644 --- a/content/tailwind-in.css +++ b/content/tailwind-in.css @@ -1 +1,3 @@ -@import "tailwindcss"; \ No newline at end of file +@import "tailwindcss/base"; +@import "tailwindcss/components"; +@import "tailwindcss/utilities"; diff --git a/content/tailwind.css b/content/tailwind.css index 80d12c3..71202e6 100644 --- a/content/tailwind.css +++ b/content/tailwind.css @@ -1,970 +1 @@ -/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */ -@layer properties; -@layer theme, base, components, utilities; -@layer theme { - :root, :host { - --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", - "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", - "Courier New", monospace; - --color-red-300: oklch(80.8% 0.114 19.571); - --color-red-500: oklch(63.7% 0.237 25.331); - --color-red-600: oklch(57.7% 0.245 27.325); - --color-amber-300: oklch(87.9% 0.169 91.605); - --color-amber-400: oklch(82.8% 0.189 84.429); - --color-amber-500: oklch(76.9% 0.188 70.08); - --color-amber-600: oklch(66.6% 0.179 58.318); - --color-emerald-300: oklch(84.5% 0.143 164.978); - --color-emerald-500: oklch(69.6% 0.17 162.48); - --color-emerald-600: oklch(59.6% 0.145 163.225); - --color-sky-300: oklch(82.8% 0.111 230.318); - --color-sky-500: oklch(68.5% 0.169 237.323); - --color-sky-600: oklch(58.8% 0.158 241.966); - --color-indigo-500: oklch(58.5% 0.233 277.117); - --color-indigo-600: oklch(51.1% 0.262 276.966); - --color-slate-100: oklch(96.8% 0.007 247.896); - --color-slate-200: oklch(92.9% 0.013 255.508); - --color-slate-300: oklch(86.9% 0.022 252.894); - --color-slate-400: oklch(70.4% 0.04 256.788); - --color-slate-500: oklch(55.4% 0.046 257.417); - --color-slate-700: oklch(37.2% 0.044 257.287); - --color-slate-800: oklch(27.9% 0.041 260.031); - --color-slate-900: oklch(20.8% 0.042 265.755); - --color-white: #fff; - --spacing: 0.25rem; - --container-xl: 36rem; - --text-xs: 0.75rem; - --text-xs--line-height: calc(1 / 0.75); - --text-sm: 0.875rem; - --text-sm--line-height: calc(1.25 / 0.875); - --text-base: 1rem; - --text-base--line-height: calc(1.5 / 1); - --text-lg: 1.125rem; - --text-lg--line-height: calc(1.75 / 1.125); - --text-xl: 1.25rem; - --text-xl--line-height: calc(1.75 / 1.25); - --text-2xl: 1.5rem; - --text-2xl--line-height: calc(2 / 1.5); - --font-weight-medium: 500; - --font-weight-semibold: 600; - --tracking-wide: 0.025em; - --radius-lg: 0.5rem; - --radius-xl: 0.75rem; - --blur-sm: 8px; - --default-transition-duration: 150ms; - --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - --default-font-family: var(--font-sans); - --default-mono-font-family: var(--font-mono); - } -} -@layer base { - *, ::after, ::before, ::backdrop, ::file-selector-button { - box-sizing: border-box; - margin: 0; - padding: 0; - border: 0 solid; - } - html, :host { - line-height: 1.5; - -webkit-text-size-adjust: 100%; - tab-size: 4; - font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); - font-feature-settings: var(--default-font-feature-settings, normal); - font-variation-settings: var(--default-font-variation-settings, normal); - -webkit-tap-highlight-color: transparent; - } - hr { - height: 0; - color: inherit; - border-top-width: 1px; - } - abbr:where([title]) { - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; - } - h1, h2, h3, h4, h5, h6 { - font-size: inherit; - font-weight: inherit; - } - a { - color: inherit; - -webkit-text-decoration: inherit; - text-decoration: inherit; - } - b, strong { - font-weight: bolder; - } - code, kbd, samp, pre { - font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); - font-feature-settings: var(--default-mono-font-feature-settings, normal); - font-variation-settings: var(--default-mono-font-variation-settings, normal); - font-size: 1em; - } - small { - font-size: 80%; - } - sub, sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; - } - sub { - bottom: -0.25em; - } - sup { - top: -0.5em; - } - table { - text-indent: 0; - border-color: inherit; - border-collapse: collapse; - } - :-moz-focusring { - outline: auto; - } - progress { - vertical-align: baseline; - } - summary { - display: list-item; - } - ol, ul, menu { - list-style: none; - } - img, svg, video, canvas, audio, iframe, embed, object { - display: block; - vertical-align: middle; - } - img, video { - max-width: 100%; - height: auto; - } - button, input, select, optgroup, textarea, ::file-selector-button { - font: inherit; - font-feature-settings: inherit; - font-variation-settings: inherit; - letter-spacing: inherit; - color: inherit; - border-radius: 0; - background-color: transparent; - opacity: 1; - } - :where(select:is([multiple], [size])) optgroup { - font-weight: bolder; - } - :where(select:is([multiple], [size])) optgroup option { - padding-inline-start: 20px; - } - ::file-selector-button { - margin-inline-end: 4px; - } - ::placeholder { - opacity: 1; - } - @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) { - ::placeholder { - color: currentcolor; - @supports (color: color-mix(in lab, red, red)) { - color: color-mix(in oklab, currentcolor 50%, transparent); - } - } - } - textarea { - resize: vertical; - } - ::-webkit-search-decoration { - -webkit-appearance: none; - } - ::-webkit-date-and-time-value { - min-height: 1lh; - text-align: inherit; - } - ::-webkit-datetime-edit { - display: inline-flex; - } - ::-webkit-datetime-edit-fields-wrapper { - padding: 0; - } - ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field { - padding-block: 0; - } - ::-webkit-calendar-picker-indicator { - line-height: 1; - } - :-moz-ui-invalid { - box-shadow: none; - } - button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button { - appearance: button; - } - ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { - height: auto; - } - [hidden]:where(:not([hidden="until-found"])) { - display: none !important; - } -} -@layer utilities { - .visible { - visibility: visible; - } - .sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip-path: inset(50%); - white-space: nowrap; - border-width: 0; - } - .absolute { - position: absolute; - } - .fixed { - position: fixed; - } - .relative { - position: relative; - } - .static { - position: static; - } - .top-2 { - top: calc(var(--spacing) * 2); - } - .right-2 { - right: calc(var(--spacing) * 2); - } - .bottom-2 { - bottom: calc(var(--spacing) * 2); - } - .left-2 { - left: calc(var(--spacing) * 2); - } - .z-10 { - z-index: 10; - } - .container { - width: 100%; - @media (width >= 40rem) { - max-width: 40rem; - } - @media (width >= 48rem) { - max-width: 48rem; - } - @media (width >= 64rem) { - max-width: 64rem; - } - @media (width >= 80rem) { - max-width: 80rem; - } - @media (width >= 96rem) { - max-width: 96rem; - } - } - .mt-0\.5 { - margin-top: calc(var(--spacing) * 0.5); - } - .mt-2 { - margin-top: calc(var(--spacing) * 2); - } - .mb-2 { - margin-bottom: calc(var(--spacing) * 2); - } - .ml-2 { - margin-left: calc(var(--spacing) * 2); - } - .block { - display: block; - } - .contents { - display: contents; - } - .flex { - display: flex; - } - .grid { - display: grid; - } - .hidden { - display: none; - } - .inline { - display: inline; - } - .h-4 { - height: calc(var(--spacing) * 4); - } - .h-5 { - height: calc(var(--spacing) * 5); - } - .h-6 { - height: calc(var(--spacing) * 6); - } - .h-7 { - height: calc(var(--spacing) * 7); - } - .h-8 { - height: calc(var(--spacing) * 8); - } - .h-10 { - height: calc(var(--spacing) * 10); - } - .h-12 { - height: calc(var(--spacing) * 12); - } - .h-14 { - height: calc(var(--spacing) * 14); - } - .max-h-48 { - max-height: calc(var(--spacing) * 48); - } - .max-h-64 { - max-height: calc(var(--spacing) * 64); - } - .min-h-screen { - min-height: 100vh; - } - .w-4 { - width: calc(var(--spacing) * 4); - } - .w-5 { - width: calc(var(--spacing) * 5); - } - .w-6 { - width: calc(var(--spacing) * 6); - } - .w-7 { - width: calc(var(--spacing) * 7); - } - .w-8 { - width: calc(var(--spacing) * 8); - } - .w-10 { - width: calc(var(--spacing) * 10); - } - .w-12 { - width: calc(var(--spacing) * 12); - } - .w-14 { - width: calc(var(--spacing) * 14); - } - .w-full { - width: 100%; - } - .max-w-xl { - max-width: var(--container-xl); - } - .min-w-0 { - min-width: calc(var(--spacing) * 0); - } - .flex-1 { - flex: 1; - } - .flex-shrink-0 { - flex-shrink: 0; - } - .grow { - flex-grow: 1; - } - .cursor-pointer { - cursor: pointer; - } - .list-inside { - list-style-position: inside; - } - .list-disc { - list-style-type: disc; - } - .list-none { - list-style-type: none; - } - .grid-cols-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - .flex-col { - flex-direction: column; - } - .flex-wrap { - flex-wrap: wrap; - } - .items-center { - align-items: center; - } - .items-end { - align-items: flex-end; - } - .items-start { - align-items: flex-start; - } - .justify-between { - justify-content: space-between; - } - .justify-center { - justify-content: center; - } - .gap-2 { - gap: calc(var(--spacing) * 2); - } - .gap-3 { - gap: calc(var(--spacing) * 3); - } - .gap-4 { - gap: calc(var(--spacing) * 4); - } - .space-y-1 { - :where(& > :not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse))); - } - } - .space-y-2 { - :where(& > :not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse))); - } - } - .space-y-3 { - :where(& > :not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse))); - } - } - .space-y-4 { - :where(& > :not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse))); - } - } - .truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - .overflow-hidden { - overflow: hidden; - } - .overflow-y-auto { - overflow-y: auto; - } - .rounded { - border-radius: 0.25rem; - } - .rounded-full { - border-radius: calc(infinity * 1px); - } - .rounded-lg { - border-radius: var(--radius-lg); - } - .rounded-xl { - border-radius: var(--radius-xl); - } - .rounded-t-xl { - border-top-left-radius: var(--radius-xl); - border-top-right-radius: var(--radius-xl); - } - .rounded-b-none { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; - } - .rounded-b-xl { - border-bottom-right-radius: var(--radius-xl); - border-bottom-left-radius: var(--radius-xl); - } - .border { - border-style: var(--tw-border-style); - border-width: 1px; - } - .border-x { - border-inline-style: var(--tw-border-style); - border-inline-width: 1px; - } - .border-t { - border-top-style: var(--tw-border-style); - border-top-width: 1px; - } - .border-b { - border-bottom-style: var(--tw-border-style); - border-bottom-width: 1px; - } - .border-slate-700 { - border-color: var(--color-slate-700); - } - .border-slate-700\/70 { - border-color: color-mix(in srgb, oklch(37.2% 0.044 257.287) 70%, transparent); - @supports (color: color-mix(in lab, red, red)) { - border-color: color-mix(in oklab, var(--color-slate-700) 70%, transparent); - } - } - .bg-amber-600 { - background-color: var(--color-amber-600); - } - .bg-emerald-600 { - background-color: var(--color-emerald-600); - } - .bg-indigo-600 { - background-color: var(--color-indigo-600); - } - .bg-red-600 { - background-color: var(--color-red-600); - } - .bg-sky-600 { - background-color: var(--color-sky-600); - } - .bg-slate-800 { - background-color: var(--color-slate-800); - } - .bg-slate-800\/80 { - background-color: color-mix(in srgb, oklch(27.9% 0.041 260.031) 80%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-slate-800) 80%, transparent); - } - } - .bg-slate-900 { - background-color: var(--color-slate-900); - } - .bg-slate-900\/50 { - background-color: color-mix(in srgb, oklch(20.8% 0.042 265.755) 50%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-slate-900) 50%, transparent); - } - } - .bg-slate-900\/80 { - background-color: color-mix(in srgb, oklch(20.8% 0.042 265.755) 80%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-slate-900) 80%, transparent); - } - } - .p-0 { - padding: calc(var(--spacing) * 0); - } - .p-1 { - padding: calc(var(--spacing) * 1); - } - .p-2 { - padding: calc(var(--spacing) * 2); - } - .p-3 { - padding: calc(var(--spacing) * 3); - } - .p-4 { - padding: calc(var(--spacing) * 4); - } - .px-1 { - padding-inline: calc(var(--spacing) * 1); - } - .px-3 { - padding-inline: calc(var(--spacing) * 3); - } - .px-4 { - padding-inline: calc(var(--spacing) * 4); - } - .py-0\.5 { - padding-block: calc(var(--spacing) * 0.5); - } - .py-1\.5 { - padding-block: calc(var(--spacing) * 1.5); - } - .py-2 { - padding-block: calc(var(--spacing) * 2); - } - .py-3 { - padding-block: calc(var(--spacing) * 3); - } - .py-4 { - padding-block: calc(var(--spacing) * 4); - } - .pt-2 { - padding-top: calc(var(--spacing) * 2); - } - .text-center { - text-align: center; - } - .text-right { - text-align: right; - } - .font-mono { - font-family: var(--font-mono); - } - .text-2xl { - font-size: var(--text-2xl); - line-height: var(--tw-leading, var(--text-2xl--line-height)); - } - .text-base { - font-size: var(--text-base); - line-height: var(--tw-leading, var(--text-base--line-height)); - } - .text-lg { - font-size: var(--text-lg); - line-height: var(--tw-leading, var(--text-lg--line-height)); - } - .text-sm { - font-size: var(--text-sm); - line-height: var(--tw-leading, var(--text-sm--line-height)); - } - .text-xl { - font-size: var(--text-xl); - line-height: var(--tw-leading, var(--text-xl--line-height)); - } - .text-xs { - font-size: var(--text-xs); - line-height: var(--tw-leading, var(--text-xs--line-height)); - } - .text-\[10px\] { - font-size: 10px; - line-height: 1; - } - .leading-5 { - --tw-leading: calc(var(--spacing) * 5); - line-height: calc(var(--spacing) * 5); - } - .leading-none { - --tw-leading: 1; - line-height: 1; - } - .font-medium { - --tw-font-weight: var(--font-weight-medium); - font-weight: var(--font-weight-medium); - } - .font-semibold { - --tw-font-weight: var(--font-weight-semibold); - font-weight: var(--font-weight-semibold); - } - .tracking-wide { - --tw-tracking: var(--tracking-wide); - letter-spacing: var(--tracking-wide); - } - .whitespace-nowrap { - white-space: nowrap; - } - .text-amber-300 { - color: var(--color-amber-300); - } - .text-amber-400 { - color: var(--color-amber-400); - } - .text-emerald-300 { - color: var(--color-emerald-300); - } - .text-red-300 { - color: var(--color-red-300); - } - .text-sky-300 { - color: var(--color-sky-300); - } - .text-slate-100 { - color: var(--color-slate-100); - } - .text-slate-300 { - color: var(--color-slate-300); - } - .text-slate-400 { - color: var(--color-slate-400); - } - .text-slate-500 { - color: var(--color-slate-500); - } - .text-white { - color: var(--color-white); - } - .lowercase { - text-transform: lowercase; - } - .uppercase { - text-transform: uppercase; - } - .italic { - font-style: italic; - } - .underline { - text-decoration-line: underline; - } - .filter { - filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); - } - .backdrop-blur-sm { - --tw-backdrop-blur: blur(var(--blur-sm)); - -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); - backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); - } - .transition-all { - transition-property: all; - transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); - transition-duration: var(--tw-duration, var(--default-transition-duration)); - } - .transition-colors { - transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to; - transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); - transition-duration: var(--tw-duration, var(--default-transition-duration)); - } - .transition-transform { - transition-property: transform, translate, scale, rotate; - transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); - transition-duration: var(--tw-duration, var(--default-transition-duration)); - } - .duration-200 { - --tw-duration: 200ms; - transition-duration: 200ms; - } - .hover\:bg-amber-500 { - &:hover { - @media (hover: hover) { - background-color: var(--color-amber-500); - } - } - } - .hover\:bg-emerald-500 { - &:hover { - @media (hover: hover) { - background-color: var(--color-emerald-500); - } - } - } - .hover\:bg-indigo-500 { - &:hover { - @media (hover: hover) { - background-color: var(--color-indigo-500); - } - } - } - .hover\:bg-red-500 { - &:hover { - @media (hover: hover) { - background-color: var(--color-red-500); - } - } - } - .hover\:bg-sky-500 { - &:hover { - @media (hover: hover) { - background-color: var(--color-sky-500); - } - } - } - .hover\:bg-slate-700 { - &:hover { - @media (hover: hover) { - background-color: var(--color-slate-700); - } - } - } - .hover\:bg-slate-700\/50 { - &:hover { - @media (hover: hover) { - background-color: color-mix(in srgb, oklch(37.2% 0.044 257.287) 50%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-slate-700) 50%, transparent); - } - } - } - } - .hover\:bg-slate-800\/60 { - &:hover { - @media (hover: hover) { - background-color: color-mix(in srgb, oklch(27.9% 0.041 260.031) 60%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-slate-800) 60%, transparent); - } - } - } - } - .hover\:text-slate-200 { - &:hover { - @media (hover: hover) { - color: var(--color-slate-200); - } - } - } - .disabled\:cursor-not-allowed { - &:disabled { - cursor: not-allowed; - } - } - .disabled\:opacity-40 { - &:disabled { - opacity: 40%; - } - } - .has-\[\:checked\]\:border-emerald-600 { - &:has(*:is(:checked)) { - border-color: var(--color-emerald-600); - } - } - .has-\[\:checked\]\:bg-emerald-600 { - &:has(*:is(:checked)) { - background-color: var(--color-emerald-600); - } - } - .sm\:inline { - @media (width >= 40rem) { - display: inline; - } - } - .sm\:h-8 { - @media (width >= 40rem) { - height: calc(var(--spacing) * 8); - } - } - .sm\:text-xl { - @media (width >= 40rem) { - font-size: var(--text-xl); - line-height: var(--tw-leading, var(--text-xl--line-height)); - } - } -} -@property --tw-space-y-reverse { - syntax: "*"; - inherits: false; - initial-value: 0; -} -@property --tw-border-style { - syntax: "*"; - inherits: false; - initial-value: solid; -} -@property --tw-leading { - syntax: "*"; - inherits: false; -} -@property --tw-font-weight { - syntax: "*"; - inherits: false; -} -@property --tw-tracking { - syntax: "*"; - inherits: false; -} -@property --tw-blur { - syntax: "*"; - inherits: false; -} -@property --tw-brightness { - syntax: "*"; - inherits: false; -} -@property --tw-contrast { - syntax: "*"; - inherits: false; -} -@property --tw-grayscale { - syntax: "*"; - inherits: false; -} -@property --tw-hue-rotate { - syntax: "*"; - inherits: false; -} -@property --tw-invert { - syntax: "*"; - inherits: false; -} -@property --tw-opacity { - syntax: "*"; - inherits: false; -} -@property --tw-saturate { - syntax: "*"; - inherits: false; -} -@property --tw-sepia { - syntax: "*"; - inherits: false; -} -@property --tw-drop-shadow { - syntax: "*"; - inherits: false; -} -@property --tw-drop-shadow-color { - syntax: "*"; - inherits: false; -} -@property --tw-drop-shadow-alpha { - syntax: ""; - inherits: false; - initial-value: 100%; -} -@property --tw-drop-shadow-size { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-blur { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-brightness { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-contrast { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-grayscale { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-hue-rotate { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-invert { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-opacity { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-saturate { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-sepia { - syntax: "*"; - inherits: false; -} -@property --tw-duration { - syntax: "*"; - inherits: false; -} -@layer properties { - @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { - *, ::before, ::after, ::backdrop { - --tw-space-y-reverse: 0; - --tw-border-style: solid; - --tw-leading: initial; - --tw-font-weight: initial; - --tw-tracking: initial; - --tw-blur: initial; - --tw-brightness: initial; - --tw-contrast: initial; - --tw-grayscale: initial; - --tw-hue-rotate: initial; - --tw-invert: initial; - --tw-opacity: initial; - --tw-saturate: initial; - --tw-sepia: initial; - --tw-drop-shadow: initial; - --tw-drop-shadow-color: initial; - --tw-drop-shadow-alpha: 100%; - --tw-drop-shadow-size: initial; - --tw-backdrop-blur: initial; - --tw-backdrop-brightness: initial; - --tw-backdrop-contrast: initial; - --tw-backdrop-grayscale: initial; - --tw-backdrop-hue-rotate: initial; - --tw-backdrop-invert: initial; - --tw-backdrop-opacity: initial; - --tw-backdrop-saturate: initial; - --tw-backdrop-sepia: initial; - --tw-duration: initial; - } - } -} +*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.bottom-2{bottom:.5rem}.left-2{left:.5rem}.right-2{right:.5rem}.top-2{top:.5rem}.z-10{z-index:10}.z-50{z-index:50}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.mt-1{margin-top:.25rem}.mt-4{margin-top:1rem}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.size-8{width:2rem;height:2rem}.h-12{height:3rem}.h-3{height:.75rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-8{height:2rem}.max-h-64{max-height:16rem}.min-h-screen{min-height:100vh}.w-12{width:3rem}.w-14{width:3.5rem}.w-3{width:.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-8{width:2rem}.w-full{width:100%}.min-w-0{min-width:0}.max-w-md{max-width:28rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.rounded-b-none{border-bottom-right-radius:0;border-bottom-left-radius:0}.rounded-b-xl{border-bottom-right-radius:.75rem;border-bottom-left-radius:.75rem}.rounded-t-xl{border-top-left-radius:.75rem;border-top-right-radius:.75rem}.border{border-width:1px}.border-x{border-left-width:1px;border-right-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-slate-600{--tw-border-opacity:1;border-color:rgb(71 85 105/var(--tw-border-opacity,1))}.border-slate-700{--tw-border-opacity:1;border-color:rgb(51 65 85/var(--tw-border-opacity,1))}.bg-amber-600{--tw-bg-opacity:1;background-color:rgb(217 119 6/var(--tw-bg-opacity,1))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.bg-emerald-600{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity,1))}.bg-red-600{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.bg-sky-600{--tw-bg-opacity:1;background-color:rgb(2 132 199/var(--tw-bg-opacity,1))}.bg-slate-700{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity,1))}.bg-slate-800\/80{background-color:rgba(30,41,59,.8)}.bg-slate-900{--tw-bg-opacity:1;background-color:rgb(15 23 42/var(--tw-bg-opacity,1))}.bg-slate-900\/80{background-color:rgba(15,23,42,.8)}.bg-opacity-50{--tw-bg-opacity:0.5}.p-0{padding:0}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pb-3{padding-bottom:.75rem}.pt-1{padding-top:.25rem}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.italic{font-style:italic}.tracking-wide{letter-spacing:.025em}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-amber-400{--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.text-emerald-300{--tw-text-opacity:1;color:rgb(110 231 183/var(--tw-text-opacity,1))}.text-emerald-400{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.text-red-300{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-sky-300{--tw-text-opacity:1;color:rgb(125 211 252/var(--tw-text-opacity,1))}.text-sky-400{--tw-text-opacity:1;color:rgb(56 189 248/var(--tw-text-opacity,1))}.text-slate-100{--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity,1))}.text-slate-200{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.opacity-0{opacity:0}.opacity-50{opacity:.5}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.hover\:bg-amber-500:hover{--tw-bg-opacity:1;background-color:rgb(245 158 11/var(--tw-bg-opacity,1))}.hover\:bg-emerald-500:hover{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.hover\:bg-emerald-700:hover{--tw-bg-opacity:1;background-color:rgb(4 120 87/var(--tw-bg-opacity,1))}.hover\:bg-indigo-500:hover{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity,1))}.hover\:bg-red-500:hover{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.hover\:bg-sky-500:hover{--tw-bg-opacity:1;background-color:rgb(14 165 233/var(--tw-bg-opacity,1))}.hover\:bg-slate-700:hover{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.hover\:bg-slate-700\/50:hover{background-color:rgba(51,65,85,.5)}.hover\:bg-slate-800\/60:hover{background-color:rgba(30,41,59,.6)}.hover\:text-sky-300:hover{--tw-text-opacity:1;color:rgb(125 211 252/var(--tw-text-opacity,1))}.hover\:text-slate-200:hover{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.focus\:border-emerald-500:focus{--tw-border-opacity:1;border-color:rgb(16 185 129/var(--tw-border-opacity,1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-emerald-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(16 185 129/var(--tw-ring-opacity,1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.peer:checked~.peer-checked\:border-emerald-600{--tw-border-opacity:1;border-color:rgb(5 150 105/var(--tw-border-opacity,1))}.peer:checked~.peer-checked\:bg-emerald-600{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.peer:focus~.peer-focus\:ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.peer:focus~.peer-focus\:ring-emerald-500{--tw-ring-opacity:1;--tw-ring-color:rgb(16 185 129/var(--tw-ring-opacity,1))}.peer:focus~.peer-focus\:ring-offset-1{--tw-ring-offset-width:1px}.peer:focus~.peer-focus\:ring-offset-slate-800{--tw-ring-offset-color:#1e293b}.has-\[\:checked\]\:border-emerald-600:has(:checked){--tw-border-opacity:1;border-color:rgb(5 150 105/var(--tw-border-opacity,1))}.has-\[\:checked\]\:bg-emerald-600:has(:checked){--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}@media (min-width:640px){.sm\:inline{display:inline}.sm\:h-14{height:3.5rem}.sm\:w-14{width:3.5rem}.sm\:text-xl{font-size:1.25rem;line-height:1.75rem}} \ No newline at end of file diff --git a/content/wardrive.js b/content/wardrive.js index f3af332..7011f45 100644 --- a/content/wardrive.js +++ b/content/wardrive.js @@ -328,6 +328,7 @@ const ADVERT_HEADER = 0x11; // Header byte for ADVERT packets // RX Packet Filter Configuration const MAX_RX_PATH_LENGTH = 9; // Maximum path length for RX packets (drop if exceeded to filter corrupted packets) +const MAX_RX_RSSI_THRESHOLD = -30; // Maximum RSSI (dBm) for RX packets (drop if ≥ -30 to filter "carpeater" - extremely close/interfering repeaters) const RX_ALLOWED_CHANNELS = ['#wardriving', 'Public', '#testing', '#ottawa']; // Allowed channels for RX wardriving (Public uses fixed key, hashtag channels use SHA-256 derivation) const RX_PRINTABLE_THRESHOLD = 0.80; // Minimum printable character ratio for GRP_TXT (80%) @@ -516,6 +517,8 @@ const txLogState = { const rxLogState = { entries: [], // Array of parsed RX log entries dropCount: 0, // Count of dropped/filtered packets + carpeaterIgnoreDropCount: 0, // User-specified repeater drops (silent) + carpeaterRssiDropCount: 0, // RSSI failsafe drops (logged) isExpanded: false, autoScroll: true, maxEntries: 100 // Limit to prevent memory issues @@ -2246,6 +2249,23 @@ function getExternalAntennaSetting() { return checkedAntenna ? checkedAntenna.value : ""; } +/** + * Get carpeater ignore settings from UI + * @returns {{enabled: boolean, repeaterId: string|null}} Settings object + */ +function getCarpeaterIgnoreSettings() { + const enabled = document.getElementById('carpeaterFilterEnabled')?.checked || false; + const idInput = document.getElementById('carpeaterIdInput')?.value?.trim()?.toLowerCase() || ''; + + // Validate hex format (2 chars, 00-FF) + const isValidHex = /^[0-9a-f]{2}$/.test(idInput); + + return { + enabled: enabled && isValidHex, + repeaterId: (enabled && isValidHex) ? idInput : null + }; +} + function buildPayload(lat, lon) { const coordsStr = `${lat.toFixed(5)}, ${lon.toFixed(5)}`; const power = getCurrentPowerSetting(); @@ -3417,7 +3437,15 @@ async function validateRxPacket(metadata) { } debugLog(`[RX FILTER] ✓ Path length OK (${metadata.pathLength} ≤ ${MAX_RX_PATH_LENGTH})`); - // VALIDATION 2: Check packet type (only ADVERT and GRP_TXT) + // VALIDATION 2: Check RSSI (Carpeater filter - drop extremely strong signals from OTHER repeaters) + // Note: User-specified carpeater is already filtered earlier in handleTxLogging/handleRxLogging + if (metadata.rssi >= MAX_RX_RSSI_THRESHOLD) { + debugLog(`[RX FILTER] ❌ DROPPED: RSSI too strong (${metadata.rssi} ≥ ${MAX_RX_RSSI_THRESHOLD}) - possible carpeater (RSSI failsafe)`); + return { valid: false, reason: 'carpeater-rssi' }; + } + debugLog(`[RX FILTER] ✓ RSSI OK (${metadata.rssi} < ${MAX_RX_RSSI_THRESHOLD})`); + + // VALIDATION 3: Check packet type (only ADVERT and GRP_TXT) if (metadata.header === CHANNEL_GROUP_TEXT_HEADER) { debugLog(`[RX FILTER] Packet type: GRP_TXT (0x15)`); @@ -3544,6 +3572,17 @@ async function handleTxLogging(metadata, data) { debugLog(`[TX LOG] Header validation passed: 0x${metadata.header.toString(16).padStart(2, '0')}`); + // VALIDATION STEP 1.5: Check RSSI (Carpeater RSSI failsafe - drop extremely strong signals) + if (metadata.rssi >= MAX_RX_RSSI_THRESHOLD) { + debugLog(`[TX LOG] ❌ DROPPED: RSSI too strong (${metadata.rssi} ≥ ${MAX_RX_RSSI_THRESHOLD}) - possible carpeater (RSSI failsafe)`); + rxLogState.dropCount++; + rxLogState.carpeaterRssiDropCount++; + updateCarpeaterErrorLog(); + updateRxLogSummary(); + return false; // Mark as handled (dropped) + } + debugLog(`[TX LOG] ✓ RSSI OK (${metadata.rssi} < ${MAX_RX_RSSI_THRESHOLD})`); + // VALIDATION STEP 2: Validate this message is for our channel by comparing channel hash // Channel message payload structure: [1 byte channel_hash][2 bytes MAC][encrypted message] if (metadata.encryptedPayload.length < 3) { @@ -3614,6 +3653,16 @@ async function handleTxLogging(metadata, data) { const firstHopId = metadata.firstHop; const pathHex = firstHopId.toString(16).padStart(2, '0'); + // Check if this repeater is the user-specified carpeater to ignore + const carpeaterSettings = getCarpeaterIgnoreSettings(); + if (carpeaterSettings.enabled && pathHex === carpeaterSettings.repeaterId) { + rxLogState.dropCount++; + rxLogState.carpeaterIgnoreDropCount++; + updateRxLogSummary(); + debugLog(`[PING] ❌ Dropped: Repeater ${pathHex} is user-specified carpeater (ignore)`); + return; + } + debugLog(`[PING] Repeater echo accepted: first_hop=${pathHex}, SNR=${metadata.snr}, full_path_length=${metadata.pathLength}`); // Check if we already have this path @@ -3788,6 +3837,13 @@ async function handleRxLogging(metadata, data) { const validation = await validateRxPacket(metadata); if (!validation.valid) { rxLogState.dropCount++; + + // Special handling for RSSI failsafe carpeater drops (not user-specified drops) + if (validation.reason === 'carpeater-rssi') { + rxLogState.carpeaterRssiDropCount++; + updateCarpeaterErrorLog(); + } + updateRxLogSummary(); const rawHex = Array.from(metadata.raw).map(b => b.toString(16).padStart(2, '0').toUpperCase()).join(' '); debugLog(`[RX LOG] ❌ Packet dropped: ${validation.reason}`); @@ -3799,6 +3855,16 @@ async function handleRxLogging(metadata, data) { const lastHopId = metadata.lastHop; const repeaterId = lastHopId.toString(16).padStart(2, '0'); + // Check if this repeater is the user-specified carpeater to ignore + const carpeaterSettings = getCarpeaterIgnoreSettings(); + if (carpeaterSettings.enabled && repeaterId === carpeaterSettings.repeaterId) { + rxLogState.dropCount++; + rxLogState.carpeaterIgnoreDropCount++; + updateRxLogSummary(); + debugLog(`[RX LOG] ❌ Dropped: Repeater ${repeaterId} is user-specified carpeater (ignore)`); + return; + } + debugLog(`[RX LOG] Packet heard via last hop: ${repeaterId}, SNR=${metadata.snr}, path_length=${metadata.pathLength}`); debugLog(`[RX LOG] ✅ Packet validated and passed filter`); @@ -4816,6 +4882,34 @@ function addErrorLogEntry(message, source = null) { debugLog(`[ERROR LOG] Added entry: ${message.substring(0, 50)}${message.length > 50 ? '...' : ''}`); } +/** + * Update or add carpeater error log entry with current drop count + * This creates a persistent error entry that updates in place rather than creating multiple entries + */ +function updateCarpeaterErrorLog() { + const message = `Possible Carpeater Detected, Dropped ${rxLogState.carpeaterRssiDropCount} packet${rxLogState.carpeaterRssiDropCount !== 1 ? 's' : ''}`; + const source = 'RX FILTER'; + + // Find existing carpeater entry by checking if message starts with "Possible Carpeater Detected" + const existingIndex = errorLogState.entries.findIndex(entry => + entry.source === source && entry.message.startsWith('Possible Carpeater Detected') + ); + + if (existingIndex !== -1) { + // Update existing entry + errorLogState.entries[existingIndex].message = message; + errorLogState.entries[existingIndex].timestamp = new Date().toISOString(); + debugLog(`[ERROR LOG] Updated carpeater entry: ${rxLogState.carpeaterDropCount} drops`); + + // Full re-render to update the displayed message + renderErrorLogEntries(true); + updateErrorLogSummary(); + } else { + // Create new entry (first carpeater detection) + addErrorLogEntry(message, source); + } +} + // ---- CSV Export Functions ---- /** @@ -5751,6 +5845,8 @@ async function connect() { rxLogState.entries = []; rxLogState.dropCount = 0; + rxLogState.carpeaterIgnoreDropCount = 0; + rxLogState.carpeaterRssiDropCount = 0; renderRxLogEntries(true); updateRxLogSummary(); @@ -6520,12 +6616,9 @@ export async function onLoad() { // Show custom confirmation modal const modal = document.getElementById("overrideModal"); - debugLog(`[UI] Modal element lookup result: ${modal ? 'found' : 'NOT FOUND'}`); if (modal) { - debugLog(`[UI] Modal current display: ${modal.style.display}, classes: ${modal.className}`); modal.classList.remove("hidden"); - modal.style.display = "flex"; - debugLog(`[UI] Modal after show - display: ${modal.style.display}, classes: ${modal.className}`); + debugLog("[UI] Override modal opened"); } else { debugError("[UI] overrideModal element not found in DOM!"); } @@ -6575,7 +6668,6 @@ export async function onLoad() { overrideModalCancel.addEventListener("click", () => { debugLog("[UI] Override canceled via custom modal"); overrideModal.classList.add("hidden"); - overrideModal.style.display = "none"; }); } @@ -6585,7 +6677,6 @@ export async function onLoad() { if (e.target === overrideModal) { debugLog("[UI] Override modal closed via backdrop click"); overrideModal.classList.add("hidden"); - overrideModal.style.display = "none"; } }); } @@ -6637,6 +6728,60 @@ export async function onLoad() { }); }); + // Carpeater filter checkbox event listener + const carpeaterCheckbox = document.getElementById('carpeaterFilterEnabled'); + const carpeaterInput = document.getElementById('carpeaterIdInput'); + + if (carpeaterCheckbox && carpeaterInput) { + // Load saved settings from localStorage + const savedEnabled = localStorage.getItem('carpeaterFilterEnabled') === 'true'; + const savedId = localStorage.getItem('carpeaterRepeaterId') || ''; + + carpeaterCheckbox.checked = savedEnabled; + carpeaterInput.value = savedId; + carpeaterInput.disabled = !savedEnabled; // Enable/disable input based on checkbox + + // Update checkmark visibility on load + const checkmarkSvg = document.querySelector('.checkmark-svg'); + if (checkmarkSvg) { + checkmarkSvg.style.opacity = savedEnabled ? '1' : '0'; + } + + // Checkbox toggle event + carpeaterCheckbox.addEventListener('change', (e) => { + const isEnabled = e.target.checked; + carpeaterInput.disabled = !isEnabled; + localStorage.setItem('carpeaterFilterEnabled', isEnabled); + debugLog(`[SETTINGS] Carpeater filter ${isEnabled ? 'enabled' : 'disabled'}`); + + // Update checkmark visibility + if (checkmarkSvg) { + checkmarkSvg.style.opacity = isEnabled ? '1' : '0'; + } + + // Focus input when enabled + if (isEnabled) { + carpeaterInput.focus(); + } + }); + + // Input validation and save event + carpeaterInput.addEventListener('input', (e) => { + const value = e.target.value.toLowerCase(); + const isValid = /^[0-9a-f]{0,2}$/.test(value); + + if (isValid) { + e.target.value = value; + if (value.length === 2) { + localStorage.setItem('carpeaterRepeaterId', value); + debugLog(`[SETTINGS] Carpeater repeater ID set to: ${value}`); + } + } else { + e.target.value = value.slice(0, -1); // Remove invalid character + } + }); + } + // Session Log event listener if (txLogSummaryBar) { txLogSummaryBar.addEventListener("click", () => { @@ -6686,6 +6831,35 @@ export async function onLoad() { }); } + // Carpeater Info link event listener + const carpeaterInfoLink = document.getElementById('carpeaterInfoLink'); + const carpeaterModal = document.getElementById('carpeaterModal'); + + if (carpeaterInfoLink && carpeaterModal) { + carpeaterInfoLink.addEventListener('click', (e) => { + e.preventDefault(); + debugLog('[UI] Carpeater Info link clicked - opening modal'); + carpeaterModal.classList.remove('hidden'); + }); + + // Close modal when clicking close buttons + const modalCloseButtons = carpeaterModal.querySelectorAll('[data-modal-close]'); + modalCloseButtons.forEach(btn => { + btn.addEventListener('click', () => { + debugLog('[UI] Carpeater modal close button clicked'); + carpeaterModal.classList.add('hidden'); + }); + }); + + // Close modal when clicking backdrop + carpeaterModal.addEventListener('click', (e) => { + if (e.target === carpeaterModal) { + debugLog('[UI] Carpeater modal closed via backdrop click'); + carpeaterModal.classList.add('hidden'); + } + }); + } + // Prompt location permission early (optional) debugLog("[GPS] Requesting initial location permission"); try { diff --git a/index.html b/index.html index 9d19af0..1374163 100644 --- a/index.html +++ b/index.html @@ -162,6 +162,26 @@

Settings< + +
+ +
+ + + + + Info +
+
+
@@ -375,14 +395,14 @@

Notes

-