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
|
||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||
cd Amnezichat/server/
|
||||
sudo docker build -t amnezichatserver:latest .
|
||||
sudo docker run -p 8080:8080 amnezichatserver:latest
|
||||
docker build --network=host -t amnezichatserver:latest .
|
||||
docker run --network=host amnezichatserver:latest
|
||||
|
||||
## Client setup:
|
||||
|
||||
**For Web UI connect to http://localhost:8000**
|
||||
|
||||
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
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
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
|
||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||
cd Amnezichat/client/
|
||||
sudo docker build -t amnezichat:latest .
|
||||
sudo docker run -p 8000:8000 amnezichat:latest
|
||||
docker build --network=host -t amnezichat .
|
||||
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:
|
||||
|
||||
|
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
|
||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||
cd Amnezichat/server/
|
||||
sudo docker build -t amnezichatserver:latest .
|
||||
sudo docker run -p 8080:8080 amnezichatserver:latest
|
||||
docker build --network=host -t amnezichatserver:latest .
|
||||
docker run --network=host amnezichatserver:latest
|
||||
|
||||
## İstemci kurulumu:
|
||||
|
||||
**Web UI için http://localhost:8000 adresine bağlanın**
|
||||
|
||||
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
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
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
|
||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||
cd Amnezichat/client/
|
||||
sudo docker build -t amnezichat:latest .
|
||||
sudo docker run -p 8000:8000 amnezichat:latest
|
||||
docker build --network=host -t amnezichat .
|
||||
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:
|
||||
|
||||
|
@ -25,3 +25,4 @@ rocket = { version = "0.5", features = ["json"] }
|
||||
eframe = "0.26"
|
||||
egui = "0.26"
|
||||
rfd = "0.12"
|
||||
which = "4.4"
|
@ -9,10 +9,21 @@ RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
curl \
|
||||
build-essential \
|
||||
clang \
|
||||
cmake \
|
||||
libclang-dev \
|
||||
llvm-dev \
|
||||
net-tools \
|
||||
libxkbcommon-x11-0 \
|
||||
git \
|
||||
tor && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
tor \
|
||||
xterm \
|
||||
pkg-config \
|
||||
iputils-ping \
|
||||
libglib2.0-dev \
|
||||
libssl-dev \
|
||||
libgtk-3-dev \
|
||||
dnsutils
|
||||
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
|
||||
@ -23,4 +34,10 @@ RUN cargo build --release
|
||||
|
||||
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,
|
||||
error::Error,
|
||||
};
|
||||
use std::fs;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use chacha20poly1305::aead::OsRng;
|
||||
use rand::RngCore;
|
||||
@ -61,6 +62,9 @@ use rfd::MessageDialog;
|
||||
use rfd::MessageButtons;
|
||||
use rfd::MessageLevel;
|
||||
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] {
|
||||
pk.as_ref()
|
||||
@ -250,11 +254,8 @@ impl Default for AppState {
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut options = eframe::NativeOptions::default();
|
||||
|
||||
options.viewport.resizable = Some(false);
|
||||
|
||||
options.viewport.inner_size = Some(egui::vec2(600.0, 900.0));
|
||||
|
||||
options.viewport.inner_size = Some(egui::vec2(600.0, 1000.0));
|
||||
eframe::run_native("Messaging Setup", options, Box::new(|_cc| Box::new(SetupApp::default())))?;
|
||||
Ok(())
|
||||
}
|
||||
@ -284,7 +285,6 @@ impl eframe::App for SetupApp {
|
||||
ui.label(egui::RichText::new("Choose an action:").size(24.0));
|
||||
ui.add_space(10.0);
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
|
||||
ui.add_space(20.0);
|
||||
if ui.add(
|
||||
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()) {
|
||||
self.state.error_message = Some(err.to_string());
|
||||
} else {
|
||||
|
||||
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 {
|
||||
ui.add_space(20.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>> {
|
||||
if state.server_url.is_empty() || state.username.is_empty() || state.private_password.is_empty() {
|
||||
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">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<title>Amnezichat</title>
|
||||
<link rel="stylesheet" href="/static/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Download Amnezichat</h1>
|
||||
<p>Anti-forensic and secure messaging. Download it now and get started.</p>
|
||||
<a href="#download" class="download-button">Download Now</a>
|
||||
|
||||
<div id="footer">
|
||||
<link rel="stylesheet" href="/static/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div
|
||||
class="bg-black h-screen flex flex-col items-center justify-center text-white"
|
||||
>
|
||||
<h1
|
||||
class="h-14 bg-linear-65 from-purple-500 to-pink-500 text-6xl font-bold text-transparent bg-clip-text"
|
||||
>
|
||||
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 -->
|
||||
<div class="main-links">
|
||||
<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>
|
||||
|
||||
<br />
|
||||
<!-- Privacy and Terms -->
|
||||
<details id="terms-of-service-section">
|
||||
<summary>Terms of Service</summary>
|
||||
<details id="terms-of-service-section" class="pt-3">
|
||||
<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>
|
||||
<ul>
|
||||
<li>Use for lawful purposes only.</li>
|
||||
<li>Do not share illegal content.</li>
|
||||
<li>Respect others while using the platform.</li>
|
||||
</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>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Privacy Policy</summary>
|
||||
<details class="pt-3 pb-3">
|
||||
<summary
|
||||
class="bg-gray-950 p-3 rounded-lg cursor-pointer shadow"
|
||||
>
|
||||
Privacy Policy
|
||||
</summary>
|
||||
<p>We value your privacy:</p>
|
||||
<ul>
|
||||
<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>
|
||||
</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>
|
||||
</small>
|
||||
</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">
|
||||
<a href="#" class="close-button">×</a>
|
||||
<h2>Installation Instructions</h2>
|
||||
<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>
|
||||
<pre>
|
||||
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
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
git clone https://github.com/umutcamliyurt/Amnezichat.git
|
||||
cd Amnezichat/client/
|
||||
cargo build --release
|
||||
cargo run --release
|
||||
</pre>
|
||||
</pre
|
||||
>
|
||||
|
||||
<h3>Or:</h3>
|
||||
<a href="/static/Amnezichat-x86_64.AppImage" class="download-button" download>Download AppImage</a>
|
||||
<a href="/static/Amnezichat-x86_64.deb" class="download-button" download>Download .deb Package</a>
|
||||
<h3 class="pb-3">Or:</h3>
|
||||
<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>
|
||||
</body>
|
||||
</div>
|
||||
</body>
|
||||
</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 {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
/*! tailwindcss v4.1.5 | MIT License | https://tailwindcss.com */
|
||||
@layer properties;
|
||||
@layer theme, base, components, utilities;
|
||||
@layer theme {
|
||||
:root, :host {
|
||||
--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
|
||||
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
||||
"Courier New", monospace;
|
||||
--color-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;
|
||||
background: linear-gradient(135deg, #1e3c72, #2a5298);
|
||||
color: #ecf0f1;
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
border: 0 solid;
|
||||
}
|
||||
html, :host {
|
||||
line-height: 1.5;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
tab-size: 4;
|
||||
font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
|
||||
font-feature-settings: var(--default-font-feature-settings, normal);
|
||||
font-variation-settings: var(--default-font-variation-settings, normal);
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
hr {
|
||||
height: 0;
|
||||
color: inherit;
|
||||
border-top-width: 1px;
|
||||
}
|
||||
abbr:where([title]) {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
-webkit-text-decoration: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
b, strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
code, kbd, samp, pre {
|
||||
font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
|
||||
font-feature-settings: var(--default-mono-font-feature-settings, normal);
|
||||
font-variation-settings: var(--default-mono-font-variation-settings, normal);
|
||||
font-size: 1em;
|
||||
}
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
sub, sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
table {
|
||||
text-indent: 0;
|
||||
border-color: inherit;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
:-moz-focusring {
|
||||
outline: auto;
|
||||
}
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
ol, ul, menu {
|
||||
list-style: none;
|
||||
}
|
||||
img, svg, video, canvas, audio, iframe, embed, object {
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
img, video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
button, input, select, optgroup, textarea, ::file-selector-button {
|
||||
font: inherit;
|
||||
font-feature-settings: inherit;
|
||||
font-variation-settings: inherit;
|
||||
letter-spacing: inherit;
|
||||
color: inherit;
|
||||
border-radius: 0;
|
||||
background-color: transparent;
|
||||
opacity: 1;
|
||||
}
|
||||
:where(select:is([multiple], [size])) optgroup {
|
||||
font-weight: bolder;
|
||||
}
|
||||
:where(select:is([multiple], [size])) optgroup option {
|
||||
padding-inline-start: 20px;
|
||||
}
|
||||
::file-selector-button {
|
||||
margin-inline-end: 4px;
|
||||
}
|
||||
::placeholder {
|
||||
opacity: 1;
|
||||
}
|
||||
@supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {
|
||||
::placeholder {
|
||||
color: currentcolor;
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
::-webkit-date-and-time-value {
|
||||
min-height: 1lh;
|
||||
text-align: inherit;
|
||||
}
|
||||
::-webkit-datetime-edit {
|
||||
display: inline-flex;
|
||||
}
|
||||
::-webkit-datetime-edit-fields-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
|
||||
padding-block: 0;
|
||||
}
|
||||
:-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;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 30px;
|
||||
background: rgba(15, 30, 60, 0.95);
|
||||
border: 1px solid #0f3b5f;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.6);
|
||||
max-width: 600px;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
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;
|
||||
@layer utilities {
|
||||
.collapse {
|
||||
visibility: collapse;
|
||||
}
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
.visible {
|
||||
visibility: visible;
|
||||
}
|
||||
.absolute {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.fixed {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
color: #c0392b;
|
||||
@property --tw-rotate-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
|
||||
.modal-content a.download-button {
|
||||
margin-left: 15px;
|
||||
@property --tw-rotate-y {
|
||||
syntax: "*";
|
||||
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