From c3f9b64605f97fe21dbb7ef56842eb13f453c4e2 Mon Sep 17 00:00:00 2001
From: 1999AZZAR <1999azzar@gmail.com>
Date: Sun, 29 Jun 2025 02:30:52 +0700
Subject: [PATCH 1/4] Remove bower.json and enhance README with detailed
features and usage instructions; update index.html for improved layout and
accessibility; refactor arf.js for better search functionality and
responsiveness.
---
README.md | 42 +++++--
bower.json | 13 --
public/css/arf.css | 289 ++++++++++++++++++++++++++++++++++++++-------
public/index.html | 91 ++++++++------
public/js/arf.js | 136 +++++++++++++++++----
5 files changed, 455 insertions(+), 116 deletions(-)
delete mode 100644 bower.json
diff --git a/README.md b/README.md
index d1c058c5..ed080e3b 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,40 @@
# OSINT Framework
-http://osintframework.com
+This is a web-based framework for Open Source Intelligence (OSINT). It provides a graph-based visualization of various OSINT resources and tools.
+
+## Features
+
+- **Interactive Graph:** Visualizes OSINT tools and resources as a tree graph.
+- **Search:** Filter nodes by name or description.
+- **Dark Mode:** A comfortable viewing mode for low-light environments.
+- **Categorized Resources:** Resources are grouped into logical categories.
+
+## Getting Started
+
+1. Clone the repository:
+ ```bash
+ git clone https://github.com/lockfale/osint-framework.git
+ ```
+2. Navigate to the `public` directory.
+3. Open `index.html` in your web browser.
+
+## How to Use
+
+- **Click on nodes** to expand or collapse categories.
+- **Click on links** to open the corresponding resource in a new tab.
+- **Use the search bar** to filter the graph.
+- **Toggle the dark mode switch** for a different theme.
+
+## Legend
+
+- **(T)**: Indicates a tool that must be installed and run locally.
+- **(D)**: Google Dork.
+- **(R)**: Requires registration.
+- **(M)**: Indicates a URL that contains the search term and the URL itself must be edited manually.
+
+## Contributing
+
+Contributions, feedback, and suggestions are welcome! Please feel free to open an issue or pull request on the [GitHub repository](https://github.com/lockfale/osint-framework).
## Notes
OSINT framework focused on gathering information from free tools or resources. The intention is to help people find free OSINT resources. Some of the sites included might require registration or offer more data for $$$, but you should be able to get at least a portion of the available information for no cost.
@@ -11,12 +45,6 @@ Please visit the framework at the link below and good hunting!
https://osintframework.com
-### Legend
-(T) - Indicates a link to a tool that must be installed and run locally
-(D) - Google Dork, for more information: Google Hacking
-(R) - Requires registration
-(M) - Indicates a URL that contains the search term and the URL itself must be edited manually
-
### For Update Notifications
Follow me on Twitter: @jnordine - https://twitter.com/jnordine
Watch or star the project on Github: https://github.com/lockfale/osint-framework
diff --git a/bower.json b/bower.json
deleted file mode 100644
index f42d5b13..00000000
--- a/bower.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "name": "ARF",
- "main": "index.html",
- "homepage": "https://github.com/lockfale/ARF",
- "authors": [
- "Justin Nordine (s0lray)"
- ],
- "description": "Advanced Reconnaissance Framework",
- "license": "",
- "dependencies": {
- "d3": "3.5.16"
- }
-}
diff --git a/public/css/arf.css b/public/css/arf.css
index 29694acd..cc5d9ac7 100644
--- a/public/css/arf.css
+++ b/public/css/arf.css
@@ -1,62 +1,271 @@
+/* General Styles */
+:root {
+ --bg-color-light: #eef2f7;
+ --text-color-light: #1c1c1e;
+ --primary-color: #0A74DA;
+ --primary-color-light: #52AFFF;
+
+ --bg-color-dark: #000000;
+ --text-color-dark: #f0f0f0;
+ --surface-color-dark: rgba(28, 28, 30, 0.75);
+ --border-color-dark: rgba(255, 255, 255, 0.15);
+}
+
body {
- background-color: #ffffff;
- font-size: 14px;
- font-family: "Helvetica Neue", Helvetica;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+ margin: 0;
+ padding: 0;
+ background-color: var(--bg-color-light);
+ color: var(--text-color-light);
+ transition: background-color 0.5s ease, color 0.5s ease;
+ background: linear-gradient(120deg, #d4e0e8 0%, #a7c5eb 100%);
+ background-size: cover;
+}
+
+a {
+ color: var(--primary-color);
+ text-decoration: none;
+ transition: color 0.3s ease;
+}
+
+a:hover {
+ color: var(--primary-color-light);
+}
+
+/* Layout */
+#container {
+ display: flex;
+ height: 100vh;
+ padding: 1rem;
+ box-sizing: border-box;
+}
+
+#sidebar {
+ width: 320px;
+ flex-shrink: 0;
+ background-color: rgba(255, 255, 255, 0.6);
+ backdrop-filter: blur(15px) saturate(180%);
+ -webkit-backdrop-filter: blur(15px) saturate(180%);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ display: flex;
+ flex-direction: column;
+ box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
+ transition: background-color 0.5s ease, border-color 0.5s ease;
+ border-radius: 1rem;
+ height: 100%;
+ margin: 0;
+}
+
+#main-content {
+ flex-grow: 1;
+ margin-left: 1rem;
+ overflow: hidden; /* Prevent scrollbars on main content */
+ position: relative;
+ background-color: rgba(255, 255, 255, 0.4);
+ backdrop-filter: blur(15px) saturate(180%);
+ -webkit-backdrop-filter: blur(15px) saturate(180%);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ border-radius: 1rem;
+ box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
+ padding: 0;
}
#body {
- margin: 0 auto;
- position: relative;
+ width: 100%;
+ height: 100%;
+}
+
+header {
+ padding: 25px;
+ border-bottom: 1px solid rgba(221, 221, 221, 0.2);
+ transition: border-color 0.5s ease;
+}
+
+header h1 {
+ margin: 0;
+ font-size: 1.8em;
+ font-weight: 600;
+}
+
+.sidebar-content {
+ padding: 25px;
+ flex-grow: 1;
+ overflow-y: auto;
+}
+
+footer {
+ padding: 25px;
+ border-top: 1px solid rgba(221, 221, 221, 0.3);
+ font-size: 0.9em;
+ color: #555;
+ transition: border-color 0.5s ease, color 0.5s ease;
+}
+
+/* Controls */
+#controls .control-group {
+ margin-bottom: 20px;
+}
+
+#controls label {
+ display: block;
+ margin-bottom: 8px;
+ font-weight: 500;
+ font-size: 1.1em;
+}
+
+#search {
+ width: 100%;
+ padding: 12px;
+ border-radius: 8px;
+ border: 1px solid transparent;
+ background-color: rgba(255, 255, 255, 0.5);
+ transition: background-color 0.3s ease, box-shadow 0.3s ease;
+ box-sizing: border-box;
+}
+#search:focus {
+ outline: none;
+ box-shadow: 0 0 0 2px var(--primary-color);
+ background-color: rgba(255, 255, 255, 0.8);
}
-#header {
- font-size: 40px;
- font-weight: bold;
- top: 20px;
- text-align: center;
+
+/* Legend */
+.legend h3 {
+ font-size: 1.2em;
+ font-weight: 500;
+}
+.legend ul {
+ list-style: none;
+ padding: 0;
+ font-size: 0.95em;
+}
+.legend li {
+ margin-bottom: 8px;
+}
+.legend-key {
+ font-weight: bold;
+ margin-right: 10px;
+ color: var(--primary-color);
}
-.dark-Mode{
- background-color: #000;
- color: #fff;
- .node text {
- fill: #fff;
- }
- .legend{
- color: #fff;
- }
- path.link{
- stroke: #444;
- }
+/* Dark Mode Toggle */
+.dark-mode-toggle {
+ display: flex;
+ align-items: center;
}
-.legend {
- position: absolute;
- top: 0px;
- right: 0;
- width: 330px;
- font-size: 11px;
- color: #000;
+#dark-mode-checkbox {
+ display: none;
}
+.slider {
+ display: inline-block;
+ width: 50px;
+ height: 26px;
+ background-color: #ccc;
+ border-radius: 26px;
+ position: relative;
+ cursor: pointer;
+ transition: background-color 0.4s ease;
+}
+
+.slider::before {
+ content: '';
+ position: absolute;
+ width: 22px;
+ height: 22px;
+ border-radius: 50%;
+ background-color: white;
+ top: 2px;
+ left: 2px;
+ transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
+}
+
+#dark-mode-checkbox:checked + .slider {
+ background-color: var(--primary-color);
+}
+
+#dark-mode-checkbox:checked + .slider::before {
+ transform: translateX(24px);
+}
+
+
+/* Dark Mode Styles */
+body.dark-mode {
+ background-color: var(--bg-color-dark);
+ color: var(--text-color-dark);
+ background: linear-gradient(120deg, #2c3e50 0%, #1a2a3a 100%);
+}
+
+.dark-mode #sidebar {
+ background-color: var(--surface-color-dark);
+ border: 1px solid var(--border-color-dark);
+}
+
+.dark-mode #main-content {
+ background-color: rgba(10, 10, 10, 0.5);
+ border: 1px solid var(--border-color-dark);
+}
+
+.dark-mode header, .dark-mode footer {
+ border-color: var(--border-color-dark);
+}
+.dark-mode footer {
+ color: #aaa;
+}
+
+.dark-mode #search {
+ background-color: rgba(0, 0, 0, 0.2);
+ color: var(--text-color-dark);
+ border-color: transparent;
+}
+.dark-mode #search:focus {
+ box-shadow: 0 0 0 2px var(--primary-color-light);
+}
+
+.dark-mode a {
+ color: var(--primary-color-light);
+}
+.dark-mode .legend-key {
+ color: var(--primary-color-light);
+}
+
+/* D3 Graph Styles */
.node {
- cursor: pointer;
+ cursor: pointer;
+ transition: opacity 0.4s ease;
}
.node circle {
- cursor: pointer;
- fill: #fff;
- stroke: steelblue;
- stroke-width: 1.5px;
+ stroke: #333;
+ stroke-width: 1.5px;
+ transition: stroke 0.5s ease, fill 0.3s ease;
}
.node text {
- font-size: 12px;
- fill: rgb(0, 0, 0);
+ font: 12px sans-serif;
+ fill: #1c1c1e;
+ transition: fill 0.5s ease;
}
-path.link {
- fill: none;
- stroke: #ccc;
- stroke-width: 1px;
+.link {
+ fill: none;
+ stroke: #8da4be;
+ stroke-width: 1.5px;
+ transition: stroke 0.5s ease;
+}
+
+.dark-mode .node text {
+ fill: var(--text-color-dark);
+}
+
+.dark-mode .link {
+ stroke: rgba(255, 255, 255, 0.25);
+}
+
+.dark-mode .node circle {
+ stroke: var(--text-color-dark);
+}
+.dark-mode .node circle:hover {
+ fill: var(--primary-color-light);
}
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
index 65126c27..b3246960 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1,40 +1,59 @@
-
-
-
-
-
+
+
+
+
OSINT Framework
-
-
-
-
-
- OSINT Framework
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
(T) - Indicates a link to a tool that must be installed and run locally
- (D) - Google Dork, for more information: Google Hacking
- (R) - Requires registration
- (M) - Indicates a URL that contains the search term and the URL itself must be edited manually
-
-
-
Notes
- OSINT framework focused on gathering information from free tools or resources. The intention is to help people find free OSINT resources. Some of the sites included might require registration or offer more data for $$$, but you should be able to get at least a portion of the available information for no cost.
-
-
I originally created this framework with an information security point of view. Since then, the response from other fields and disciplines has been incredible. I would love to be able to include any other OSINT resources, especially from fields outside of infosec. Please let me know about anything that might be missing!
- Feedback or new tool suggestions are extremely welcome! Please feel free to reach out on Twitter or submit an issue on Github.
-
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/public/js/arf.js b/public/js/arf.js
index ca3b2d5c..50772224 100644
--- a/public/js/arf.js
+++ b/public/js/arf.js
@@ -1,25 +1,56 @@
var margin = [20, 120, 20, 140],
- width = 1280 - margin[1] - margin[3],
- height = 800 - margin[0] - margin[2],
i = 0,
- duration = 1250,
- root;
+ duration = 750,
+ root,
+ allNodes = [];
-var tree = d3.layout.tree()
- .size([height, width]);
+var tree, diagonal, vis;
-var diagonal = d3.svg.diagonal()
- .projection(function(d) { return [d.y, d.x]; });
+function redraw() {
+ d3.select("#body svg").remove();
-var vis = d3.select("#body").append("svg:svg")
- .attr("width", width + margin[1] + margin[3])
- .attr("height", height + margin[0] + margin[2])
- .append("svg:g")
- .attr("transform", "translate(" + margin[3] + "," + margin[0] + ")");
+ var container = d3.select("#body").node();
+ var width = container.clientWidth;
+ var height = container.clientHeight;
+
+ tree = d3.layout.tree();
+
+ diagonal = d3.svg.diagonal()
+ .projection(function(d) { return [d.y, d.x]; });
+
+ vis = d3.select("#body").append("svg:svg")
+ .attr("width", width)
+ .attr("height", height)
+ .append("svg:g")
+ .attr("transform", "translate(" + margin[3] + "," + margin[0] + ")");
+
+ update(root);
+}
d3.json("arf.json", function(json) {
root = json;
- root.x0 = height / 2;
+
+ // Pre-process data: assign parent references and unique IDs
+ var nodeIdCounter = 0;
+ function processData(node, parent) {
+ node.id = ++nodeIdCounter;
+ node.parent = parent;
+ allNodes.push(node);
+ var children = node.children ? node.children : (node._children ? node._children : []);
+ children.forEach(function(child) {
+ processData(child, node);
+ });
+ }
+ processData(root, null);
+
+ // Populate autocompletion datalist
+ var uniqueNodeNames = [...new Set(allNodes.map(function(n) { return n.name; }))];
+ var datalist = d3.select("#search-suggestions");
+ uniqueNodeNames.forEach(function(name) {
+ datalist.append("option").attr("value", name);
+ });
+
+ root.x0 = 800 / 2; // Initial position, will be updated
root.y0 = 0;
function collapse(d) {
@@ -37,17 +68,22 @@ d3.json("arf.json", function(json) {
}
} */
root.children.forEach(collapse);
- update(root);
+ redraw();
+ d3.select(window).on("resize", redraw);
});
function update(source) {
- // var duration = d3.event && d3.event.altKey ? 5000 : 500;
+ var container = d3.select("#body").node();
+ var width = container.clientWidth;
+ var height = container.clientHeight;
+
+ tree.size([height - margin[0] - margin[2], width - margin[3] - margin[1]]);
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse();
// Normalize for fixed-depth.
- nodes.forEach(function(d) { d.y = d.depth * 180; });
+ nodes.forEach(function(d) { d.y = d.depth * 240; }); // Increased depth spacing
// Update the nodesβ¦
var node = vis.selectAll("g.node")
@@ -149,8 +185,68 @@ function toggle(d) {
d._children = null;
}
}
-//Togle Dark Mode
+
+// Toggle Dark Mode
function goDark() {
var element = document.body;
- element.classList.toggle("dark-Mode");
-}
\ No newline at end of file
+ element.classList.toggle("dark-mode");
+}
+
+function search(searchTerm) {
+ var lowerCaseSearchTerm = searchTerm.toLowerCase();
+
+ // Find all matching nodes
+ var matchedNodes = allNodes.filter(function(d) {
+ return d.name.toLowerCase().includes(lowerCaseSearchTerm) ||
+ (d.description && d.description.toLowerCase().includes(lowerCaseSearchTerm));
+ });
+
+ // Expand the parents of matched nodes
+ var nodesToExpand = new Set();
+ matchedNodes.forEach(function(d) {
+ var current = d.parent;
+ while(current) {
+ nodesToExpand.add(current);
+ current = current.parent;
+ }
+ });
+
+ nodesToExpand.forEach(function(d) {
+ if (d._children) {
+ toggle(d);
+ }
+ });
+
+ update(root); // Redraw the tree with expanded nodes
+
+ // Highlight the matched nodes and their ancestors
+ var nodesToHighlight = new Set(matchedNodes);
+ matchedNodes.forEach(function(d){
+ var current = d;
+ while(current){
+ nodesToHighlight.add(current);
+ current = current.parent;
+ }
+ });
+
+ vis.selectAll("g.node")
+ .style("opacity", d => nodesToHighlight.has(d) ? "1" : "0.2");
+}
+
+function clearSearch() {
+ vis.selectAll("g.node").style("opacity", "1");
+ // Collapse all nodes except root's immediate children
+ if(root.children) {
+ root.children.forEach(collapse);
+ }
+ update(root);
+}
+
+d3.select("#search").on("input", function() {
+ var searchTerm = this.value;
+ if (searchTerm.length > 2) {
+ search(searchTerm);
+ } else {
+ clearSearch();
+ }
+});
\ No newline at end of file
From 950fa8b5168e9e649584972d0d6f3941ade40cb5 Mon Sep 17 00:00:00 2001
From: 1999AZZAR <1999azzar@gmail.com>
Date: Sun, 29 Jun 2025 02:40:03 +0700
Subject: [PATCH 2/4] Enhance README with a comprehensive overview, modern UI
features, and updated installation instructions; improve project structure
and contributing guidelines.
---
README.md | 104 ++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 89 insertions(+), 15 deletions(-)
diff --git a/README.md b/README.md
index ed080e3b..868f1a36 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,100 @@
-# OSINT Framework
+# OSINT Framework β¨
-This is a web-based framework for Open Source Intelligence (OSINT). It provides a graph-based visualization of various OSINT resources and tools.
+The OSINT Framework is a dynamic, web-based interface for a vast collection of Open Source Intelligence (OSINT) tools and resources. Originally created for the information security community, it has since grown to become an essential resource for a wide array of fields. This framework presents OSINT resources in an interactive, mind-map-style graph, making it easy to navigate and discover tools for your specific needs.
-## Features
+This version features a completely redesigned user interface with a modern, professional aesthetic, including glassmorphism effects, a responsive layout, and a user-friendly dark mode.
-- **Interactive Graph:** Visualizes OSINT tools and resources as a tree graph.
-- **Search:** Filter nodes by name or description.
-- **Dark Mode:** A comfortable viewing mode for low-light environments.
-- **Categorized Resources:** Resources are grouped into logical categories.
+## π Features
-## Getting Started
+- **Interactive & Responsive Graph:** A fully responsive D3.js-powered tree graph that visualizes the entire OSINT landscape.
+- **Modern UI:** A beautiful and intuitive interface built with a glassmorphism design, featuring a light and dark mode.
+- **Powerful Search:** Instantly find any tool or resource with a powerful search that features autocompletion.
+- **Dynamic Highlighting:** The search function expands the tree to reveal matches and highlights all relevant nodes and their parent branches for easy identification.
+- **Categorized & Easy to Navigate:** Resources are logically grouped, and the graph interface makes discovering new tools intuitive and efficient.
+- **Client-Side:** The entire application runs directly in your browser. No server-side processing is required.
-1. Clone the repository:
+## π οΈ Tech Stack
+
+- **HTML5 & CSS3:** For the core structure and modern styling.
+- **JavaScript (ES6+):** For all client-side logic and interactivity.
+- **D3.js (v3):** For rendering the powerful and interactive data visualization.
+- **Font Awesome:** For modern, scalable icons.
+- **live-server:** A simple development server with live reload functionality.
+
+## π¦ Getting Started
+
+### Prerequisites
+
+You need to have [Node.js](https://nodejs.org/) and npm (which comes with Node.js) installed on your system.
+
+### Installation & Launch
+
+1. **Clone the repository:**
```bash
git clone https://github.com/lockfale/osint-framework.git
+ cd osint-framework
```
-2. Navigate to the `public` directory.
-3. Open `index.html` in your web browser.
+
+2. **Install `live-server` (if you don't have it):**
+ ```bash
+ npm install -g live-server
+ ```
+
+3. **Launch the application:**
+ Navigate to the project's root directory and run the following command to start the server:
+ ```bash
+ live-server --port=8080 public/
+ ```
+
+4. Open your web browser and navigate to `http://127.0.0.1:8080`.
+
+## π Project Structure
+
+```
+OSINT-Framework/
+βββ public/
+β βββ css/
+β β βββ arf.css # Main stylesheet with glassmorphism UI
+β β
+β βββ js/
+β β βββ arf.js # Core JavaScript for D3 graph and search
+β β βββ d3.v3.min.js # D3.js library
+β βββ arf.json # The dataset for the OSINT graph
+β βββ index.html # Main HTML file
+βββ package.json
+βββ package-lock.json
+βββ README.md
+```
+
+## π€ Contributing
+
+Contributions are what make the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
+
+If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".
+
+### Adding a New OSINT Resource
+
+1. **Fork the Project.**
+2. **Update the Data:** Open `public/arf.json` and add your new resource. Please ensure the resource is publicly accessible and free to use. Follow the existing format:
+ ```json
+ {
+ "name": "Example Name",
+ "type": "url",
+ "url": "http://example.com",
+ "description": "A brief description of the resource."
+ }
+ ```
+ *If you are adding to an existing category, remember to add a comma after the preceding entry.*
+3. **Create a Pull Request:** Submit your changes for review.
+
+## π License
+
+This project is licensed under the MIT License. See the `LICENSE` file for details.
+
+## π Acknowledgements
+
+- A big thank you to **Justin Nordine** ([@jnordine](https://twitter.com/jnordine)) for creating and maintaining the original OSINT Framework and its invaluable dataset.
+- All the contributors who have helped expand the framework over the years.
## How to Use
@@ -32,10 +110,6 @@ This is a web-based framework for Open Source Intelligence (OSINT). It provides
- **(R)**: Requires registration.
- **(M)**: Indicates a URL that contains the search term and the URL itself must be edited manually.
-## Contributing
-
-Contributions, feedback, and suggestions are welcome! Please feel free to open an issue or pull request on the [GitHub repository](https://github.com/lockfale/osint-framework).
-
## Notes
OSINT framework focused on gathering information from free tools or resources. The intention is to help people find free OSINT resources. Some of the sites included might require registration or offer more data for $$$, but you should be able to get at least a portion of the available information for no cost.
From b8c170ae341a09fecb55878abd9fde03b23fb76f Mon Sep 17 00:00:00 2001
From: 1999AZZAR <1999azzar@gmail.com>
Date: Sun, 29 Jun 2025 03:21:15 +0700
Subject: [PATCH 3/4] Add responsive design features, loader animation, and
search functionality enhancements; improve sidebar visibility toggle and
clear search option.
---
public/css/arf.css | 98 +++++++++++++++++++++++++++++++++++++++++++++-
public/index.html | 11 +++++-
public/js/arf.js | 82 ++++++++++++++++++++++++++------------
3 files changed, 161 insertions(+), 30 deletions(-)
diff --git a/public/css/arf.css b/public/css/arf.css
index cc5d9ac7..c582c627 100644
--- a/public/css/arf.css
+++ b/public/css/arf.css
@@ -20,6 +20,7 @@ body {
transition: background-color 0.5s ease, color 0.5s ease;
background: linear-gradient(120deg, #d4e0e8 0%, #a7c5eb 100%);
background-size: cover;
+ overflow: auto;
}
a {
@@ -59,7 +60,6 @@ a:hover {
#main-content {
flex-grow: 1;
margin-left: 1rem;
- overflow: hidden; /* Prevent scrollbars on main content */
position: relative;
background-color: rgba(255, 255, 255, 0.4);
backdrop-filter: blur(15px) saturate(180%);
@@ -70,9 +70,33 @@ a:hover {
padding: 0;
}
+#loader {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ z-index: 1;
+ width: 60px;
+ height: 60px;
+ margin: -30px 0 0 -30px;
+ border: 8px solid rgba(0, 0, 0, 0.1);
+ border-radius: 50%;
+ border-top-color: var(--primary-color);
+ animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+ to { transform: rotate(360deg); }
+}
+
+.dark-mode #loader {
+ border-color: rgba(255, 255, 255, 0.1);
+ border-top-color: var(--primary-color-light);
+}
+
#body {
width: 100%;
height: 100%;
+ overflow: auto;
}
header {
@@ -113,6 +137,25 @@ footer {
font-size: 1.1em;
}
+.search-wrapper {
+ position: relative;
+}
+
+#clear-search {
+ position: absolute;
+ right: 15px;
+ top: 50%;
+ transform: translateY(-50%);
+ cursor: pointer;
+ color: #999;
+ opacity: 0;
+ transition: opacity 0.3s ease;
+}
+
+#search:not(:placeholder-shown) + #clear-search {
+ opacity: 1;
+}
+
#search {
width: 100%;
padding: 12px;
@@ -237,7 +280,6 @@ body.dark-mode {
}
.node circle {
- stroke: #333;
stroke-width: 1.5px;
transition: stroke 0.5s ease, fill 0.3s ease;
}
@@ -268,4 +310,56 @@ body.dark-mode {
}
.dark-mode .node circle:hover {
fill: var(--primary-color-light);
+}
+
+/* Responsive Styles */
+#menu-toggle {
+ display: none; /* Hidden by default */
+ position: absolute;
+ top: 20px;
+ left: 20px;
+ z-index: 1000;
+ cursor: pointer;
+ font-size: 1.5rem;
+ color: var(--text-color-light);
+}
+.dark-mode #menu-toggle {
+ color: var(--text-color-dark);
+}
+
+
+@media (max-width: 768px) {
+ #container {
+ flex-direction: column;
+ padding: 0.5rem;
+ }
+
+ #sidebar {
+ position: fixed;
+ left: -320px; /* Hidden by default */
+ top: 0;
+ bottom: 0;
+ height: 100vh;
+ z-index: 1000;
+ width: 300px;
+ margin: 0;
+ border-radius: 0;
+ transition: left 0.3s ease-in-out;
+ }
+
+ #sidebar.visible {
+ left: 0;
+ }
+
+ #main-content {
+ margin-left: 0;
+ width: 100%;
+ }
+
+ #menu-toggle {
+ display: block;
+ }
+ #body {
+ overflow: auto;
+ }
}
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
index b3246960..eddee9c6 100644
--- a/public/index.html
+++ b/public/index.html
@@ -18,7 +18,10 @@