WIP: redo the web UI #6
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
server/node_modules
|
||||||
|
client/node_modules
|
17
README.md
17
README.md
@ -65,15 +65,15 @@ Amnezichat offers a highly secure and privacy-focused messaging experience by en
|
|||||||
sudo apt install docker.io git
|
sudo apt install docker.io git
|
||||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||||
cd Amnezichat/server/
|
cd Amnezichat/server/
|
||||||
sudo docker build -t amnezichatserver:latest .
|
docker build --network=host -t amnezichatserver:latest .
|
||||||
sudo docker run -p 8080:8080 amnezichatserver:latest
|
docker run --network=host amnezichatserver:latest
|
||||||
|
|
||||||
## Client setup:
|
## Client setup:
|
||||||
|
|
||||||
**For Web UI connect to http://localhost:8000**
|
**For Web UI connect to http://localhost:8000**
|
||||||
|
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install curl build-essential git tor
|
sudo apt install curl build-essential git tor xterm
|
||||||
sudo systemctl enable --now tor.service
|
sudo systemctl enable --now tor.service
|
||||||
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||||
@ -87,8 +87,15 @@ Amnezichat offers a highly secure and privacy-focused messaging experience by en
|
|||||||
sudo apt install docker.io git
|
sudo apt install docker.io git
|
||||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||||
cd Amnezichat/client/
|
cd Amnezichat/client/
|
||||||
sudo docker build -t amnezichat:latest .
|
docker build --network=host -t amnezichat .
|
||||||
sudo docker run -p 8000:8000 amnezichat:latest
|
xhost +local:docker
|
||||||
|
docker run --rm \
|
||||||
|
--network=host \
|
||||||
|
-e DISPLAY=$DISPLAY \
|
||||||
|
-v /tmp/.X11-unix:/tmp/.X11-unix \
|
||||||
|
--env QT_X11_NO_MITSHM=1 \
|
||||||
|
amnezichat:latest
|
||||||
|
|
||||||
|
|
||||||
## Requirements:
|
## Requirements:
|
||||||
|
|
||||||
|
16
README_TR.md
16
README_TR.md
@ -65,15 +65,15 @@ Amnezichat, hiçbir kayıt tutulmamasını ve tüm mesaj verilerinin yalnızca s
|
|||||||
sudo apt install docker.io git
|
sudo apt install docker.io git
|
||||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||||
cd Amnezichat/server/
|
cd Amnezichat/server/
|
||||||
sudo docker build -t amnezichatserver:latest .
|
docker build --network=host -t amnezichatserver:latest .
|
||||||
sudo docker run -p 8080:8080 amnezichatserver:latest
|
docker run --network=host amnezichatserver:latest
|
||||||
|
|
||||||
## İstemci kurulumu:
|
## İstemci kurulumu:
|
||||||
|
|
||||||
**Web UI için http://localhost:8000 adresine bağlanın**
|
**Web UI için http://localhost:8000 adresine bağlanın**
|
||||||
|
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install curl build-essential git tor
|
sudo apt install curl build-essential git tor xterm
|
||||||
sudo systemctl enable --now tor.service
|
sudo systemctl enable --now tor.service
|
||||||
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||||
@ -87,8 +87,14 @@ Amnezichat, hiçbir kayıt tutulmamasını ve tüm mesaj verilerinin yalnızca s
|
|||||||
sudo apt install docker.io git
|
sudo apt install docker.io git
|
||||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||||
cd Amnezichat/client/
|
cd Amnezichat/client/
|
||||||
sudo docker build -t amnezichat:latest .
|
docker build --network=host -t amnezichat .
|
||||||
sudo docker run -p 8000:8000 amnezichat:latest
|
xhost +local:docker
|
||||||
|
docker run --rm \
|
||||||
|
--network=host \
|
||||||
|
-e DISPLAY=$DISPLAY \
|
||||||
|
-v /tmp/.X11-unix:/tmp/.X11-unix \
|
||||||
|
--env QT_X11_NO_MITSHM=1 \
|
||||||
|
amnezichat:latest
|
||||||
|
|
||||||
## Gereksinimler:
|
## Gereksinimler:
|
||||||
|
|
||||||
|
@ -25,3 +25,4 @@ rocket = { version = "0.5", features = ["json"] }
|
|||||||
eframe = "0.26"
|
eframe = "0.26"
|
||||||
egui = "0.26"
|
egui = "0.26"
|
||||||
rfd = "0.12"
|
rfd = "0.12"
|
||||||
|
which = "4.4"
|
@ -9,10 +9,21 @@ RUN apt-get update && \
|
|||||||
apt-get install -y \
|
apt-get install -y \
|
||||||
curl \
|
curl \
|
||||||
build-essential \
|
build-essential \
|
||||||
|
clang \
|
||||||
|
cmake \
|
||||||
|
libclang-dev \
|
||||||
|
llvm-dev \
|
||||||
|
net-tools \
|
||||||
|
libxkbcommon-x11-0 \
|
||||||
git \
|
git \
|
||||||
tor && \
|
tor \
|
||||||
apt-get clean && \
|
xterm \
|
||||||
rm -rf /var/lib/apt/lists/*
|
pkg-config \
|
||||||
|
iputils-ping \
|
||||||
|
libglib2.0-dev \
|
||||||
|
libssl-dev \
|
||||||
|
libgtk-3-dev \
|
||||||
|
dnsutils
|
||||||
|
|
||||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
|
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||||
|
|
||||||
@ -23,4 +34,10 @@ RUN cargo build --release
|
|||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
CMD tor & cargo run --release
|
CMD bash -c "\
|
||||||
|
if pgrep -x tor > /dev/null; then \
|
||||||
|
echo 'Killing existing Tor process...'; \
|
||||||
|
pkill -x tor; \
|
||||||
|
sleep 1; \
|
||||||
|
fi; \
|
||||||
|
cargo run --release"
|
@ -51,6 +51,7 @@ use std::{
|
|||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
error::Error,
|
error::Error,
|
||||||
};
|
};
|
||||||
|
use std::fs;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use chacha20poly1305::aead::OsRng;
|
use chacha20poly1305::aead::OsRng;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
@ -61,6 +62,9 @@ use rfd::MessageDialog;
|
|||||||
use rfd::MessageButtons;
|
use rfd::MessageButtons;
|
||||||
use rfd::MessageLevel;
|
use rfd::MessageLevel;
|
||||||
use rfd::MessageDialogResult;
|
use rfd::MessageDialogResult;
|
||||||
|
use std::process::Stdio;
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
use which::which;
|
||||||
|
|
||||||
fn get_raw_bytes_public_key(pk: &PublicKey) -> &[u8] {
|
fn get_raw_bytes_public_key(pk: &PublicKey) -> &[u8] {
|
||||||
pk.as_ref()
|
pk.as_ref()
|
||||||
@ -250,11 +254,8 @@ impl Default for AppState {
|
|||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let mut options = eframe::NativeOptions::default();
|
let mut options = eframe::NativeOptions::default();
|
||||||
|
|
||||||
options.viewport.resizable = Some(false);
|
options.viewport.resizable = Some(false);
|
||||||
|
options.viewport.inner_size = Some(egui::vec2(600.0, 1000.0));
|
||||||
options.viewport.inner_size = Some(egui::vec2(600.0, 900.0));
|
|
||||||
|
|
||||||
eframe::run_native("Messaging Setup", options, Box::new(|_cc| Box::new(SetupApp::default())))?;
|
eframe::run_native("Messaging Setup", options, Box::new(|_cc| Box::new(SetupApp::default())))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -284,7 +285,6 @@ impl eframe::App for SetupApp {
|
|||||||
ui.label(egui::RichText::new("Choose an action:").size(24.0));
|
ui.label(egui::RichText::new("Choose an action:").size(24.0));
|
||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
ui.horizontal_wrapped(|ui| {
|
ui.horizontal_wrapped(|ui| {
|
||||||
|
|
||||||
ui.add_space(20.0);
|
ui.add_space(20.0);
|
||||||
if ui.add(
|
if ui.add(
|
||||||
egui::Button::new(egui::RichText::new("➕ Create Room").size(24.0))
|
egui::Button::new(egui::RichText::new("➕ Create Room").size(24.0))
|
||||||
@ -390,11 +390,25 @@ impl eframe::App for SetupApp {
|
|||||||
if let Err(err) = validate_and_start(self.state.clone()) {
|
if let Err(err) = validate_and_start(self.state.clone()) {
|
||||||
self.state.error_message = Some(err.to_string());
|
self.state.error_message = Some(err.to_string());
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
self.state.show_url_label = true;
|
self.state.show_url_label = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui.add_space(20.0);
|
||||||
|
|
||||||
|
if ui.add(
|
||||||
|
egui::Button::new(egui::RichText::new("🌐 Host Server").size(24.0))
|
||||||
|
.fill(egui::Color32::from_rgb(30, 30, 150))
|
||||||
|
.min_size(egui::vec2(250.0, 50.0))
|
||||||
|
).clicked() {
|
||||||
|
self.state.error_message = None;
|
||||||
|
std::thread::spawn(|| {
|
||||||
|
if let Err(e) = host_server() {
|
||||||
|
eprintln!("Host server error: {}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(err) = &self.state.error_message {
|
if let Some(err) = &self.state.error_message {
|
||||||
ui.add_space(20.0);
|
ui.add_space(20.0);
|
||||||
ui.colored_label(egui::Color32::RED, egui::RichText::new(format!("❗ {}", err)).size(22.0));
|
ui.colored_label(egui::Color32::RED, egui::RichText::new(format!("❗ {}", err)).size(22.0));
|
||||||
@ -409,6 +423,110 @@ impl eframe::App for SetupApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn host_server() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let pkg_install = if which("apt").is_ok() {
|
||||||
|
"sudo apt update && sudo apt install -y git curl build-essential tor"
|
||||||
|
} else if which("dnf").is_ok() {
|
||||||
|
"sudo dnf install -y git curl gcc cmake make kernel-devel tor"
|
||||||
|
} else if which("pacman").is_ok() {
|
||||||
|
"sudo pacman -Sy --noconfirm git curl base-devel tor"
|
||||||
|
} else {
|
||||||
|
return Err("No supported package manager found".into());
|
||||||
|
};
|
||||||
|
|
||||||
|
Command::new("xterm")
|
||||||
|
.arg("-e")
|
||||||
|
.arg(format!("bash -c '{}'", pkg_install))
|
||||||
|
.spawn()?
|
||||||
|
.wait()?;
|
||||||
|
|
||||||
|
let setup_script = r#"
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Install Rust if not already installed
|
||||||
|
if ! command -v cargo &> /dev/null; then
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||||
|
source $HOME/.cargo/env
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clone the repo if not already cloned
|
||||||
|
if [ ! -d "Amnezichat" ]; then
|
||||||
|
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd Amnezichat
|
||||||
|
|
||||||
|
# Clean everything except 'server'
|
||||||
|
find . -mindepth 1 -maxdepth 1 ! -name 'server' -exec rm -rf {} +
|
||||||
|
|
||||||
|
cd server
|
||||||
|
cargo build --release
|
||||||
|
cargo run --release
|
||||||
|
"#;
|
||||||
|
|
||||||
|
fs::write("start_server.sh", setup_script)?;
|
||||||
|
fs::set_permissions("start_server.sh", fs::Permissions::from_mode(0o755))?;
|
||||||
|
|
||||||
|
Command::new("xterm")
|
||||||
|
.arg("-e")
|
||||||
|
.arg("bash -c './start_server.sh'")
|
||||||
|
.spawn()?
|
||||||
|
.wait()?;
|
||||||
|
|
||||||
|
configure_tor_for_onion_service()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn configure_tor_for_onion_service() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let hidden_dir = "./hidden_service";
|
||||||
|
fs::create_dir_all(hidden_dir)?;
|
||||||
|
fs::set_permissions(hidden_dir, fs::Permissions::from_mode(0o700))?;
|
||||||
|
|
||||||
|
let torrc_path = format!("{}/torrc", hidden_dir);
|
||||||
|
let torrc_content = format!(
|
||||||
|
"HiddenServiceDir {}\nHiddenServicePort 80 127.0.0.1:8080\n",
|
||||||
|
hidden_dir
|
||||||
|
);
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open(&torrc_path)?;
|
||||||
|
file.write_all(torrc_content.as_bytes())?;
|
||||||
|
|
||||||
|
let _ = Command::new("pkill").arg("tor").output();
|
||||||
|
|
||||||
|
let tor_cmd = format!("tor -f {}", torrc_path);
|
||||||
|
Command::new("nohup")
|
||||||
|
.arg("bash")
|
||||||
|
.arg("-c")
|
||||||
|
.arg(&tor_cmd)
|
||||||
|
.stdout(Stdio::null())
|
||||||
|
.stderr(Stdio::null())
|
||||||
|
.spawn()?;
|
||||||
|
|
||||||
|
let hostname_path = format!("{}/hostname", hidden_dir);
|
||||||
|
let start_time = std::time::Instant::now();
|
||||||
|
while !Path::new(&hostname_path).exists() {
|
||||||
|
if start_time.elapsed().as_secs() > 30 {
|
||||||
|
return Err("Timeout waiting for Tor to create the .onion address.".into());
|
||||||
|
}
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
let onion = fs::read_to_string(&hostname_path)?.trim().to_string();
|
||||||
|
println!("Your Amnezichat server is live at: http://{}", onion);
|
||||||
|
|
||||||
|
MessageDialog::new()
|
||||||
|
.set_title("Tor Hidden Service")
|
||||||
|
.set_description(&format!("Your Amnezichat server is live at: http://{}", onion))
|
||||||
|
.show();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn validate_and_start(state: AppState) -> Result<(), Box<dyn Error>> {
|
fn validate_and_start(state: AppState) -> Result<(), Box<dyn Error>> {
|
||||||
if state.server_url.is_empty() || state.username.is_empty() || state.private_password.is_empty() {
|
if state.server_url.is_empty() || state.username.is_empty() || state.private_password.is_empty() {
|
||||||
return Err("Please fill in all fields.".into());
|
return Err("Please fill in all fields.".into());
|
||||||
|
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
Before Width: | Height: | Size: 333 KiB After Width: | Height: | Size: 338 KiB |
@ -1,71 +1,150 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||||
|
/>
|
||||||
<title>Amnezichat</title>
|
<title>Amnezichat</title>
|
||||||
<link rel="stylesheet" href="/static/styles.css">
|
<link rel="stylesheet" href="/static/styles.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div
|
||||||
<h1>Download Amnezichat</h1>
|
class="bg-black h-screen flex flex-col items-center justify-center text-white"
|
||||||
<p>Anti-forensic and secure messaging. Download it now and get started.</p>
|
>
|
||||||
<a href="#download" class="download-button">Download Now</a>
|
<h1
|
||||||
|
class="h-14 bg-linear-65 from-purple-500 to-pink-500 text-6xl font-bold text-transparent bg-clip-text"
|
||||||
<div id="footer">
|
>
|
||||||
|
Amnezichat
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
Anti-forensic and secure messaging. Download it now and get
|
||||||
|
started. Intended for secure chats that
|
||||||
|
<span
|
||||||
|
class="bg-gradient-to-r from-pink-200 to-transparent inline-block text-transparent bg-clip-text"
|
||||||
|
>disappear when you're done.</span
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<br />
|
||||||
|
<a
|
||||||
|
href="#download"
|
||||||
|
class="bg-linear-65 from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-500 text-white font-semibold py-2 px-6 rounded-full transition duration-300 text-2xl m-5"
|
||||||
|
>Download Now</a
|
||||||
|
>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
<!-- Main Links -->
|
<!-- Main Links -->
|
||||||
<div class="main-links">
|
<br />
|
||||||
<a href="https://github.com/umutcamliyurt/Amnezichat" target="_blank">Source Code</a>
|
|
||||||
<a href="http://aqfyl6g24k44oyes3n35nrnlhdfvdwfvi4a7umjalu4dcstuzkxft4id.onion" target="_blank">Onionsite</a>
|
|
||||||
<a href="http://epmrgx35crapamcxlpggowr7vg3fbxosmkow66konjomn4nlphda.b32.i2p" target="_blank">Eepsite</a>
|
|
||||||
<a href="https://github.com/umutcamliyurt/Amnezichat?tab=readme-ov-file#donate-to-support-development-of-this-project">Donate Monero</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Privacy and Terms -->
|
<!-- Privacy and Terms -->
|
||||||
<details id="terms-of-service-section">
|
<details id="terms-of-service-section" class="pt-3">
|
||||||
<summary>Terms of Service</summary>
|
<summary
|
||||||
|
class="bg-gray-950 p-3 rounded-lg cursor-pointer shadow"
|
||||||
|
>
|
||||||
|
Terms of Service
|
||||||
|
</summary>
|
||||||
<p>By using Amnezichat, you agree to the following terms:</p>
|
<p>By using Amnezichat, you agree to the following terms:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Use for lawful purposes only.</li>
|
<li>Use for lawful purposes only.</li>
|
||||||
<li>Do not share illegal content.</li>
|
<li>Do not share illegal content.</li>
|
||||||
<li>Respect others while using the platform.</li>
|
<li>Respect others while using the platform.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Amnezichat reserves the right to modify or discontinue the service without notice.</p>
|
<p>
|
||||||
|
Amnezichat reserves the right to modify or discontinue the
|
||||||
|
service without notice.
|
||||||
|
</p>
|
||||||
|
<small class="text-gray-500">
|
||||||
|
We can't actually enforce these. Please keep them in mind
|
||||||
|
though.
|
||||||
|
</small>
|
||||||
<p>Contact: nemesisuks@protonmail.com</p>
|
<p>Contact: nemesisuks@protonmail.com</p>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details class="pt-3 pb-3">
|
||||||
<summary>Privacy Policy</summary>
|
<summary
|
||||||
|
class="bg-gray-950 p-3 rounded-lg cursor-pointer shadow"
|
||||||
|
>
|
||||||
|
Privacy Policy
|
||||||
|
</summary>
|
||||||
<p>We value your privacy:</p>
|
<p>We value your privacy:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>No personal information or chat logs are stored.</li>
|
<li>No personal information or chat logs are stored.</li>
|
||||||
<li>Messages are encrypted and temporary.</li>
|
<li>
|
||||||
|
Messages are
|
||||||
|
<span class="text-green-400">encrypted</span> and
|
||||||
|
<span class="text-green-400">temporary</span>.
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
|
<br />
|
||||||
|
<!-- Main Links -->
|
||||||
|
<small>
|
||||||
|
<div class="main-links">
|
||||||
|
<a
|
||||||
|
href="https://github.com/umutcamliyurt/Amnezichat"
|
||||||
|
target="_blank"
|
||||||
|
class="text-blue-300 hover:text-blue-400 transition duration-300"
|
||||||
|
>Source Code</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="http://aqfyl6g24k44oyes3n35nrnlhdfvdwfvi4a7umjalu4dcstuzkxft4id.onion"
|
||||||
|
target="_blank"
|
||||||
|
class="text-blue-300 hover:text-blue-400 transition duration-300"
|
||||||
|
>Onionsite</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="http://epmrgx35crapamcxlpggowr7vg3fbxosmkow66konjomn4nlphda.b32.i2p"
|
||||||
|
target="_blank"
|
||||||
|
class="text-blue-300 hover:text-blue-400 transition duration-300"
|
||||||
|
>Eepsite</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="https://github.com/umutcamliyurt/Amnezichat?tab=readme-ov-file#donate-to-support-development-of-this-project"
|
||||||
|
class="text-blue-300 hover:text-blue-400 transition duration-300"
|
||||||
|
>Donate Monero</a
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="download" class="modal">
|
<div
|
||||||
|
id="download"
|
||||||
|
class="bg-gray-900 h-screen flex flex-col items-center justify-center text-white"
|
||||||
|
>
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<a href="#" class="close-button">×</a>
|
<h2
|
||||||
<h2>Installation Instructions</h2>
|
class="bg-linear-65 from-purple-500 to-pink-500 text-2xl font-bold text-transparent bg-clip-text"
|
||||||
|
>
|
||||||
|
Installation Instructions
|
||||||
|
</h2>
|
||||||
|
|
||||||
<h3>Build it Yourself</h3>
|
<h3>Build it Yourself</h3>
|
||||||
<pre>
|
<pre>
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install curl build-essential git tor
|
sudo apt install curl build-essential git tor xterm
|
||||||
sudo systemctl enable --now tor.service
|
sudo systemctl enable --now tor.service
|
||||||
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||||
cd Amnezichat/client/
|
cd Amnezichat/client/
|
||||||
cargo build --release
|
cargo build --release
|
||||||
cargo run --release
|
cargo run --release
|
||||||
</pre>
|
</pre
|
||||||
|
>
|
||||||
|
|
||||||
<h3>Or:</h3>
|
<h3 class="pb-3">Or:</h3>
|
||||||
<a href="/static/Amnezichat-x86_64.AppImage" class="download-button" download>Download AppImage</a>
|
<a
|
||||||
<a href="/static/Amnezichat-x86_64.deb" class="download-button" download>Download .deb Package</a>
|
href="/static/Amnezichat-x86_64.AppImage"
|
||||||
|
class="bg-blue-300 hover:bg-blue-400 text-gray-900 py-2 px-6 rounded-full transition duration-300"
|
||||||
|
download
|
||||||
|
>Download AppImage</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="/static/Amnezichat-x86_64.deb"
|
||||||
|
class="bg-blue-300 hover:bg-blue-400 text-gray-900 py-2 px-6 rounded-full transition duration-300"
|
||||||
|
download
|
||||||
|
>Download .deb Package</a
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
1
server/static/input.css
Normal file
1
server/static/input.css
Normal file
@ -0,0 +1 @@
|
|||||||
|
@import "tailwindcss";
|
@ -1,139 +1,732 @@
|
|||||||
body {
|
/*! tailwindcss v4.1.5 | MIT License | https://tailwindcss.com */
|
||||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
@layer properties;
|
||||||
display: flex;
|
@layer theme, base, components, utilities;
|
||||||
justify-content: center;
|
@layer theme {
|
||||||
align-items: center;
|
:root, :host {
|
||||||
min-height: 100vh;
|
--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-green-400: oklch(79.2% 0.209 151.711);
|
||||||
|
--color-blue-300: oklch(80.9% 0.105 251.813);
|
||||||
|
--color-blue-400: oklch(70.7% 0.165 254.624);
|
||||||
|
--color-blue-500: oklch(62.3% 0.214 259.815);
|
||||||
|
--color-blue-600: oklch(54.6% 0.245 262.881);
|
||||||
|
--color-purple-500: oklch(62.7% 0.265 303.9);
|
||||||
|
--color-pink-200: oklch(89.9% 0.061 343.231);
|
||||||
|
--color-pink-500: oklch(65.6% 0.241 354.308);
|
||||||
|
--color-gray-500: oklch(55.1% 0.027 264.364);
|
||||||
|
--color-gray-900: oklch(21% 0.034 264.665);
|
||||||
|
--color-gray-950: oklch(13% 0.028 261.692);
|
||||||
|
--color-black: #000;
|
||||||
|
--color-white: #fff;
|
||||||
|
--spacing: 0.25rem;
|
||||||
|
--text-2xl: 1.5rem;
|
||||||
|
--text-2xl--line-height: calc(2 / 1.5);
|
||||||
|
--text-6xl: 3.75rem;
|
||||||
|
--text-6xl--line-height: 1;
|
||||||
|
--font-weight-semibold: 600;
|
||||||
|
--font-weight-bold: 700;
|
||||||
|
--radius-lg: 0.5rem;
|
||||||
|
--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;
|
margin: 0;
|
||||||
background: linear-gradient(135deg, #1e3c72, #2a5298);
|
padding: 0;
|
||||||
color: #ecf0f1;
|
border: 0 solid;
|
||||||
text-align: center;
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
:-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 {
|
||||||
.container {
|
.collapse {
|
||||||
padding: 30px;
|
visibility: collapse;
|
||||||
background: rgba(15, 30, 60, 0.95);
|
}
|
||||||
border: 1px solid #0f3b5f;
|
.invisible {
|
||||||
border-radius: 12px;
|
visibility: hidden;
|
||||||
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.6);
|
}
|
||||||
max-width: 600px;
|
.visible {
|
||||||
width: 90%;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
.absolute {
|
||||||
h1 {
|
|
||||||
font-size: 2rem;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
color: #ffffff;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
margin-bottom: 25px;
|
|
||||||
color: #bdc3c7;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.download-button {
|
|
||||||
display: inline-block;
|
|
||||||
text-decoration: none;
|
|
||||||
color: #ffffff;
|
|
||||||
background: linear-gradient(45deg, #2980b9, #1e90ff);
|
|
||||||
padding: 12px 25px;
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
transition: background 0.3s ease, transform 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.download-button:hover {
|
|
||||||
background: linear-gradient(45deg, #1e90ff, #2980b9);
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-links {
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-links a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: #2980b9;
|
|
||||||
margin: 0 8px;
|
|
||||||
font-size: 1rem;
|
|
||||||
transition: color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-links a:hover {
|
|
||||||
color: #1e90ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
details {
|
|
||||||
margin: 10px 0;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
details summary {
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #ecf0f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
details p, details ul {
|
|
||||||
margin: 10px 0;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
color: #bdc3c7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal {
|
|
||||||
display: none;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1000;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: rgba(0, 0, 0, 0.85);
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal:target {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-content {
|
|
||||||
background: #0f1e3c;
|
|
||||||
padding: 20px;
|
|
||||||
border: 1px solid #0a2b4f;
|
|
||||||
border-radius: 12px;
|
|
||||||
width: 90%;
|
|
||||||
max-width: 600px;
|
|
||||||
color: #ecf0f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-content pre {
|
|
||||||
background: #0a2b4f;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 8px;
|
|
||||||
color: #ecf0f1;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-button {
|
|
||||||
color: #e74c3c;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 15px;
|
}
|
||||||
right: 15px;
|
.fixed {
|
||||||
font-weight: bold;
|
position: fixed;
|
||||||
|
}
|
||||||
|
.relative {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.relative\! {
|
||||||
|
position: relative !important;
|
||||||
|
}
|
||||||
|
.static {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.m-5 {
|
||||||
|
margin: calc(var(--spacing) * 5);
|
||||||
|
}
|
||||||
|
.block {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.contents {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.inline {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.inline-block {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
.h-4 {
|
||||||
|
height: calc(var(--spacing) * 4);
|
||||||
|
}
|
||||||
|
.h-14 {
|
||||||
|
height: calc(var(--spacing) * 14);
|
||||||
|
}
|
||||||
|
.h-screen {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
.shrink {
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
.grow {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
.transform {
|
||||||
|
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
|
||||||
|
}
|
||||||
|
.cursor-pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.resize {
|
||||||
|
resize: both;
|
||||||
|
}
|
||||||
|
.flex-col {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.justify-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.truncate {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.rounded {
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
.rounded-full {
|
||||||
|
border-radius: calc(infinity * 1px);
|
||||||
|
}
|
||||||
|
.rounded-lg {
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
}
|
||||||
|
.bg-black {
|
||||||
|
background-color: var(--color-black);
|
||||||
|
}
|
||||||
|
.bg-blue-300 {
|
||||||
|
background-color: var(--color-blue-300);
|
||||||
|
}
|
||||||
|
.bg-gray-900 {
|
||||||
|
background-color: var(--color-gray-900);
|
||||||
|
}
|
||||||
|
.bg-gray-950 {
|
||||||
|
background-color: var(--color-gray-950);
|
||||||
|
}
|
||||||
|
.bg-linear-65 {
|
||||||
|
--tw-gradient-position: 65deg;
|
||||||
|
@supports (background-image: linear-gradient(in lab, red, red)) {
|
||||||
|
--tw-gradient-position: 65deg in oklab;
|
||||||
|
}
|
||||||
|
background-image: linear-gradient(var(--tw-gradient-stops));
|
||||||
|
}
|
||||||
|
.bg-gradient-to-r {
|
||||||
|
--tw-gradient-position: to right in oklab;
|
||||||
|
background-image: linear-gradient(var(--tw-gradient-stops));
|
||||||
|
}
|
||||||
|
.from-blue-500 {
|
||||||
|
--tw-gradient-from: var(--color-blue-500);
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
.from-pink-200 {
|
||||||
|
--tw-gradient-from: var(--color-pink-200);
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
.from-purple-500 {
|
||||||
|
--tw-gradient-from: var(--color-purple-500);
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
.to-blue-600 {
|
||||||
|
--tw-gradient-to: var(--color-blue-600);
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
.to-pink-500 {
|
||||||
|
--tw-gradient-to: var(--color-pink-500);
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
.to-transparent {
|
||||||
|
--tw-gradient-to: transparent;
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
.bg-clip-text {
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
.p-0 {
|
||||||
|
padding: calc(var(--spacing) * 0);
|
||||||
|
}
|
||||||
|
.p-3 {
|
||||||
|
padding: calc(var(--spacing) * 3);
|
||||||
|
}
|
||||||
|
.p-6 {
|
||||||
|
padding: calc(var(--spacing) * 6);
|
||||||
|
}
|
||||||
|
.p-9 {
|
||||||
|
padding: calc(var(--spacing) * 9);
|
||||||
|
}
|
||||||
|
.px-6 {
|
||||||
|
padding-inline: calc(var(--spacing) * 6);
|
||||||
|
}
|
||||||
|
.py-2 {
|
||||||
|
padding-block: calc(var(--spacing) * 2);
|
||||||
|
}
|
||||||
|
.pt-3 {
|
||||||
|
padding-top: calc(var(--spacing) * 3);
|
||||||
|
}
|
||||||
|
.pb-3 {
|
||||||
|
padding-bottom: calc(var(--spacing) * 3);
|
||||||
|
}
|
||||||
|
.text-2xl {
|
||||||
|
font-size: var(--text-2xl);
|
||||||
|
line-height: var(--tw-leading, var(--text-2xl--line-height));
|
||||||
|
}
|
||||||
|
.text-6xl {
|
||||||
|
font-size: var(--text-6xl);
|
||||||
|
line-height: var(--tw-leading, var(--text-6xl--line-height));
|
||||||
|
}
|
||||||
|
.font-bold {
|
||||||
|
--tw-font-weight: var(--font-weight-bold);
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
}
|
||||||
|
.font-semibold {
|
||||||
|
--tw-font-weight: var(--font-weight-semibold);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
}
|
||||||
|
.text-blue-300 {
|
||||||
|
color: var(--color-blue-300);
|
||||||
|
}
|
||||||
|
.text-gray-500 {
|
||||||
|
color: var(--color-gray-500);
|
||||||
|
}
|
||||||
|
.text-gray-900 {
|
||||||
|
color: var(--color-gray-900);
|
||||||
|
}
|
||||||
|
.text-green-400 {
|
||||||
|
color: var(--color-green-400);
|
||||||
|
}
|
||||||
|
.text-transparent {
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
.text-white {
|
||||||
|
color: var(--color-white);
|
||||||
|
}
|
||||||
|
.lowercase {
|
||||||
|
text-transform: lowercase;
|
||||||
|
}
|
||||||
|
.uppercase {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.ordinal {
|
||||||
|
--tw-ordinal: ordinal;
|
||||||
|
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
|
||||||
|
}
|
||||||
|
.underline {
|
||||||
|
text-decoration-line: underline;
|
||||||
|
}
|
||||||
|
.shadow {
|
||||||
|
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
||||||
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
.invert {
|
||||||
|
--tw-invert: invert(100%);
|
||||||
|
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,);
|
||||||
|
}
|
||||||
|
.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,);
|
||||||
|
}
|
||||||
|
.transition {
|
||||||
|
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, visibility, content-visibility, overlay, pointer-events;
|
||||||
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||||
|
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
||||||
|
}
|
||||||
|
.duration-300 {
|
||||||
|
--tw-duration: 300ms;
|
||||||
|
transition-duration: 300ms;
|
||||||
|
}
|
||||||
|
.hover\:bg-blue-400 {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
background-color: var(--color-blue-400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.hover\:from-blue-600 {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
--tw-gradient-from: var(--color-blue-600);
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.hover\:to-blue-500 {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
--tw-gradient-to: var(--color-blue-500);
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.hover\:text-blue-400 {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
color: var(--color-blue-400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@property --tw-rotate-x {
|
||||||
.close-button:hover {
|
syntax: "*";
|
||||||
color: #c0392b;
|
inherits: false;
|
||||||
}
|
}
|
||||||
|
@property --tw-rotate-y {
|
||||||
.modal-content a.download-button {
|
syntax: "*";
|
||||||
margin-left: 15px;
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-rotate-z {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-skew-x {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-skew-y {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-gradient-position {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-gradient-from {
|
||||||
|
syntax: "<color>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: #0000;
|
||||||
|
}
|
||||||
|
@property --tw-gradient-via {
|
||||||
|
syntax: "<color>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: #0000;
|
||||||
|
}
|
||||||
|
@property --tw-gradient-to {
|
||||||
|
syntax: "<color>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: #0000;
|
||||||
|
}
|
||||||
|
@property --tw-gradient-stops {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-gradient-via-stops {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-gradient-from-position {
|
||||||
|
syntax: "<length-percentage>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 0%;
|
||||||
|
}
|
||||||
|
@property --tw-gradient-via-position {
|
||||||
|
syntax: "<length-percentage>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 50%;
|
||||||
|
}
|
||||||
|
@property --tw-gradient-to-position {
|
||||||
|
syntax: "<length-percentage>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 100%;
|
||||||
|
}
|
||||||
|
@property --tw-font-weight {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-ordinal {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-slashed-zero {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-numeric-figure {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-numeric-spacing {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-numeric-fraction {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-shadow {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 0 0 #0000;
|
||||||
|
}
|
||||||
|
@property --tw-shadow-color {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-shadow-alpha {
|
||||||
|
syntax: "<percentage>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 100%;
|
||||||
|
}
|
||||||
|
@property --tw-inset-shadow {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 0 0 #0000;
|
||||||
|
}
|
||||||
|
@property --tw-inset-shadow-color {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-inset-shadow-alpha {
|
||||||
|
syntax: "<percentage>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 100%;
|
||||||
|
}
|
||||||
|
@property --tw-ring-color {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-ring-shadow {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 0 0 #0000;
|
||||||
|
}
|
||||||
|
@property --tw-inset-ring-color {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-inset-ring-shadow {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 0 0 #0000;
|
||||||
|
}
|
||||||
|
@property --tw-ring-inset {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --tw-ring-offset-width {
|
||||||
|
syntax: "<length>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 0px;
|
||||||
|
}
|
||||||
|
@property --tw-ring-offset-color {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: #fff;
|
||||||
|
}
|
||||||
|
@property --tw-ring-offset-shadow {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 0 0 #0000;
|
||||||
|
}
|
||||||
|
@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: "<percentage>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 100%;
|
||||||
|
}
|
||||||
|
@property --tw-drop-shadow-size {
|
||||||
|
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-rotate-x: initial;
|
||||||
|
--tw-rotate-y: initial;
|
||||||
|
--tw-rotate-z: initial;
|
||||||
|
--tw-skew-x: initial;
|
||||||
|
--tw-skew-y: initial;
|
||||||
|
--tw-gradient-position: initial;
|
||||||
|
--tw-gradient-from: #0000;
|
||||||
|
--tw-gradient-via: #0000;
|
||||||
|
--tw-gradient-to: #0000;
|
||||||
|
--tw-gradient-stops: initial;
|
||||||
|
--tw-gradient-via-stops: initial;
|
||||||
|
--tw-gradient-from-position: 0%;
|
||||||
|
--tw-gradient-via-position: 50%;
|
||||||
|
--tw-gradient-to-position: 100%;
|
||||||
|
--tw-font-weight: initial;
|
||||||
|
--tw-ordinal: initial;
|
||||||
|
--tw-slashed-zero: initial;
|
||||||
|
--tw-numeric-figure: initial;
|
||||||
|
--tw-numeric-spacing: initial;
|
||||||
|
--tw-numeric-fraction: initial;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow-color: initial;
|
||||||
|
--tw-shadow-alpha: 100%;
|
||||||
|
--tw-inset-shadow: 0 0 #0000;
|
||||||
|
--tw-inset-shadow-color: initial;
|
||||||
|
--tw-inset-shadow-alpha: 100%;
|
||||||
|
--tw-ring-color: initial;
|
||||||
|
--tw-ring-shadow: 0 0 #0000;
|
||||||
|
--tw-inset-ring-color: initial;
|
||||||
|
--tw-inset-ring-shadow: 0 0 #0000;
|
||||||
|
--tw-ring-inset: initial;
|
||||||
|
--tw-ring-offset-width: 0px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-offset-shadow: 0 0 #0000;
|
||||||
|
--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-duration: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user