diff --git a/public/arf.json b/public/arf.json index f26d28d..4f930c6 100644 --- a/public/arf.json +++ b/public/arf.json @@ -10,6 +10,26 @@ "name": "Username Search Engines", "type": "folder", "children": [ + { + "name": "WhatsMyName (T)", + "type": "url", + "url": "https://github.com/WebBreacher/WhatsMyName", + "description": "OSINT project maintaining a curated JSON database of website detection patterns for username enumeration. Web interface available at whatsmyname.app.", + "status": "live", + "pricing": "free", + "bestFor": "Username enumeration using community-maintained site detection data", + "input": "Username", + "output": "List of sites where the username exists, based on HTTP response pattern matching", + "opsec": "active", + "opsecNote": "Makes HTTP requests to each target site to check for username existence.", + "localInstall": false, + "googleDork": false, + "registration": false, + "editUrl": false, + "api": false, + "invitationOnly": false, + "deprecated": false + }, { "name": "Sylva Identity Discovery (T)", "type": "url", @@ -70,26 +90,6 @@ "invitationOnly": false, "deprecated": false }, - { - "name": "WhatsMyName (T)", - "type": "url", - "url": "https://github.com/WebBreacher/WhatsMyName", - "description": "OSINT project maintaining a curated JSON database of website detection patterns for username enumeration. Web interface available at whatsmyname.app.", - "status": "live", - "pricing": "free", - "bestFor": "Username enumeration using community-maintained site detection data", - "input": "Username", - "output": "List of sites where the username exists, based on HTTP response pattern matching", - "opsec": "active", - "opsecNote": "Makes HTTP requests to each target site to check for username existence.", - "localInstall": false, - "googleDork": false, - "registration": false, - "editUrl": false, - "api": false, - "invitationOnly": false, - "deprecated": false - }, { "name": "Thats Them", "type": "url", @@ -2696,8 +2696,8 @@ "name": "Fedifinder", "type": "url", "url": "https://fedifinder.glitch.me/", - "description": "Web tool that scans your Twitter/X following list to find accounts that have migrated to the Fediverse by checking bios and pinned tweets for Mastodon handles.", - "status": "live", + "description": "Web tool that scanned Twitter profiles to find Fediverse/Mastodon handles among your contacts and exported them as CSV. The hosted instance now returns HTTP 410 and is no longer functional due to Twitter API restrictions.", + "status": "down", "pricing": "free", "bestFor": "Finding Twitter contacts who moved to Mastodon/Fediverse", "input": "Twitter/X account (via OAuth login)", @@ -2710,7 +2710,7 @@ "editUrl": false, "api": false, "invitationOnly": false, - "deprecated": false + "deprecated": true }, { "name": "Fediverse Observer", @@ -2735,9 +2735,9 @@ { "name": "Fediverse_OSINT (T)", "type": "url", - "url": "https://github.com/anantshri/fediverse_osint", - "description": "Open-source tool for searching and gathering intelligence across multiple Fediverse platforms including Mastodon, Pleroma, and Misskey instances.", - "status": "live", + "url": "https://github.com/cyfinoid/fediverse_osint", + "description": "Python CLI tool for checking whether a domain belongs to the Fediverse and hunting usernames across discoverable Fediverse servers.", + "status": "degraded", "pricing": "free", "bestFor": "Cross-instance Fediverse user and content search", "input": "Username or search terms", @@ -3037,8 +3037,8 @@ "name": "TikTok-OSINT (T)", "type": "url", "url": "https://github.com/Omicron166/TikTok-OSINT", - "description": "Python CLI tool for collecting OSINT data from TikTok profiles including user metadata, video listings, and engagement statistics.", - "status": "live", + "description": "Python CLI tool for collecting OSINT data from TikTok profiles including user metadata, video listings, and engagement statistics. Last updated October 2022.", + "status": "degraded", "pricing": "free", "bestFor": "Automated TikTok profile data collection", "input": "TikTok username or profile URL", @@ -3057,15 +3057,15 @@ "name": "Unfurl", "type": "url", "url": "https://dfir.blog/unfurl/", - "description": "Web-based tool that extracts and visualizes metadata embedded in URLs, including TikTok share links, timestamps, and tracking parameters.", + "description": "Web and CLI tool that extracts and visualizes metadata embedded in URLs, including TikTok share links, timestamps, and tracking parameters. Also installable locally via Python.", "status": "live", "pricing": "free", "bestFor": "URL metadata extraction and timestamp analysis", "input": "Any URL (including TikTok share/video links)", "output": "Visual graph of extracted URL components, timestamps, and embedded identifiers", "opsec": "passive", - "opsecNote": "Parses URL structure locally in browser or on the Unfurl server; does not contact the target platform.", - "localInstall": false, + "opsecNote": "Parses URL structure locally in browser or on the Unfurl server; does not contact the target platform. Local install available for sensitive investigations.", + "localInstall": true, "googleDork": false, "registration": false, "editUrl": false, @@ -3106,6 +3106,92 @@ } ] }, + { + "name": "Threads", + "type": "folder", + "children": [ + { + "name": "Bellingcat Meta Content Library", + "type": "url", + "url": "https://bellingcat.gitbook.io/toolkit/more/all-tools/meta-content-library", + "description": "Bellingcat's guide to Meta's Content Library, a research platform providing near-real-time searchable archive of public Threads, Facebook, and Instagram content.", + "status": "live", + "pricing": "free", + "bestFor": "Large-scale Threads content search for academic and non-profit research", + "input": "Search queries, date ranges, content filters", + "output": "Public posts, engagement metrics, and text-in-image search results from Threads and other Meta platforms", + "opsec": "passive", + "opsecNote": "Searches Meta's research archive; does not interact with target accounts directly. Requires academic/non-profit eligibility approval.", + "localInstall": false, + "googleDork": false, + "registration": true, + "editUrl": false, + "api": true, + "invitationOnly": true, + "deprecated": false + }, + { + "name": "Threads Dashboard", + "type": "url", + "url": "https://www.threadsdashboard.com/", + "description": "Analytics and insights platform for Threads accounts using the official API. Tracks audience demographics, engagement metrics, and historical posting data.", + "status": "live", + "pricing": "freemium", + "bestFor": "Threads account analytics and engagement investigation", + "input": "Threads username or account URL", + "output": "Audience demographics, engagement rates, posting frequency, optimal posting times, and historical data", + "opsec": "passive", + "opsecNote": "Retrieves data via Meta's official Threads API; no direct contact with the target account.", + "localInstall": false, + "googleDork": false, + "registration": true, + "editUrl": false, + "api": true, + "invitationOnly": false, + "deprecated": false + }, + { + "name": "Threads-Scraper (T)", + "type": "url", + "url": "https://github.com/Zeeshanahmad4/Threads-Scraper", + "description": "Python browser automation tool that scrapes public Threads posts and profiles without authentication, outputting structured data in JSON, CSV, or XML. Last updated July 2023.", + "status": "degraded", + "pricing": "free", + "bestFor": "Bulk extraction of Threads posts for offline analysis", + "input": "Threads profile URL or post URL", + "output": "Extracted posts in JSON, CSV, or XML format with metadata", + "opsec": "active", + "opsecNote": "Scrapes Threads directly; depends on site structure and may trigger rate limiting.", + "localInstall": true, + "googleDork": false, + "registration": false, + "editUrl": false, + "api": false, + "invitationOnly": false, + "deprecated": false + }, + { + "name": "ThreadsRecon (T)", + "type": "url", + "url": "https://github.com/offseq/threadsrecon", + "description": "Python OSINT tool for Threads profile analysis including sentiment analysis, network visualization, and automated PDF reporting.", + "status": "live", + "pricing": "free", + "bestFor": "Threads profile investigation with sentiment and network analysis", + "input": "Threads username", + "output": "Profile analysis, sentiment scores, network graphs, and PDF investigation reports", + "opsec": "active", + "opsecNote": "Makes direct requests to Threads to collect profile and post data for analysis.", + "localInstall": true, + "googleDork": false, + "registration": false, + "editUrl": false, + "api": false, + "invitationOnly": false, + "deprecated": false + } + ] + }, { "name": "Steam, Discord & Gaming Networks", "type": "folder", @@ -5420,12 +5506,42 @@ { "name": "Live Journal Seek", "type": "url", - "url": "https://ljseek.com/" + "url": "https://ljseek.com/", + "description": "Search tool for LiveJournal journals and communities across public entries that are indexed.", + "status": "live", + "pricing": "free", + "bestFor": "Finding public LiveJournal entries and historical community discussions", + "input": "Keywords and search terms", + "output": "Matching journal entries with author, date, and snippets", + "opsec": "passive", + "opsecNote": "Searches publicly indexed content and does not contact journal owners directly; queries are likely logged.", + "localInstall": false, + "googleDork": false, + "registration": false, + "editUrl": true, + "api": false, + "invitationOnly": false, + "deprecated": false }, { "name": "Blog Search Engine", "type": "url", - "url": "https://www.blogsearchengine.org/" + "url": "https://www.blogsearchengine.org/", + "description": "Blog-focused search engine for discovering blog posts, directories, and RSS-connected content.", + "status": "live", + "pricing": "free", + "bestFor": "Blog discovery and topic-focused blog post searching", + "input": "Keywords and blog topics", + "output": "Matching blog posts, listings, and feed-linked results", + "opsec": "passive", + "opsecNote": "Aggregates publicly indexed blog data without direct user contact to target blogs; queries are logged.", + "localInstall": false, + "googleDork": false, + "registration": false, + "editUrl": true, + "api": false, + "invitationOnly": false, + "deprecated": false } ] }, @@ -5436,17 +5552,62 @@ { "name": "Discord Bot List", "type": "url", - "url": "https://discord.bots.gg/" + "url": "https://discord.bots.gg/", + "description": "Searchable directory of Discord bots with listings, categories, and discovery metadata.", + "status": "live", + "pricing": "free", + "bestFor": "Discord bot discovery and ecosystem mapping", + "input": "Bot names, keywords, and categories", + "output": "Bot profiles with descriptions, ratings, and invite metadata", + "opsec": "passive", + "opsecNote": "Enumerates publicly listed bots and does not require direct Discord account interaction for browsing.", + "localInstall": false, + "googleDork": false, + "registration": false, + "editUrl": false, + "api": true, + "invitationOnly": false, + "deprecated": false }, { "name": "ReconXplorer (T)", "type": "url", - "url": "https://github.com/root7am/ReconXplorer" + "url": "https://github.com/root7am/ReconXplorer", + "description": "Open-source reconnaissance toolkit with modules for IP, email, and Discord-focused lookups.", + "status": "live", + "pricing": "free", + "bestFor": "Multi-input OSINT checks from a local scriptable toolkit", + "input": "IP addresses, emails, Discord tokens, and host data", + "output": "Recon results including geolocation, service, and account-related metadata", + "opsec": "active", + "opsecNote": "Runs direct external queries from the operator environment and may trigger service-side detection or logging.", + "localInstall": true, + "googleDork": false, + "registration": false, + "editUrl": false, + "api": true, + "invitationOnly": false, + "deprecated": false }, { "name": "Top.gg", "type": "url", - "url": "https://top.gg/" + "url": "https://top.gg/", + "description": "Large Discord bot and app discovery platform with ranking, filtering, and listing data.", + "status": "live", + "pricing": "free", + "bestFor": "Discord bot ranking analysis and app discovery", + "input": "Bot names, tags, and search filters", + "output": "Bot listings with popularity, server counts, and profile details", + "opsec": "passive", + "opsecNote": "Uses public listing data and does not require direct target interaction for standard browsing.", + "localInstall": false, + "googleDork": false, + "registration": false, + "editUrl": false, + "api": true, + "invitationOnly": false, + "deprecated": false } ] }, @@ -5457,27 +5618,102 @@ { "name": "BoardReader", "type": "url", - "url": "https://boardreader.com/" + "url": "https://boardreader.com/", + "description": "Forum search engine that indexes discussions across message boards and community platforms.", + "status": "live", + "pricing": "free", + "bestFor": "Finding forum threads and topic-centric discussion history", + "input": "Keywords, forum names, and topical queries", + "output": "Indexed posts and thread references with source links", + "opsec": "passive", + "opsecNote": "Searches indexed forum content and avoids direct interaction with target forum users.", + "localInstall": false, + "googleDork": true, + "registration": false, + "editUrl": true, + "api": false, + "invitationOnly": false, + "deprecated": false }, { "name": "Omgili", "type": "url", - "url": "https://webz.io/" + "url": "https://webz.io/", + "description": "Forum and discussion search capability operated through Webz.io infrastructure and data products.", + "status": "live", + "pricing": "freemium", + "bestFor": "Forum discussion discovery with optional API-driven workflows", + "input": "Keywords and Boolean-style forum queries", + "output": "Discussion posts and thread-level matching results", + "opsec": "passive", + "opsecNote": "Uses indexed discussion datasets from a third-party provider; user-side browsing is passive.", + "localInstall": false, + "googleDork": true, + "registration": false, + "editUrl": true, + "api": true, + "invitationOnly": false, + "deprecated": false }, { "name": "Craigslist Forums", "type": "url", - "url": "https://forums.craigslist.org/" + "url": "https://forums.craigslist.org/", + "description": "Craigslist-hosted forum system for public community discussions and region-oriented threads.", + "status": "live", + "pricing": "free", + "bestFor": "Reviewing Craigslist community discussions and regional forum activity", + "input": "Forum categories, keywords, and regional navigation", + "output": "Forum threads, post content, and timing context", + "opsec": "passive", + "opsecNote": "Reads publicly visible forum content and does not require direct messaging or contact with users.", + "localInstall": false, + "googleDork": true, + "registration": false, + "editUrl": true, + "api": false, + "invitationOnly": false, + "deprecated": false }, { "name": "Delphi Forum Search", "type": "url", - "url": "https://www.delphiforums.com/" + "url": "https://www.delphiforums.com/", + "description": "Forum platform with searchable user communities across niche interest categories.", + "status": "live", + "pricing": "freemium", + "bestFor": "Niche forum discovery and historical community thread review", + "input": "Forum names, categories, and keywords", + "output": "Forum listings, thread titles, and message pages", + "opsec": "passive", + "opsecNote": "Public forum browsing is passive; some communities may require registration for deeper access.", + "localInstall": false, + "googleDork": false, + "registration": false, + "editUrl": true, + "api": false, + "invitationOnly": false, + "deprecated": false }, { "name": "Google Groups Search", "type": "url", - "url": "https://groups.google.com/forum/#!overview" + "url": "https://groups.google.com/forum/#!overview", + "description": "Search interface for Google Groups and archived discussion content, including historical threads.", + "status": "live", + "pricing": "free", + "bestFor": "Researching archived mailing-list and discussion-group content", + "input": "Keywords, group names, authors, and date ranges", + "output": "Thread messages and group-level discussion results", + "opsec": "passive", + "opsecNote": "Searches archived public discussions through Google-hosted infrastructure where activity is logged.", + "localInstall": false, + "googleDork": true, + "registration": false, + "editUrl": true, + "api": true, + "invitationOnly": false, + "deprecated": false } ] }, @@ -5488,22 +5724,82 @@ { "name": "Mibbit", "type": "url", - "url": "https://search.mibbit.com/" + "url": "https://search.mibbit.com/", + "description": "Former web IRC client and channel search service that is no longer operational.", + "status": "down", + "pricing": "free", + "bestFor": "Legacy reference for historical IRC channel search workflows", + "input": "Channel or keyword queries (historical behavior)", + "output": "No current output; service is discontinued", + "opsec": "Unknown", + "opsecNote": "Service shut down on August 30, 2024 and cannot be relied on for active workflows.", + "localInstall": false, + "googleDork": false, + "registration": false, + "editUrl": false, + "api": false, + "invitationOnly": false, + "deprecated": true }, { "name": "IRCP (T)", "type": "url", - "url": "https://github.com/internet-relay-chat/IRCP" + "url": "https://github.com/internet-relay-chat/IRCP", + "description": "Python-based IRC probing utility for scanning servers and collecting network/channel metadata.", + "status": "live", + "pricing": "free", + "bestFor": "IRC server enumeration and protocol-level reconnaissance", + "input": "Target ranges, IRC ports, and server parameters", + "output": "Server and channel metadata in machine-readable output", + "opsec": "active", + "opsecNote": "Actively connects to IRC services and may be detectable by network monitoring and server logs.", + "localInstall": true, + "googleDork": false, + "registration": false, + "editUrl": false, + "api": false, + "invitationOnly": false, + "deprecated": false }, { "name": "ircsnapshot (T)", "type": "url", - "url": "https://github.com/bwall/ircsnapshot" + "url": "https://github.com/bwall/ircsnapshot", + "description": "IRC data collection tool that connects bots to servers for user and channel mapping.", + "status": "live", + "pricing": "free", + "bestFor": "IRC topology mapping and user/channel relationship analysis", + "input": "IRC server details, bot config, and channel targets", + "output": "Collected user, hostmask, and channel affiliation data", + "opsec": "active", + "opsecNote": "Requires active network participation via bot accounts and is likely visible to channel operators.", + "localInstall": true, + "googleDork": false, + "registration": false, + "editUrl": false, + "api": false, + "invitationOnly": false, + "deprecated": false }, { "name": "netsplit.de", "type": "url", - "url": "https://netsplit.de/channels/search.php" + "url": "https://netsplit.de/channels/search.php", + "description": "IRC directory and search portal for channel listings, network stats, and discovery workflows.", + "status": "live", + "pricing": "free", + "bestFor": "Passive IRC channel discovery and network trend checks", + "input": "Channel names, keywords, and network filters", + "output": "Channel listings with network and user-count context", + "opsec": "passive", + "opsecNote": "Uses aggregated indexed IRC data and does not require direct IRC server interaction for searches.", + "localInstall": false, + "googleDork": true, + "registration": false, + "editUrl": true, + "api": false, + "invitationOnly": false, + "deprecated": false } ] }, @@ -5514,17 +5810,62 @@ { "name": "Arctic Shift", "type": "url", - "url": "https://arctic-shift.photon-reddit.com/" + "url": "https://arctic-shift.photon-reddit.com/", + "description": "Search and access layer for Reddit datasets with tools for historical content retrieval and analysis.", + "status": "live", + "pricing": "freemium", + "bestFor": "Historical Reddit dataset analysis and subreddit research", + "input": "Search terms, dataset queries, or API-style requests", + "output": "Matching Reddit posts, comments, and metadata from indexed datasets", + "opsec": "passive", + "opsecNote": "Works against archived or indexed data sources without requiring direct engagement with target accounts.", + "localInstall": false, + "googleDork": false, + "registration": false, + "editUrl": false, + "api": true, + "invitationOnly": false, + "deprecated": false }, { "name": "Cama's Reddit Search", "type": "url", - "url": "https://camas.github.io/reddit-search/" + "url": "https://camas.github.io/reddit-search/", + "description": "Web tool for searching Reddit posts and comments by author, subreddit, text, and time filters.", + "status": "live", + "pricing": "free", + "bestFor": "Reddit user and subreddit content discovery", + "input": "Usernames, subreddits, keywords, and date constraints", + "output": "Filtered post/comment search results with metadata", + "opsec": "passive", + "opsecNote": "Uses public data indexing paths; original GitHub hosting was discontinued but alternative hosting remains available.", + "localInstall": false, + "googleDork": false, + "registration": false, + "editUrl": false, + "api": false, + "invitationOnly": false, + "deprecated": false }, { "name": "Reveddit", "type": "url", - "url": "https://www.reveddit.com/" + "url": "https://www.reveddit.com/", + "description": "Interface for viewing Reddit content removals using archived and moderation-related visibility signals.", + "status": "live", + "pricing": "free", + "bestFor": "Investigating deleted or removed Reddit discussions", + "input": "Reddit URLs, usernames, or subreddit paths", + "output": "Recovered or flagged removed-content views with moderation indicators", + "opsec": "passive", + "opsecNote": "Queries archive-backed sources and public content pathways without direct contact to target users.", + "localInstall": false, + "googleDork": false, + "registration": false, + "editUrl": true, + "api": false, + "invitationOnly": false, + "deprecated": false } ] } diff --git a/public/css/arf.css b/public/css/arf.css index 18153d4..2c52415 100644 --- a/public/css/arf.css +++ b/public/css/arf.css @@ -70,6 +70,8 @@ body { color: var(--color-text-primary); font-size: var(--font-size-base); font-family: var(--font-family); + margin: 0; + overflow: hidden; } noscript p { @@ -94,7 +96,8 @@ noscript p { svg { display: block; width: 100%; - height: auto; + /* Fill remaining viewport height below header + search bar */ + height: calc(100vh - 120px); cursor: grab; } @@ -103,20 +106,50 @@ svg:active { } #header { + display: flex; + align-items: center; + justify-content: center; + position: relative; font-size: var(--font-size-xl); font-weight: bold; - top: 20px; text-align: center; color: var(--color-header); + padding: var(--space-2) var(--space-4); +} + +#header-actions { + position: absolute; + right: var(--space-4); + top: 50%; + transform: translateY(-50%); + display: flex; + gap: var(--space-2); + align-items: center; +} + +#header-actions button { + background: none; + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + color: var(--color-text-secondary); + font-size: var(--font-size-sm); + font-family: var(--font-family); + padding: var(--space-1) var(--space-2); + cursor: pointer; + white-space: nowrap; +} + +#header-actions button:hover { + color: var(--color-text-primary); + border-color: var(--color-text-secondary); } .legend { - position: absolute; - top: 0px; - right: 0; - width: 330px; - font-size: var(--font-size-sm); - color: var(--color-legend); + display: none; +} + +#notes-content { + display: none; } .legend a { @@ -260,18 +293,158 @@ a { text-align: center; } +/* Mobile floating notes button (hidden on desktop; header button used instead) */ +#mobile-notes-btn { + display: none; +} + +/* Notes overlay */ +#notes-overlay { + display: none; + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 299; +} + +#notes-overlay.visible { + display: block; +} + +/* Notes panel (desktop: side panel) */ +#notes-panel { + display: flex; + flex-direction: column; + position: fixed; + top: 0; + right: 0; + width: 400px; + max-width: 100vw; + height: 100vh; + background: var(--color-surface); + z-index: 300; + transform: translateX(100%); + transition: transform 250ms ease; + will-change: transform; + box-shadow: var(--shadow-md); +} + +#notes-panel.open { + transform: translateX(0); +} + +#notes-panel-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--space-4); + border-bottom: 1px solid var(--color-border); + flex-shrink: 0; +} + +#notes-panel-title { + font-size: var(--font-size-lg); + font-weight: bold; + color: var(--color-text-primary); +} + +#notes-panel-close { + background: none; + border: none; + color: var(--color-text-secondary); + font-size: 20px; + line-height: 1; + cursor: pointer; + padding: 2px var(--space-1); + border-radius: var(--radius-sm); +} + +#notes-panel-close:hover { + color: var(--color-text-primary); + background: var(--color-bg); +} + +#notes-panel-body { + flex: 1; + padding: var(--space-4); + overflow-y: auto; + font-size: var(--font-size-base); + color: var(--color-text-primary); + line-height: 1.6; +} + +#notes-panel-body a { + color: var(--color-node-stroke); +} + +#notes-panel-body h3 { + margin-top: var(--space-4); + margin-bottom: var(--space-2); +} + +#notes-panel-body h3:first-child { + margin-top: 0; +} + /* === Mobile responsive === */ @media (max-width: 768px) { #header { font-size: var(--font-size-lg); - top: 10px; + top: 0; + position: relative; + padding: var(--space-2) var(--space-3); } - .legend { - position: relative; - width: auto; - max-width: 100%; - padding: var(--space-2) var(--space-3); - box-sizing: border-box; + #header-actions { + right: var(--space-3); + } + + /* Hide desktop notes button on mobile (floating button used instead) */ + #header-notes-btn { + display: none; + } + + #search-container { + padding: var(--space-1) 0; + } + + #search-input { + padding: var(--space-1) var(--space-2); + font-size: 13px; + } + + /* Maximize SVG tree viewport */ + svg { + height: calc(100vh - 80px); + } + + /* Floating notes button (mobile only) */ + #mobile-notes-btn { + display: block; + position: fixed; + bottom: var(--space-4); + left: 50%; + transform: translateX(-50%); + background: var(--color-surface); + color: var(--color-text-primary); + border: 1px solid var(--color-border); + border-radius: 20px; + padding: var(--space-2) var(--space-5); + font-size: var(--font-size-base); + font-family: var(--font-family); + font-weight: bold; + cursor: pointer; + box-shadow: var(--shadow-md); + z-index: 100; + } + + #mobile-notes-btn:hover { + background: var(--color-bg); + } + + /* Full-width notes panel on mobile */ + #notes-panel { + width: 100vw; + box-shadow: none; } } diff --git a/public/css/panel.css b/public/css/panel.css index 7128b1c..f623f76 100644 --- a/public/css/panel.css +++ b/public/css/panel.css @@ -11,6 +11,7 @@ #panel-overlay.visible { display: block; + pointer-events: none; } /* Panel container */ @@ -20,6 +21,7 @@ right: 0; width: 340px; height: 100vh; + height: 100dvh; background: var(--color-surface); border-left: 1px solid var(--color-border); box-shadow: var(--shadow-md); @@ -187,50 +189,122 @@ gap: var(--space-2); } -/* Community rating / vote */ +/* Community rating */ #panel-rating-section { display: flex; flex-direction: column; gap: var(--space-2); } -#panel-vote-row { +#panel-rating-row { display: flex; align-items: center; gap: var(--space-3); } -.vote-btn { +#star-rating { + display: flex; + align-items: center; + gap: 2px; +} + +.star-zero-btn { background: none; - border: 1px solid var(--color-border); - border-radius: var(--radius-sm); - padding: var(--space-1) var(--space-2); - font-size: 18px; + border: 1px solid var(--color-text-secondary); + border-radius: 50%; + width: 20px; + height: 20px; + font-size: 11px; + font-weight: 600; cursor: pointer; + color: var(--color-text-secondary); line-height: 1; - transition: background 150ms ease, border-color 150ms ease; + display: flex; + align-items: center; + justify-content: center; + margin-right: 2px; + transition: color 100ms ease, border-color 100ms ease, transform 100ms ease; } -.vote-btn:hover { - background: var(--color-bg); - border-color: var(--color-text-secondary); +.star-zero-btn:hover { + transform: scale(1.15); + color: #e8960f; + border-color: #e8960f; } -.vote-btn.active { - background: var(--color-accent); - border-color: var(--color-accent); +.star-zero-btn.active { + color: #e8960f; + border-color: #e8960f; + background: rgba(232, 150, 15, 0.1); } -.vote-score { - font-size: var(--font-size-lg); - font-weight: bold; - min-width: 2ch; - text-align: center; +.star-pos { + position: relative; + display: inline-block; + cursor: pointer; } -.vote-score.positive { color: #2d9e2d; } -.vote-score.negative { color: #c84040; } -.vote-score.zero { color: var(--color-text-secondary); } +.star-icon { + font-size: 22px; + line-height: 1; + color: var(--color-text-secondary); + pointer-events: none; + transition: color 100ms ease, transform 100ms ease; +} + +.star-pos:hover .star-icon { + transform: scale(1.15); +} + +.star-icon.filled { + color: #f5a623; +} + +.star-icon.half-filled { + background: linear-gradient(to right, #f5a623 50%, var(--color-text-secondary) 50%); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; +} + +.star-icon.user-rated { + color: #e8960f; +} + +.star-icon.user-rated.half-filled { + background: linear-gradient(to right, #e8960f 50%, var(--color-text-secondary) 50%); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; +} + +.star-click { + position: absolute; + top: 0; + height: 100%; + background: none; + border: none; + cursor: pointer; + opacity: 0; + padding: 0; + margin: 0; +} + +.star-click.star-left { + left: 0; + width: 50%; +} + +.star-click.star-right { + left: 50%; + width: 50%; +} + +#rating-avg { + font-size: var(--font-size-sm); + color: var(--color-text-secondary); + white-space: nowrap; +} /* Footer (sticky, always visible) */ #panel-footer { @@ -335,7 +409,14 @@ .badge-active { background: #c84040; } /* Unknown / fallback */ -.badge-unknown { background: #606060; } +.badge-unknown { background: #606060; } + +/* Boolean feature badges */ +.badge-api { background: #1e90cc; } +.badge-invitation-only { background: #b87800; } +.badge-deprecated { background: #8b3030; } +.badge-nsfw { background: #9b2b9b; } +.badge-region { background: #2e7d32; } /* OPSEC row layout */ .opsec-row { @@ -378,9 +459,14 @@ #tool-panel { width: 100vw; height: 100vh; + height: 100dvh; top: 0; right: 0; border-left: none; border-radius: 0; } + + #panel-overlay.visible { + pointer-events: auto; + } } diff --git a/public/index.html b/public/index.html index 236bab2..c566702 100644 --- a/public/index.html +++ b/public/index.html @@ -26,8 +26,11 @@
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!
+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!
-