diff --git a/package-lock.json b/package-lock.json index 844ec4e..a86bf92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,12 +9,10 @@ "version": "0.0.1", "dependencies": { "@sveltestrap/sveltestrap": "^7.1.0", - "@types/leaflet": "^1.9.19", - "bootstrap-icons": "^1.13.1", + "bootstrap-icons": "^1.11.3", "js-cookie": "^3.0.5", "leaflet": "^1.9.4", - "leaflet-velocity": "^2.1.4", - "leaflet.heat": "^0.2.0" + "leaflet-velocity": "^2.1.4" }, "devDependencies": { "@sveltejs/adapter-auto": "^4.0.0", @@ -868,19 +866,6 @@ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==" }, - "node_modules/@types/geojson": { - "version": "7946.0.16", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", - "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==" - }, - "node_modules/@types/leaflet": { - "version": "1.9.19", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.19.tgz", - "integrity": "sha512-pB+n2daHcZPF2FDaWa+6B0a0mSDf4dPU35y5iTXsx7x/PzzshiX5atYiS1jlBn43X7XvM8AP+AB26lnSk0J4GA==", - "dependencies": { - "@types/geojson": "*" - } - }, "node_modules/acorn": { "version": "8.14.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", @@ -909,9 +894,9 @@ } }, "node_modules/bootstrap-icons": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.13.1.tgz", - "integrity": "sha512-ijombt4v6bv5CLeXvRWKy7CuM3TRTuPEuGaGKvTV5cz65rQSY8RQ2JcHt6b90cBBAC7s8fsf2EkQDldzCoXUjw==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz", + "integrity": "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==", "funding": [ { "type": "github", @@ -1113,11 +1098,6 @@ "resolved": "https://registry.npmjs.org/leaflet-velocity/-/leaflet-velocity-2.1.4.tgz", "integrity": "sha512-uTmSb2/Kn28S0itlmJBMy2ZRKsisWUr2wm9rtkKXjpq9Sai7tqKdTRHKfLgTOgEdWFf5Ctt2bQoB7kb50qC7eg==" }, - "node_modules/leaflet.heat": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/leaflet.heat/-/leaflet.heat-0.2.0.tgz", - "integrity": "sha512-Cd5PbAA/rX3X3XKxfDoUGi9qp78FyhWYurFg3nsfhntcM/MCNK08pRkf4iEenO1KNqwVPKCmkyktjW3UD+h9bQ==" - }, "node_modules/locate-character": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", diff --git a/package.json b/package.json index 9d82df6..db0e69e 100644 --- a/package.json +++ b/package.json @@ -22,11 +22,9 @@ }, "dependencies": { "@sveltestrap/sveltestrap": "^7.1.0", - "@types/leaflet": "^1.9.19", - "bootstrap-icons": "^1.13.1", + "bootstrap-icons": "^1.11.3", "js-cookie": "^3.0.5", "leaflet": "^1.9.4", - "leaflet-velocity": "^2.1.4", - "leaflet.heat": "^0.2.0" + "leaflet-velocity": "^2.1.4" } } diff --git a/src/app.html b/src/app.html index 3ba5379..a01612f 100644 --- a/src/app.html +++ b/src/app.html @@ -4,15 +4,8 @@ - - - - %sveltekit.head% diff --git a/src/lib/components/PanelContainer.svelte b/src/lib/components/PanelContainer.svelte deleted file mode 100644 index 3a9bb43..0000000 --- a/src/lib/components/PanelContainer.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - -
- -
diff --git a/src/lib/components/ScenarioPanel.svelte b/src/lib/components/ScenarioPanel.svelte deleted file mode 100644 index 4791ced..0000000 --- a/src/lib/components/ScenarioPanel.svelte +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - {#if !isCollapsed} - - - - - - - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - -
- {/if} -
diff --git a/src/lib/components/TabComponent.svelte b/src/lib/components/TabComponent.svelte deleted file mode 100644 index 594f4d0..0000000 --- a/src/lib/components/TabComponent.svelte +++ /dev/null @@ -1,50 +0,0 @@ - - -
- {#each tabs as tab (tab.id)} - - {/each} -
- - \ No newline at end of file diff --git a/src/lib/components/TelemetryPanel.svelte b/src/lib/components/TelemetryPanel.svelte deleted file mode 100644 index 7a69ca4..0000000 --- a/src/lib/components/TelemetryPanel.svelte +++ /dev/null @@ -1,97 +0,0 @@ - - - - - Последние данные телеметрии - - - {#if !isCollapsed} - - - - - - - - - - - - - - - - - - - - - - - {/if} - - diff --git a/src/lib/ext/leaflet-ruler/leaflet-ruler.ts b/src/lib/ext/leaflet-ruler/leaflet-ruler.ts deleted file mode 100644 index 40ef2be..0000000 --- a/src/lib/ext/leaflet-ruler/leaflet-ruler.ts +++ /dev/null @@ -1,286 +0,0 @@ -import * as L from "leaflet"; -import { distHaversine, bearingHaversine } from "$lib/mathutil"; - -// Define an interface for the control's options for type safety. -export interface RulerOptions extends L.ControlOptions { - events?: { - onToggle?: (isActive: boolean) => void; - }; - circleMarker?: L.CircleMarkerOptions; - lineStyle?: L.PolylineOptions; - lengthUnit?: { - display?: string; - decimal?: number; - factor?: number | null; - label?: string; - }; - angleUnit?: { - display?: string; - decimal?: number; - factor?: number | null; - label?: string; - }; -} - -// Define an interface for the measurement result. -interface MeasurementResult { - Bearing: number; - Distance: number; -} - -// Use a modern TypeScript class that extends L.Control. -export class Ruler extends L.Control { - // Override the default options with our custom ones. - public options: RulerOptions = { - position: "topright", - events: { - onToggle: () => {}, - }, - circleMarker: { - color: "red", - radius: 2, - }, - lineStyle: { - color: "red", - dashArray: "1,6", - }, - lengthUnit: { - display: "km", - decimal: 2, - factor: null, - label: "Distance:", - }, - angleUnit: { - display: "°", - decimal: 2, - factor: null, - label: "Bearing:", - }, - }; - - // Declare class properties with types. - private _lastClickTime = 0; - private _map?: L.Map; - private _container?: HTMLElement; - private _choice = false; - private _defaultCursor = ""; - private _allLayers: L.LayerGroup = L.layerGroup(); - private _clickedLatLong: L.LatLng | null = null; - private _clickedPoints: L.LatLng[] = []; - private _totalLength = 0; - private _clickCount = 0; - private _tempLine: L.FeatureGroup = L.featureGroup(); - private _tempPoint: L.FeatureGroup = L.featureGroup(); - private _pointLayer: L.FeatureGroup = L.featureGroup(); - private _polylineLayer: L.FeatureGroup = L.featureGroup(); - private _movingLatLong: L.LatLng | null = null; - private _result: MeasurementResult = { Bearing: 0, Distance: 0 }; - private _addedLength = 0; - - constructor(options?: RulerOptions) { - super(options); - L.Util.setOptions(this, options); - } - - public isActive(): boolean { - return this._choice; - } - - public onAdd(map: L.Map): HTMLElement { - this._map = map; - this._container = L.DomUtil.create("div", "leaflet-bar leaflet-ruler"); - L.DomEvent.disableClickPropagation(this._container); - L.DomEvent.on(this._container, "click", this._toggleMeasure, this); - this._defaultCursor = this._map.getContainer().style.cursor; - this._allLayers = L.layerGroup(); - return this._container; - } - - public onRemove(): void { - if (this._container) { - L.DomEvent.off(this._container, "click", this._toggleMeasure, this); - } - if (this._choice) { - this._toggleMeasure(); // Turn off measurements - } - } - - private _toggleMeasure(): void { - this._choice = !this._choice; - this.options.events?.onToggle?.(this._choice); - - this._clickedLatLong = null; - this._clickedPoints = []; - this._totalLength = 0; - - if (!this._map || !this._container) return; - - const mapContainer = this._map.getContainer(); - - if (this._choice) { - this._map.doubleClickZoom.disable(); - L.DomEvent.on(mapContainer, "keydown", this._escape, this); - L.DomEvent.on(mapContainer, "dblclick", this._closePath, this); - this._container.classList.add("leaflet-ruler-clicked"); - this._clickCount = 0; - this._tempLine = L.featureGroup().addTo(this._allLayers); - this._tempPoint = L.featureGroup().addTo(this._allLayers); - this._pointLayer = L.featureGroup().addTo(this._allLayers); - this._polylineLayer = L.featureGroup().addTo(this._allLayers); - this._allLayers.addTo(this._map); - mapContainer.style.cursor = "crosshair"; - this._map.on("click", this._clicked, this); - this._map.on("mousemove", this._moving, this); - } else { - this._map.doubleClickZoom.enable(); - L.DomEvent.off(mapContainer, "keydown", this._escape, this); - L.DomEvent.off(mapContainer, "dblclick", this._closePath, this); - this._container.classList.remove("leaflet-ruler-clicked"); - this._map.removeLayer(this._allLayers); - this._allLayers = L.layerGroup(); - mapContainer.style.cursor = this._defaultCursor; - this._map.off("click", this._clicked, this); - this._map.off("mousemove", this._moving, this); - } - } - - private _clicked(e: L.LeafletMouseEvent): void { - // hack to prevent adding the same point twice on double click - let clickTime = Date.now(); - if (clickTime - this._lastClickTime < 200) { - this._closePath(); - return; - } - - this._lastClickTime = clickTime; - - this._clickedLatLong = e.latlng; - this._clickedPoints.push(this._clickedLatLong); - L.circleMarker(this._clickedLatLong, this.options.circleMarker).addTo(this._pointLayer); - - if (this._clickCount > 0 && !e.latlng.equals(this._clickedPoints[this._clickedPoints.length - 2], 0.0001)) { - if (this._movingLatLong) { - L.polyline( - [this._clickedPoints[this._clickCount - 1], this._movingLatLong], - this.options.lineStyle - ).addTo(this._polylineLayer); - } - let text: string; - this._totalLength += this._result.Distance; - const angleUnit = this.options.angleUnit!; - const lengthUnit = this.options.lengthUnit!; - - if (this._clickCount > 1) { - text = `${angleUnit.label} ${this._result.Bearing.toFixed(angleUnit.decimal)} ${ - angleUnit.display - }
${lengthUnit.label} ${this._totalLength.toFixed(lengthUnit.decimal)} ${ - lengthUnit.display - }`; - } else { - text = `${angleUnit.label} ${this._result.Bearing.toFixed(angleUnit.decimal)} ${ - angleUnit.display - }
${lengthUnit.label} ${this._result.Distance.toFixed(lengthUnit.decimal)} ${ - lengthUnit.display - }`; - } - L.circleMarker(this._clickedLatLong, this.options.circleMarker) - .bindTooltip(text, { permanent: true, className: "result-tooltip" }) - .addTo(this._pointLayer) - .openTooltip(); - } - this._clickCount++; - } - - private _moving(e: L.LeafletMouseEvent): void { - if (this._clickedLatLong && this._map) { - this._movingLatLong = e.latlng; - - this._tempLine.clearLayers(); - this._tempPoint.clearLayers(); - - this._calculateBearingAndDistance(); - this._addedLength = this._result.Distance + this._totalLength; - - L.polyline([this._clickedLatLong, this._movingLatLong], this.options.lineStyle).addTo(this._tempLine); - - const angleUnit = this.options.angleUnit!; - const lengthUnit = this.options.lengthUnit!; - let text: string; - - if (this._clickCount > 1) { - text = `${angleUnit.label} ${this._result.Bearing.toFixed(angleUnit.decimal)} ${ - angleUnit.display - }
${lengthUnit.label} ${this._addedLength.toFixed(lengthUnit.decimal)} ${ - lengthUnit.display - }
(+${this._result.Distance.toFixed(lengthUnit.decimal)})
`; - } else { - text = `${angleUnit.label} ${this._result.Bearing.toFixed(angleUnit.decimal)} ${ - angleUnit.display - }
${lengthUnit.label} ${this._result.Distance.toFixed(lengthUnit.decimal)} ${ - lengthUnit.display - }`; - } - L.circleMarker(this._movingLatLong, this.options.circleMarker) - .bindTooltip(text, { sticky: true, offset: L.point(0, -40), className: "moving-tooltip" }) - .addTo(this._tempPoint) - .openTooltip(); - } - } - - private _escape(e: Event): void { - if ((e as KeyboardEvent).key === "Escape") { - if (this._clickCount > 0) { - this._closePath(); - } else { - this._toggleMeasure(); - } - } - } - - private _calculateBearingAndDistance(): void { - if (!this._clickedLatLong || !this._movingLatLong) return; - - const f1 = this._clickedLatLong.lat; - const l1 = this._clickedLatLong.lng; - const f2 = this._movingLatLong.lat; - const l2 = this._movingLatLong.lng; - - const angleUnit = this.options.angleUnit!; - const lengthUnit = this.options.lengthUnit!; - - const brng = bearingHaversine({ lat: f1, lng: l1 }, { lat: f2, lng: l2 }); - - const distance = distHaversine({ lat: f1, lng: l1 }, { lat: f2, lng: l2 }); - - if (angleUnit.factor) { - this._result.Bearing = brng * angleUnit.factor; - } else { - this._result.Bearing = brng; - } - - if (lengthUnit.factor) { - this._result.Distance = distance * lengthUnit.factor; - } else { - this._result.Distance = distance; - } - - this._result = { - Bearing: brng, - Distance: distance, - }; - } - - private _closePath(): void { - if (!this._map || !this._container) return; - - this._map.removeLayer(this._tempLine); - this._map.removeLayer(this._tempPoint); - this._choice = false; - this._toggleMeasure(); - } -} - -// Factory function for creating the control, maintaining the Leaflet convention. -export const ruler = (options?: RulerOptions) => { - return new Ruler(options); -}; diff --git a/src/lib/mathutil.ts b/src/lib/mathutil.ts index eee4bac..75bcebe 100644 --- a/src/lib/mathutil.ts +++ b/src/lib/mathutil.ts @@ -2,7 +2,7 @@ export function distHaversine( p1: { lat: number; lng: number }, p2: { lat: number; lng: number }, precision?: number -): number { +): string { const R = 6371; // Earth's mean radius in km const rad = (x: number): number => (x * Math.PI) / 180; @@ -20,20 +20,5 @@ export function distHaversine( const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); const d = R * c; - return precision ? parseFloat(d.toFixed(precision)) : d; -} - -export function bearingHaversine( - p1: { lat: number; lng: number }, - p2: { lat: number; lng: number } -): number { - const rad = (x: number): number => (x * Math.PI) / 180; - - const dLong = rad(p2.lng - p1.lng); - const y = Math.sin(dLong) * Math.cos(rad(p2.lat)); - const x = - Math.cos(rad(p1.lat)) * Math.sin(rad(p2.lat)) - - Math.sin(rad(p1.lat)) * Math.cos(rad(p2.lat)) * Math.cos(dLong); - - return (Math.atan2(y, x) * 180) / Math.PI; + return d.toFixed(precision ?? 3); } \ No newline at end of file diff --git a/src/lib/types.ts b/src/lib/types.ts index 388f8d0..34029d5 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -23,11 +23,6 @@ export interface FlightParameters { version: number; } -export interface Point { - latlng: LatLngLiteral & { alt: number }; - datetime: Date; -} - export interface TelemetryPoint { altitude: number; datetime: string; @@ -47,8 +42,11 @@ export interface RawTelemetry { } export interface Telemetry { - flight_path: LatLngExpression[]; - launch: Point; + flight_path: [number, number, number][]; + launch: { + latlng: LatLngExpression; + datetime: Date; + }; datapoints: TelemetryPoint[]; } @@ -76,10 +74,38 @@ export interface RawPrediction { } export interface Prediction { - flight_path: LatLngExpression[]; - launch: Point; - burst: Point; - landing: Point; + flight_path: [number, number, number][]; + launch: { + latlng: LatLngExpression; + datetime: Date; + }; + burst: { + latlng: LatLngExpression; + datetime: Date; + }; + landing: { + latlng: LatLngExpression; + datetime: Date; + }; profile: string; flight_time: number; } + +export interface Point { + latlng: LatLngLiteral & { alt: number }; + datetime: Date; +} + +export interface PredictionData { + launch: Point; + landing: Point; + burst: Point; + flight_path: LatLngExpression[]; + flight_time: number; +} + +export interface TelemetryData { + launch: Point; + datapoints: TelemetryPoint[]; + flight_path: LatLngExpression[]; +} \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index cbb97e2..f961cbf 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,5 +1,5 @@
diff --git a/src/routes/ControlPanel.svelte b/src/routes/ControlPanel.svelte new file mode 100644 index 0000000..5288255 --- /dev/null +++ b/src/routes/ControlPanel.svelte @@ -0,0 +1,296 @@ + + +
+ + + + + + {#if !isCollapsed} + + + + + + {#each Object.keys(PROFILE_MAP) as profileName} + + {/each} + + + + + + + + + + + + + + + + + + + + + + / + + + + + + + + + + + + + + +
+ + + + + + + + +
+ +
+ + + + + + + + +
+ + + + + + +
+ + + +
+
+ {/if} +
+
diff --git a/src/routes/Navbar.svelte b/src/routes/Navbar.svelte new file mode 100644 index 0000000..3197208 --- /dev/null +++ b/src/routes/Navbar.svelte @@ -0,0 +1,109 @@ + + + + + + + + diff --git a/src/routes/TelemetryPanel.svelte b/src/routes/TelemetryPanel.svelte new file mode 100644 index 0000000..20e9b19 --- /dev/null +++ b/src/routes/TelemetryPanel.svelte @@ -0,0 +1,74 @@ + + +
+
+
Последние данные телеметрии
+ +
+ {#if !isCollapsed} +
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+
+ {/if} +
+ + diff --git a/src/lib/components/Toast.svelte b/src/routes/Toast.svelte similarity index 100% rename from src/lib/components/Toast.svelte rename to src/routes/Toast.svelte diff --git a/src/lib/components/WindVisualisation.svelte b/src/routes/WindVisualisation.svelte similarity index 99% rename from src/lib/components/WindVisualisation.svelte rename to src/routes/WindVisualisation.svelte index 386c503..b028916 100644 --- a/src/lib/components/WindVisualisation.svelte +++ b/src/routes/WindVisualisation.svelte @@ -96,7 +96,7 @@ displayValues: true, displayOptions: { velocityType: 'Wind Speed', - position: 'bottomright', + position: 'bottomleft', emptyString: 'No wind data', }, data: windData diff --git a/src/lib/components/Map.svelte b/src/routes/map.svelte similarity index 83% rename from src/lib/components/Map.svelte rename to src/routes/map.svelte index 5e6cc7a..fc0c0d1 100644 --- a/src/lib/components/Map.svelte +++ b/src/routes/map.svelte @@ -1,43 +1,39 @@
diff --git a/static/css/custom.css b/static/css/custom.css index e716523..b9ce25f 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -2,26 +2,26 @@ height: var(--navbar-height); padding-top: 0rem; padding-bottom: 0rem; - z-index: 1002; + z-index: 1000; border: none; background-color: white !important; } -.nav-full-height.nav-link { +.nav-link { color: inherit; padding-left: 1rem !important; padding-right: 1rem !important; padding-top: 12px; - background-color: white; - margin-right: -1px; + background-color: var(--bs-light); + margin-right: 1px; } -.nav-full-height.nav-link:hover { +.nav-link:hover { color: white !important;; background-color: var(--bs-primary); } -.nav-full-height.nav-link.active { +.nav-link.active { color: white !important; background-color: var(--bs-primary); } @@ -39,7 +39,7 @@ margin-right: 1em; } .navbar { - z-index: 1002; + z-index: 1001; } .card { @@ -51,8 +51,6 @@ :root { --navbar-height: 44px; - --panel-left: 20px; - --panel-top: 20px; } .map-container { @@ -71,6 +69,7 @@ font-family: Arial, sans-serif; font-size: 14px; z-index: 1000; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); border: 1px solid #ccc; width: auto; white-space: nowrap; @@ -78,45 +77,7 @@ .panel-container { position: absolute; - top: var(--panel-top); - left: var(--panel-left); - width: 23rem; - max-height: 90vh; - max-width: calc(100vw - var(--panel-left) - var(--panel-left)); - overflow-y: auto; - z-index: 1001; -} - -.leaflet-bar { - border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; - border-radius: var(--bs-border-radius) !important; -} - -.leaflet-tooltip-top::before { - border-top-color: var(--bs-border-color) !important; -} -.leaflet-tooltip-bottom::before { - border-bottom-color: var(--bs-border-color) !important; -} -.leaflet-tooltip-left::before { - border-left-color: var(--bs-border-color) !important; -} -.leaflet-tooltip-right::before { - border-right-color: var(--bs-border-color) !important; -} - -.leaflet-tooltip { - background-color: var(--bs-body-bg) !important; - border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; - border-radius: var(--bs-border-radius) !important; - color: var(--bs-body-color); - box-shadow: none !important; -} - - -@media (max-width: 767.98px) -{ - .coordinates-display { - display: none; - } -} + bottom: 20px; + left: 20px; + z-index: 1000; +} \ No newline at end of file diff --git a/static/ext/leaflet-ruler/icon.png b/static/ext/leaflet-ruler/icon.png deleted file mode 100644 index 028741e..0000000 Binary files a/static/ext/leaflet-ruler/icon.png and /dev/null differ diff --git a/static/ext/leaflet-ruler/leaflet-ruler.css b/static/ext/leaflet-ruler/leaflet-ruler.css deleted file mode 100644 index 69927c3..0000000 --- a/static/ext/leaflet-ruler/leaflet-ruler.css +++ /dev/null @@ -1,41 +0,0 @@ -.leaflet-ruler{ - height: 35px; - width: 35px; - background-image: url("./icon.png"); /*
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
*/ - background-repeat: no-repeat; - background-position: center; -} -.leaflet-ruler:hover{ - background-image: url("./icon.png"); /*
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
*/ -} -.leaflet-ruler-clicked{ - height: 35px; - width: 35px; - background-repeat: no-repeat; - background-position: center; - background-image: url("./icon.png"); - border-color: chartreuse !important; -} -.leaflet-bar{ - background-color: #ffffff; -} -.leaflet-control { - cursor: pointer; -} -.result-tooltip{ - background-color: white; - border-width: medium; - border-color: #de0000; - font-size: smaller; -} -.moving-tooltip{ - background-color: rgba(255, 255, 255, .7); - background-clip: padding-box; - opacity: 0.5; - border: dotted; - border-color: red; - font-size: smaller; -} -.plus-length{ - padding-left: 45px; -} \ No newline at end of file