diff --git a/content/blog/post-5.md b/content/blog/post-5.md index cb91908..2c2e25e 100644 --- a/content/blog/post-5.md +++ b/content/blog/post-5.md @@ -29,17 +29,17 @@ Once clients start resolving names through the attacker's DNS, the attacker can Tools like `ntlmrelayx` allow relaying to: -* **SMB**: for file access, command execution, or dumping secrets via `secretsdump.py` -* **LDAP/LDAPS**: to enumerate AD users, modify objects, or create backdoor accounts -* **HTTP/WSMAN**: to access internal web apps or trigger remote code execution +* SMB: for file access, command execution, or dumping secrets via `secretsdump.py` +* LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts +* HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t. #### Realistic Attack Chain -1. **Launch mitm6** to poison IPv6 and become DNS for the subnet. -2. **Run ntlmrelayx** with appropriate targets (e.g., `--smb2support --target smb://10.0.0.5`). -3. **Wait**: a victim resolves an internal name (e.g., `fileshare`), the attacker responds. +1. Launch mitm6 to poison IPv6 and become DNS for the subnet. +2. Run ntlmrelayx with appropriate targets (e.g., `--smb2support --target smb://10.0.0.5`). +3. Wait: a victim resolves an internal name (e.g., `fileshare`), the attacker responds. 4. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. 5. `ntlmrelayx` relays these to the actual target server. 6. If successful, the attacker gains authenticated access. @@ -50,9 +50,9 @@ In parallel, `Responder` can be used for LLMNR/NBT-NS-based interception in IPv4 This isn't new, but it's often neglected. To prevent these attacks: -* Disable **LLMNR** and **NBT-NS** via Group Policy. -* Disable **IPv6** on clients if it's not explicitly required. -* Enforce **SMB signing** and **LDAP channel binding**. +* Disable LLMNR and NBT-NS via Group Policy. +* Disable IPv6 on clients if it's not explicitly required. +* Enforce SMB signing and LDAP channel binding. * Segment your network to reduce the blast radius. * Prefer **Kerberos** authentication over NTLM where possible. * Monitor for rogue IPv6 RAs and anomalous name resolution. diff --git a/hugo_stats.json b/hugo_stats.json index 1a2be32..4eaf22e 100644 --- a/hugo_stats.json +++ b/hugo_stats.json @@ -14,7 +14,6 @@ "figure", "footer", "form", - "g", "h1", "h2", "h3", @@ -32,12 +31,10 @@ "main", "meta", "nav", - "notice", "ol", "p", "path", "picture", - "polygon", "pre", "script", "section", @@ -49,7 +46,6 @@ "table", "tbody", "td", - "text", "textarea", "th", "thead", @@ -79,7 +75,6 @@ "caption-Picture-of-the-solution", "caption-SARV001-Kanji", "caption-SARV001-Lume", - "caption-SARV001-Lume-whilst-changing-day", "card", "card-body", "card-btn", @@ -150,7 +145,6 @@ "gap-3", "gap-4", "gap-5", - "goat", "gx-md-5", "gx-xxl-5", "gy-4", @@ -177,6 +171,7 @@ "list-inline", "list-inline-item", "mb-0", + "mb-1", "mb-2", "mb-3", "mb-4", @@ -217,6 +212,8 @@ "pe-3", "position-fixed", "position-relative", + "post-categories", + "post-date", "post-meta", "progress", "progress-bar", @@ -247,7 +244,6 @@ "section-title", "small", "social-links", - "svg-container", "text-capitalize", "text-center", "text-lg-center", @@ -277,14 +273,11 @@ "caption-Picture of the solution", "caption-SARV001 Kanji", "caption-SARV001 Lume", - "caption-SARV001 Lume whilst changing day", "capturing-vs-relaying", "caveats--limitations", - "cheap-camera-expensive-risk-hacking-an-iot-ptz-camera", "contact", "creating-the-hugo-site", "customization", - "cyber-defence-on-the-digital-frontline-a-mission-with-nato", "de-praktijk-vs-certificaten", "defending-in-the-digital-age", "delegation-more-trust-more-problems", @@ -308,15 +301,11 @@ "ipv6-enabled-by-default-forgotten-by-admins", "irc-ngircd", "kerberoasting-plaintext-passwords-in-disguise", - "kerberos-under-siege-abusing-the-trust-backbone-of-windows-domains", "kwetsbaarheden-in-active-directory", "lastName", "leading-with-innovation", - "lean-and-local-dns-vpn-irc-and-ad-blocking-with-alpine-linux", - "let-me-know-if-youd-like-to-plug-this-directly-into-the-markdown-file-or-add-screenshotsterminal-views", "limitations-and-workarounds", "making-it-stick-lbu", - "matrix-building-a-decentralized-communication-future", "matrix-in-cybersecurity-contexts", "message", "mitigation", @@ -332,25 +321,18 @@ "real-world-examples", "real-world-usage", "realistic-attack-chain", - "red-team-talk-een-blik-achter-de-schermen-bij-offensive-security", "repository", "resume", - "reversing-rebuilding-and-failing-better-my-cyber-security-challenge-belgium-qualifier-experience", "runlevel-integration", "running-your-own-homeserver", "sample-home-setup", - "securing-cyberspace-belgian-cyber-command-at-howest", "security-end-to-end-encryption-by-default", - "seiko-sarv001-the-jdm-sleeper-that-punches-above-its-weight", "sidebarContent", - "silent-interception-exploiting-llmnr-nbt-ns-mdns-and-ipv6-in-modern-networks", "skill", "the-black-team-rapid-response-in-action", "the-challenge-that-stuck-with-me-rebuilding-a-split-dex", - "the-developer-angle", "the-exercise-locked-shields", "the-one-that-got-away-tls-fingerprinting", - "the-smart-home-trap-isolate-or-be-owned", "ticket-forgery-and-impersonation", "toggler", "tools-tips-en-oefenen", diff --git a/public/.htaccess b/public/.htaccess deleted file mode 100644 index ad01b82..0000000 --- a/public/.htaccess +++ /dev/null @@ -1,88 +0,0 @@ -##### Optimize default expiration time - BEGIN - - - ## Enable expiration control - ExpiresActive On - - ## CSS and JS expiration: 1 week after request - ExpiresByType text/css "now plus 1 week" - ExpiresByType application/javascript "now plus 1 week" - ExpiresByType application/x-javascript "now plus 1 week" - - ## Image files expiration: 1 month after request - ExpiresByType image/bmp "now plus 1 month" - ExpiresByType image/gif "now plus 1 month" - ExpiresByType image/jpeg "now plus 1 month" - ExpiresByType image/webp "now plus 1 month" - ExpiresByType image/jp2 "now plus 1 month" - ExpiresByType image/pipeg "now plus 1 month" - ExpiresByType image/png "now plus 1 month" - ExpiresByType image/svg+xml "now plus 1 month" - ExpiresByType image/tiff "now plus 1 month" - ExpiresByType image/x-icon "now plus 1 month" - ExpiresByType image/ico "now plus 1 month" - ExpiresByType image/icon "now plus 1 month" - ExpiresByType text/ico "now plus 1 month" - ExpiresByType application/ico "now plus 1 month" - ExpiresByType image/vnd.wap.wbmp "now plus 1 month" - - ## Font files expiration: 1 month after request - ExpiresByType application/x-font-ttf "now plus 1 month" - ExpiresByType application/x-font-opentype "now plus 1 month" - ExpiresByType application/x-font-woff "now plus 1 month" - ExpiresByType font/woff2 "now plus 1 month" - ExpiresByType image/svg+xml "now plus 1 month" - - ## Audio files expiration: 1 month after request - ExpiresByType audio/ogg "now plus 1 month" - ExpiresByType application/ogg "now plus 1 month" - ExpiresByType audio/basic "now plus 1 month" - ExpiresByType audio/mid "now plus 1 month" - ExpiresByType audio/midi "now plus 1 month" - ExpiresByType audio/mpeg "now plus 1 month" - ExpiresByType audio/mp3 "now plus 1 month" - ExpiresByType audio/x-aiff "now plus 1 month" - ExpiresByType audio/x-mpegurl "now plus 1 month" - ExpiresByType audio/x-pn-realaudio "now plus 1 month" - ExpiresByType audio/x-wav "now plus 1 month" - - ## Movie files expiration: 1 month after request - ExpiresByType application/x-shockwave-flash "now plus 1 month" - ExpiresByType x-world/x-vrml "now plus 1 month" - ExpiresByType video/x-msvideo "now plus 1 month" - ExpiresByType video/mpeg "now plus 1 month" - ExpiresByType video/mp4 "now plus 1 month" - ExpiresByType video/quicktime "now plus 1 month" - ExpiresByType video/x-la-asf "now plus 1 month" - ExpiresByType video/x-ms-asf "now plus 1 month" - -##### Optimize default expiration time - END - -##### 1 Month for most static resources - - Header set Cache-Control "public, max-age=31536000, immutable" - - -##### Enable gzip compression for resources - - mod_gzip_on Yes - mod_gzip_dechunk Yes - mod_gzip_item_include file .(html?|txt|css|js|php)$ - mod_gzip_item_include handler ^cgi-script$ - mod_gzip_item_include mime ^text/.* - mod_gzip_item_include mime ^application/x-javascript.* - mod_gzip_item_exclude mime ^image/.* - mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.* - - -##### Or, compress certain file types by extension: - - SetOutputFilter DEFLATE - - -##### Set Header Vary: Accept-Encoding - - - Header append Vary: Accept-Encoding - - diff --git a/public/404.html b/public/404.html deleted file mode 100644 index 24abdea..0000000 --- a/public/404.html +++ /dev/null @@ -1,9191 +0,0 @@ - - - - - - -404 Page not found - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

404 Page Not Found!

- Back To Home -
-
-
-
- -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/_index.md_backup b/public/_index.md_backup deleted file mode 100644 index e029564..0000000 --- a/public/_index.md_backup +++ /dev/null @@ -1,153 +0,0 @@ ---- -title: Home | Joren -description: '' - -# banner -banner: - greeting: "Hi there!" - title: "I'm **Joren Schipman**" - image: "images/hero-image.png" - designation: "Student Applied Computer Science" - institution: "Howest University of Applied Sciences" - description: "A professor of artificial intelligence at the Stanford AI Lab. I research interests include distributed robotics, mobile computing and programmable matter." - - additional_info: - - title: "Email" - content: "jorenschipman@gmail.com" - - title: "Phone" - content: "+32456069255" - - title: "Age" - content: "21 years" - - title: "Languages" - content: "Dutch, English" - - title: "Address" - content: "Kapelseweg 58a, 2811 Mechelen" - - button: - enable: true - label: "Download Resume" - isDownloadable: true - link: "#?" - - -# skill -skill: - enable: true - title: "My **Skills**" - skills: - - title: "Playing Science" - percentage: "95" - - title: "Arts And Craft" - percentage: "90" - - title: "Creative Writing" - percentage: "55" - - title: "English Lessons" - percentage: "95" - - title: "SQL" - percentage: "80" - - title: "Mongodb" - percentage: "95" - - title: "Tableau" - percentage: "75" - - title: "Stella Architect" - percentage: "90" - - -# experience -experience: - enable: true - title: "Experiences" - experience_list: - - title: "University of Eastern Finland" - duration: "Jan 2022 – Present" - company: "Rolling Thunder" - icon: "fa-solid fa-pen-ruler" - description: | - Maecenas tempus faucibus rutrum. Duis eu aliquam urna. Proin vitae nulla tristique, ornare felis id congue libero. - - - title: "University of Jyväskylä" - duration: "Jan 2020 – Dec 2021" - company: "Apple Inc." - icon: "fa-solid fa-palette" - description: | - Aliquam tincidunt malesuada tortor vitae iaculis. In eu turpis risus quis. Quisque fringilla mollis risus eu pulvinar. - - - title: "University of Eastern Finland" - duration: "Jan 2016 – Dec 2019" - company: "Google Inc." - icon: "fa-solid fa-laptop-code" - description: | - Aliquam tincidunt malesuada tortor vitae iaculis. In eu turpis risus quis. Quisque fringilla mollis risus eu pulvinar. - - - -# education -education: - enable: true - title: "Education" - education_list: - - title: "PhD in Statistics" - duration: "Jan 2021 to Dec 2022" - icon: "fa-solid fa-building-columns" - description: | - Aliquam tincidunt malesuada tortor vitae iaculis. In eu turpis risus quis. Quisque fringilla mollis risus eu pulvinar. - - - title: "MSc in Statistics" - description: "" - institution: "" - duration: "Jan 2019 - Dec 2020" - icon: "fa-solid fa-person-chalkboard" - description: | - Aliquam tincidunt malesuada tortor vitae iaculis. In eu turpis risus quis. Quisque fringilla mollis risus eu pulvinar. - - - title: "BSc in Statistics" - description: "" - institution: "" - duration: "Jan 2019 - Dec 2020" - icon: "fa-solid fa-graduation-cap" - description: | - Aliquam tincidunt malesuada tortor vitae iaculis. In eu turpis risus quis. Quisque fringilla mollis risus eu pulvinar. - - -# projects -projects: - enable: true - button: - link: "projects/" - label: "All Projects" - - -# blogs -blogs: - enable: true - button: - link: "blog/" - label: "All Blogs" - - -# contact -contact: - enable: true - title: "Get in Touch" - - contact_info: - title: "Contact" - subtitle: "Fill up the form and our Team will get back to you within 24 hours." - - contact_details: - - name: "Call" - icon: "fa-solid fa-phone-volume" - content: "[310-437-2766](tel:310-437-2766)" - - - name: "Mail" - icon: "fa-solid fa-envelope" - content: "[williamson@gmail.com](mailto:williamson@gmail.com)" - - - name: "Address" - icon: "fa-solid fa-location-dot" - content: "1901 Thornridge Cir. Shiloh, Hawaii" - - - name: "Fax" - icon: "fa-solid fa-phone-volume" - content: "[555-123-4567](tel:555-123-4567)" ---- diff --git a/public/blog/index.html b/public/blog/index.html deleted file mode 100644 index 7143b52..0000000 --- a/public/blog/index.html +++ /dev/null @@ -1,10769 +0,0 @@ - - - - - - -Recent Posts - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Recent Posts - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

//Recent Posts

-
-
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/blog/index.xml b/public/blog/index.xml deleted file mode 100644 index fad6c15..0000000 --- a/public/blog/index.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - Recent Posts on Joren's Site - http://localhost:1313/blog/ - Recent content in Recent Posts on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera - http://localhost:1313/blog/post-8/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-8/ - <p>When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?</p> - - - Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains - http://localhost:1313/blog/post-7/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-7/ - <p>Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like <strong>Kerberoasting</strong>, <strong>delegation abuse</strong>, and <strong>ticket impersonation</strong>.</p> - - - Matrix: Building a Decentralized Communication Future - http://localhost:1313/blog/post-6/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-6/ - <p>If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn&rsquo;t trapped in walled gardens.</p> - - - Seiko SARV001: The JDM Sleeper That Punches Above Its Weight - http://localhost:1313/blog/post-9/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-9/ - <p>In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.</p> - - - Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks - http://localhost:1313/blog/post-5/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-5/ - <p>In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using <code>Responder</code> and <code>mitm6</code>.</p> - - - The Smart Home Trap: Isolate or Be Owned - http://localhost:1313/blog/post-10/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-10/ - <p>Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you&rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.</p> - - - Red Team Talk: Een Blik Achter de Schermen bij Offensive Security - http://localhost:1313/blog/post-4/ - Tue, 20 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-4/ - <p>In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met <strong>Thomas Castronovo</strong>, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.</p> - - - Cyber Defence on the Digital Frontline: A Mission with NATO - http://localhost:1313/blog/post-1/ - Tue, 13 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-1/ - <h4 id="on-a-mission-with-nato-cyber-defence-on-the-frontline">On a Mission with NATO: Cyber Defence on the Frontline</h4> <p>Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO&rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.</p> - - - Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience - http://localhost:1313/blog/post-2/ - Sat, 15 Mar 2025 00:00:00 +0000 - http://localhost:1313/blog/post-2/ - <p>On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.</p> - - - Securing Cyberspace: Belgian Cyber Command at Howest - http://localhost:1313/blog/post-3/ - Tue, 12 Nov 2024 00:00:00 +0000 - http://localhost:1313/blog/post-3/ - <p>On November 12, we had the opportunity to attend a Tech&amp;Meet session unlike any other. The speaker was <strong>Colonel Gunther Godefridis</strong>, Director for Development &amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.</p> - - - diff --git a/public/blog/post-1/index.html b/public/blog/post-1/index.html deleted file mode 100644 index 1e4a137..0000000 --- a/public/blog/post-1/index.html +++ /dev/null @@ -1,9365 +0,0 @@ - - - - - - -Cyber Defence on the Digital Frontline: A Mission with NATO - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Cyber Defence on the Digital Frontline: A Mission with NATO - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- -

Cyber Defence on the Digital Frontline: A Mission with NATO

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cyber Defence on the Digital Frontline: A Mission with NATO - - - - - - - - - - - -
- - -
-

On a Mission with NATO: Cyber Defence on the Frontline

-

Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO’s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.

-

The Exercise: Locked Shields

-

Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.

-

And yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.

-

High Stakes, Real Lessons

-

What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.

-

The exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not “port 8443 unreachable”, but “our air defence system is degraded, and we cannot fly planes”.

-

The Black Team: Rapid Response in Action

-

A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.

-

Their presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.

-

Highlights and Blooper Reel

-

There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.

-

Human Factors and Growth

-

From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.

-

The biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.

-

From the Battlefield to the Classroom

-

This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.

-

As one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”

-

Final Thoughts

-

The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.

-

Want to see how cyber defence works in real life? This is it.

- -
-
-
-
-
-
- - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/blog/post-10/index.html b/public/blog/post-10/index.html deleted file mode 100644 index 212fed3..0000000 --- a/public/blog/post-10/index.html +++ /dev/null @@ -1,9480 +0,0 @@ - - - - - - -The Smart Home Trap: Isolate or Be Owned - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The Smart Home Trap: Isolate or Be Owned - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- -

The Smart Home Trap: Isolate or Be Owned

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The Smart Home Trap: Isolate or Be Owned - - - - - - - - - - - -
- - -
-

Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you’ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.

-
-

Why Segmentation Matters

-

Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.

-

IoT vendors prioritize cost and features, not security. Devices often ship with:

-
    -
  • Default credentials
  • -
  • No software updates
  • -
  • Open ports and broadcast protocols
  • -
  • Aggressive telemetry to unknown hosts
  • -
-

A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?

-
-

VLANs 101

-

A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.

-

VLANs let you:

-
    -
  • Group devices by function (IoT, work, guest)
  • -
  • Apply granular rules between segments
  • -
  • Limit broadcast traffic and discovery protocols
  • -
  • Deny unnecessary cross-talk
  • -
-

And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.

-
-

Sample Home Setup

-

Let’s say you have a smart home with:

-
    -
  • A Nest thermostat
  • -
  • A Samsung smart TV
  • -
  • A couple of Tuya smart plugs
  • -
  • A doorbell camera
  • -
  • Your personal laptop and NAS
  • -
-

Step 1: Define VLANs

- - - - - - - - - - - - - - - - - - - - - - - - - -
VLAN IDPurposeExample Devices
10LAN (trusted)Laptop, NAS
20IoTSmart TV, plugs, doorbell
30Guest WiFiFriends’ phones
-

Step 2: Assign Interfaces

-

Most routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.

-

Step 3: Firewall Rules

-

On VLAN 20 (IoT):

-
    -
  • Block → LAN (VLAN 10)
  • -
  • Block → VLAN 20 (intra-IoT)
  • -
  • Allow → DNS, NTP, and cloud endpoints
  • -
  • Allow → Internet (443)
  • -
  • Log → Any unknown destination
  • -
-

Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.

-
-

Real-World Examples

-

Case 1: Smart TV

-

Blocked LAN access. Within 5 minutes of boot, it tried to contact:

-
    -
  • Samsung cloud
  • -
  • Akamai CDN
  • -
  • Google DNS
  • -
  • DoubleClick
  • -
  • Random advertising domains
  • -
-

Video streaming still worked fine. Everything else was noise.

-

Case 2: IP Camera

-

On the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.

-
-

Caveats & Limitations

-
    -
  • Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking.
  • -
  • Chromecast-style devices need special rules if you want casting from your main network.
  • -
  • VLANs require managed switches or VLAN-aware APs.
  • -
  • Guest VLANs may need bandwidth limits or isolation tweaks.
  • -
-

Still, the benefits far outweigh the complexity.

-
-

Final Thoughts

-

If you’ve ever installed a smart plug and noticed it phones home every few minutes, you’re not alone. And if you haven’t noticed, maybe you should.

-

Security in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.

-

Your lightbulb shouldn’t have access to your tax documents.

- - - - - - - -
-
- -

Tip

-
-

Looking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.

-
- - -
-
-
-
-
-
- - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/blog/post-2/index.html b/public/blog/post-2/index.html deleted file mode 100644 index 988d5e9..0000000 --- a/public/blog/post-2/index.html +++ /dev/null @@ -1,9819 +0,0 @@ - - - - - - -Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- -

Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience - - - - - - - - - - - -
- - -
-

On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.

-

What follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.

-

A Buffer Overflow to Warm Up

-

One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - alter-text - -
- Binary Exploitation Flag -
-
- - - - - - - - - - - -

OurEncIsSec: Zip Bombs and OEIS

-

Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.

-

Using this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - alter-text - -
- Picture of the solution -
-
- - - - - - - - - - - -

Infinite Luck: One in a Million?

-

One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.

-

Infinite Luck Banner -Infinite Luck Solved - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - alter-text - -
- Challange picture -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - alter-text - -
- Correct number order -
-
- - - - - - - - - - -

-

Android Reversing: FRIDA and JADX

-

Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.

-

The Challenge That Stuck with Me: Rebuilding a Split DEX

-

This one stood out.

-

The app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.

-
Class loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader())
-    .loadClass("be.dauntless.flag.Flag");
-

Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.

-

That challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.

-

The One That Got Away: TLS Fingerprinting

-

Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:

-
tls.Config{
-    MinVersion: tls.VersionTLS13,
-    CipherSuites: []uint16{
-        tls.TLS_AES_128_GCM_SHA256,
-        // ...
-    },
-    NextProtos: []string{"h2"},
-}
-

Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.

-

Final Thoughts

-

I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.

-

Working as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.

-

The Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.

- -
-
-
-
-
-
- - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/blog/post-3/index.html b/public/blog/post-3/index.html deleted file mode 100644 index feaa94e..0000000 --- a/public/blog/post-3/index.html +++ /dev/null @@ -1,9397 +0,0 @@ - - - - - - -Securing Cyberspace: Belgian Cyber Command at Howest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Securing Cyberspace: Belgian Cyber Command at Howest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- -

Securing Cyberspace: Belgian Cyber Command at Howest

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Securing Cyberspace: Belgian Cyber Command at Howest - - - - - - - - - - - -
- - -
-

On November 12, we had the opportunity to attend a Tech&Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development & Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.

-

Held at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.

-

Defending in the Digital Age

-

Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.

-

With society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.

-

Working Together: Academia, Industry, Government

-

One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.

-

He also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.

-

Leading with Innovation

-

With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military’s response.

-

He discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.

-

A Transparent, Human Conversation

-

The Q&A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.

-

Colonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.

-

Final Thoughts

-

If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.

-

Whether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.

- - - - - - - -
-
- -

Tip

-
-

Want to learn more about Cyber Command? Visit the official website at mil.be

-
- - -
-
-
-
-
-
- - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/blog/post-4/index.html b/public/blog/post-4/index.html deleted file mode 100644 index 42b6d06..0000000 --- a/public/blog/post-4/index.html +++ /dev/null @@ -1,9375 +0,0 @@ - - - - - - -Red Team Talk: Een Blik Achter de Schermen bij Offensive Security - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Red Team Talk: Een Blik Achter de Schermen bij Offensive Security - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- -

Red Team Talk: Een Blik Achter de Schermen bij Offensive Security

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Red Team Talk: Een Blik Achter de Schermen bij Offensive Security - - - - - - - - - - - -
- - -
-

In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.

-

Van Interesse tot Loopbaan

-

Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.

-

Offensive vs. Defensive Security

-

Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.

-

Wat doet een pentester nu echt?

-

Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.

-

Kwetsbaarheden in Active Directory

-

Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:

-
    -
  • LLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen
  • -
  • DNS wildcard records die leiden tot man-in-the-middle aanvallen
  • -
-

Tools, Tips en Oefenen

-

Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.

-

De Praktijk vs. Certificaten

-

Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.

-

Afsluiter

-

De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.

-
- -
- -
-
-
-
-
-
- - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/blog/post-5/index.html b/public/blog/post-5/index.html deleted file mode 100644 index a0b33ff..0000000 --- a/public/blog/post-5/index.html +++ /dev/null @@ -1,9386 +0,0 @@ - - - - - - -Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- -

Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks - - - - - - - - - - - -
- - -
-

In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.

-

Name Resolution Chaos

-

When Windows can’t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”

-

An attacker on the local network can answer “yes” and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.

-

IPv6: Enabled by Default, Forgotten by Admins

-

Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there’s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.

-

Once clients start resolving names through the attacker’s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.

-

Capturing vs. Relaying

-

Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it’s often more powerful to relay them live to a legitimate service.

-

Tools like ntlmrelayx allow relaying to:

-
    -
  • SMB: for file access, command execution, or dumping secrets via secretsdump.py
  • -
  • LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts
  • -
  • HTTP/WSMAN: to access internal web apps or trigger remote code execution
  • -
-

The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.

-

Realistic Attack Chain

-
    -
  1. Launch mitm6 to poison IPv6 and become DNS for the subnet.
  2. -
  3. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5).
  4. -
  5. Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds.
  6. -
  7. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials.
  8. -
  9. ntlmrelayx relays these to the actual target server.
  10. -
  11. If successful, the attacker gains authenticated access.
  12. -
-

In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.

-

Mitigation

-

This isn’t new, but it’s often neglected. To prevent these attacks:

-
    -
  • Disable LLMNR and NBT-NS via Group Policy.
  • -
  • Disable IPv6 on clients if it’s not explicitly required.
  • -
  • Enforce SMB signing and LDAP channel binding.
  • -
  • Segment your network to reduce the blast radius.
  • -
  • Prefer Kerberos authentication over NTLM where possible.
  • -
  • Monitor for rogue IPv6 RAs and anomalous name resolution.
  • -
-

Final Thoughts

-

If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.

-

Responder and mitm6 aren’t magic. They just reveal what’s already broken.

- -
-
-
-
-
-
- - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/blog/post-6/index.html b/public/blog/post-6/index.html deleted file mode 100644 index 7f3d8f5..0000000 --- a/public/blog/post-6/index.html +++ /dev/null @@ -1,9511 +0,0 @@ - - - - - - -Matrix: Building a Decentralized Communication Future - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Matrix: Building a Decentralized Communication Future - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- -

Matrix: Building a Decentralized Communication Future

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Matrix: Building a Decentralized Communication Future - - - - - - - - - - - -
- - -
-

If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn’t trapped in walled gardens.

-

In this post, we explore what Matrix is, how it works, where it’s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.

-
-

What is Matrix?

-

Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.

-

Matrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.

-

Matrix supports:

-
    -
  • Text messaging (1:1 and group)
  • -
  • End-to-end encryption (Olm/Megolm)
  • -
  • Voice and video calls (WebRTC)
  • -
  • File sharing
  • -
  • Threaded conversations
  • -
  • Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.)
  • -
  • Bots, widgets, and integrations
  • -
-
-

Federation and Interoperability

-

The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.

-

Bridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.

-

Supported bridge targets include:

-
    -
  • Slack
  • -
  • Discord
  • -
  • Microsoft Teams
  • -
  • IRC
  • -
  • Telegram
  • -
  • WhatsApp
  • -
  • Signal (community bridges)
  • -
-
-

Security: End-to-End Encryption by Default

-

Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.

-

Encryption features include:

-
    -
  • Forward secrecy
  • -
  • Device verification and cross-signing
  • -
  • Secure backup with recovery keys
  • -
  • Key sharing and gossiping for reliable message delivery
  • -
  • Support for multiple devices per user
  • -
-

In contrast to Signal, Matrix’s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.

-
-

Real-World Usage

-

Matrix is not just experimental, it’s deployed at scale:

-
    -
  • The French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries.
  • -
  • German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards.
  • -
  • Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration.
  • -
  • The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations.
  • -
-
-

Matrix in Cybersecurity Contexts

-

In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:

-
    -
  • Out-of-band communication when primary networks are compromised.
  • -
  • C2 channel simulation in adversary emulation labs.
  • -
  • Logging and transparency during incident response (Matrix rooms retain full audit trails).
  • -
  • Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management).
  • -
  • Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios.
  • -
-

In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.

-
-

Running Your Own Homeserver

-

Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.

-

Minimum Setup:

-
    -
  • Synapse (Python-based)
  • -
  • PostgreSQL backend
  • -
  • Reverse proxy (NGINX)
  • -
  • DNS (SRV + .well-known for federation)
  • -
  • TLS via Let’s Encrypt
  • -
  • Optional: SSO, LDAP, backup, TURN server for VoIP
  • -
-

Pro Tips:

-
    -
  • Use https://element.io/pricing for managed hosting if self-hosting is too much overhead.
  • -
  • Enable E2EE backup to retain message history across devices.
  • -
  • Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers.
  • -
-
-

Limitations and Workarounds

-

Matrix is powerful, but not perfect:

-
    -
  • Federation sync can be resource-heavy on large rooms.
  • -
  • Encrypted rooms sometimes lag on low-powered clients.
  • -
  • Bridges can break when third-party APIs change.
  • -
  • Identity is room-based, no global handles like @user across servers.
  • -
  • Message ordering across federated servers is eventually consistent, not immediate.
  • -
-

Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.

-
-

Final Thoughts

-

Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It’s not just a protocol. It’s a philosophy of sovereignty, transparency, and trustless interoperability.

-

Whether you’re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.

- - - - - - - -
-
- -

Tip

-
-

Visit matrix.org to learn more, or get started today at element.io.

-
- - -
-
-
-
-
-
- - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/blog/post-7/index.html b/public/blog/post-7/index.html deleted file mode 100644 index ee0bb96..0000000 --- a/public/blog/post-7/index.html +++ /dev/null @@ -1,9384 +0,0 @@ - - - - - - -Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- -

Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains - - - - - - - - - - - -
- - -
-

Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.

-
-

How Kerberos Actually Works

-

Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.

-

From a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.

-

Spoiler: they rarely are.

-
-

Kerberoasting: Plaintext Passwords in Disguise

-

If a service account uses a weak password, it’s game over.

-

Service tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.

-
Request SPN ticket → Extract ticket → Crack with hashcat
-

Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.

-

Default AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.

-
-

Delegation: More Trust, More Problems

-

Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.

-

Unconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.

-

Constrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.

-

These trust edges form a privilege escalation graph. BloodHound maps this beautifully.

-
-

Ticket Forgery and Impersonation

-

Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.

-

More subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.

-

Tools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.

-
-

Worked Example: Kerberoasting with Rubeus

-
Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local
-

→ Dumps service tickets in hashcat format.

-
hashcat -m 13100 hashes.txt rockyou.txt
-

→ Cracks the SPN ticket. If the password is weak, you’re in.

-

This is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.

-
-

Final Thoughts

-

Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.

-

Strong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.

-

In red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.

-

Want to defend the kingdom? Start by defending the keys.

- -
-
-
-
-
-
- - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/blog/post-8/index.html b/public/blog/post-8/index.html deleted file mode 100644 index c72eaf5..0000000 --- a/public/blog/post-8/index.html +++ /dev/null @@ -1,9389 +0,0 @@ - - - - - - -Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- -

Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera - - - - - - - - - - - -
- - -
-

When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?

-

This post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.

-
-

Triggering Debug Mode with a MicroSD Card

-

Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.

-

Insert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.

-

This is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.

-
-

UART Interface: Disabled Login, But Still There

-

A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.

-

Combined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.

-
-

What Could Go Wrong?

-

Plenty. With root access via SD card:

-
    -
  • You can replace binaries or inject backdoors.
  • -
  • Extract credentials, keys, or tokens stored in the SQLite database.
  • -
  • Modify the video stream, disable motion detection, or proxy footage.
  • -
  • Use the device as a pivot point in a local network attack.
  • -
-

All of this without triggering any alarms, logs, or user notifications.

-
-

But It Encrypts Traffic?

-

Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.

-

But physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.

-
-

What Can Be Done?

-

Fixing this requires more than software updates. It’s about rethinking assumptions.

-
    -
  • Factory debug hooks should be disabled or removed before shipment.
  • -
  • Bootloaders should verify signatures, not blindly trust SD cards.
  • -
  • Telnet should never be enabled automatically, ever.
  • -
  • Sensitive functions should not run as root unless absolutely required.
  • -
-

Until then, buyers are getting more than they bargained for.

-
-

Final Thoughts

-

This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.

-

If you’re building IoT gear: assume physical access and plan for it. -If you’re buying IoT gear: assume nothing until you’ve torn it apart.

-

Security is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.

-
- -
-
-
-
-
-
- - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/blog/post-9/index.html b/public/blog/post-9/index.html deleted file mode 100644 index 594ad54..0000000 --- a/public/blog/post-9/index.html +++ /dev/null @@ -1,9587 +0,0 @@ - - - - - - -Seiko SARV001: The JDM Sleeper That Punches Above Its Weight - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Seiko SARV001: The JDM Sleeper That Punches Above Its Weight - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- -

Seiko SARV001: The JDM Sleeper That Punches Above Its Weight

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Seiko SARV001: The JDM Sleeper That Punches Above Its Weight - - - - - - - - - - - -
- - -
-

In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.

-
-

Design & Build Quality

-

The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o’clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - alter-text - -
- SARV001 Kanji -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - alter-text - -
- SARV001 Lume -
-
- - - - - - - - - - - -
-

The case is protected by Seiko’s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch’s mechanical heart.

-
-

Movement & Performance

-

At its core, the SARV001 is powered by Seiko’s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it’s not designed for diving.

-
-

Wearability & Versatility

-

The watch’s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.

-
-

Value Proposition

-

Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.

-
-

Final Thoughts

-

The Seiko SARV001 exemplifies the brand’s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.

-
- -
-
-
-
-
-
- - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git "a/public/categories/\\cybersecurity-offensive-windows/index.xml" "b/public/categories/\\cybersecurity-offensive-windows/index.xml" deleted file mode 100644 index f6ebe42..0000000 --- "a/public/categories/\\cybersecurity-offensive-windows/index.xml" +++ /dev/null @@ -1,11 +0,0 @@ - - - - \["Cybersecurity", "Offensive", "Windows"] on Joren's Site - http://localhost:1313/categories/%5Ccybersecurity-offensive-windows/ - Recent content in \["Cybersecurity", "Offensive", "Windows"] on Joren's Site - Hugo - en - - - diff --git "a/public/categories/\\self-hosting-networking-alpine-linux-vpn-dns/index.xml" "b/public/categories/\\self-hosting-networking-alpine-linux-vpn-dns/index.xml" deleted file mode 100644 index c7e92da..0000000 --- "a/public/categories/\\self-hosting-networking-alpine-linux-vpn-dns/index.xml" +++ /dev/null @@ -1,11 +0,0 @@ - - - - \["Self-Hosting", "Networking", "Alpine-Linux", "Vpn", "Dns"] on Joren's Site - http://localhost:1313/categories/%5Cself-hosting-networking-alpine-linux-vpn-dns/ - Recent content in \["Self-Hosting", "Networking", "Alpine-Linux", "Vpn", "Dns"] on Joren's Site - Hugo - en - - - diff --git a/public/categories/alpine-linux/index.html b/public/categories/alpine-linux/index.html deleted file mode 100644 index 11789e1..0000000 --- a/public/categories/alpine-linux/index.html +++ /dev/null @@ -1,9378 +0,0 @@ - - - - - - -Alpine-Linux - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Alpine-Linux

-
-
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/alpine-linux/index.xml b/public/categories/alpine-linux/index.xml deleted file mode 100644 index a6e31a9..0000000 --- a/public/categories/alpine-linux/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Alpine-Linux on Joren's Site - https://joren.blog/categories/alpine-linux/ - Recent content in Alpine-Linux on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Lean and Local: DNS, VPN, IRC and Ad Blocking - https://joren.blog/project/project-3/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/project/project-3/ - <p>Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.</p> - - - diff --git a/public/categories/communication/index.html b/public/categories/communication/index.html deleted file mode 100644 index 3cb8191..0000000 --- a/public/categories/communication/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Communication - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Communication

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/communication/index.xml b/public/categories/communication/index.xml deleted file mode 100644 index 535064c..0000000 --- a/public/categories/communication/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Communication on Joren's Site - https://joren.blog/categories/communication/ - Recent content in Communication on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Matrix: Building a Decentralized Communication Future - https://joren.blog/blog/post-6/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-6/ - <p>If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn&rsquo;t trapped in walled gardens.</p> - - - diff --git a/public/categories/ctf/index.html b/public/categories/ctf/index.html deleted file mode 100644 index aa538c2..0000000 --- a/public/categories/ctf/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -CTF - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//CTF

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/ctf/index.xml b/public/categories/ctf/index.xml deleted file mode 100644 index 547412f..0000000 --- a/public/categories/ctf/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - CTF on Joren's Site - https://joren.blog/categories/ctf/ - Recent content in CTF on Joren's Site - Hugo - en - Sat, 15 Mar 2025 00:00:00 +0000 - - - Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience - https://joren.blog/blog/post-2/ - Sat, 15 Mar 2025 00:00:00 +0000 - https://joren.blog/blog/post-2/ - <p>On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.</p> - - - diff --git a/public/categories/cybersecurity/index.html b/public/categories/cybersecurity/index.html deleted file mode 100644 index f51105e..0000000 --- a/public/categories/cybersecurity/index.html +++ /dev/null @@ -1,10455 +0,0 @@ - - - - - - -Cybersecurity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Cybersecurity

-
-
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/cybersecurity/index.xml b/public/categories/cybersecurity/index.xml deleted file mode 100644 index 1ce74f2..0000000 --- a/public/categories/cybersecurity/index.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - Cybersecurity on Joren's Site - http://localhost:1313/categories/cybersecurity/ - Recent content in Cybersecurity on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains - http://localhost:1313/blog/post-7/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-7/ - <p>Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like <strong>Kerberoasting</strong>, <strong>delegation abuse</strong>, and <strong>ticket impersonation</strong>.</p> - - - Matrix: Building a Decentralized Communication Future - http://localhost:1313/blog/post-6/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-6/ - <p>If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn&rsquo;t trapped in walled gardens.</p> - - - Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks - http://localhost:1313/blog/post-5/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-5/ - <p>In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using <code>Responder</code> and <code>mitm6</code>.</p> - - - The Smart Home Trap: Isolate or Be Owned - http://localhost:1313/blog/post-10/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-10/ - <p>Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you&rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.</p> - - - Red Team Talk: Een Blik Achter de Schermen bij Offensive Security - http://localhost:1313/blog/post-4/ - Tue, 20 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-4/ - <p>In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met <strong>Thomas Castronovo</strong>, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.</p> - - - Cyber Defence on the Digital Frontline: A Mission with NATO - http://localhost:1313/blog/post-1/ - Tue, 13 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-1/ - <h4 id="on-a-mission-with-nato-cyber-defence-on-the-frontline">On a Mission with NATO: Cyber Defence on the Frontline</h4> <p>Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO&rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.</p> - - - Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience - http://localhost:1313/blog/post-2/ - Sat, 15 Mar 2025 00:00:00 +0000 - http://localhost:1313/blog/post-2/ - <p>On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.</p> - - - Securing Cyberspace: Belgian Cyber Command at Howest - http://localhost:1313/blog/post-3/ - Tue, 12 Nov 2024 00:00:00 +0000 - http://localhost:1313/blog/post-3/ - <p>On November 12, we had the opportunity to attend a Tech&amp;Meet session unlike any other. The speaker was <strong>Colonel Gunther Godefridis</strong>, Director for Development &amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.</p> - - - diff --git a/public/categories/decentralization/index.html b/public/categories/decentralization/index.html deleted file mode 100644 index 7cab16e..0000000 --- a/public/categories/decentralization/index.html +++ /dev/null @@ -1,9360 +0,0 @@ - - - - - - -Decentralization - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Decentralization

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/decentralization/index.xml b/public/categories/decentralization/index.xml deleted file mode 100644 index 77c0532..0000000 --- a/public/categories/decentralization/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Decentralization on Joren's Site - http://localhost:1313/categories/decentralization/ - Recent content in Decentralization on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Matrix: Building a Decentralized Communication Future - http://localhost:1313/blog/post-6/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-6/ - <p>If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn&rsquo;t trapped in walled gardens.</p> - - - diff --git a/public/categories/defense/index.html b/public/categories/defense/index.html deleted file mode 100644 index 74c78c5..0000000 --- a/public/categories/defense/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Defense - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Defense

-
-
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/defense/index.xml b/public/categories/defense/index.xml deleted file mode 100644 index 5b2feac..0000000 --- a/public/categories/defense/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Defense on Joren's Site - https://joren.blog/categories/defense/ - Recent content in Defense on Joren's Site - Hugo - en - Tue, 12 Nov 2024 00:00:00 +0000 - - - Securing Cyberspace: Belgian Cyber Command at Howest - https://joren.blog/blog/post-3/ - Tue, 12 Nov 2024 00:00:00 +0000 - https://joren.blog/blog/post-3/ - <p>On November 12, we had the opportunity to attend a Tech&amp;Meet session unlike any other. The speaker was <strong>Colonel Gunther Godefridis</strong>, Director for Development &amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.</p> - - - diff --git a/public/categories/dns/index.html b/public/categories/dns/index.html deleted file mode 100644 index 8fb5eb2..0000000 --- a/public/categories/dns/index.html +++ /dev/null @@ -1,9378 +0,0 @@ - - - - - - -Dns - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Dns

-
-
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/dns/index.xml b/public/categories/dns/index.xml deleted file mode 100644 index 0d52dbf..0000000 --- a/public/categories/dns/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Dns on Joren's Site - https://joren.blog/categories/dns/ - Recent content in Dns on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Lean and Local: DNS, VPN, IRC and Ad Blocking - https://joren.blog/project/project-3/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/project/project-3/ - <p>Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.</p> - - - diff --git a/public/categories/education/index.html b/public/categories/education/index.html deleted file mode 100644 index 0312bc8..0000000 --- a/public/categories/education/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Education - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Education

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/education/index.xml b/public/categories/education/index.xml deleted file mode 100644 index 39d43da..0000000 --- a/public/categories/education/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Education on Joren's Site - https://joren.blog/categories/education/ - Recent content in Education on Joren's Site - Hugo - en - Sat, 15 Mar 2025 00:00:00 +0000 - - - Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience - https://joren.blog/blog/post-2/ - Sat, 15 Mar 2025 00:00:00 +0000 - https://joren.blog/blog/post-2/ - <p>On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.</p> - - - diff --git a/public/categories/event/index.html b/public/categories/event/index.html deleted file mode 100644 index 797b46f..0000000 --- a/public/categories/event/index.html +++ /dev/null @@ -1,9523 +0,0 @@ - - - - - - -Event - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Event

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/event/index.xml b/public/categories/event/index.xml deleted file mode 100644 index 3f044df..0000000 --- a/public/categories/event/index.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - Event on Joren's Site - https://joren.blog/categories/event/ - Recent content in Event on Joren's Site - Hugo - en - Tue, 13 May 2025 00:00:00 +0000 - - - Cyber Defence on the Digital Frontline: A Mission with NATO - https://joren.blog/blog/post-1/ - Tue, 13 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-1/ - <h4 id="on-a-mission-with-nato-cyber-defence-on-the-frontline">On a Mission with NATO: Cyber Defence on the Frontline</h4> <p>Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO&rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.</p> - - - Securing Cyberspace: Belgian Cyber Command at Howest - https://joren.blog/blog/post-3/ - Tue, 12 Nov 2024 00:00:00 +0000 - https://joren.blog/blog/post-3/ - <p>On November 12, we had the opportunity to attend a Tech&amp;Meet session unlike any other. The speaker was <strong>Colonel Gunther Godefridis</strong>, Director for Development &amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.</p> - - - diff --git a/public/categories/hardware/index.html b/public/categories/hardware/index.html deleted file mode 100644 index 0122614..0000000 --- a/public/categories/hardware/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Hardware - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Hardware

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/hardware/index.xml b/public/categories/hardware/index.xml deleted file mode 100644 index c1a081d..0000000 --- a/public/categories/hardware/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Hardware on Joren's Site - https://joren.blog/categories/hardware/ - Recent content in Hardware on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera - https://joren.blog/blog/post-8/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-8/ - <p>When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?</p> - - - diff --git a/public/categories/index.html b/public/categories/index.html deleted file mode 100644 index b542a65..0000000 --- a/public/categories/index.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/public/categories/index.xml b/public/categories/index.xml deleted file mode 100644 index d48c01c..0000000 --- a/public/categories/index.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - - Categories on Joren's Site - https://joren.blog/categories/ - Recent content in Categories on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Alpine-Linux - https://joren.blog/categories/alpine-linux/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/alpine-linux/ - - - - Communication - https://joren.blog/categories/communication/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/communication/ - - - - Cybersecurity - https://joren.blog/categories/cybersecurity/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/cybersecurity/ - - - - Decentralization - https://joren.blog/categories/decentralization/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/decentralization/ - - - - Dns - https://joren.blog/categories/dns/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/dns/ - - - - Hardware - https://joren.blog/categories/hardware/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/hardware/ - - - - Iot - https://joren.blog/categories/iot/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/iot/ - - - - Jdm - https://joren.blog/categories/jdm/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/jdm/ - - - - Network - https://joren.blog/categories/network/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/network/ - - - - Networking - https://joren.blog/categories/networking/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/networking/ - - - - Offensive - https://joren.blog/categories/offensive/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/offensive/ - - - - Reverse Engineering - https://joren.blog/categories/reverse-engineering/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/reverse-engineering/ - - - - Seiko - https://joren.blog/categories/seiko/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/seiko/ - - - - Self-Hosting - https://joren.blog/categories/self-hosting/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/self-hosting/ - - - - Vpn - https://joren.blog/categories/vpn/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/vpn/ - - - - Watches - https://joren.blog/categories/watches/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/watches/ - - - - Windows - https://joren.blog/categories/windows/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/categories/windows/ - - - - Interview - https://joren.blog/categories/interview/ - Tue, 20 May 2025 00:00:00 +0000 - https://joren.blog/categories/interview/ - - - - Podcast - https://joren.blog/categories/podcast/ - Tue, 20 May 2025 00:00:00 +0000 - https://joren.blog/categories/podcast/ - - - - Event - https://joren.blog/categories/event/ - Tue, 13 May 2025 00:00:00 +0000 - https://joren.blog/categories/event/ - - - - CTF - https://joren.blog/categories/ctf/ - Sat, 15 Mar 2025 00:00:00 +0000 - https://joren.blog/categories/ctf/ - - - - Education - https://joren.blog/categories/education/ - Sat, 15 Mar 2025 00:00:00 +0000 - https://joren.blog/categories/education/ - - - - Defense - https://joren.blog/categories/defense/ - Tue, 12 Nov 2024 00:00:00 +0000 - https://joren.blog/categories/defense/ - - - - diff --git a/public/categories/interview/index.html b/public/categories/interview/index.html deleted file mode 100644 index 2bf4ab1..0000000 --- a/public/categories/interview/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Interview - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Interview

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/interview/index.xml b/public/categories/interview/index.xml deleted file mode 100644 index c735f17..0000000 --- a/public/categories/interview/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Interview on Joren's Site - https://joren.blog/categories/interview/ - Recent content in Interview on Joren's Site - Hugo - en - Tue, 20 May 2025 00:00:00 +0000 - - - Red Team Talk: Een Blik Achter de Schermen bij Offensive Security - https://joren.blog/blog/post-4/ - Tue, 20 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-4/ - <p>In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met <strong>Thomas Castronovo</strong>, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.</p> - - - diff --git a/public/categories/iot/index.html b/public/categories/iot/index.html deleted file mode 100644 index 28df03e..0000000 --- a/public/categories/iot/index.html +++ /dev/null @@ -1,9454 +0,0 @@ - - - - - - -Iot - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Iot

-
-
- -
- -
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/iot/index.xml b/public/categories/iot/index.xml deleted file mode 100644 index 4641f4a..0000000 --- a/public/categories/iot/index.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - Iot on Joren's Site - https://joren.blog/categories/iot/ - Recent content in Iot on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera - https://joren.blog/blog/post-8/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-8/ - <p>When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?</p> - - - The Smart Home Trap: Isolate or Be Owned - https://joren.blog/blog/post-10/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-10/ - <h1 id="the-smart-home-trap-isolate-or-be-owned">The Smart Home Trap: Isolate or Be Owned</h1> <p>Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you&rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.</p> - - - diff --git a/public/categories/jdm/index.html b/public/categories/jdm/index.html deleted file mode 100644 index 24c1630..0000000 --- a/public/categories/jdm/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Jdm - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Jdm

-
-
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/jdm/index.xml b/public/categories/jdm/index.xml deleted file mode 100644 index 746cf75..0000000 --- a/public/categories/jdm/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Jdm on Joren's Site - https://joren.blog/categories/jdm/ - Recent content in Jdm on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Seiko SARV001: The JDM Sleeper That Punches Above Its Weight - https://joren.blog/blog/post-9/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-9/ - <p>In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001—a watch that combines classic design, reliable mechanics, and exceptional value.</p> - - - diff --git a/public/categories/network/index.html b/public/categories/network/index.html deleted file mode 100644 index 1d8aea0..0000000 --- a/public/categories/network/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Network - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Network

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/network/index.xml b/public/categories/network/index.xml deleted file mode 100644 index 880dea9..0000000 --- a/public/categories/network/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Network on Joren's Site - https://joren.blog/categories/network/ - Recent content in Network on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks - https://joren.blog/blog/post-5/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-5/ - <p>In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using <code>Responder</code> and <code>mitm6</code>.</p> - - - diff --git a/public/categories/networking/index.html b/public/categories/networking/index.html deleted file mode 100644 index adecb73..0000000 --- a/public/categories/networking/index.html +++ /dev/null @@ -1,9462 +0,0 @@ - - - - - - -Networking - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Networking

-
-
- -
- -
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/networking/index.xml b/public/categories/networking/index.xml deleted file mode 100644 index 2a5feae..0000000 --- a/public/categories/networking/index.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - Networking on Joren's Site - https://joren.blog/categories/networking/ - Recent content in Networking on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Lean and Local: DNS, VPN, IRC and Ad Blocking - https://joren.blog/project/project-3/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/project/project-3/ - <p>Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.</p> - - - The Smart Home Trap: Isolate or Be Owned - https://joren.blog/blog/post-10/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-10/ - <h1 id="the-smart-home-trap-isolate-or-be-owned">The Smart Home Trap: Isolate or Be Owned</h1> <p>Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you&rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.</p> - - - diff --git a/public/categories/offensive/index.html b/public/categories/offensive/index.html deleted file mode 100644 index 245e3d5..0000000 --- a/public/categories/offensive/index.html +++ /dev/null @@ -1,9527 +0,0 @@ - - - - - - -Offensive - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Offensive

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/offensive/index.xml b/public/categories/offensive/index.xml deleted file mode 100644 index 5920d05..0000000 --- a/public/categories/offensive/index.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - Offensive on Joren's Site - https://joren.blog/categories/offensive/ - Recent content in Offensive on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains - https://joren.blog/blog/post-7/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-7/ - <p>Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like <strong>Kerberoasting</strong>, <strong>delegation abuse</strong>, and <strong>ticket impersonation</strong>.</p> - - - Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks - https://joren.blog/blog/post-5/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-5/ - <p>In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using <code>Responder</code> and <code>mitm6</code>.</p> - - - diff --git a/public/categories/podcast/index.html b/public/categories/podcast/index.html deleted file mode 100644 index 4faf784..0000000 --- a/public/categories/podcast/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Podcast - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Podcast

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/podcast/index.xml b/public/categories/podcast/index.xml deleted file mode 100644 index 0592de6..0000000 --- a/public/categories/podcast/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Podcast on Joren's Site - https://joren.blog/categories/podcast/ - Recent content in Podcast on Joren's Site - Hugo - en - Tue, 20 May 2025 00:00:00 +0000 - - - Red Team Talk: Een Blik Achter de Schermen bij Offensive Security - https://joren.blog/blog/post-4/ - Tue, 20 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-4/ - <p>In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met <strong>Thomas Castronovo</strong>, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.</p> - - - diff --git a/public/categories/reverse-engineering/index.html b/public/categories/reverse-engineering/index.html deleted file mode 100644 index 920d471..0000000 --- a/public/categories/reverse-engineering/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Reverse Engineering - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Reverse Engineering

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/reverse-engineering/index.xml b/public/categories/reverse-engineering/index.xml deleted file mode 100644 index d1cbb49..0000000 --- a/public/categories/reverse-engineering/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Reverse Engineering on Joren's Site - https://joren.blog/categories/reverse-engineering/ - Recent content in Reverse Engineering on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera - https://joren.blog/blog/post-8/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-8/ - <p>When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?</p> - - - diff --git a/public/categories/seiko/index.html b/public/categories/seiko/index.html deleted file mode 100644 index a2148f0..0000000 --- a/public/categories/seiko/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Seiko - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Seiko

-
-
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/seiko/index.xml b/public/categories/seiko/index.xml deleted file mode 100644 index 5904f89..0000000 --- a/public/categories/seiko/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Seiko on Joren's Site - https://joren.blog/categories/seiko/ - Recent content in Seiko on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Seiko SARV001: The JDM Sleeper That Punches Above Its Weight - https://joren.blog/blog/post-9/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-9/ - <p>In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001—a watch that combines classic design, reliable mechanics, and exceptional value.</p> - - - diff --git a/public/categories/self-hosting/index.html b/public/categories/self-hosting/index.html deleted file mode 100644 index efde1e8..0000000 --- a/public/categories/self-hosting/index.html +++ /dev/null @@ -1,9378 +0,0 @@ - - - - - - -Self-Hosting - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Self-Hosting

-
-
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/self-hosting/index.xml b/public/categories/self-hosting/index.xml deleted file mode 100644 index 78e7905..0000000 --- a/public/categories/self-hosting/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Self-Hosting on Joren's Site - https://joren.blog/categories/self-hosting/ - Recent content in Self-Hosting on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Lean and Local: DNS, VPN, IRC and Ad Blocking - https://joren.blog/project/project-3/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/project/project-3/ - <p>Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.</p> - - - diff --git a/public/categories/vpn/index.html b/public/categories/vpn/index.html deleted file mode 100644 index b4b9639..0000000 --- a/public/categories/vpn/index.html +++ /dev/null @@ -1,9378 +0,0 @@ - - - - - - -Vpn - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Vpn

-
-
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/vpn/index.xml b/public/categories/vpn/index.xml deleted file mode 100644 index 9654f0f..0000000 --- a/public/categories/vpn/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Vpn on Joren's Site - https://joren.blog/categories/vpn/ - Recent content in Vpn on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Lean and Local: DNS, VPN, IRC and Ad Blocking - https://joren.blog/project/project-3/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/project/project-3/ - <p>Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.</p> - - - diff --git a/public/categories/watches/index.html b/public/categories/watches/index.html deleted file mode 100644 index 85cdecb..0000000 --- a/public/categories/watches/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Watches - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Watches

-
-
- -
- -
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/watches/index.xml b/public/categories/watches/index.xml deleted file mode 100644 index 0421ae0..0000000 --- a/public/categories/watches/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Watches on Joren's Site - https://joren.blog/categories/watches/ - Recent content in Watches on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Seiko SARV001: The JDM Sleeper That Punches Above Its Weight - https://joren.blog/blog/post-9/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-9/ - <p>In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001—a watch that combines classic design, reliable mechanics, and exceptional value.</p> - - - diff --git a/public/categories/windows/index.html b/public/categories/windows/index.html deleted file mode 100644 index bf19069..0000000 --- a/public/categories/windows/index.html +++ /dev/null @@ -1,9370 +0,0 @@ - - - - - - -Windows - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Joren's Site - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
-
-
-
- -

Category

- -

//Windows

-
- -
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/categories/windows/index.xml b/public/categories/windows/index.xml deleted file mode 100644 index 2060fb4..0000000 --- a/public/categories/windows/index.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Windows on Joren's Site - https://joren.blog/categories/windows/ - Recent content in Windows on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains - https://joren.blog/blog/post-7/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/blog/post-7/ - <p>Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like <strong>Kerberoasting</strong>, <strong>delegation abuse</strong>, and <strong>ticket impersonation</strong>.</p> - - - diff --git a/public/css/style.af64285d60a6cb7cb62ddf607404d8222a33b5fd6b0c9aacafef33456be01ed2.css b/public/css/style.af64285d60a6cb7cb62ddf607404d8222a33b5fd6b0c9aacafef33456be01ed2.css deleted file mode 100644 index 80c036b..0000000 --- a/public/css/style.af64285d60a6cb7cb62ddf607404d8222a33b5fd6b0c9aacafef33456be01ed2.css +++ /dev/null @@ -1,18567 +0,0 @@ -/*! - * Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - * Copyright 2023 Fonticons, Inc. - */ -:root, -:host { - --fa-font-brands: normal 400 1em/1 "Font Awesome 6 Brands"; -} - -@font-face { - font-family: "Font Awesome 6 Brands"; - font-style: normal; - font-weight: 400; - font-display: block; - src: url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/webfonts/fa-brands-400.woff2") - format("woff2"), - url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/webfonts/fa-brands-400.ttf") - format("truetype"); -} - -.fab, -.fa-brands { - font-weight: 400; } - -.fa-monero:before { - content: "\f3d0"; } - -.fa-hooli:before { - content: "\f427"; } - -.fa-yelp:before { - content: "\f1e9"; } - -.fa-cc-visa:before { - content: "\f1f0"; } - -.fa-lastfm:before { - content: "\f202"; } - -.fa-shopware:before { - content: "\f5b5"; } - -.fa-creative-commons-nc:before { - content: "\f4e8"; } - -.fa-aws:before { - content: "\f375"; } - -.fa-redhat:before { - content: "\f7bc"; } - -.fa-yoast:before { - content: "\f2b1"; } - -.fa-cloudflare:before { - content: "\e07d"; } - -.fa-ups:before { - content: "\f7e0"; } - -.fa-wpexplorer:before { - content: "\f2de"; } - -.fa-dyalog:before { - content: "\f399"; } - -.fa-bity:before { - content: "\f37a"; } - -.fa-stackpath:before { - content: "\f842"; } - -.fa-buysellads:before { - content: "\f20d"; } - -.fa-first-order:before { - content: "\f2b0"; } - -.fa-modx:before { - content: "\f285"; } - -.fa-guilded:before { - content: "\e07e"; } - -.fa-vnv:before { - content: "\f40b"; } - -.fa-square-js:before { - content: "\f3b9"; } - -.fa-js-square:before { - content: "\f3b9"; } - -.fa-microsoft:before { - content: "\f3ca"; } - -.fa-qq:before { - content: "\f1d6"; } - -.fa-orcid:before { - content: "\f8d2"; } - -.fa-java:before { - content: "\f4e4"; } - -.fa-invision:before { - content: "\f7b0"; } - -.fa-creative-commons-pd-alt:before { - content: "\f4ed"; } - -.fa-centercode:before { - content: "\f380"; } - -.fa-glide-g:before { - content: "\f2a6"; } - -.fa-drupal:before { - content: "\f1a9"; } - -.fa-hire-a-helper:before { - content: "\f3b0"; } - -.fa-creative-commons-by:before { - content: "\f4e7"; } - -.fa-unity:before { - content: "\e049"; } - -.fa-whmcs:before { - content: "\f40d"; } - -.fa-rocketchat:before { - content: "\f3e8"; } - -.fa-vk:before { - content: "\f189"; } - -.fa-untappd:before { - content: "\f405"; } - -.fa-mailchimp:before { - content: "\f59e"; } - -.fa-css3-alt:before { - content: "\f38b"; } - -.fa-square-reddit:before { - content: "\f1a2"; } - -.fa-reddit-square:before { - content: "\f1a2"; } - -.fa-vimeo-v:before { - content: "\f27d"; } - -.fa-contao:before { - content: "\f26d"; } - -.fa-square-font-awesome:before { - content: "\e5ad"; } - -.fa-deskpro:before { - content: "\f38f"; } - -.fa-sistrix:before { - content: "\f3ee"; } - -.fa-square-instagram:before { - content: "\e055"; } - -.fa-instagram-square:before { - content: "\e055"; } - -.fa-battle-net:before { - content: "\f835"; } - -.fa-the-red-yeti:before { - content: "\f69d"; } - -.fa-square-hacker-news:before { - content: "\f3af"; } - -.fa-hacker-news-square:before { - content: "\f3af"; } - -.fa-edge:before { - content: "\f282"; } - -.fa-threads:before { - content: "\e618"; } - -.fa-napster:before { - content: "\f3d2"; } - -.fa-square-snapchat:before { - content: "\f2ad"; } - -.fa-snapchat-square:before { - content: "\f2ad"; } - -.fa-google-plus-g:before { - content: "\f0d5"; } - -.fa-artstation:before { - content: "\f77a"; } - -.fa-markdown:before { - content: "\f60f"; } - -.fa-sourcetree:before { - content: "\f7d3"; } - -.fa-google-plus:before { - content: "\f2b3"; } - -.fa-diaspora:before { - content: "\f791"; } - -.fa-foursquare:before { - content: "\f180"; } - -.fa-stack-overflow:before { - content: "\f16c"; } - -.fa-github-alt:before { - content: "\f113"; } - -.fa-phoenix-squadron:before { - content: "\f511"; } - -.fa-pagelines:before { - content: "\f18c"; } - -.fa-algolia:before { - content: "\f36c"; } - -.fa-red-river:before { - content: "\f3e3"; } - -.fa-creative-commons-sa:before { - content: "\f4ef"; } - -.fa-safari:before { - content: "\f267"; } - -.fa-google:before { - content: "\f1a0"; } - -.fa-square-font-awesome-stroke:before { - content: "\f35c"; } - -.fa-font-awesome-alt:before { - content: "\f35c"; } - -.fa-atlassian:before { - content: "\f77b"; } - -.fa-linkedin-in:before { - content: "\f0e1"; } - -.fa-digital-ocean:before { - content: "\f391"; } - -.fa-nimblr:before { - content: "\f5a8"; } - -.fa-chromecast:before { - content: "\f838"; } - -.fa-evernote:before { - content: "\f839"; } - -.fa-hacker-news:before { - content: "\f1d4"; } - -.fa-creative-commons-sampling:before { - content: "\f4f0"; } - -.fa-adversal:before { - content: "\f36a"; } - -.fa-creative-commons:before { - content: "\f25e"; } - -.fa-watchman-monitoring:before { - content: "\e087"; } - -.fa-fonticons:before { - content: "\f280"; } - -.fa-weixin:before { - content: "\f1d7"; } - -.fa-shirtsinbulk:before { - content: "\f214"; } - -.fa-codepen:before { - content: "\f1cb"; } - -.fa-git-alt:before { - content: "\f841"; } - -.fa-lyft:before { - content: "\f3c3"; } - -.fa-rev:before { - content: "\f5b2"; } - -.fa-windows:before { - content: "\f17a"; } - -.fa-wizards-of-the-coast:before { - content: "\f730"; } - -.fa-square-viadeo:before { - content: "\f2aa"; } - -.fa-viadeo-square:before { - content: "\f2aa"; } - -.fa-meetup:before { - content: "\f2e0"; } - -.fa-centos:before { - content: "\f789"; } - -.fa-adn:before { - content: "\f170"; } - -.fa-cloudsmith:before { - content: "\f384"; } - -.fa-pied-piper-alt:before { - content: "\f1a8"; } - -.fa-square-dribbble:before { - content: "\f397"; } - -.fa-dribbble-square:before { - content: "\f397"; } - -.fa-codiepie:before { - content: "\f284"; } - -.fa-node:before { - content: "\f419"; } - -.fa-mix:before { - content: "\f3cb"; } - -.fa-steam:before { - content: "\f1b6"; } - -.fa-cc-apple-pay:before { - content: "\f416"; } - -.fa-scribd:before { - content: "\f28a"; } - -.fa-debian:before { - content: "\e60b"; } - -.fa-openid:before { - content: "\f19b"; } - -.fa-instalod:before { - content: "\e081"; } - -.fa-expeditedssl:before { - content: "\f23e"; } - -.fa-sellcast:before { - content: "\f2da"; } - -.fa-square-twitter:before { - content: "\f081"; } - -.fa-twitter-square:before { - content: "\f081"; } - -.fa-r-project:before { - content: "\f4f7"; } - -.fa-delicious:before { - content: "\f1a5"; } - -.fa-freebsd:before { - content: "\f3a4"; } - -.fa-vuejs:before { - content: "\f41f"; } - -.fa-accusoft:before { - content: "\f369"; } - -.fa-ioxhost:before { - content: "\f208"; } - -.fa-fonticons-fi:before { - content: "\f3a2"; } - -.fa-app-store:before { - content: "\f36f"; } - -.fa-cc-mastercard:before { - content: "\f1f1"; } - -.fa-itunes-note:before { - content: "\f3b5"; } - -.fa-golang:before { - content: "\e40f"; } - -.fa-kickstarter:before { - content: "\f3bb"; } - -.fa-grav:before { - content: "\f2d6"; } - -.fa-weibo:before { - content: "\f18a"; } - -.fa-uncharted:before { - content: "\e084"; } - -.fa-firstdraft:before { - content: "\f3a1"; } - -.fa-square-youtube:before { - content: "\f431"; } - -.fa-youtube-square:before { - content: "\f431"; } - -.fa-wikipedia-w:before { - content: "\f266"; } - -.fa-wpressr:before { - content: "\f3e4"; } - -.fa-rendact:before { - content: "\f3e4"; } - -.fa-angellist:before { - content: "\f209"; } - -.fa-galactic-republic:before { - content: "\f50c"; } - -.fa-nfc-directional:before { - content: "\e530"; } - -.fa-skype:before { - content: "\f17e"; } - -.fa-joget:before { - content: "\f3b7"; } - -.fa-fedora:before { - content: "\f798"; } - -.fa-stripe-s:before { - content: "\f42a"; } - -.fa-meta:before { - content: "\e49b"; } - -.fa-laravel:before { - content: "\f3bd"; } - -.fa-hotjar:before { - content: "\f3b1"; } - -.fa-bluetooth-b:before { - content: "\f294"; } - -.fa-sticker-mule:before { - content: "\f3f7"; } - -.fa-creative-commons-zero:before { - content: "\f4f3"; } - -.fa-hips:before { - content: "\f452"; } - -.fa-behance:before { - content: "\f1b4"; } - -.fa-reddit:before { - content: "\f1a1"; } - -.fa-discord:before { - content: "\f392"; } - -.fa-chrome:before { - content: "\f268"; } - -.fa-app-store-ios:before { - content: "\f370"; } - -.fa-cc-discover:before { - content: "\f1f2"; } - -.fa-wpbeginner:before { - content: "\f297"; } - -.fa-confluence:before { - content: "\f78d"; } - -.fa-mdb:before { - content: "\f8ca"; } - -.fa-dochub:before { - content: "\f394"; } - -.fa-accessible-icon:before { - content: "\f368"; } - -.fa-ebay:before { - content: "\f4f4"; } - -.fa-amazon:before { - content: "\f270"; } - -.fa-unsplash:before { - content: "\e07c"; } - -.fa-yarn:before { - content: "\f7e3"; } - -.fa-square-steam:before { - content: "\f1b7"; } - -.fa-steam-square:before { - content: "\f1b7"; } - -.fa-500px:before { - content: "\f26e"; } - -.fa-square-vimeo:before { - content: "\f194"; } - -.fa-vimeo-square:before { - content: "\f194"; } - -.fa-asymmetrik:before { - content: "\f372"; } - -.fa-font-awesome:before { - content: "\f2b4"; } - -.fa-font-awesome-flag:before { - content: "\f2b4"; } - -.fa-font-awesome-logo-full:before { - content: "\f2b4"; } - -.fa-gratipay:before { - content: "\f184"; } - -.fa-apple:before { - content: "\f179"; } - -.fa-hive:before { - content: "\e07f"; } - -.fa-gitkraken:before { - content: "\f3a6"; } - -.fa-keybase:before { - content: "\f4f5"; } - -.fa-apple-pay:before { - content: "\f415"; } - -.fa-padlet:before { - content: "\e4a0"; } - -.fa-amazon-pay:before { - content: "\f42c"; } - -.fa-square-github:before { - content: "\f092"; } - -.fa-github-square:before { - content: "\f092"; } - -.fa-stumbleupon:before { - content: "\f1a4"; } - -.fa-fedex:before { - content: "\f797"; } - -.fa-phoenix-framework:before { - content: "\f3dc"; } - -.fa-shopify:before { - content: "\e057"; } - -.fa-neos:before { - content: "\f612"; } - -.fa-square-threads:before { - content: "\e619"; } - -.fa-hackerrank:before { - content: "\f5f7"; } - -.fa-researchgate:before { - content: "\f4f8"; } - -.fa-swift:before { - content: "\f8e1"; } - -.fa-angular:before { - content: "\f420"; } - -.fa-speakap:before { - content: "\f3f3"; } - -.fa-angrycreative:before { - content: "\f36e"; } - -.fa-y-combinator:before { - content: "\f23b"; } - -.fa-empire:before { - content: "\f1d1"; } - -.fa-envira:before { - content: "\f299"; } - -.fa-square-gitlab:before { - content: "\e5ae"; } - -.fa-gitlab-square:before { - content: "\e5ae"; } - -.fa-studiovinari:before { - content: "\f3f8"; } - -.fa-pied-piper:before { - content: "\f2ae"; } - -.fa-wordpress:before { - content: "\f19a"; } - -.fa-product-hunt:before { - content: "\f288"; } - -.fa-firefox:before { - content: "\f269"; } - -.fa-linode:before { - content: "\f2b8"; } - -.fa-goodreads:before { - content: "\f3a8"; } - -.fa-square-odnoklassniki:before { - content: "\f264"; } - -.fa-odnoklassniki-square:before { - content: "\f264"; } - -.fa-jsfiddle:before { - content: "\f1cc"; } - -.fa-sith:before { - content: "\f512"; } - -.fa-themeisle:before { - content: "\f2b2"; } - -.fa-page4:before { - content: "\f3d7"; } - -.fa-hashnode:before { - content: "\e499"; } - -.fa-react:before { - content: "\f41b"; } - -.fa-cc-paypal:before { - content: "\f1f4"; } - -.fa-squarespace:before { - content: "\f5be"; } - -.fa-cc-stripe:before { - content: "\f1f5"; } - -.fa-creative-commons-share:before { - content: "\f4f2"; } - -.fa-bitcoin:before { - content: "\f379"; } - -.fa-keycdn:before { - content: "\f3ba"; } - -.fa-opera:before { - content: "\f26a"; } - -.fa-itch-io:before { - content: "\f83a"; } - -.fa-umbraco:before { - content: "\f8e8"; } - -.fa-galactic-senate:before { - content: "\f50d"; } - -.fa-ubuntu:before { - content: "\f7df"; } - -.fa-draft2digital:before { - content: "\f396"; } - -.fa-stripe:before { - content: "\f429"; } - -.fa-houzz:before { - content: "\f27c"; } - -.fa-gg:before { - content: "\f260"; } - -.fa-dhl:before { - content: "\f790"; } - -.fa-square-pinterest:before { - content: "\f0d3"; } - -.fa-pinterest-square:before { - content: "\f0d3"; } - -.fa-xing:before { - content: "\f168"; } - -.fa-blackberry:before { - content: "\f37b"; } - -.fa-creative-commons-pd:before { - content: "\f4ec"; } - -.fa-playstation:before { - content: "\f3df"; } - -.fa-quinscape:before { - content: "\f459"; } - -.fa-less:before { - content: "\f41d"; } - -.fa-blogger-b:before { - content: "\f37d"; } - -.fa-opencart:before { - content: "\f23d"; } - -.fa-vine:before { - content: "\f1ca"; } - -.fa-paypal:before { - content: "\f1ed"; } - -.fa-gitlab:before { - content: "\f296"; } - -.fa-typo3:before { - content: "\f42b"; } - -.fa-reddit-alien:before { - content: "\f281"; } - -.fa-yahoo:before { - content: "\f19e"; } - -.fa-dailymotion:before { - content: "\e052"; } - -.fa-affiliatetheme:before { - content: "\f36b"; } - -.fa-pied-piper-pp:before { - content: "\f1a7"; } - -.fa-bootstrap:before { - content: "\f836"; } - -.fa-odnoklassniki:before { - content: "\f263"; } - -.fa-nfc-symbol:before { - content: "\e531"; } - -.fa-ethereum:before { - content: "\f42e"; } - -.fa-speaker-deck:before { - content: "\f83c"; } - -.fa-creative-commons-nc-eu:before { - content: "\f4e9"; } - -.fa-patreon:before { - content: "\f3d9"; } - -.fa-avianex:before { - content: "\f374"; } - -.fa-ello:before { - content: "\f5f1"; } - -.fa-gofore:before { - content: "\f3a7"; } - -.fa-bimobject:before { - content: "\f378"; } - -.fa-facebook-f:before { - content: "\f39e"; } - -.fa-square-google-plus:before { - content: "\f0d4"; } - -.fa-google-plus-square:before { - content: "\f0d4"; } - -.fa-mandalorian:before { - content: "\f50f"; } - -.fa-first-order-alt:before { - content: "\f50a"; } - -.fa-osi:before { - content: "\f41a"; } - -.fa-google-wallet:before { - content: "\f1ee"; } - -.fa-d-and-d-beyond:before { - content: "\f6ca"; } - -.fa-periscope:before { - content: "\f3da"; } - -.fa-fulcrum:before { - content: "\f50b"; } - -.fa-cloudscale:before { - content: "\f383"; } - -.fa-forumbee:before { - content: "\f211"; } - -.fa-mizuni:before { - content: "\f3cc"; } - -.fa-schlix:before { - content: "\f3ea"; } - -.fa-square-xing:before { - content: "\f169"; } - -.fa-xing-square:before { - content: "\f169"; } - -.fa-bandcamp:before { - content: "\f2d5"; } - -.fa-wpforms:before { - content: "\f298"; } - -.fa-cloudversify:before { - content: "\f385"; } - -.fa-usps:before { - content: "\f7e1"; } - -.fa-megaport:before { - content: "\f5a3"; } - -.fa-magento:before { - content: "\f3c4"; } - -.fa-spotify:before { - content: "\f1bc"; } - -.fa-optin-monster:before { - content: "\f23c"; } - -.fa-fly:before { - content: "\f417"; } - -.fa-aviato:before { - content: "\f421"; } - -.fa-itunes:before { - content: "\f3b4"; } - -.fa-cuttlefish:before { - content: "\f38c"; } - -.fa-blogger:before { - content: "\f37c"; } - -.fa-flickr:before { - content: "\f16e"; } - -.fa-viber:before { - content: "\f409"; } - -.fa-soundcloud:before { - content: "\f1be"; } - -.fa-digg:before { - content: "\f1a6"; } - -.fa-tencent-weibo:before { - content: "\f1d5"; } - -.fa-symfony:before { - content: "\f83d"; } - -.fa-maxcdn:before { - content: "\f136"; } - -.fa-etsy:before { - content: "\f2d7"; } - -.fa-facebook-messenger:before { - content: "\f39f"; } - -.fa-audible:before { - content: "\f373"; } - -.fa-think-peaks:before { - content: "\f731"; } - -.fa-bilibili:before { - content: "\e3d9"; } - -.fa-erlang:before { - content: "\f39d"; } - -.fa-x-twitter:before { - content: "\e61b"; } - -.fa-cotton-bureau:before { - content: "\f89e"; } - -.fa-dashcube:before { - content: "\f210"; } - -.fa-42-group:before { - content: "\e080"; } - -.fa-innosoft:before { - content: "\e080"; } - -.fa-stack-exchange:before { - content: "\f18d"; } - -.fa-elementor:before { - content: "\f430"; } - -.fa-square-pied-piper:before { - content: "\e01e"; } - -.fa-pied-piper-square:before { - content: "\e01e"; } - -.fa-creative-commons-nd:before { - content: "\f4eb"; } - -.fa-palfed:before { - content: "\f3d8"; } - -.fa-superpowers:before { - content: "\f2dd"; } - -.fa-resolving:before { - content: "\f3e7"; } - -.fa-xbox:before { - content: "\f412"; } - -.fa-searchengin:before { - content: "\f3eb"; } - -.fa-tiktok:before { - content: "\e07b"; } - -.fa-square-facebook:before { - content: "\f082"; } - -.fa-facebook-square:before { - content: "\f082"; } - -.fa-renren:before { - content: "\f18b"; } - -.fa-linux:before { - content: "\f17c"; } - -.fa-glide:before { - content: "\f2a5"; } - -.fa-linkedin:before { - content: "\f08c"; } - -.fa-hubspot:before { - content: "\f3b2"; } - -.fa-deploydog:before { - content: "\f38e"; } - -.fa-twitch:before { - content: "\f1e8"; } - -.fa-ravelry:before { - content: "\f2d9"; } - -.fa-mixer:before { - content: "\e056"; } - -.fa-square-lastfm:before { - content: "\f203"; } - -.fa-lastfm-square:before { - content: "\f203"; } - -.fa-vimeo:before { - content: "\f40a"; } - -.fa-mendeley:before { - content: "\f7b3"; } - -.fa-uniregistry:before { - content: "\f404"; } - -.fa-figma:before { - content: "\f799"; } - -.fa-creative-commons-remix:before { - content: "\f4ee"; } - -.fa-cc-amazon-pay:before { - content: "\f42d"; } - -.fa-dropbox:before { - content: "\f16b"; } - -.fa-instagram:before { - content: "\f16d"; } - -.fa-cmplid:before { - content: "\e360"; } - -.fa-facebook:before { - content: "\f09a"; } - -.fa-gripfire:before { - content: "\f3ac"; } - -.fa-jedi-order:before { - content: "\f50e"; } - -.fa-uikit:before { - content: "\f403"; } - -.fa-fort-awesome-alt:before { - content: "\f3a3"; } - -.fa-phabricator:before { - content: "\f3db"; } - -.fa-ussunnah:before { - content: "\f407"; } - -.fa-earlybirds:before { - content: "\f39a"; } - -.fa-trade-federation:before { - content: "\f513"; } - -.fa-autoprefixer:before { - content: "\f41c"; } - -.fa-whatsapp:before { - content: "\f232"; } - -.fa-slideshare:before { - content: "\f1e7"; } - -.fa-google-play:before { - content: "\f3ab"; } - -.fa-viadeo:before { - content: "\f2a9"; } - -.fa-line:before { - content: "\f3c0"; } - -.fa-google-drive:before { - content: "\f3aa"; } - -.fa-servicestack:before { - content: "\f3ec"; } - -.fa-simplybuilt:before { - content: "\f215"; } - -.fa-bitbucket:before { - content: "\f171"; } - -.fa-imdb:before { - content: "\f2d8"; } - -.fa-deezer:before { - content: "\e077"; } - -.fa-raspberry-pi:before { - content: "\f7bb"; } - -.fa-jira:before { - content: "\f7b1"; } - -.fa-docker:before { - content: "\f395"; } - -.fa-screenpal:before { - content: "\e570"; } - -.fa-bluetooth:before { - content: "\f293"; } - -.fa-gitter:before { - content: "\f426"; } - -.fa-d-and-d:before { - content: "\f38d"; } - -.fa-microblog:before { - content: "\e01a"; } - -.fa-cc-diners-club:before { - content: "\f24c"; } - -.fa-gg-circle:before { - content: "\f261"; } - -.fa-pied-piper-hat:before { - content: "\f4e5"; } - -.fa-kickstarter-k:before { - content: "\f3bc"; } - -.fa-yandex:before { - content: "\f413"; } - -.fa-readme:before { - content: "\f4d5"; } - -.fa-html5:before { - content: "\f13b"; } - -.fa-sellsy:before { - content: "\f213"; } - -.fa-sass:before { - content: "\f41e"; } - -.fa-wirsindhandwerk:before { - content: "\e2d0"; } - -.fa-wsh:before { - content: "\e2d0"; } - -.fa-buromobelexperte:before { - content: "\f37f"; } - -.fa-salesforce:before { - content: "\f83b"; } - -.fa-octopus-deploy:before { - content: "\e082"; } - -.fa-medapps:before { - content: "\f3c6"; } - -.fa-ns8:before { - content: "\f3d5"; } - -.fa-pinterest-p:before { - content: "\f231"; } - -.fa-apper:before { - content: "\f371"; } - -.fa-fort-awesome:before { - content: "\f286"; } - -.fa-waze:before { - content: "\f83f"; } - -.fa-cc-jcb:before { - content: "\f24b"; } - -.fa-snapchat:before { - content: "\f2ab"; } - -.fa-snapchat-ghost:before { - content: "\f2ab"; } - -.fa-fantasy-flight-games:before { - content: "\f6dc"; } - -.fa-rust:before { - content: "\e07a"; } - -.fa-wix:before { - content: "\f5cf"; } - -.fa-square-behance:before { - content: "\f1b5"; } - -.fa-behance-square:before { - content: "\f1b5"; } - -.fa-supple:before { - content: "\f3f9"; } - -.fa-rebel:before { - content: "\f1d0"; } - -.fa-css3:before { - content: "\f13c"; } - -.fa-staylinked:before { - content: "\f3f5"; } - -.fa-kaggle:before { - content: "\f5fa"; } - -.fa-space-awesome:before { - content: "\e5ac"; } - -.fa-deviantart:before { - content: "\f1bd"; } - -.fa-cpanel:before { - content: "\f388"; } - -.fa-goodreads-g:before { - content: "\f3a9"; } - -.fa-square-git:before { - content: "\f1d2"; } - -.fa-git-square:before { - content: "\f1d2"; } - -.fa-square-tumblr:before { - content: "\f174"; } - -.fa-tumblr-square:before { - content: "\f174"; } - -.fa-trello:before { - content: "\f181"; } - -.fa-creative-commons-nc-jp:before { - content: "\f4ea"; } - -.fa-get-pocket:before { - content: "\f265"; } - -.fa-perbyte:before { - content: "\e083"; } - -.fa-grunt:before { - content: "\f3ad"; } - -.fa-weebly:before { - content: "\f5cc"; } - -.fa-connectdevelop:before { - content: "\f20e"; } - -.fa-leanpub:before { - content: "\f212"; } - -.fa-black-tie:before { - content: "\f27e"; } - -.fa-themeco:before { - content: "\f5c6"; } - -.fa-python:before { - content: "\f3e2"; } - -.fa-android:before { - content: "\f17b"; } - -.fa-bots:before { - content: "\e340"; } - -.fa-free-code-camp:before { - content: "\f2c5"; } - -.fa-hornbill:before { - content: "\f592"; } - -.fa-js:before { - content: "\f3b8"; } - -.fa-ideal:before { - content: "\e013"; } - -.fa-git:before { - content: "\f1d3"; } - -.fa-dev:before { - content: "\f6cc"; } - -.fa-sketch:before { - content: "\f7c6"; } - -.fa-yandex-international:before { - content: "\f414"; } - -.fa-cc-amex:before { - content: "\f1f3"; } - -.fa-uber:before { - content: "\f402"; } - -.fa-github:before { - content: "\f09b"; } - -.fa-php:before { - content: "\f457"; } - -.fa-alipay:before { - content: "\f642"; } - -.fa-youtube:before { - content: "\f167"; } - -.fa-skyatlas:before { - content: "\f216"; } - -.fa-firefox-browser:before { - content: "\e007"; } - -.fa-replyd:before { - content: "\f3e6"; } - -.fa-suse:before { - content: "\f7d6"; } - -.fa-jenkins:before { - content: "\f3b6"; } - -.fa-twitter:before { - content: "\f099"; } - -.fa-rockrms:before { - content: "\f3e9"; } - -.fa-pinterest:before { - content: "\f0d2"; } - -.fa-buffer:before { - content: "\f837"; } - -.fa-npm:before { - content: "\f3d4"; } - -.fa-yammer:before { - content: "\f840"; } - -.fa-btc:before { - content: "\f15a"; } - -.fa-dribbble:before { - content: "\f17d"; } - -.fa-stumbleupon-circle:before { - content: "\f1a3"; } - -.fa-internet-explorer:before { - content: "\f26b"; } - -.fa-stubber:before { - content: "\e5c7"; } - -.fa-telegram:before { - content: "\f2c6"; } - -.fa-telegram-plane:before { - content: "\f2c6"; } - -.fa-old-republic:before { - content: "\f510"; } - -.fa-odysee:before { - content: "\e5c6"; } - -.fa-square-whatsapp:before { - content: "\f40c"; } - -.fa-whatsapp-square:before { - content: "\f40c"; } - -.fa-node-js:before { - content: "\f3d3"; } - -.fa-edge-legacy:before { - content: "\e078"; } - -.fa-slack:before { - content: "\f198"; } - -.fa-slack-hash:before { - content: "\f198"; } - -.fa-medrt:before { - content: "\f3c8"; } - -.fa-usb:before { - content: "\f287"; } - -.fa-tumblr:before { - content: "\f173"; } - -.fa-vaadin:before { - content: "\f408"; } - -.fa-quora:before { - content: "\f2c4"; } - -.fa-square-x-twitter:before { - content: "\e61a"; } - -.fa-reacteurope:before { - content: "\f75d"; } - -.fa-medium:before { - content: "\f23a"; } - -.fa-medium-m:before { - content: "\f23a"; } - -.fa-amilia:before { - content: "\f36d"; } - -.fa-mixcloud:before { - content: "\f289"; } - -.fa-flipboard:before { - content: "\f44d"; } - -.fa-viacoin:before { - content: "\f237"; } - -.fa-critical-role:before { - content: "\f6c9"; } - -.fa-sitrox:before { - content: "\e44a"; } - -.fa-discourse:before { - content: "\f393"; } - -.fa-joomla:before { - content: "\f1aa"; } - -.fa-mastodon:before { - content: "\f4f6"; } - -.fa-airbnb:before { - content: "\f834"; } - -.fa-wolf-pack-battalion:before { - content: "\f514"; } - -.fa-buy-n-large:before { - content: "\f8a6"; } - -.fa-gulp:before { - content: "\f3ae"; } - -.fa-creative-commons-sampling-plus:before { - content: "\f4f1"; } - -.fa-strava:before { - content: "\f428"; } - -.fa-ember:before { - content: "\f423"; } - -.fa-canadian-maple-leaf:before { - content: "\f785"; } - -.fa-teamspeak:before { - content: "\f4f9"; } - -.fa-pushed:before { - content: "\f3e1"; } - -.fa-wordpress-simple:before { - content: "\f411"; } - -.fa-nutritionix:before { - content: "\f3d6"; } - -.fa-wodu:before { - content: "\e088"; } - -.fa-google-pay:before { - content: "\e079"; } - -.fa-intercom:before { - content: "\f7af"; } - -.fa-zhihu:before { - content: "\f63f"; } - -.fa-korvue:before { - content: "\f42f"; } - -.fa-pix:before { - content: "\e43a"; } - -.fa-steam-symbol:before { - content: "\f3f6"; }/*! - * Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - * Copyright 2023 Fonticons, Inc. - */ - :root, :host { - --fa-style-family-classic: 'Font Awesome 6 Free'; - --fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; } - -@font-face { - font-family: 'Font Awesome 6 Free'; - font-style: normal; - font-weight: 900; - font-display: block; - src: url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/webfonts/fa-solid-900.woff2") - format("woff2"), - url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/webfonts/fa-solid-900.ttf") - format("truetype"); } - -.fas, -.fa-solid { - font-weight: 900; } -/*! - * Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - * Copyright 2023 Fonticons, Inc. - */ - .fa { - font-family: var(--fa-style-family, "Font Awesome 6 Free"); - font-weight: var(--fa-style, 900); } - -.fa, -.fa-classic, -.fa-sharp, -.fas, -.fa-solid, -.far, -.fa-regular, -.fab, -.fa-brands { - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - display: var(--fa-display, inline-block); - font-style: normal; - font-variant: normal; - line-height: 1; - text-rendering: auto; } - -.fas, -.fa-classic, -.fa-solid, -.far, -.fa-regular { - font-family: 'Font Awesome 6 Free'; } - -.fab, -.fa-brands { - font-family: 'Font Awesome 6 Brands'; } - -.fa-1x { - font-size: 1em; } - -.fa-2x { - font-size: 2em; } - -.fa-3x { - font-size: 3em; } - -.fa-4x { - font-size: 4em; } - -.fa-5x { - font-size: 5em; } - -.fa-6x { - font-size: 6em; } - -.fa-7x { - font-size: 7em; } - -.fa-8x { - font-size: 8em; } - -.fa-9x { - font-size: 9em; } - -.fa-10x { - font-size: 10em; } - -.fa-2xs { - font-size: 0.625em; - line-height: 0.1em; - vertical-align: 0.225em; } - -.fa-xs { - font-size: 0.75em; - line-height: 0.08333em; - vertical-align: 0.125em; } - -.fa-sm { - font-size: 0.875em; - line-height: 0.07143em; - vertical-align: 0.05357em; } - -.fa-lg { - font-size: 1.25em; - line-height: 0.05em; - vertical-align: -0.075em; } - -.fa-xl { - font-size: 1.5em; - line-height: 0.04167em; - vertical-align: -0.125em; } - -.fa-2xl { - font-size: 2em; - line-height: 0.03125em; - vertical-align: -0.1875em; } - -.fa-fw { - text-align: center; - width: 1.25em; } - -.fa-ul { - list-style-type: none; - margin-left: var(--fa-li-margin, 2.5em); - padding-left: 0; } - .fa-ul > li { - position: relative; } - -.fa-li { - left: calc(var(--fa-li-width, 2em) * -1); - position: absolute; - text-align: center; - width: var(--fa-li-width, 2em); - line-height: inherit; } - -.fa-border { - border-color: var(--fa-border-color, #eee); - border-radius: var(--fa-border-radius, 0.1em); - border-style: var(--fa-border-style, solid); - border-width: var(--fa-border-width, 0.08em); - padding: var(--fa-border-padding, 0.2em 0.25em 0.15em); } - -.fa-pull-left { - float: left; - margin-right: var(--fa-pull-margin, 0.3em); } - -.fa-pull-right { - float: right; - margin-left: var(--fa-pull-margin, 0.3em); } - -.fa-beat { - -webkit-animation-name: fa-beat; - animation-name: fa-beat; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out); - animation-timing-function: var(--fa-animation-timing, ease-in-out); } - -.fa-bounce { - -webkit-animation-name: fa-bounce; - animation-name: fa-bounce; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); - animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); } - -.fa-fade { - -webkit-animation-name: fa-fade; - animation-name: fa-fade; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); - animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); } - -.fa-beat-fade { - -webkit-animation-name: fa-beat-fade; - animation-name: fa-beat-fade; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); - animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); } - -.fa-flip { - -webkit-animation-name: fa-flip; - animation-name: fa-flip; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out); - animation-timing-function: var(--fa-animation-timing, ease-in-out); } - -.fa-shake { - -webkit-animation-name: fa-shake; - animation-name: fa-shake; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, linear); - animation-timing-function: var(--fa-animation-timing, linear); } - -.fa-spin { - -webkit-animation-name: fa-spin; - animation-name: fa-spin; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 2s); - animation-duration: var(--fa-animation-duration, 2s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, linear); - animation-timing-function: var(--fa-animation-timing, linear); } - -.fa-spin-reverse { - --fa-animation-direction: reverse; } - -.fa-pulse, -.fa-spin-pulse { - -webkit-animation-name: fa-spin; - animation-name: fa-spin; - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, steps(8)); - animation-timing-function: var(--fa-animation-timing, steps(8)); } - -@media (prefers-reduced-motion: reduce) { - .fa-beat, - .fa-bounce, - .fa-fade, - .fa-beat-fade, - .fa-flip, - .fa-pulse, - .fa-shake, - .fa-spin, - .fa-spin-pulse { - -webkit-animation-delay: -1ms; - animation-delay: -1ms; - -webkit-animation-duration: 1ms; - animation-duration: 1ms; - -webkit-animation-iteration-count: 1; - animation-iteration-count: 1; - -webkit-transition-delay: 0s; - transition-delay: 0s; - -webkit-transition-duration: 0s; - transition-duration: 0s; } } - -@-webkit-keyframes fa-beat { - 0%, 90% { - -webkit-transform: scale(1); - transform: scale(1); } - 45% { - -webkit-transform: scale(var(--fa-beat-scale, 1.25)); - transform: scale(var(--fa-beat-scale, 1.25)); } } - -@keyframes fa-beat { - 0%, 90% { - -webkit-transform: scale(1); - transform: scale(1); } - 45% { - -webkit-transform: scale(var(--fa-beat-scale, 1.25)); - transform: scale(var(--fa-beat-scale, 1.25)); } } - -@-webkit-keyframes fa-bounce { - 0% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } - 10% { - -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); - transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); } - 30% { - -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); - transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); } - 50% { - -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); - transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); } - 57% { - -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); - transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); } - 64% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } - 100% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } } - -@keyframes fa-bounce { - 0% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } - 10% { - -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); - transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); } - 30% { - -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); - transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); } - 50% { - -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); - transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); } - 57% { - -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); - transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); } - 64% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } - 100% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } } - -@-webkit-keyframes fa-fade { - 50% { - opacity: var(--fa-fade-opacity, 0.4); } } - -@keyframes fa-fade { - 50% { - opacity: var(--fa-fade-opacity, 0.4); } } - -@-webkit-keyframes fa-beat-fade { - 0%, 100% { - opacity: var(--fa-beat-fade-opacity, 0.4); - -webkit-transform: scale(1); - transform: scale(1); } - 50% { - opacity: 1; - -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125)); - transform: scale(var(--fa-beat-fade-scale, 1.125)); } } - -@keyframes fa-beat-fade { - 0%, 100% { - opacity: var(--fa-beat-fade-opacity, 0.4); - -webkit-transform: scale(1); - transform: scale(1); } - 50% { - opacity: 1; - -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125)); - transform: scale(var(--fa-beat-fade-scale, 1.125)); } } - -@-webkit-keyframes fa-flip { - 50% { - -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); - transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } } - -@keyframes fa-flip { - 50% { - -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); - transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } } - -@-webkit-keyframes fa-shake { - 0% { - -webkit-transform: rotate(-15deg); - transform: rotate(-15deg); } - 4% { - -webkit-transform: rotate(15deg); - transform: rotate(15deg); } - 8%, 24% { - -webkit-transform: rotate(-18deg); - transform: rotate(-18deg); } - 12%, 28% { - -webkit-transform: rotate(18deg); - transform: rotate(18deg); } - 16% { - -webkit-transform: rotate(-22deg); - transform: rotate(-22deg); } - 20% { - -webkit-transform: rotate(22deg); - transform: rotate(22deg); } - 32% { - -webkit-transform: rotate(-12deg); - transform: rotate(-12deg); } - 36% { - -webkit-transform: rotate(12deg); - transform: rotate(12deg); } - 40%, 100% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); } } - -@keyframes fa-shake { - 0% { - -webkit-transform: rotate(-15deg); - transform: rotate(-15deg); } - 4% { - -webkit-transform: rotate(15deg); - transform: rotate(15deg); } - 8%, 24% { - -webkit-transform: rotate(-18deg); - transform: rotate(-18deg); } - 12%, 28% { - -webkit-transform: rotate(18deg); - transform: rotate(18deg); } - 16% { - -webkit-transform: rotate(-22deg); - transform: rotate(-22deg); } - 20% { - -webkit-transform: rotate(22deg); - transform: rotate(22deg); } - 32% { - -webkit-transform: rotate(-12deg); - transform: rotate(-12deg); } - 36% { - -webkit-transform: rotate(12deg); - transform: rotate(12deg); } - 40%, 100% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); } } - -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); } } - -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); } } - -.fa-rotate-90 { - -webkit-transform: rotate(90deg); - transform: rotate(90deg); } - -.fa-rotate-180 { - -webkit-transform: rotate(180deg); - transform: rotate(180deg); } - -.fa-rotate-270 { - -webkit-transform: rotate(270deg); - transform: rotate(270deg); } - -.fa-flip-horizontal { - -webkit-transform: scale(-1, 1); - transform: scale(-1, 1); } - -.fa-flip-vertical { - -webkit-transform: scale(1, -1); - transform: scale(1, -1); } - -.fa-flip-both, -.fa-flip-horizontal.fa-flip-vertical { - -webkit-transform: scale(-1, -1); - transform: scale(-1, -1); } - -.fa-rotate-by { - -webkit-transform: rotate(var(--fa-rotate-angle, none)); - transform: rotate(var(--fa-rotate-angle, none)); } - -.fa-stack { - display: inline-block; - height: 2em; - line-height: 2em; - position: relative; - vertical-align: middle; - width: 2.5em; } - -.fa-stack-1x, -.fa-stack-2x { - left: 0; - position: absolute; - text-align: center; - width: 100%; - z-index: var(--fa-stack-z-index, auto); } - -.fa-stack-1x { - line-height: inherit; } - -.fa-stack-2x { - font-size: 2em; } - -.fa-inverse { - color: var(--fa-inverse, #fff); } - -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen -readers do not read off random characters that represent icons */ - -.fa-0::before { - content: "\30"; } - -.fa-1::before { - content: "\31"; } - -.fa-2::before { - content: "\32"; } - -.fa-3::before { - content: "\33"; } - -.fa-4::before { - content: "\34"; } - -.fa-5::before { - content: "\35"; } - -.fa-6::before { - content: "\36"; } - -.fa-7::before { - content: "\37"; } - -.fa-8::before { - content: "\38"; } - -.fa-9::before { - content: "\39"; } - -.fa-fill-drip::before { - content: "\f576"; } - -.fa-arrows-to-circle::before { - content: "\e4bd"; } - -.fa-circle-chevron-right::before { - content: "\f138"; } - -.fa-chevron-circle-right::before { - content: "\f138"; } - -.fa-at::before { - content: "\40"; } - -.fa-trash-can::before { - content: "\f2ed"; } - -.fa-trash-alt::before { - content: "\f2ed"; } - -.fa-text-height::before { - content: "\f034"; } - -.fa-user-xmark::before { - content: "\f235"; } - -.fa-user-times::before { - content: "\f235"; } - -.fa-stethoscope::before { - content: "\f0f1"; } - -.fa-message::before { - content: "\f27a"; } - -.fa-comment-alt::before { - content: "\f27a"; } - -.fa-info::before { - content: "\f129"; } - -.fa-down-left-and-up-right-to-center::before { - content: "\f422"; } - -.fa-compress-alt::before { - content: "\f422"; } - -.fa-explosion::before { - content: "\e4e9"; } - -.fa-file-lines::before { - content: "\f15c"; } - -.fa-file-alt::before { - content: "\f15c"; } - -.fa-file-text::before { - content: "\f15c"; } - -.fa-wave-square::before { - content: "\f83e"; } - -.fa-ring::before { - content: "\f70b"; } - -.fa-building-un::before { - content: "\e4d9"; } - -.fa-dice-three::before { - content: "\f527"; } - -.fa-calendar-days::before { - content: "\f073"; } - -.fa-calendar-alt::before { - content: "\f073"; } - -.fa-anchor-circle-check::before { - content: "\e4aa"; } - -.fa-building-circle-arrow-right::before { - content: "\e4d1"; } - -.fa-volleyball::before { - content: "\f45f"; } - -.fa-volleyball-ball::before { - content: "\f45f"; } - -.fa-arrows-up-to-line::before { - content: "\e4c2"; } - -.fa-sort-down::before { - content: "\f0dd"; } - -.fa-sort-desc::before { - content: "\f0dd"; } - -.fa-circle-minus::before { - content: "\f056"; } - -.fa-minus-circle::before { - content: "\f056"; } - -.fa-door-open::before { - content: "\f52b"; } - -.fa-right-from-bracket::before { - content: "\f2f5"; } - -.fa-sign-out-alt::before { - content: "\f2f5"; } - -.fa-atom::before { - content: "\f5d2"; } - -.fa-soap::before { - content: "\e06e"; } - -.fa-icons::before { - content: "\f86d"; } - -.fa-heart-music-camera-bolt::before { - content: "\f86d"; } - -.fa-microphone-lines-slash::before { - content: "\f539"; } - -.fa-microphone-alt-slash::before { - content: "\f539"; } - -.fa-bridge-circle-check::before { - content: "\e4c9"; } - -.fa-pump-medical::before { - content: "\e06a"; } - -.fa-fingerprint::before { - content: "\f577"; } - -.fa-hand-point-right::before { - content: "\f0a4"; } - -.fa-magnifying-glass-location::before { - content: "\f689"; } - -.fa-search-location::before { - content: "\f689"; } - -.fa-forward-step::before { - content: "\f051"; } - -.fa-step-forward::before { - content: "\f051"; } - -.fa-face-smile-beam::before { - content: "\f5b8"; } - -.fa-smile-beam::before { - content: "\f5b8"; } - -.fa-flag-checkered::before { - content: "\f11e"; } - -.fa-football::before { - content: "\f44e"; } - -.fa-football-ball::before { - content: "\f44e"; } - -.fa-school-circle-exclamation::before { - content: "\e56c"; } - -.fa-crop::before { - content: "\f125"; } - -.fa-angles-down::before { - content: "\f103"; } - -.fa-angle-double-down::before { - content: "\f103"; } - -.fa-users-rectangle::before { - content: "\e594"; } - -.fa-people-roof::before { - content: "\e537"; } - -.fa-people-line::before { - content: "\e534"; } - -.fa-beer-mug-empty::before { - content: "\f0fc"; } - -.fa-beer::before { - content: "\f0fc"; } - -.fa-diagram-predecessor::before { - content: "\e477"; } - -.fa-arrow-up-long::before { - content: "\f176"; } - -.fa-long-arrow-up::before { - content: "\f176"; } - -.fa-fire-flame-simple::before { - content: "\f46a"; } - -.fa-burn::before { - content: "\f46a"; } - -.fa-person::before { - content: "\f183"; } - -.fa-male::before { - content: "\f183"; } - -.fa-laptop::before { - content: "\f109"; } - -.fa-file-csv::before { - content: "\f6dd"; } - -.fa-menorah::before { - content: "\f676"; } - -.fa-truck-plane::before { - content: "\e58f"; } - -.fa-record-vinyl::before { - content: "\f8d9"; } - -.fa-face-grin-stars::before { - content: "\f587"; } - -.fa-grin-stars::before { - content: "\f587"; } - -.fa-bong::before { - content: "\f55c"; } - -.fa-spaghetti-monster-flying::before { - content: "\f67b"; } - -.fa-pastafarianism::before { - content: "\f67b"; } - -.fa-arrow-down-up-across-line::before { - content: "\e4af"; } - -.fa-spoon::before { - content: "\f2e5"; } - -.fa-utensil-spoon::before { - content: "\f2e5"; } - -.fa-jar-wheat::before { - content: "\e517"; } - -.fa-envelopes-bulk::before { - content: "\f674"; } - -.fa-mail-bulk::before { - content: "\f674"; } - -.fa-file-circle-exclamation::before { - content: "\e4eb"; } - -.fa-circle-h::before { - content: "\f47e"; } - -.fa-hospital-symbol::before { - content: "\f47e"; } - -.fa-pager::before { - content: "\f815"; } - -.fa-address-book::before { - content: "\f2b9"; } - -.fa-contact-book::before { - content: "\f2b9"; } - -.fa-strikethrough::before { - content: "\f0cc"; } - -.fa-k::before { - content: "\4b"; } - -.fa-landmark-flag::before { - content: "\e51c"; } - -.fa-pencil::before { - content: "\f303"; } - -.fa-pencil-alt::before { - content: "\f303"; } - -.fa-backward::before { - content: "\f04a"; } - -.fa-caret-right::before { - content: "\f0da"; } - -.fa-comments::before { - content: "\f086"; } - -.fa-paste::before { - content: "\f0ea"; } - -.fa-file-clipboard::before { - content: "\f0ea"; } - -.fa-code-pull-request::before { - content: "\e13c"; } - -.fa-clipboard-list::before { - content: "\f46d"; } - -.fa-truck-ramp-box::before { - content: "\f4de"; } - -.fa-truck-loading::before { - content: "\f4de"; } - -.fa-user-check::before { - content: "\f4fc"; } - -.fa-vial-virus::before { - content: "\e597"; } - -.fa-sheet-plastic::before { - content: "\e571"; } - -.fa-blog::before { - content: "\f781"; } - -.fa-user-ninja::before { - content: "\f504"; } - -.fa-person-arrow-up-from-line::before { - content: "\e539"; } - -.fa-scroll-torah::before { - content: "\f6a0"; } - -.fa-torah::before { - content: "\f6a0"; } - -.fa-broom-ball::before { - content: "\f458"; } - -.fa-quidditch::before { - content: "\f458"; } - -.fa-quidditch-broom-ball::before { - content: "\f458"; } - -.fa-toggle-off::before { - content: "\f204"; } - -.fa-box-archive::before { - content: "\f187"; } - -.fa-archive::before { - content: "\f187"; } - -.fa-person-drowning::before { - content: "\e545"; } - -.fa-arrow-down-9-1::before { - content: "\f886"; } - -.fa-sort-numeric-desc::before { - content: "\f886"; } - -.fa-sort-numeric-down-alt::before { - content: "\f886"; } - -.fa-face-grin-tongue-squint::before { - content: "\f58a"; } - -.fa-grin-tongue-squint::before { - content: "\f58a"; } - -.fa-spray-can::before { - content: "\f5bd"; } - -.fa-truck-monster::before { - content: "\f63b"; } - -.fa-w::before { - content: "\57"; } - -.fa-earth-africa::before { - content: "\f57c"; } - -.fa-globe-africa::before { - content: "\f57c"; } - -.fa-rainbow::before { - content: "\f75b"; } - -.fa-circle-notch::before { - content: "\f1ce"; } - -.fa-tablet-screen-button::before { - content: "\f3fa"; } - -.fa-tablet-alt::before { - content: "\f3fa"; } - -.fa-paw::before { - content: "\f1b0"; } - -.fa-cloud::before { - content: "\f0c2"; } - -.fa-trowel-bricks::before { - content: "\e58a"; } - -.fa-face-flushed::before { - content: "\f579"; } - -.fa-flushed::before { - content: "\f579"; } - -.fa-hospital-user::before { - content: "\f80d"; } - -.fa-tent-arrow-left-right::before { - content: "\e57f"; } - -.fa-gavel::before { - content: "\f0e3"; } - -.fa-legal::before { - content: "\f0e3"; } - -.fa-binoculars::before { - content: "\f1e5"; } - -.fa-microphone-slash::before { - content: "\f131"; } - -.fa-box-tissue::before { - content: "\e05b"; } - -.fa-motorcycle::before { - content: "\f21c"; } - -.fa-bell-concierge::before { - content: "\f562"; } - -.fa-concierge-bell::before { - content: "\f562"; } - -.fa-pen-ruler::before { - content: "\f5ae"; } - -.fa-pencil-ruler::before { - content: "\f5ae"; } - -.fa-people-arrows::before { - content: "\e068"; } - -.fa-people-arrows-left-right::before { - content: "\e068"; } - -.fa-mars-and-venus-burst::before { - content: "\e523"; } - -.fa-square-caret-right::before { - content: "\f152"; } - -.fa-caret-square-right::before { - content: "\f152"; } - -.fa-scissors::before { - content: "\f0c4"; } - -.fa-cut::before { - content: "\f0c4"; } - -.fa-sun-plant-wilt::before { - content: "\e57a"; } - -.fa-toilets-portable::before { - content: "\e584"; } - -.fa-hockey-puck::before { - content: "\f453"; } - -.fa-table::before { - content: "\f0ce"; } - -.fa-magnifying-glass-arrow-right::before { - content: "\e521"; } - -.fa-tachograph-digital::before { - content: "\f566"; } - -.fa-digital-tachograph::before { - content: "\f566"; } - -.fa-users-slash::before { - content: "\e073"; } - -.fa-clover::before { - content: "\e139"; } - -.fa-reply::before { - content: "\f3e5"; } - -.fa-mail-reply::before { - content: "\f3e5"; } - -.fa-star-and-crescent::before { - content: "\f699"; } - -.fa-house-fire::before { - content: "\e50c"; } - -.fa-square-minus::before { - content: "\f146"; } - -.fa-minus-square::before { - content: "\f146"; } - -.fa-helicopter::before { - content: "\f533"; } - -.fa-compass::before { - content: "\f14e"; } - -.fa-square-caret-down::before { - content: "\f150"; } - -.fa-caret-square-down::before { - content: "\f150"; } - -.fa-file-circle-question::before { - content: "\e4ef"; } - -.fa-laptop-code::before { - content: "\f5fc"; } - -.fa-swatchbook::before { - content: "\f5c3"; } - -.fa-prescription-bottle::before { - content: "\f485"; } - -.fa-bars::before { - content: "\f0c9"; } - -.fa-navicon::before { - content: "\f0c9"; } - -.fa-people-group::before { - content: "\e533"; } - -.fa-hourglass-end::before { - content: "\f253"; } - -.fa-hourglass-3::before { - content: "\f253"; } - -.fa-heart-crack::before { - content: "\f7a9"; } - -.fa-heart-broken::before { - content: "\f7a9"; } - -.fa-square-up-right::before { - content: "\f360"; } - -.fa-external-link-square-alt::before { - content: "\f360"; } - -.fa-face-kiss-beam::before { - content: "\f597"; } - -.fa-kiss-beam::before { - content: "\f597"; } - -.fa-film::before { - content: "\f008"; } - -.fa-ruler-horizontal::before { - content: "\f547"; } - -.fa-people-robbery::before { - content: "\e536"; } - -.fa-lightbulb::before { - content: "\f0eb"; } - -.fa-caret-left::before { - content: "\f0d9"; } - -.fa-circle-exclamation::before { - content: "\f06a"; } - -.fa-exclamation-circle::before { - content: "\f06a"; } - -.fa-school-circle-xmark::before { - content: "\e56d"; } - -.fa-arrow-right-from-bracket::before { - content: "\f08b"; } - -.fa-sign-out::before { - content: "\f08b"; } - -.fa-circle-chevron-down::before { - content: "\f13a"; } - -.fa-chevron-circle-down::before { - content: "\f13a"; } - -.fa-unlock-keyhole::before { - content: "\f13e"; } - -.fa-unlock-alt::before { - content: "\f13e"; } - -.fa-cloud-showers-heavy::before { - content: "\f740"; } - -.fa-headphones-simple::before { - content: "\f58f"; } - -.fa-headphones-alt::before { - content: "\f58f"; } - -.fa-sitemap::before { - content: "\f0e8"; } - -.fa-circle-dollar-to-slot::before { - content: "\f4b9"; } - -.fa-donate::before { - content: "\f4b9"; } - -.fa-memory::before { - content: "\f538"; } - -.fa-road-spikes::before { - content: "\e568"; } - -.fa-fire-burner::before { - content: "\e4f1"; } - -.fa-flag::before { - content: "\f024"; } - -.fa-hanukiah::before { - content: "\f6e6"; } - -.fa-feather::before { - content: "\f52d"; } - -.fa-volume-low::before { - content: "\f027"; } - -.fa-volume-down::before { - content: "\f027"; } - -.fa-comment-slash::before { - content: "\f4b3"; } - -.fa-cloud-sun-rain::before { - content: "\f743"; } - -.fa-compress::before { - content: "\f066"; } - -.fa-wheat-awn::before { - content: "\e2cd"; } - -.fa-wheat-alt::before { - content: "\e2cd"; } - -.fa-ankh::before { - content: "\f644"; } - -.fa-hands-holding-child::before { - content: "\e4fa"; } - -.fa-asterisk::before { - content: "\2a"; } - -.fa-square-check::before { - content: "\f14a"; } - -.fa-check-square::before { - content: "\f14a"; } - -.fa-peseta-sign::before { - content: "\e221"; } - -.fa-heading::before { - content: "\f1dc"; } - -.fa-header::before { - content: "\f1dc"; } - -.fa-ghost::before { - content: "\f6e2"; } - -.fa-list::before { - content: "\f03a"; } - -.fa-list-squares::before { - content: "\f03a"; } - -.fa-square-phone-flip::before { - content: "\f87b"; } - -.fa-phone-square-alt::before { - content: "\f87b"; } - -.fa-cart-plus::before { - content: "\f217"; } - -.fa-gamepad::before { - content: "\f11b"; } - -.fa-circle-dot::before { - content: "\f192"; } - -.fa-dot-circle::before { - content: "\f192"; } - -.fa-face-dizzy::before { - content: "\f567"; } - -.fa-dizzy::before { - content: "\f567"; } - -.fa-egg::before { - content: "\f7fb"; } - -.fa-house-medical-circle-xmark::before { - content: "\e513"; } - -.fa-campground::before { - content: "\f6bb"; } - -.fa-folder-plus::before { - content: "\f65e"; } - -.fa-futbol::before { - content: "\f1e3"; } - -.fa-futbol-ball::before { - content: "\f1e3"; } - -.fa-soccer-ball::before { - content: "\f1e3"; } - -.fa-paintbrush::before { - content: "\f1fc"; } - -.fa-paint-brush::before { - content: "\f1fc"; } - -.fa-lock::before { - content: "\f023"; } - -.fa-gas-pump::before { - content: "\f52f"; } - -.fa-hot-tub-person::before { - content: "\f593"; } - -.fa-hot-tub::before { - content: "\f593"; } - -.fa-map-location::before { - content: "\f59f"; } - -.fa-map-marked::before { - content: "\f59f"; } - -.fa-house-flood-water::before { - content: "\e50e"; } - -.fa-tree::before { - content: "\f1bb"; } - -.fa-bridge-lock::before { - content: "\e4cc"; } - -.fa-sack-dollar::before { - content: "\f81d"; } - -.fa-pen-to-square::before { - content: "\f044"; } - -.fa-edit::before { - content: "\f044"; } - -.fa-car-side::before { - content: "\f5e4"; } - -.fa-share-nodes::before { - content: "\f1e0"; } - -.fa-share-alt::before { - content: "\f1e0"; } - -.fa-heart-circle-minus::before { - content: "\e4ff"; } - -.fa-hourglass-half::before { - content: "\f252"; } - -.fa-hourglass-2::before { - content: "\f252"; } - -.fa-microscope::before { - content: "\f610"; } - -.fa-sink::before { - content: "\e06d"; } - -.fa-bag-shopping::before { - content: "\f290"; } - -.fa-shopping-bag::before { - content: "\f290"; } - -.fa-arrow-down-z-a::before { - content: "\f881"; } - -.fa-sort-alpha-desc::before { - content: "\f881"; } - -.fa-sort-alpha-down-alt::before { - content: "\f881"; } - -.fa-mitten::before { - content: "\f7b5"; } - -.fa-person-rays::before { - content: "\e54d"; } - -.fa-users::before { - content: "\f0c0"; } - -.fa-eye-slash::before { - content: "\f070"; } - -.fa-flask-vial::before { - content: "\e4f3"; } - -.fa-hand::before { - content: "\f256"; } - -.fa-hand-paper::before { - content: "\f256"; } - -.fa-om::before { - content: "\f679"; } - -.fa-worm::before { - content: "\e599"; } - -.fa-house-circle-xmark::before { - content: "\e50b"; } - -.fa-plug::before { - content: "\f1e6"; } - -.fa-chevron-up::before { - content: "\f077"; } - -.fa-hand-spock::before { - content: "\f259"; } - -.fa-stopwatch::before { - content: "\f2f2"; } - -.fa-face-kiss::before { - content: "\f596"; } - -.fa-kiss::before { - content: "\f596"; } - -.fa-bridge-circle-xmark::before { - content: "\e4cb"; } - -.fa-face-grin-tongue::before { - content: "\f589"; } - -.fa-grin-tongue::before { - content: "\f589"; } - -.fa-chess-bishop::before { - content: "\f43a"; } - -.fa-face-grin-wink::before { - content: "\f58c"; } - -.fa-grin-wink::before { - content: "\f58c"; } - -.fa-ear-deaf::before { - content: "\f2a4"; } - -.fa-deaf::before { - content: "\f2a4"; } - -.fa-deafness::before { - content: "\f2a4"; } - -.fa-hard-of-hearing::before { - content: "\f2a4"; } - -.fa-road-circle-check::before { - content: "\e564"; } - -.fa-dice-five::before { - content: "\f523"; } - -.fa-square-rss::before { - content: "\f143"; } - -.fa-rss-square::before { - content: "\f143"; } - -.fa-land-mine-on::before { - content: "\e51b"; } - -.fa-i-cursor::before { - content: "\f246"; } - -.fa-stamp::before { - content: "\f5bf"; } - -.fa-stairs::before { - content: "\e289"; } - -.fa-i::before { - content: "\49"; } - -.fa-hryvnia-sign::before { - content: "\f6f2"; } - -.fa-hryvnia::before { - content: "\f6f2"; } - -.fa-pills::before { - content: "\f484"; } - -.fa-face-grin-wide::before { - content: "\f581"; } - -.fa-grin-alt::before { - content: "\f581"; } - -.fa-tooth::before { - content: "\f5c9"; } - -.fa-v::before { - content: "\56"; } - -.fa-bangladeshi-taka-sign::before { - content: "\e2e6"; } - -.fa-bicycle::before { - content: "\f206"; } - -.fa-staff-snake::before { - content: "\e579"; } - -.fa-rod-asclepius::before { - content: "\e579"; } - -.fa-rod-snake::before { - content: "\e579"; } - -.fa-staff-aesculapius::before { - content: "\e579"; } - -.fa-head-side-cough-slash::before { - content: "\e062"; } - -.fa-truck-medical::before { - content: "\f0f9"; } - -.fa-ambulance::before { - content: "\f0f9"; } - -.fa-wheat-awn-circle-exclamation::before { - content: "\e598"; } - -.fa-snowman::before { - content: "\f7d0"; } - -.fa-mortar-pestle::before { - content: "\f5a7"; } - -.fa-road-barrier::before { - content: "\e562"; } - -.fa-school::before { - content: "\f549"; } - -.fa-igloo::before { - content: "\f7ae"; } - -.fa-joint::before { - content: "\f595"; } - -.fa-angle-right::before { - content: "\f105"; } - -.fa-horse::before { - content: "\f6f0"; } - -.fa-q::before { - content: "\51"; } - -.fa-g::before { - content: "\47"; } - -.fa-notes-medical::before { - content: "\f481"; } - -.fa-temperature-half::before { - content: "\f2c9"; } - -.fa-temperature-2::before { - content: "\f2c9"; } - -.fa-thermometer-2::before { - content: "\f2c9"; } - -.fa-thermometer-half::before { - content: "\f2c9"; } - -.fa-dong-sign::before { - content: "\e169"; } - -.fa-capsules::before { - content: "\f46b"; } - -.fa-poo-storm::before { - content: "\f75a"; } - -.fa-poo-bolt::before { - content: "\f75a"; } - -.fa-face-frown-open::before { - content: "\f57a"; } - -.fa-frown-open::before { - content: "\f57a"; } - -.fa-hand-point-up::before { - content: "\f0a6"; } - -.fa-money-bill::before { - content: "\f0d6"; } - -.fa-bookmark::before { - content: "\f02e"; } - -.fa-align-justify::before { - content: "\f039"; } - -.fa-umbrella-beach::before { - content: "\f5ca"; } - -.fa-helmet-un::before { - content: "\e503"; } - -.fa-bullseye::before { - content: "\f140"; } - -.fa-bacon::before { - content: "\f7e5"; } - -.fa-hand-point-down::before { - content: "\f0a7"; } - -.fa-arrow-up-from-bracket::before { - content: "\e09a"; } - -.fa-folder::before { - content: "\f07b"; } - -.fa-folder-blank::before { - content: "\f07b"; } - -.fa-file-waveform::before { - content: "\f478"; } - -.fa-file-medical-alt::before { - content: "\f478"; } - -.fa-radiation::before { - content: "\f7b9"; } - -.fa-chart-simple::before { - content: "\e473"; } - -.fa-mars-stroke::before { - content: "\f229"; } - -.fa-vial::before { - content: "\f492"; } - -.fa-gauge::before { - content: "\f624"; } - -.fa-dashboard::before { - content: "\f624"; } - -.fa-gauge-med::before { - content: "\f624"; } - -.fa-tachometer-alt-average::before { - content: "\f624"; } - -.fa-wand-magic-sparkles::before { - content: "\e2ca"; } - -.fa-magic-wand-sparkles::before { - content: "\e2ca"; } - -.fa-e::before { - content: "\45"; } - -.fa-pen-clip::before { - content: "\f305"; } - -.fa-pen-alt::before { - content: "\f305"; } - -.fa-bridge-circle-exclamation::before { - content: "\e4ca"; } - -.fa-user::before { - content: "\f007"; } - -.fa-school-circle-check::before { - content: "\e56b"; } - -.fa-dumpster::before { - content: "\f793"; } - -.fa-van-shuttle::before { - content: "\f5b6"; } - -.fa-shuttle-van::before { - content: "\f5b6"; } - -.fa-building-user::before { - content: "\e4da"; } - -.fa-square-caret-left::before { - content: "\f191"; } - -.fa-caret-square-left::before { - content: "\f191"; } - -.fa-highlighter::before { - content: "\f591"; } - -.fa-key::before { - content: "\f084"; } - -.fa-bullhorn::before { - content: "\f0a1"; } - -.fa-globe::before { - content: "\f0ac"; } - -.fa-synagogue::before { - content: "\f69b"; } - -.fa-person-half-dress::before { - content: "\e548"; } - -.fa-road-bridge::before { - content: "\e563"; } - -.fa-location-arrow::before { - content: "\f124"; } - -.fa-c::before { - content: "\43"; } - -.fa-tablet-button::before { - content: "\f10a"; } - -.fa-building-lock::before { - content: "\e4d6"; } - -.fa-pizza-slice::before { - content: "\f818"; } - -.fa-money-bill-wave::before { - content: "\f53a"; } - -.fa-chart-area::before { - content: "\f1fe"; } - -.fa-area-chart::before { - content: "\f1fe"; } - -.fa-house-flag::before { - content: "\e50d"; } - -.fa-person-circle-minus::before { - content: "\e540"; } - -.fa-ban::before { - content: "\f05e"; } - -.fa-cancel::before { - content: "\f05e"; } - -.fa-camera-rotate::before { - content: "\e0d8"; } - -.fa-spray-can-sparkles::before { - content: "\f5d0"; } - -.fa-air-freshener::before { - content: "\f5d0"; } - -.fa-star::before { - content: "\f005"; } - -.fa-repeat::before { - content: "\f363"; } - -.fa-cross::before { - content: "\f654"; } - -.fa-box::before { - content: "\f466"; } - -.fa-venus-mars::before { - content: "\f228"; } - -.fa-arrow-pointer::before { - content: "\f245"; } - -.fa-mouse-pointer::before { - content: "\f245"; } - -.fa-maximize::before { - content: "\f31e"; } - -.fa-expand-arrows-alt::before { - content: "\f31e"; } - -.fa-charging-station::before { - content: "\f5e7"; } - -.fa-shapes::before { - content: "\f61f"; } - -.fa-triangle-circle-square::before { - content: "\f61f"; } - -.fa-shuffle::before { - content: "\f074"; } - -.fa-random::before { - content: "\f074"; } - -.fa-person-running::before { - content: "\f70c"; } - -.fa-running::before { - content: "\f70c"; } - -.fa-mobile-retro::before { - content: "\e527"; } - -.fa-grip-lines-vertical::before { - content: "\f7a5"; } - -.fa-spider::before { - content: "\f717"; } - -.fa-hands-bound::before { - content: "\e4f9"; } - -.fa-file-invoice-dollar::before { - content: "\f571"; } - -.fa-plane-circle-exclamation::before { - content: "\e556"; } - -.fa-x-ray::before { - content: "\f497"; } - -.fa-spell-check::before { - content: "\f891"; } - -.fa-slash::before { - content: "\f715"; } - -.fa-computer-mouse::before { - content: "\f8cc"; } - -.fa-mouse::before { - content: "\f8cc"; } - -.fa-arrow-right-to-bracket::before { - content: "\f090"; } - -.fa-sign-in::before { - content: "\f090"; } - -.fa-shop-slash::before { - content: "\e070"; } - -.fa-store-alt-slash::before { - content: "\e070"; } - -.fa-server::before { - content: "\f233"; } - -.fa-virus-covid-slash::before { - content: "\e4a9"; } - -.fa-shop-lock::before { - content: "\e4a5"; } - -.fa-hourglass-start::before { - content: "\f251"; } - -.fa-hourglass-1::before { - content: "\f251"; } - -.fa-blender-phone::before { - content: "\f6b6"; } - -.fa-building-wheat::before { - content: "\e4db"; } - -.fa-person-breastfeeding::before { - content: "\e53a"; } - -.fa-right-to-bracket::before { - content: "\f2f6"; } - -.fa-sign-in-alt::before { - content: "\f2f6"; } - -.fa-venus::before { - content: "\f221"; } - -.fa-passport::before { - content: "\f5ab"; } - -.fa-heart-pulse::before { - content: "\f21e"; } - -.fa-heartbeat::before { - content: "\f21e"; } - -.fa-people-carry-box::before { - content: "\f4ce"; } - -.fa-people-carry::before { - content: "\f4ce"; } - -.fa-temperature-high::before { - content: "\f769"; } - -.fa-microchip::before { - content: "\f2db"; } - -.fa-crown::before { - content: "\f521"; } - -.fa-weight-hanging::before { - content: "\f5cd"; } - -.fa-xmarks-lines::before { - content: "\e59a"; } - -.fa-file-prescription::before { - content: "\f572"; } - -.fa-weight-scale::before { - content: "\f496"; } - -.fa-weight::before { - content: "\f496"; } - -.fa-user-group::before { - content: "\f500"; } - -.fa-user-friends::before { - content: "\f500"; } - -.fa-arrow-up-a-z::before { - content: "\f15e"; } - -.fa-sort-alpha-up::before { - content: "\f15e"; } - -.fa-chess-knight::before { - content: "\f441"; } - -.fa-face-laugh-squint::before { - content: "\f59b"; } - -.fa-laugh-squint::before { - content: "\f59b"; } - -.fa-wheelchair::before { - content: "\f193"; } - -.fa-circle-arrow-up::before { - content: "\f0aa"; } - -.fa-arrow-circle-up::before { - content: "\f0aa"; } - -.fa-toggle-on::before { - content: "\f205"; } - -.fa-person-walking::before { - content: "\f554"; } - -.fa-walking::before { - content: "\f554"; } - -.fa-l::before { - content: "\4c"; } - -.fa-fire::before { - content: "\f06d"; } - -.fa-bed-pulse::before { - content: "\f487"; } - -.fa-procedures::before { - content: "\f487"; } - -.fa-shuttle-space::before { - content: "\f197"; } - -.fa-space-shuttle::before { - content: "\f197"; } - -.fa-face-laugh::before { - content: "\f599"; } - -.fa-laugh::before { - content: "\f599"; } - -.fa-folder-open::before { - content: "\f07c"; } - -.fa-heart-circle-plus::before { - content: "\e500"; } - -.fa-code-fork::before { - content: "\e13b"; } - -.fa-city::before { - content: "\f64f"; } - -.fa-microphone-lines::before { - content: "\f3c9"; } - -.fa-microphone-alt::before { - content: "\f3c9"; } - -.fa-pepper-hot::before { - content: "\f816"; } - -.fa-unlock::before { - content: "\f09c"; } - -.fa-colon-sign::before { - content: "\e140"; } - -.fa-headset::before { - content: "\f590"; } - -.fa-store-slash::before { - content: "\e071"; } - -.fa-road-circle-xmark::before { - content: "\e566"; } - -.fa-user-minus::before { - content: "\f503"; } - -.fa-mars-stroke-up::before { - content: "\f22a"; } - -.fa-mars-stroke-v::before { - content: "\f22a"; } - -.fa-champagne-glasses::before { - content: "\f79f"; } - -.fa-glass-cheers::before { - content: "\f79f"; } - -.fa-clipboard::before { - content: "\f328"; } - -.fa-house-circle-exclamation::before { - content: "\e50a"; } - -.fa-file-arrow-up::before { - content: "\f574"; } - -.fa-file-upload::before { - content: "\f574"; } - -.fa-wifi::before { - content: "\f1eb"; } - -.fa-wifi-3::before { - content: "\f1eb"; } - -.fa-wifi-strong::before { - content: "\f1eb"; } - -.fa-bath::before { - content: "\f2cd"; } - -.fa-bathtub::before { - content: "\f2cd"; } - -.fa-underline::before { - content: "\f0cd"; } - -.fa-user-pen::before { - content: "\f4ff"; } - -.fa-user-edit::before { - content: "\f4ff"; } - -.fa-signature::before { - content: "\f5b7"; } - -.fa-stroopwafel::before { - content: "\f551"; } - -.fa-bold::before { - content: "\f032"; } - -.fa-anchor-lock::before { - content: "\e4ad"; } - -.fa-building-ngo::before { - content: "\e4d7"; } - -.fa-manat-sign::before { - content: "\e1d5"; } - -.fa-not-equal::before { - content: "\f53e"; } - -.fa-border-top-left::before { - content: "\f853"; } - -.fa-border-style::before { - content: "\f853"; } - -.fa-map-location-dot::before { - content: "\f5a0"; } - -.fa-map-marked-alt::before { - content: "\f5a0"; } - -.fa-jedi::before { - content: "\f669"; } - -.fa-square-poll-vertical::before { - content: "\f681"; } - -.fa-poll::before { - content: "\f681"; } - -.fa-mug-hot::before { - content: "\f7b6"; } - -.fa-car-battery::before { - content: "\f5df"; } - -.fa-battery-car::before { - content: "\f5df"; } - -.fa-gift::before { - content: "\f06b"; } - -.fa-dice-two::before { - content: "\f528"; } - -.fa-chess-queen::before { - content: "\f445"; } - -.fa-glasses::before { - content: "\f530"; } - -.fa-chess-board::before { - content: "\f43c"; } - -.fa-building-circle-check::before { - content: "\e4d2"; } - -.fa-person-chalkboard::before { - content: "\e53d"; } - -.fa-mars-stroke-right::before { - content: "\f22b"; } - -.fa-mars-stroke-h::before { - content: "\f22b"; } - -.fa-hand-back-fist::before { - content: "\f255"; } - -.fa-hand-rock::before { - content: "\f255"; } - -.fa-square-caret-up::before { - content: "\f151"; } - -.fa-caret-square-up::before { - content: "\f151"; } - -.fa-cloud-showers-water::before { - content: "\e4e4"; } - -.fa-chart-bar::before { - content: "\f080"; } - -.fa-bar-chart::before { - content: "\f080"; } - -.fa-hands-bubbles::before { - content: "\e05e"; } - -.fa-hands-wash::before { - content: "\e05e"; } - -.fa-less-than-equal::before { - content: "\f537"; } - -.fa-train::before { - content: "\f238"; } - -.fa-eye-low-vision::before { - content: "\f2a8"; } - -.fa-low-vision::before { - content: "\f2a8"; } - -.fa-crow::before { - content: "\f520"; } - -.fa-sailboat::before { - content: "\e445"; } - -.fa-window-restore::before { - content: "\f2d2"; } - -.fa-square-plus::before { - content: "\f0fe"; } - -.fa-plus-square::before { - content: "\f0fe"; } - -.fa-torii-gate::before { - content: "\f6a1"; } - -.fa-frog::before { - content: "\f52e"; } - -.fa-bucket::before { - content: "\e4cf"; } - -.fa-image::before { - content: "\f03e"; } - -.fa-microphone::before { - content: "\f130"; } - -.fa-cow::before { - content: "\f6c8"; } - -.fa-caret-up::before { - content: "\f0d8"; } - -.fa-screwdriver::before { - content: "\f54a"; } - -.fa-folder-closed::before { - content: "\e185"; } - -.fa-house-tsunami::before { - content: "\e515"; } - -.fa-square-nfi::before { - content: "\e576"; } - -.fa-arrow-up-from-ground-water::before { - content: "\e4b5"; } - -.fa-martini-glass::before { - content: "\f57b"; } - -.fa-glass-martini-alt::before { - content: "\f57b"; } - -.fa-rotate-left::before { - content: "\f2ea"; } - -.fa-rotate-back::before { - content: "\f2ea"; } - -.fa-rotate-backward::before { - content: "\f2ea"; } - -.fa-undo-alt::before { - content: "\f2ea"; } - -.fa-table-columns::before { - content: "\f0db"; } - -.fa-columns::before { - content: "\f0db"; } - -.fa-lemon::before { - content: "\f094"; } - -.fa-head-side-mask::before { - content: "\e063"; } - -.fa-handshake::before { - content: "\f2b5"; } - -.fa-gem::before { - content: "\f3a5"; } - -.fa-dolly::before { - content: "\f472"; } - -.fa-dolly-box::before { - content: "\f472"; } - -.fa-smoking::before { - content: "\f48d"; } - -.fa-minimize::before { - content: "\f78c"; } - -.fa-compress-arrows-alt::before { - content: "\f78c"; } - -.fa-monument::before { - content: "\f5a6"; } - -.fa-snowplow::before { - content: "\f7d2"; } - -.fa-angles-right::before { - content: "\f101"; } - -.fa-angle-double-right::before { - content: "\f101"; } - -.fa-cannabis::before { - content: "\f55f"; } - -.fa-circle-play::before { - content: "\f144"; } - -.fa-play-circle::before { - content: "\f144"; } - -.fa-tablets::before { - content: "\f490"; } - -.fa-ethernet::before { - content: "\f796"; } - -.fa-euro-sign::before { - content: "\f153"; } - -.fa-eur::before { - content: "\f153"; } - -.fa-euro::before { - content: "\f153"; } - -.fa-chair::before { - content: "\f6c0"; } - -.fa-circle-check::before { - content: "\f058"; } - -.fa-check-circle::before { - content: "\f058"; } - -.fa-circle-stop::before { - content: "\f28d"; } - -.fa-stop-circle::before { - content: "\f28d"; } - -.fa-compass-drafting::before { - content: "\f568"; } - -.fa-drafting-compass::before { - content: "\f568"; } - -.fa-plate-wheat::before { - content: "\e55a"; } - -.fa-icicles::before { - content: "\f7ad"; } - -.fa-person-shelter::before { - content: "\e54f"; } - -.fa-neuter::before { - content: "\f22c"; } - -.fa-id-badge::before { - content: "\f2c1"; } - -.fa-marker::before { - content: "\f5a1"; } - -.fa-face-laugh-beam::before { - content: "\f59a"; } - -.fa-laugh-beam::before { - content: "\f59a"; } - -.fa-helicopter-symbol::before { - content: "\e502"; } - -.fa-universal-access::before { - content: "\f29a"; } - -.fa-circle-chevron-up::before { - content: "\f139"; } - -.fa-chevron-circle-up::before { - content: "\f139"; } - -.fa-lari-sign::before { - content: "\e1c8"; } - -.fa-volcano::before { - content: "\f770"; } - -.fa-person-walking-dashed-line-arrow-right::before { - content: "\e553"; } - -.fa-sterling-sign::before { - content: "\f154"; } - -.fa-gbp::before { - content: "\f154"; } - -.fa-pound-sign::before { - content: "\f154"; } - -.fa-viruses::before { - content: "\e076"; } - -.fa-square-person-confined::before { - content: "\e577"; } - -.fa-user-tie::before { - content: "\f508"; } - -.fa-arrow-down-long::before { - content: "\f175"; } - -.fa-long-arrow-down::before { - content: "\f175"; } - -.fa-tent-arrow-down-to-line::before { - content: "\e57e"; } - -.fa-certificate::before { - content: "\f0a3"; } - -.fa-reply-all::before { - content: "\f122"; } - -.fa-mail-reply-all::before { - content: "\f122"; } - -.fa-suitcase::before { - content: "\f0f2"; } - -.fa-person-skating::before { - content: "\f7c5"; } - -.fa-skating::before { - content: "\f7c5"; } - -.fa-filter-circle-dollar::before { - content: "\f662"; } - -.fa-funnel-dollar::before { - content: "\f662"; } - -.fa-camera-retro::before { - content: "\f083"; } - -.fa-circle-arrow-down::before { - content: "\f0ab"; } - -.fa-arrow-circle-down::before { - content: "\f0ab"; } - -.fa-file-import::before { - content: "\f56f"; } - -.fa-arrow-right-to-file::before { - content: "\f56f"; } - -.fa-square-arrow-up-right::before { - content: "\f14c"; } - -.fa-external-link-square::before { - content: "\f14c"; } - -.fa-box-open::before { - content: "\f49e"; } - -.fa-scroll::before { - content: "\f70e"; } - -.fa-spa::before { - content: "\f5bb"; } - -.fa-location-pin-lock::before { - content: "\e51f"; } - -.fa-pause::before { - content: "\f04c"; } - -.fa-hill-avalanche::before { - content: "\e507"; } - -.fa-temperature-empty::before { - content: "\f2cb"; } - -.fa-temperature-0::before { - content: "\f2cb"; } - -.fa-thermometer-0::before { - content: "\f2cb"; } - -.fa-thermometer-empty::before { - content: "\f2cb"; } - -.fa-bomb::before { - content: "\f1e2"; } - -.fa-registered::before { - content: "\f25d"; } - -.fa-address-card::before { - content: "\f2bb"; } - -.fa-contact-card::before { - content: "\f2bb"; } - -.fa-vcard::before { - content: "\f2bb"; } - -.fa-scale-unbalanced-flip::before { - content: "\f516"; } - -.fa-balance-scale-right::before { - content: "\f516"; } - -.fa-subscript::before { - content: "\f12c"; } - -.fa-diamond-turn-right::before { - content: "\f5eb"; } - -.fa-directions::before { - content: "\f5eb"; } - -.fa-burst::before { - content: "\e4dc"; } - -.fa-house-laptop::before { - content: "\e066"; } - -.fa-laptop-house::before { - content: "\e066"; } - -.fa-face-tired::before { - content: "\f5c8"; } - -.fa-tired::before { - content: "\f5c8"; } - -.fa-money-bills::before { - content: "\e1f3"; } - -.fa-smog::before { - content: "\f75f"; } - -.fa-crutch::before { - content: "\f7f7"; } - -.fa-cloud-arrow-up::before { - content: "\f0ee"; } - -.fa-cloud-upload::before { - content: "\f0ee"; } - -.fa-cloud-upload-alt::before { - content: "\f0ee"; } - -.fa-palette::before { - content: "\f53f"; } - -.fa-arrows-turn-right::before { - content: "\e4c0"; } - -.fa-vest::before { - content: "\e085"; } - -.fa-ferry::before { - content: "\e4ea"; } - -.fa-arrows-down-to-people::before { - content: "\e4b9"; } - -.fa-seedling::before { - content: "\f4d8"; } - -.fa-sprout::before { - content: "\f4d8"; } - -.fa-left-right::before { - content: "\f337"; } - -.fa-arrows-alt-h::before { - content: "\f337"; } - -.fa-boxes-packing::before { - content: "\e4c7"; } - -.fa-circle-arrow-left::before { - content: "\f0a8"; } - -.fa-arrow-circle-left::before { - content: "\f0a8"; } - -.fa-group-arrows-rotate::before { - content: "\e4f6"; } - -.fa-bowl-food::before { - content: "\e4c6"; } - -.fa-candy-cane::before { - content: "\f786"; } - -.fa-arrow-down-wide-short::before { - content: "\f160"; } - -.fa-sort-amount-asc::before { - content: "\f160"; } - -.fa-sort-amount-down::before { - content: "\f160"; } - -.fa-cloud-bolt::before { - content: "\f76c"; } - -.fa-thunderstorm::before { - content: "\f76c"; } - -.fa-text-slash::before { - content: "\f87d"; } - -.fa-remove-format::before { - content: "\f87d"; } - -.fa-face-smile-wink::before { - content: "\f4da"; } - -.fa-smile-wink::before { - content: "\f4da"; } - -.fa-file-word::before { - content: "\f1c2"; } - -.fa-file-powerpoint::before { - content: "\f1c4"; } - -.fa-arrows-left-right::before { - content: "\f07e"; } - -.fa-arrows-h::before { - content: "\f07e"; } - -.fa-house-lock::before { - content: "\e510"; } - -.fa-cloud-arrow-down::before { - content: "\f0ed"; } - -.fa-cloud-download::before { - content: "\f0ed"; } - -.fa-cloud-download-alt::before { - content: "\f0ed"; } - -.fa-children::before { - content: "\e4e1"; } - -.fa-chalkboard::before { - content: "\f51b"; } - -.fa-blackboard::before { - content: "\f51b"; } - -.fa-user-large-slash::before { - content: "\f4fa"; } - -.fa-user-alt-slash::before { - content: "\f4fa"; } - -.fa-envelope-open::before { - content: "\f2b6"; } - -.fa-handshake-simple-slash::before { - content: "\e05f"; } - -.fa-handshake-alt-slash::before { - content: "\e05f"; } - -.fa-mattress-pillow::before { - content: "\e525"; } - -.fa-guarani-sign::before { - content: "\e19a"; } - -.fa-arrows-rotate::before { - content: "\f021"; } - -.fa-refresh::before { - content: "\f021"; } - -.fa-sync::before { - content: "\f021"; } - -.fa-fire-extinguisher::before { - content: "\f134"; } - -.fa-cruzeiro-sign::before { - content: "\e152"; } - -.fa-greater-than-equal::before { - content: "\f532"; } - -.fa-shield-halved::before { - content: "\f3ed"; } - -.fa-shield-alt::before { - content: "\f3ed"; } - -.fa-book-atlas::before { - content: "\f558"; } - -.fa-atlas::before { - content: "\f558"; } - -.fa-virus::before { - content: "\e074"; } - -.fa-envelope-circle-check::before { - content: "\e4e8"; } - -.fa-layer-group::before { - content: "\f5fd"; } - -.fa-arrows-to-dot::before { - content: "\e4be"; } - -.fa-archway::before { - content: "\f557"; } - -.fa-heart-circle-check::before { - content: "\e4fd"; } - -.fa-house-chimney-crack::before { - content: "\f6f1"; } - -.fa-house-damage::before { - content: "\f6f1"; } - -.fa-file-zipper::before { - content: "\f1c6"; } - -.fa-file-archive::before { - content: "\f1c6"; } - -.fa-square::before { - content: "\f0c8"; } - -.fa-martini-glass-empty::before { - content: "\f000"; } - -.fa-glass-martini::before { - content: "\f000"; } - -.fa-couch::before { - content: "\f4b8"; } - -.fa-cedi-sign::before { - content: "\e0df"; } - -.fa-italic::before { - content: "\f033"; } - -.fa-church::before { - content: "\f51d"; } - -.fa-comments-dollar::before { - content: "\f653"; } - -.fa-democrat::before { - content: "\f747"; } - -.fa-z::before { - content: "\5a"; } - -.fa-person-skiing::before { - content: "\f7c9"; } - -.fa-skiing::before { - content: "\f7c9"; } - -.fa-road-lock::before { - content: "\e567"; } - -.fa-a::before { - content: "\41"; } - -.fa-temperature-arrow-down::before { - content: "\e03f"; } - -.fa-temperature-down::before { - content: "\e03f"; } - -.fa-feather-pointed::before { - content: "\f56b"; } - -.fa-feather-alt::before { - content: "\f56b"; } - -.fa-p::before { - content: "\50"; } - -.fa-snowflake::before { - content: "\f2dc"; } - -.fa-newspaper::before { - content: "\f1ea"; } - -.fa-rectangle-ad::before { - content: "\f641"; } - -.fa-ad::before { - content: "\f641"; } - -.fa-circle-arrow-right::before { - content: "\f0a9"; } - -.fa-arrow-circle-right::before { - content: "\f0a9"; } - -.fa-filter-circle-xmark::before { - content: "\e17b"; } - -.fa-locust::before { - content: "\e520"; } - -.fa-sort::before { - content: "\f0dc"; } - -.fa-unsorted::before { - content: "\f0dc"; } - -.fa-list-ol::before { - content: "\f0cb"; } - -.fa-list-1-2::before { - content: "\f0cb"; } - -.fa-list-numeric::before { - content: "\f0cb"; } - -.fa-person-dress-burst::before { - content: "\e544"; } - -.fa-money-check-dollar::before { - content: "\f53d"; } - -.fa-money-check-alt::before { - content: "\f53d"; } - -.fa-vector-square::before { - content: "\f5cb"; } - -.fa-bread-slice::before { - content: "\f7ec"; } - -.fa-language::before { - content: "\f1ab"; } - -.fa-face-kiss-wink-heart::before { - content: "\f598"; } - -.fa-kiss-wink-heart::before { - content: "\f598"; } - -.fa-filter::before { - content: "\f0b0"; } - -.fa-question::before { - content: "\3f"; } - -.fa-file-signature::before { - content: "\f573"; } - -.fa-up-down-left-right::before { - content: "\f0b2"; } - -.fa-arrows-alt::before { - content: "\f0b2"; } - -.fa-house-chimney-user::before { - content: "\e065"; } - -.fa-hand-holding-heart::before { - content: "\f4be"; } - -.fa-puzzle-piece::before { - content: "\f12e"; } - -.fa-money-check::before { - content: "\f53c"; } - -.fa-star-half-stroke::before { - content: "\f5c0"; } - -.fa-star-half-alt::before { - content: "\f5c0"; } - -.fa-code::before { - content: "\f121"; } - -.fa-whiskey-glass::before { - content: "\f7a0"; } - -.fa-glass-whiskey::before { - content: "\f7a0"; } - -.fa-building-circle-exclamation::before { - content: "\e4d3"; } - -.fa-magnifying-glass-chart::before { - content: "\e522"; } - -.fa-arrow-up-right-from-square::before { - content: "\f08e"; } - -.fa-external-link::before { - content: "\f08e"; } - -.fa-cubes-stacked::before { - content: "\e4e6"; } - -.fa-won-sign::before { - content: "\f159"; } - -.fa-krw::before { - content: "\f159"; } - -.fa-won::before { - content: "\f159"; } - -.fa-virus-covid::before { - content: "\e4a8"; } - -.fa-austral-sign::before { - content: "\e0a9"; } - -.fa-f::before { - content: "\46"; } - -.fa-leaf::before { - content: "\f06c"; } - -.fa-road::before { - content: "\f018"; } - -.fa-taxi::before { - content: "\f1ba"; } - -.fa-cab::before { - content: "\f1ba"; } - -.fa-person-circle-plus::before { - content: "\e541"; } - -.fa-chart-pie::before { - content: "\f200"; } - -.fa-pie-chart::before { - content: "\f200"; } - -.fa-bolt-lightning::before { - content: "\e0b7"; } - -.fa-sack-xmark::before { - content: "\e56a"; } - -.fa-file-excel::before { - content: "\f1c3"; } - -.fa-file-contract::before { - content: "\f56c"; } - -.fa-fish-fins::before { - content: "\e4f2"; } - -.fa-building-flag::before { - content: "\e4d5"; } - -.fa-face-grin-beam::before { - content: "\f582"; } - -.fa-grin-beam::before { - content: "\f582"; } - -.fa-object-ungroup::before { - content: "\f248"; } - -.fa-poop::before { - content: "\f619"; } - -.fa-location-pin::before { - content: "\f041"; } - -.fa-map-marker::before { - content: "\f041"; } - -.fa-kaaba::before { - content: "\f66b"; } - -.fa-toilet-paper::before { - content: "\f71e"; } - -.fa-helmet-safety::before { - content: "\f807"; } - -.fa-hard-hat::before { - content: "\f807"; } - -.fa-hat-hard::before { - content: "\f807"; } - -.fa-eject::before { - content: "\f052"; } - -.fa-circle-right::before { - content: "\f35a"; } - -.fa-arrow-alt-circle-right::before { - content: "\f35a"; } - -.fa-plane-circle-check::before { - content: "\e555"; } - -.fa-face-rolling-eyes::before { - content: "\f5a5"; } - -.fa-meh-rolling-eyes::before { - content: "\f5a5"; } - -.fa-object-group::before { - content: "\f247"; } - -.fa-chart-line::before { - content: "\f201"; } - -.fa-line-chart::before { - content: "\f201"; } - -.fa-mask-ventilator::before { - content: "\e524"; } - -.fa-arrow-right::before { - content: "\f061"; } - -.fa-signs-post::before { - content: "\f277"; } - -.fa-map-signs::before { - content: "\f277"; } - -.fa-cash-register::before { - content: "\f788"; } - -.fa-person-circle-question::before { - content: "\e542"; } - -.fa-h::before { - content: "\48"; } - -.fa-tarp::before { - content: "\e57b"; } - -.fa-screwdriver-wrench::before { - content: "\f7d9"; } - -.fa-tools::before { - content: "\f7d9"; } - -.fa-arrows-to-eye::before { - content: "\e4bf"; } - -.fa-plug-circle-bolt::before { - content: "\e55b"; } - -.fa-heart::before { - content: "\f004"; } - -.fa-mars-and-venus::before { - content: "\f224"; } - -.fa-house-user::before { - content: "\e1b0"; } - -.fa-home-user::before { - content: "\e1b0"; } - -.fa-dumpster-fire::before { - content: "\f794"; } - -.fa-house-crack::before { - content: "\e3b1"; } - -.fa-martini-glass-citrus::before { - content: "\f561"; } - -.fa-cocktail::before { - content: "\f561"; } - -.fa-face-surprise::before { - content: "\f5c2"; } - -.fa-surprise::before { - content: "\f5c2"; } - -.fa-bottle-water::before { - content: "\e4c5"; } - -.fa-circle-pause::before { - content: "\f28b"; } - -.fa-pause-circle::before { - content: "\f28b"; } - -.fa-toilet-paper-slash::before { - content: "\e072"; } - -.fa-apple-whole::before { - content: "\f5d1"; } - -.fa-apple-alt::before { - content: "\f5d1"; } - -.fa-kitchen-set::before { - content: "\e51a"; } - -.fa-r::before { - content: "\52"; } - -.fa-temperature-quarter::before { - content: "\f2ca"; } - -.fa-temperature-1::before { - content: "\f2ca"; } - -.fa-thermometer-1::before { - content: "\f2ca"; } - -.fa-thermometer-quarter::before { - content: "\f2ca"; } - -.fa-cube::before { - content: "\f1b2"; } - -.fa-bitcoin-sign::before { - content: "\e0b4"; } - -.fa-shield-dog::before { - content: "\e573"; } - -.fa-solar-panel::before { - content: "\f5ba"; } - -.fa-lock-open::before { - content: "\f3c1"; } - -.fa-elevator::before { - content: "\e16d"; } - -.fa-money-bill-transfer::before { - content: "\e528"; } - -.fa-money-bill-trend-up::before { - content: "\e529"; } - -.fa-house-flood-water-circle-arrow-right::before { - content: "\e50f"; } - -.fa-square-poll-horizontal::before { - content: "\f682"; } - -.fa-poll-h::before { - content: "\f682"; } - -.fa-circle::before { - content: "\f111"; } - -.fa-backward-fast::before { - content: "\f049"; } - -.fa-fast-backward::before { - content: "\f049"; } - -.fa-recycle::before { - content: "\f1b8"; } - -.fa-user-astronaut::before { - content: "\f4fb"; } - -.fa-plane-slash::before { - content: "\e069"; } - -.fa-trademark::before { - content: "\f25c"; } - -.fa-basketball::before { - content: "\f434"; } - -.fa-basketball-ball::before { - content: "\f434"; } - -.fa-satellite-dish::before { - content: "\f7c0"; } - -.fa-circle-up::before { - content: "\f35b"; } - -.fa-arrow-alt-circle-up::before { - content: "\f35b"; } - -.fa-mobile-screen-button::before { - content: "\f3cd"; } - -.fa-mobile-alt::before { - content: "\f3cd"; } - -.fa-volume-high::before { - content: "\f028"; } - -.fa-volume-up::before { - content: "\f028"; } - -.fa-users-rays::before { - content: "\e593"; } - -.fa-wallet::before { - content: "\f555"; } - -.fa-clipboard-check::before { - content: "\f46c"; } - -.fa-file-audio::before { - content: "\f1c7"; } - -.fa-burger::before { - content: "\f805"; } - -.fa-hamburger::before { - content: "\f805"; } - -.fa-wrench::before { - content: "\f0ad"; } - -.fa-bugs::before { - content: "\e4d0"; } - -.fa-rupee-sign::before { - content: "\f156"; } - -.fa-rupee::before { - content: "\f156"; } - -.fa-file-image::before { - content: "\f1c5"; } - -.fa-circle-question::before { - content: "\f059"; } - -.fa-question-circle::before { - content: "\f059"; } - -.fa-plane-departure::before { - content: "\f5b0"; } - -.fa-handshake-slash::before { - content: "\e060"; } - -.fa-book-bookmark::before { - content: "\e0bb"; } - -.fa-code-branch::before { - content: "\f126"; } - -.fa-hat-cowboy::before { - content: "\f8c0"; } - -.fa-bridge::before { - content: "\e4c8"; } - -.fa-phone-flip::before { - content: "\f879"; } - -.fa-phone-alt::before { - content: "\f879"; } - -.fa-truck-front::before { - content: "\e2b7"; } - -.fa-cat::before { - content: "\f6be"; } - -.fa-anchor-circle-exclamation::before { - content: "\e4ab"; } - -.fa-truck-field::before { - content: "\e58d"; } - -.fa-route::before { - content: "\f4d7"; } - -.fa-clipboard-question::before { - content: "\e4e3"; } - -.fa-panorama::before { - content: "\e209"; } - -.fa-comment-medical::before { - content: "\f7f5"; } - -.fa-teeth-open::before { - content: "\f62f"; } - -.fa-file-circle-minus::before { - content: "\e4ed"; } - -.fa-tags::before { - content: "\f02c"; } - -.fa-wine-glass::before { - content: "\f4e3"; } - -.fa-forward-fast::before { - content: "\f050"; } - -.fa-fast-forward::before { - content: "\f050"; } - -.fa-face-meh-blank::before { - content: "\f5a4"; } - -.fa-meh-blank::before { - content: "\f5a4"; } - -.fa-square-parking::before { - content: "\f540"; } - -.fa-parking::before { - content: "\f540"; } - -.fa-house-signal::before { - content: "\e012"; } - -.fa-bars-progress::before { - content: "\f828"; } - -.fa-tasks-alt::before { - content: "\f828"; } - -.fa-faucet-drip::before { - content: "\e006"; } - -.fa-cart-flatbed::before { - content: "\f474"; } - -.fa-dolly-flatbed::before { - content: "\f474"; } - -.fa-ban-smoking::before { - content: "\f54d"; } - -.fa-smoking-ban::before { - content: "\f54d"; } - -.fa-terminal::before { - content: "\f120"; } - -.fa-mobile-button::before { - content: "\f10b"; } - -.fa-house-medical-flag::before { - content: "\e514"; } - -.fa-basket-shopping::before { - content: "\f291"; } - -.fa-shopping-basket::before { - content: "\f291"; } - -.fa-tape::before { - content: "\f4db"; } - -.fa-bus-simple::before { - content: "\f55e"; } - -.fa-bus-alt::before { - content: "\f55e"; } - -.fa-eye::before { - content: "\f06e"; } - -.fa-face-sad-cry::before { - content: "\f5b3"; } - -.fa-sad-cry::before { - content: "\f5b3"; } - -.fa-audio-description::before { - content: "\f29e"; } - -.fa-person-military-to-person::before { - content: "\e54c"; } - -.fa-file-shield::before { - content: "\e4f0"; } - -.fa-user-slash::before { - content: "\f506"; } - -.fa-pen::before { - content: "\f304"; } - -.fa-tower-observation::before { - content: "\e586"; } - -.fa-file-code::before { - content: "\f1c9"; } - -.fa-signal::before { - content: "\f012"; } - -.fa-signal-5::before { - content: "\f012"; } - -.fa-signal-perfect::before { - content: "\f012"; } - -.fa-bus::before { - content: "\f207"; } - -.fa-heart-circle-xmark::before { - content: "\e501"; } - -.fa-house-chimney::before { - content: "\e3af"; } - -.fa-home-lg::before { - content: "\e3af"; } - -.fa-window-maximize::before { - content: "\f2d0"; } - -.fa-face-frown::before { - content: "\f119"; } - -.fa-frown::before { - content: "\f119"; } - -.fa-prescription::before { - content: "\f5b1"; } - -.fa-shop::before { - content: "\f54f"; } - -.fa-store-alt::before { - content: "\f54f"; } - -.fa-floppy-disk::before { - content: "\f0c7"; } - -.fa-save::before { - content: "\f0c7"; } - -.fa-vihara::before { - content: "\f6a7"; } - -.fa-scale-unbalanced::before { - content: "\f515"; } - -.fa-balance-scale-left::before { - content: "\f515"; } - -.fa-sort-up::before { - content: "\f0de"; } - -.fa-sort-asc::before { - content: "\f0de"; } - -.fa-comment-dots::before { - content: "\f4ad"; } - -.fa-commenting::before { - content: "\f4ad"; } - -.fa-plant-wilt::before { - content: "\e5aa"; } - -.fa-diamond::before { - content: "\f219"; } - -.fa-face-grin-squint::before { - content: "\f585"; } - -.fa-grin-squint::before { - content: "\f585"; } - -.fa-hand-holding-dollar::before { - content: "\f4c0"; } - -.fa-hand-holding-usd::before { - content: "\f4c0"; } - -.fa-bacterium::before { - content: "\e05a"; } - -.fa-hand-pointer::before { - content: "\f25a"; } - -.fa-drum-steelpan::before { - content: "\f56a"; } - -.fa-hand-scissors::before { - content: "\f257"; } - -.fa-hands-praying::before { - content: "\f684"; } - -.fa-praying-hands::before { - content: "\f684"; } - -.fa-arrow-rotate-right::before { - content: "\f01e"; } - -.fa-arrow-right-rotate::before { - content: "\f01e"; } - -.fa-arrow-rotate-forward::before { - content: "\f01e"; } - -.fa-redo::before { - content: "\f01e"; } - -.fa-biohazard::before { - content: "\f780"; } - -.fa-location-crosshairs::before { - content: "\f601"; } - -.fa-location::before { - content: "\f601"; } - -.fa-mars-double::before { - content: "\f227"; } - -.fa-child-dress::before { - content: "\e59c"; } - -.fa-users-between-lines::before { - content: "\e591"; } - -.fa-lungs-virus::before { - content: "\e067"; } - -.fa-face-grin-tears::before { - content: "\f588"; } - -.fa-grin-tears::before { - content: "\f588"; } - -.fa-phone::before { - content: "\f095"; } - -.fa-calendar-xmark::before { - content: "\f273"; } - -.fa-calendar-times::before { - content: "\f273"; } - -.fa-child-reaching::before { - content: "\e59d"; } - -.fa-head-side-virus::before { - content: "\e064"; } - -.fa-user-gear::before { - content: "\f4fe"; } - -.fa-user-cog::before { - content: "\f4fe"; } - -.fa-arrow-up-1-9::before { - content: "\f163"; } - -.fa-sort-numeric-up::before { - content: "\f163"; } - -.fa-door-closed::before { - content: "\f52a"; } - -.fa-shield-virus::before { - content: "\e06c"; } - -.fa-dice-six::before { - content: "\f526"; } - -.fa-mosquito-net::before { - content: "\e52c"; } - -.fa-bridge-water::before { - content: "\e4ce"; } - -.fa-person-booth::before { - content: "\f756"; } - -.fa-text-width::before { - content: "\f035"; } - -.fa-hat-wizard::before { - content: "\f6e8"; } - -.fa-pen-fancy::before { - content: "\f5ac"; } - -.fa-person-digging::before { - content: "\f85e"; } - -.fa-digging::before { - content: "\f85e"; } - -.fa-trash::before { - content: "\f1f8"; } - -.fa-gauge-simple::before { - content: "\f629"; } - -.fa-gauge-simple-med::before { - content: "\f629"; } - -.fa-tachometer-average::before { - content: "\f629"; } - -.fa-book-medical::before { - content: "\f7e6"; } - -.fa-poo::before { - content: "\f2fe"; } - -.fa-quote-right::before { - content: "\f10e"; } - -.fa-quote-right-alt::before { - content: "\f10e"; } - -.fa-shirt::before { - content: "\f553"; } - -.fa-t-shirt::before { - content: "\f553"; } - -.fa-tshirt::before { - content: "\f553"; } - -.fa-cubes::before { - content: "\f1b3"; } - -.fa-divide::before { - content: "\f529"; } - -.fa-tenge-sign::before { - content: "\f7d7"; } - -.fa-tenge::before { - content: "\f7d7"; } - -.fa-headphones::before { - content: "\f025"; } - -.fa-hands-holding::before { - content: "\f4c2"; } - -.fa-hands-clapping::before { - content: "\e1a8"; } - -.fa-republican::before { - content: "\f75e"; } - -.fa-arrow-left::before { - content: "\f060"; } - -.fa-person-circle-xmark::before { - content: "\e543"; } - -.fa-ruler::before { - content: "\f545"; } - -.fa-align-left::before { - content: "\f036"; } - -.fa-dice-d6::before { - content: "\f6d1"; } - -.fa-restroom::before { - content: "\f7bd"; } - -.fa-j::before { - content: "\4a"; } - -.fa-users-viewfinder::before { - content: "\e595"; } - -.fa-file-video::before { - content: "\f1c8"; } - -.fa-up-right-from-square::before { - content: "\f35d"; } - -.fa-external-link-alt::before { - content: "\f35d"; } - -.fa-table-cells::before { - content: "\f00a"; } - -.fa-th::before { - content: "\f00a"; } - -.fa-file-pdf::before { - content: "\f1c1"; } - -.fa-book-bible::before { - content: "\f647"; } - -.fa-bible::before { - content: "\f647"; } - -.fa-o::before { - content: "\4f"; } - -.fa-suitcase-medical::before { - content: "\f0fa"; } - -.fa-medkit::before { - content: "\f0fa"; } - -.fa-user-secret::before { - content: "\f21b"; } - -.fa-otter::before { - content: "\f700"; } - -.fa-person-dress::before { - content: "\f182"; } - -.fa-female::before { - content: "\f182"; } - -.fa-comment-dollar::before { - content: "\f651"; } - -.fa-business-time::before { - content: "\f64a"; } - -.fa-briefcase-clock::before { - content: "\f64a"; } - -.fa-table-cells-large::before { - content: "\f009"; } - -.fa-th-large::before { - content: "\f009"; } - -.fa-book-tanakh::before { - content: "\f827"; } - -.fa-tanakh::before { - content: "\f827"; } - -.fa-phone-volume::before { - content: "\f2a0"; } - -.fa-volume-control-phone::before { - content: "\f2a0"; } - -.fa-hat-cowboy-side::before { - content: "\f8c1"; } - -.fa-clipboard-user::before { - content: "\f7f3"; } - -.fa-child::before { - content: "\f1ae"; } - -.fa-lira-sign::before { - content: "\f195"; } - -.fa-satellite::before { - content: "\f7bf"; } - -.fa-plane-lock::before { - content: "\e558"; } - -.fa-tag::before { - content: "\f02b"; } - -.fa-comment::before { - content: "\f075"; } - -.fa-cake-candles::before { - content: "\f1fd"; } - -.fa-birthday-cake::before { - content: "\f1fd"; } - -.fa-cake::before { - content: "\f1fd"; } - -.fa-envelope::before { - content: "\f0e0"; } - -.fa-angles-up::before { - content: "\f102"; } - -.fa-angle-double-up::before { - content: "\f102"; } - -.fa-paperclip::before { - content: "\f0c6"; } - -.fa-arrow-right-to-city::before { - content: "\e4b3"; } - -.fa-ribbon::before { - content: "\f4d6"; } - -.fa-lungs::before { - content: "\f604"; } - -.fa-arrow-up-9-1::before { - content: "\f887"; } - -.fa-sort-numeric-up-alt::before { - content: "\f887"; } - -.fa-litecoin-sign::before { - content: "\e1d3"; } - -.fa-border-none::before { - content: "\f850"; } - -.fa-circle-nodes::before { - content: "\e4e2"; } - -.fa-parachute-box::before { - content: "\f4cd"; } - -.fa-indent::before { - content: "\f03c"; } - -.fa-truck-field-un::before { - content: "\e58e"; } - -.fa-hourglass::before { - content: "\f254"; } - -.fa-hourglass-empty::before { - content: "\f254"; } - -.fa-mountain::before { - content: "\f6fc"; } - -.fa-user-doctor::before { - content: "\f0f0"; } - -.fa-user-md::before { - content: "\f0f0"; } - -.fa-circle-info::before { - content: "\f05a"; } - -.fa-info-circle::before { - content: "\f05a"; } - -.fa-cloud-meatball::before { - content: "\f73b"; } - -.fa-camera::before { - content: "\f030"; } - -.fa-camera-alt::before { - content: "\f030"; } - -.fa-square-virus::before { - content: "\e578"; } - -.fa-meteor::before { - content: "\f753"; } - -.fa-car-on::before { - content: "\e4dd"; } - -.fa-sleigh::before { - content: "\f7cc"; } - -.fa-arrow-down-1-9::before { - content: "\f162"; } - -.fa-sort-numeric-asc::before { - content: "\f162"; } - -.fa-sort-numeric-down::before { - content: "\f162"; } - -.fa-hand-holding-droplet::before { - content: "\f4c1"; } - -.fa-hand-holding-water::before { - content: "\f4c1"; } - -.fa-water::before { - content: "\f773"; } - -.fa-calendar-check::before { - content: "\f274"; } - -.fa-braille::before { - content: "\f2a1"; } - -.fa-prescription-bottle-medical::before { - content: "\f486"; } - -.fa-prescription-bottle-alt::before { - content: "\f486"; } - -.fa-landmark::before { - content: "\f66f"; } - -.fa-truck::before { - content: "\f0d1"; } - -.fa-crosshairs::before { - content: "\f05b"; } - -.fa-person-cane::before { - content: "\e53c"; } - -.fa-tent::before { - content: "\e57d"; } - -.fa-vest-patches::before { - content: "\e086"; } - -.fa-check-double::before { - content: "\f560"; } - -.fa-arrow-down-a-z::before { - content: "\f15d"; } - -.fa-sort-alpha-asc::before { - content: "\f15d"; } - -.fa-sort-alpha-down::before { - content: "\f15d"; } - -.fa-money-bill-wheat::before { - content: "\e52a"; } - -.fa-cookie::before { - content: "\f563"; } - -.fa-arrow-rotate-left::before { - content: "\f0e2"; } - -.fa-arrow-left-rotate::before { - content: "\f0e2"; } - -.fa-arrow-rotate-back::before { - content: "\f0e2"; } - -.fa-arrow-rotate-backward::before { - content: "\f0e2"; } - -.fa-undo::before { - content: "\f0e2"; } - -.fa-hard-drive::before { - content: "\f0a0"; } - -.fa-hdd::before { - content: "\f0a0"; } - -.fa-face-grin-squint-tears::before { - content: "\f586"; } - -.fa-grin-squint-tears::before { - content: "\f586"; } - -.fa-dumbbell::before { - content: "\f44b"; } - -.fa-rectangle-list::before { - content: "\f022"; } - -.fa-list-alt::before { - content: "\f022"; } - -.fa-tarp-droplet::before { - content: "\e57c"; } - -.fa-house-medical-circle-check::before { - content: "\e511"; } - -.fa-person-skiing-nordic::before { - content: "\f7ca"; } - -.fa-skiing-nordic::before { - content: "\f7ca"; } - -.fa-calendar-plus::before { - content: "\f271"; } - -.fa-plane-arrival::before { - content: "\f5af"; } - -.fa-circle-left::before { - content: "\f359"; } - -.fa-arrow-alt-circle-left::before { - content: "\f359"; } - -.fa-train-subway::before { - content: "\f239"; } - -.fa-subway::before { - content: "\f239"; } - -.fa-chart-gantt::before { - content: "\e0e4"; } - -.fa-indian-rupee-sign::before { - content: "\e1bc"; } - -.fa-indian-rupee::before { - content: "\e1bc"; } - -.fa-inr::before { - content: "\e1bc"; } - -.fa-crop-simple::before { - content: "\f565"; } - -.fa-crop-alt::before { - content: "\f565"; } - -.fa-money-bill-1::before { - content: "\f3d1"; } - -.fa-money-bill-alt::before { - content: "\f3d1"; } - -.fa-left-long::before { - content: "\f30a"; } - -.fa-long-arrow-alt-left::before { - content: "\f30a"; } - -.fa-dna::before { - content: "\f471"; } - -.fa-virus-slash::before { - content: "\e075"; } - -.fa-minus::before { - content: "\f068"; } - -.fa-subtract::before { - content: "\f068"; } - -.fa-chess::before { - content: "\f439"; } - -.fa-arrow-left-long::before { - content: "\f177"; } - -.fa-long-arrow-left::before { - content: "\f177"; } - -.fa-plug-circle-check::before { - content: "\e55c"; } - -.fa-street-view::before { - content: "\f21d"; } - -.fa-franc-sign::before { - content: "\e18f"; } - -.fa-volume-off::before { - content: "\f026"; } - -.fa-hands-asl-interpreting::before { - content: "\f2a3"; } - -.fa-american-sign-language-interpreting::before { - content: "\f2a3"; } - -.fa-asl-interpreting::before { - content: "\f2a3"; } - -.fa-hands-american-sign-language-interpreting::before { - content: "\f2a3"; } - -.fa-gear::before { - content: "\f013"; } - -.fa-cog::before { - content: "\f013"; } - -.fa-droplet-slash::before { - content: "\f5c7"; } - -.fa-tint-slash::before { - content: "\f5c7"; } - -.fa-mosque::before { - content: "\f678"; } - -.fa-mosquito::before { - content: "\e52b"; } - -.fa-star-of-david::before { - content: "\f69a"; } - -.fa-person-military-rifle::before { - content: "\e54b"; } - -.fa-cart-shopping::before { - content: "\f07a"; } - -.fa-shopping-cart::before { - content: "\f07a"; } - -.fa-vials::before { - content: "\f493"; } - -.fa-plug-circle-plus::before { - content: "\e55f"; } - -.fa-place-of-worship::before { - content: "\f67f"; } - -.fa-grip-vertical::before { - content: "\f58e"; } - -.fa-arrow-turn-up::before { - content: "\f148"; } - -.fa-level-up::before { - content: "\f148"; } - -.fa-u::before { - content: "\55"; } - -.fa-square-root-variable::before { - content: "\f698"; } - -.fa-square-root-alt::before { - content: "\f698"; } - -.fa-clock::before { - content: "\f017"; } - -.fa-clock-four::before { - content: "\f017"; } - -.fa-backward-step::before { - content: "\f048"; } - -.fa-step-backward::before { - content: "\f048"; } - -.fa-pallet::before { - content: "\f482"; } - -.fa-faucet::before { - content: "\e005"; } - -.fa-baseball-bat-ball::before { - content: "\f432"; } - -.fa-s::before { - content: "\53"; } - -.fa-timeline::before { - content: "\e29c"; } - -.fa-keyboard::before { - content: "\f11c"; } - -.fa-caret-down::before { - content: "\f0d7"; } - -.fa-house-chimney-medical::before { - content: "\f7f2"; } - -.fa-clinic-medical::before { - content: "\f7f2"; } - -.fa-temperature-three-quarters::before { - content: "\f2c8"; } - -.fa-temperature-3::before { - content: "\f2c8"; } - -.fa-thermometer-3::before { - content: "\f2c8"; } - -.fa-thermometer-three-quarters::before { - content: "\f2c8"; } - -.fa-mobile-screen::before { - content: "\f3cf"; } - -.fa-mobile-android-alt::before { - content: "\f3cf"; } - -.fa-plane-up::before { - content: "\e22d"; } - -.fa-piggy-bank::before { - content: "\f4d3"; } - -.fa-battery-half::before { - content: "\f242"; } - -.fa-battery-3::before { - content: "\f242"; } - -.fa-mountain-city::before { - content: "\e52e"; } - -.fa-coins::before { - content: "\f51e"; } - -.fa-khanda::before { - content: "\f66d"; } - -.fa-sliders::before { - content: "\f1de"; } - -.fa-sliders-h::before { - content: "\f1de"; } - -.fa-folder-tree::before { - content: "\f802"; } - -.fa-network-wired::before { - content: "\f6ff"; } - -.fa-map-pin::before { - content: "\f276"; } - -.fa-hamsa::before { - content: "\f665"; } - -.fa-cent-sign::before { - content: "\e3f5"; } - -.fa-flask::before { - content: "\f0c3"; } - -.fa-person-pregnant::before { - content: "\e31e"; } - -.fa-wand-sparkles::before { - content: "\f72b"; } - -.fa-ellipsis-vertical::before { - content: "\f142"; } - -.fa-ellipsis-v::before { - content: "\f142"; } - -.fa-ticket::before { - content: "\f145"; } - -.fa-power-off::before { - content: "\f011"; } - -.fa-right-long::before { - content: "\f30b"; } - -.fa-long-arrow-alt-right::before { - content: "\f30b"; } - -.fa-flag-usa::before { - content: "\f74d"; } - -.fa-laptop-file::before { - content: "\e51d"; } - -.fa-tty::before { - content: "\f1e4"; } - -.fa-teletype::before { - content: "\f1e4"; } - -.fa-diagram-next::before { - content: "\e476"; } - -.fa-person-rifle::before { - content: "\e54e"; } - -.fa-house-medical-circle-exclamation::before { - content: "\e512"; } - -.fa-closed-captioning::before { - content: "\f20a"; } - -.fa-person-hiking::before { - content: "\f6ec"; } - -.fa-hiking::before { - content: "\f6ec"; } - -.fa-venus-double::before { - content: "\f226"; } - -.fa-images::before { - content: "\f302"; } - -.fa-calculator::before { - content: "\f1ec"; } - -.fa-people-pulling::before { - content: "\e535"; } - -.fa-n::before { - content: "\4e"; } - -.fa-cable-car::before { - content: "\f7da"; } - -.fa-tram::before { - content: "\f7da"; } - -.fa-cloud-rain::before { - content: "\f73d"; } - -.fa-building-circle-xmark::before { - content: "\e4d4"; } - -.fa-ship::before { - content: "\f21a"; } - -.fa-arrows-down-to-line::before { - content: "\e4b8"; } - -.fa-download::before { - content: "\f019"; } - -.fa-face-grin::before { - content: "\f580"; } - -.fa-grin::before { - content: "\f580"; } - -.fa-delete-left::before { - content: "\f55a"; } - -.fa-backspace::before { - content: "\f55a"; } - -.fa-eye-dropper::before { - content: "\f1fb"; } - -.fa-eye-dropper-empty::before { - content: "\f1fb"; } - -.fa-eyedropper::before { - content: "\f1fb"; } - -.fa-file-circle-check::before { - content: "\e5a0"; } - -.fa-forward::before { - content: "\f04e"; } - -.fa-mobile::before { - content: "\f3ce"; } - -.fa-mobile-android::before { - content: "\f3ce"; } - -.fa-mobile-phone::before { - content: "\f3ce"; } - -.fa-face-meh::before { - content: "\f11a"; } - -.fa-meh::before { - content: "\f11a"; } - -.fa-align-center::before { - content: "\f037"; } - -.fa-book-skull::before { - content: "\f6b7"; } - -.fa-book-dead::before { - content: "\f6b7"; } - -.fa-id-card::before { - content: "\f2c2"; } - -.fa-drivers-license::before { - content: "\f2c2"; } - -.fa-outdent::before { - content: "\f03b"; } - -.fa-dedent::before { - content: "\f03b"; } - -.fa-heart-circle-exclamation::before { - content: "\e4fe"; } - -.fa-house::before { - content: "\f015"; } - -.fa-home::before { - content: "\f015"; } - -.fa-home-alt::before { - content: "\f015"; } - -.fa-home-lg-alt::before { - content: "\f015"; } - -.fa-calendar-week::before { - content: "\f784"; } - -.fa-laptop-medical::before { - content: "\f812"; } - -.fa-b::before { - content: "\42"; } - -.fa-file-medical::before { - content: "\f477"; } - -.fa-dice-one::before { - content: "\f525"; } - -.fa-kiwi-bird::before { - content: "\f535"; } - -.fa-arrow-right-arrow-left::before { - content: "\f0ec"; } - -.fa-exchange::before { - content: "\f0ec"; } - -.fa-rotate-right::before { - content: "\f2f9"; } - -.fa-redo-alt::before { - content: "\f2f9"; } - -.fa-rotate-forward::before { - content: "\f2f9"; } - -.fa-utensils::before { - content: "\f2e7"; } - -.fa-cutlery::before { - content: "\f2e7"; } - -.fa-arrow-up-wide-short::before { - content: "\f161"; } - -.fa-sort-amount-up::before { - content: "\f161"; } - -.fa-mill-sign::before { - content: "\e1ed"; } - -.fa-bowl-rice::before { - content: "\e2eb"; } - -.fa-skull::before { - content: "\f54c"; } - -.fa-tower-broadcast::before { - content: "\f519"; } - -.fa-broadcast-tower::before { - content: "\f519"; } - -.fa-truck-pickup::before { - content: "\f63c"; } - -.fa-up-long::before { - content: "\f30c"; } - -.fa-long-arrow-alt-up::before { - content: "\f30c"; } - -.fa-stop::before { - content: "\f04d"; } - -.fa-code-merge::before { - content: "\f387"; } - -.fa-upload::before { - content: "\f093"; } - -.fa-hurricane::before { - content: "\f751"; } - -.fa-mound::before { - content: "\e52d"; } - -.fa-toilet-portable::before { - content: "\e583"; } - -.fa-compact-disc::before { - content: "\f51f"; } - -.fa-file-arrow-down::before { - content: "\f56d"; } - -.fa-file-download::before { - content: "\f56d"; } - -.fa-caravan::before { - content: "\f8ff"; } - -.fa-shield-cat::before { - content: "\e572"; } - -.fa-bolt::before { - content: "\f0e7"; } - -.fa-zap::before { - content: "\f0e7"; } - -.fa-glass-water::before { - content: "\e4f4"; } - -.fa-oil-well::before { - content: "\e532"; } - -.fa-vault::before { - content: "\e2c5"; } - -.fa-mars::before { - content: "\f222"; } - -.fa-toilet::before { - content: "\f7d8"; } - -.fa-plane-circle-xmark::before { - content: "\e557"; } - -.fa-yen-sign::before { - content: "\f157"; } - -.fa-cny::before { - content: "\f157"; } - -.fa-jpy::before { - content: "\f157"; } - -.fa-rmb::before { - content: "\f157"; } - -.fa-yen::before { - content: "\f157"; } - -.fa-ruble-sign::before { - content: "\f158"; } - -.fa-rouble::before { - content: "\f158"; } - -.fa-rub::before { - content: "\f158"; } - -.fa-ruble::before { - content: "\f158"; } - -.fa-sun::before { - content: "\f185"; } - -.fa-guitar::before { - content: "\f7a6"; } - -.fa-face-laugh-wink::before { - content: "\f59c"; } - -.fa-laugh-wink::before { - content: "\f59c"; } - -.fa-horse-head::before { - content: "\f7ab"; } - -.fa-bore-hole::before { - content: "\e4c3"; } - -.fa-industry::before { - content: "\f275"; } - -.fa-circle-down::before { - content: "\f358"; } - -.fa-arrow-alt-circle-down::before { - content: "\f358"; } - -.fa-arrows-turn-to-dots::before { - content: "\e4c1"; } - -.fa-florin-sign::before { - content: "\e184"; } - -.fa-arrow-down-short-wide::before { - content: "\f884"; } - -.fa-sort-amount-desc::before { - content: "\f884"; } - -.fa-sort-amount-down-alt::before { - content: "\f884"; } - -.fa-less-than::before { - content: "\3c"; } - -.fa-angle-down::before { - content: "\f107"; } - -.fa-car-tunnel::before { - content: "\e4de"; } - -.fa-head-side-cough::before { - content: "\e061"; } - -.fa-grip-lines::before { - content: "\f7a4"; } - -.fa-thumbs-down::before { - content: "\f165"; } - -.fa-user-lock::before { - content: "\f502"; } - -.fa-arrow-right-long::before { - content: "\f178"; } - -.fa-long-arrow-right::before { - content: "\f178"; } - -.fa-anchor-circle-xmark::before { - content: "\e4ac"; } - -.fa-ellipsis::before { - content: "\f141"; } - -.fa-ellipsis-h::before { - content: "\f141"; } - -.fa-chess-pawn::before { - content: "\f443"; } - -.fa-kit-medical::before { - content: "\f479"; } - -.fa-first-aid::before { - content: "\f479"; } - -.fa-person-through-window::before { - content: "\e5a9"; } - -.fa-toolbox::before { - content: "\f552"; } - -.fa-hands-holding-circle::before { - content: "\e4fb"; } - -.fa-bug::before { - content: "\f188"; } - -.fa-credit-card::before { - content: "\f09d"; } - -.fa-credit-card-alt::before { - content: "\f09d"; } - -.fa-car::before { - content: "\f1b9"; } - -.fa-automobile::before { - content: "\f1b9"; } - -.fa-hand-holding-hand::before { - content: "\e4f7"; } - -.fa-book-open-reader::before { - content: "\f5da"; } - -.fa-book-reader::before { - content: "\f5da"; } - -.fa-mountain-sun::before { - content: "\e52f"; } - -.fa-arrows-left-right-to-line::before { - content: "\e4ba"; } - -.fa-dice-d20::before { - content: "\f6cf"; } - -.fa-truck-droplet::before { - content: "\e58c"; } - -.fa-file-circle-xmark::before { - content: "\e5a1"; } - -.fa-temperature-arrow-up::before { - content: "\e040"; } - -.fa-temperature-up::before { - content: "\e040"; } - -.fa-medal::before { - content: "\f5a2"; } - -.fa-bed::before { - content: "\f236"; } - -.fa-square-h::before { - content: "\f0fd"; } - -.fa-h-square::before { - content: "\f0fd"; } - -.fa-podcast::before { - content: "\f2ce"; } - -.fa-temperature-full::before { - content: "\f2c7"; } - -.fa-temperature-4::before { - content: "\f2c7"; } - -.fa-thermometer-4::before { - content: "\f2c7"; } - -.fa-thermometer-full::before { - content: "\f2c7"; } - -.fa-bell::before { - content: "\f0f3"; } - -.fa-superscript::before { - content: "\f12b"; } - -.fa-plug-circle-xmark::before { - content: "\e560"; } - -.fa-star-of-life::before { - content: "\f621"; } - -.fa-phone-slash::before { - content: "\f3dd"; } - -.fa-paint-roller::before { - content: "\f5aa"; } - -.fa-handshake-angle::before { - content: "\f4c4"; } - -.fa-hands-helping::before { - content: "\f4c4"; } - -.fa-location-dot::before { - content: "\f3c5"; } - -.fa-map-marker-alt::before { - content: "\f3c5"; } - -.fa-file::before { - content: "\f15b"; } - -.fa-greater-than::before { - content: "\3e"; } - -.fa-person-swimming::before { - content: "\f5c4"; } - -.fa-swimmer::before { - content: "\f5c4"; } - -.fa-arrow-down::before { - content: "\f063"; } - -.fa-droplet::before { - content: "\f043"; } - -.fa-tint::before { - content: "\f043"; } - -.fa-eraser::before { - content: "\f12d"; } - -.fa-earth-americas::before { - content: "\f57d"; } - -.fa-earth::before { - content: "\f57d"; } - -.fa-earth-america::before { - content: "\f57d"; } - -.fa-globe-americas::before { - content: "\f57d"; } - -.fa-person-burst::before { - content: "\e53b"; } - -.fa-dove::before { - content: "\f4ba"; } - -.fa-battery-empty::before { - content: "\f244"; } - -.fa-battery-0::before { - content: "\f244"; } - -.fa-socks::before { - content: "\f696"; } - -.fa-inbox::before { - content: "\f01c"; } - -.fa-section::before { - content: "\e447"; } - -.fa-gauge-high::before { - content: "\f625"; } - -.fa-tachometer-alt::before { - content: "\f625"; } - -.fa-tachometer-alt-fast::before { - content: "\f625"; } - -.fa-envelope-open-text::before { - content: "\f658"; } - -.fa-hospital::before { - content: "\f0f8"; } - -.fa-hospital-alt::before { - content: "\f0f8"; } - -.fa-hospital-wide::before { - content: "\f0f8"; } - -.fa-wine-bottle::before { - content: "\f72f"; } - -.fa-chess-rook::before { - content: "\f447"; } - -.fa-bars-staggered::before { - content: "\f550"; } - -.fa-reorder::before { - content: "\f550"; } - -.fa-stream::before { - content: "\f550"; } - -.fa-dharmachakra::before { - content: "\f655"; } - -.fa-hotdog::before { - content: "\f80f"; } - -.fa-person-walking-with-cane::before { - content: "\f29d"; } - -.fa-blind::before { - content: "\f29d"; } - -.fa-drum::before { - content: "\f569"; } - -.fa-ice-cream::before { - content: "\f810"; } - -.fa-heart-circle-bolt::before { - content: "\e4fc"; } - -.fa-fax::before { - content: "\f1ac"; } - -.fa-paragraph::before { - content: "\f1dd"; } - -.fa-check-to-slot::before { - content: "\f772"; } - -.fa-vote-yea::before { - content: "\f772"; } - -.fa-star-half::before { - content: "\f089"; } - -.fa-boxes-stacked::before { - content: "\f468"; } - -.fa-boxes::before { - content: "\f468"; } - -.fa-boxes-alt::before { - content: "\f468"; } - -.fa-link::before { - content: "\f0c1"; } - -.fa-chain::before { - content: "\f0c1"; } - -.fa-ear-listen::before { - content: "\f2a2"; } - -.fa-assistive-listening-systems::before { - content: "\f2a2"; } - -.fa-tree-city::before { - content: "\e587"; } - -.fa-play::before { - content: "\f04b"; } - -.fa-font::before { - content: "\f031"; } - -.fa-rupiah-sign::before { - content: "\e23d"; } - -.fa-magnifying-glass::before { - content: "\f002"; } - -.fa-search::before { - content: "\f002"; } - -.fa-table-tennis-paddle-ball::before { - content: "\f45d"; } - -.fa-ping-pong-paddle-ball::before { - content: "\f45d"; } - -.fa-table-tennis::before { - content: "\f45d"; } - -.fa-person-dots-from-line::before { - content: "\f470"; } - -.fa-diagnoses::before { - content: "\f470"; } - -.fa-trash-can-arrow-up::before { - content: "\f82a"; } - -.fa-trash-restore-alt::before { - content: "\f82a"; } - -.fa-naira-sign::before { - content: "\e1f6"; } - -.fa-cart-arrow-down::before { - content: "\f218"; } - -.fa-walkie-talkie::before { - content: "\f8ef"; } - -.fa-file-pen::before { - content: "\f31c"; } - -.fa-file-edit::before { - content: "\f31c"; } - -.fa-receipt::before { - content: "\f543"; } - -.fa-square-pen::before { - content: "\f14b"; } - -.fa-pen-square::before { - content: "\f14b"; } - -.fa-pencil-square::before { - content: "\f14b"; } - -.fa-suitcase-rolling::before { - content: "\f5c1"; } - -.fa-person-circle-exclamation::before { - content: "\e53f"; } - -.fa-chevron-down::before { - content: "\f078"; } - -.fa-battery-full::before { - content: "\f240"; } - -.fa-battery::before { - content: "\f240"; } - -.fa-battery-5::before { - content: "\f240"; } - -.fa-skull-crossbones::before { - content: "\f714"; } - -.fa-code-compare::before { - content: "\e13a"; } - -.fa-list-ul::before { - content: "\f0ca"; } - -.fa-list-dots::before { - content: "\f0ca"; } - -.fa-school-lock::before { - content: "\e56f"; } - -.fa-tower-cell::before { - content: "\e585"; } - -.fa-down-long::before { - content: "\f309"; } - -.fa-long-arrow-alt-down::before { - content: "\f309"; } - -.fa-ranking-star::before { - content: "\e561"; } - -.fa-chess-king::before { - content: "\f43f"; } - -.fa-person-harassing::before { - content: "\e549"; } - -.fa-brazilian-real-sign::before { - content: "\e46c"; } - -.fa-landmark-dome::before { - content: "\f752"; } - -.fa-landmark-alt::before { - content: "\f752"; } - -.fa-arrow-up::before { - content: "\f062"; } - -.fa-tv::before { - content: "\f26c"; } - -.fa-television::before { - content: "\f26c"; } - -.fa-tv-alt::before { - content: "\f26c"; } - -.fa-shrimp::before { - content: "\e448"; } - -.fa-list-check::before { - content: "\f0ae"; } - -.fa-tasks::before { - content: "\f0ae"; } - -.fa-jug-detergent::before { - content: "\e519"; } - -.fa-circle-user::before { - content: "\f2bd"; } - -.fa-user-circle::before { - content: "\f2bd"; } - -.fa-user-shield::before { - content: "\f505"; } - -.fa-wind::before { - content: "\f72e"; } - -.fa-car-burst::before { - content: "\f5e1"; } - -.fa-car-crash::before { - content: "\f5e1"; } - -.fa-y::before { - content: "\59"; } - -.fa-person-snowboarding::before { - content: "\f7ce"; } - -.fa-snowboarding::before { - content: "\f7ce"; } - -.fa-truck-fast::before { - content: "\f48b"; } - -.fa-shipping-fast::before { - content: "\f48b"; } - -.fa-fish::before { - content: "\f578"; } - -.fa-user-graduate::before { - content: "\f501"; } - -.fa-circle-half-stroke::before { - content: "\f042"; } - -.fa-adjust::before { - content: "\f042"; } - -.fa-clapperboard::before { - content: "\e131"; } - -.fa-circle-radiation::before { - content: "\f7ba"; } - -.fa-radiation-alt::before { - content: "\f7ba"; } - -.fa-baseball::before { - content: "\f433"; } - -.fa-baseball-ball::before { - content: "\f433"; } - -.fa-jet-fighter-up::before { - content: "\e518"; } - -.fa-diagram-project::before { - content: "\f542"; } - -.fa-project-diagram::before { - content: "\f542"; } - -.fa-copy::before { - content: "\f0c5"; } - -.fa-volume-xmark::before { - content: "\f6a9"; } - -.fa-volume-mute::before { - content: "\f6a9"; } - -.fa-volume-times::before { - content: "\f6a9"; } - -.fa-hand-sparkles::before { - content: "\e05d"; } - -.fa-grip::before { - content: "\f58d"; } - -.fa-grip-horizontal::before { - content: "\f58d"; } - -.fa-share-from-square::before { - content: "\f14d"; } - -.fa-share-square::before { - content: "\f14d"; } - -.fa-child-combatant::before { - content: "\e4e0"; } - -.fa-child-rifle::before { - content: "\e4e0"; } - -.fa-gun::before { - content: "\e19b"; } - -.fa-square-phone::before { - content: "\f098"; } - -.fa-phone-square::before { - content: "\f098"; } - -.fa-plus::before { - content: "\2b"; } - -.fa-add::before { - content: "\2b"; } - -.fa-expand::before { - content: "\f065"; } - -.fa-computer::before { - content: "\e4e5"; } - -.fa-xmark::before { - content: "\f00d"; } - -.fa-close::before { - content: "\f00d"; } - -.fa-multiply::before { - content: "\f00d"; } - -.fa-remove::before { - content: "\f00d"; } - -.fa-times::before { - content: "\f00d"; } - -.fa-arrows-up-down-left-right::before { - content: "\f047"; } - -.fa-arrows::before { - content: "\f047"; } - -.fa-chalkboard-user::before { - content: "\f51c"; } - -.fa-chalkboard-teacher::before { - content: "\f51c"; } - -.fa-peso-sign::before { - content: "\e222"; } - -.fa-building-shield::before { - content: "\e4d8"; } - -.fa-baby::before { - content: "\f77c"; } - -.fa-users-line::before { - content: "\e592"; } - -.fa-quote-left::before { - content: "\f10d"; } - -.fa-quote-left-alt::before { - content: "\f10d"; } - -.fa-tractor::before { - content: "\f722"; } - -.fa-trash-arrow-up::before { - content: "\f829"; } - -.fa-trash-restore::before { - content: "\f829"; } - -.fa-arrow-down-up-lock::before { - content: "\e4b0"; } - -.fa-lines-leaning::before { - content: "\e51e"; } - -.fa-ruler-combined::before { - content: "\f546"; } - -.fa-copyright::before { - content: "\f1f9"; } - -.fa-equals::before { - content: "\3d"; } - -.fa-blender::before { - content: "\f517"; } - -.fa-teeth::before { - content: "\f62e"; } - -.fa-shekel-sign::before { - content: "\f20b"; } - -.fa-ils::before { - content: "\f20b"; } - -.fa-shekel::before { - content: "\f20b"; } - -.fa-sheqel::before { - content: "\f20b"; } - -.fa-sheqel-sign::before { - content: "\f20b"; } - -.fa-map::before { - content: "\f279"; } - -.fa-rocket::before { - content: "\f135"; } - -.fa-photo-film::before { - content: "\f87c"; } - -.fa-photo-video::before { - content: "\f87c"; } - -.fa-folder-minus::before { - content: "\f65d"; } - -.fa-store::before { - content: "\f54e"; } - -.fa-arrow-trend-up::before { - content: "\e098"; } - -.fa-plug-circle-minus::before { - content: "\e55e"; } - -.fa-sign-hanging::before { - content: "\f4d9"; } - -.fa-sign::before { - content: "\f4d9"; } - -.fa-bezier-curve::before { - content: "\f55b"; } - -.fa-bell-slash::before { - content: "\f1f6"; } - -.fa-tablet::before { - content: "\f3fb"; } - -.fa-tablet-android::before { - content: "\f3fb"; } - -.fa-school-flag::before { - content: "\e56e"; } - -.fa-fill::before { - content: "\f575"; } - -.fa-angle-up::before { - content: "\f106"; } - -.fa-drumstick-bite::before { - content: "\f6d7"; } - -.fa-holly-berry::before { - content: "\f7aa"; } - -.fa-chevron-left::before { - content: "\f053"; } - -.fa-bacteria::before { - content: "\e059"; } - -.fa-hand-lizard::before { - content: "\f258"; } - -.fa-notdef::before { - content: "\e1fe"; } - -.fa-disease::before { - content: "\f7fa"; } - -.fa-briefcase-medical::before { - content: "\f469"; } - -.fa-genderless::before { - content: "\f22d"; } - -.fa-chevron-right::before { - content: "\f054"; } - -.fa-retweet::before { - content: "\f079"; } - -.fa-car-rear::before { - content: "\f5de"; } - -.fa-car-alt::before { - content: "\f5de"; } - -.fa-pump-soap::before { - content: "\e06b"; } - -.fa-video-slash::before { - content: "\f4e2"; } - -.fa-battery-quarter::before { - content: "\f243"; } - -.fa-battery-2::before { - content: "\f243"; } - -.fa-radio::before { - content: "\f8d7"; } - -.fa-baby-carriage::before { - content: "\f77d"; } - -.fa-carriage-baby::before { - content: "\f77d"; } - -.fa-traffic-light::before { - content: "\f637"; } - -.fa-thermometer::before { - content: "\f491"; } - -.fa-vr-cardboard::before { - content: "\f729"; } - -.fa-hand-middle-finger::before { - content: "\f806"; } - -.fa-percent::before { - content: "\25"; } - -.fa-percentage::before { - content: "\25"; } - -.fa-truck-moving::before { - content: "\f4df"; } - -.fa-glass-water-droplet::before { - content: "\e4f5"; } - -.fa-display::before { - content: "\e163"; } - -.fa-face-smile::before { - content: "\f118"; } - -.fa-smile::before { - content: "\f118"; } - -.fa-thumbtack::before { - content: "\f08d"; } - -.fa-thumb-tack::before { - content: "\f08d"; } - -.fa-trophy::before { - content: "\f091"; } - -.fa-person-praying::before { - content: "\f683"; } - -.fa-pray::before { - content: "\f683"; } - -.fa-hammer::before { - content: "\f6e3"; } - -.fa-hand-peace::before { - content: "\f25b"; } - -.fa-rotate::before { - content: "\f2f1"; } - -.fa-sync-alt::before { - content: "\f2f1"; } - -.fa-spinner::before { - content: "\f110"; } - -.fa-robot::before { - content: "\f544"; } - -.fa-peace::before { - content: "\f67c"; } - -.fa-gears::before { - content: "\f085"; } - -.fa-cogs::before { - content: "\f085"; } - -.fa-warehouse::before { - content: "\f494"; } - -.fa-arrow-up-right-dots::before { - content: "\e4b7"; } - -.fa-splotch::before { - content: "\f5bc"; } - -.fa-face-grin-hearts::before { - content: "\f584"; } - -.fa-grin-hearts::before { - content: "\f584"; } - -.fa-dice-four::before { - content: "\f524"; } - -.fa-sim-card::before { - content: "\f7c4"; } - -.fa-transgender::before { - content: "\f225"; } - -.fa-transgender-alt::before { - content: "\f225"; } - -.fa-mercury::before { - content: "\f223"; } - -.fa-arrow-turn-down::before { - content: "\f149"; } - -.fa-level-down::before { - content: "\f149"; } - -.fa-person-falling-burst::before { - content: "\e547"; } - -.fa-award::before { - content: "\f559"; } - -.fa-ticket-simple::before { - content: "\f3ff"; } - -.fa-ticket-alt::before { - content: "\f3ff"; } - -.fa-building::before { - content: "\f1ad"; } - -.fa-angles-left::before { - content: "\f100"; } - -.fa-angle-double-left::before { - content: "\f100"; } - -.fa-qrcode::before { - content: "\f029"; } - -.fa-clock-rotate-left::before { - content: "\f1da"; } - -.fa-history::before { - content: "\f1da"; } - -.fa-face-grin-beam-sweat::before { - content: "\f583"; } - -.fa-grin-beam-sweat::before { - content: "\f583"; } - -.fa-file-export::before { - content: "\f56e"; } - -.fa-arrow-right-from-file::before { - content: "\f56e"; } - -.fa-shield::before { - content: "\f132"; } - -.fa-shield-blank::before { - content: "\f132"; } - -.fa-arrow-up-short-wide::before { - content: "\f885"; } - -.fa-sort-amount-up-alt::before { - content: "\f885"; } - -.fa-house-medical::before { - content: "\e3b2"; } - -.fa-golf-ball-tee::before { - content: "\f450"; } - -.fa-golf-ball::before { - content: "\f450"; } - -.fa-circle-chevron-left::before { - content: "\f137"; } - -.fa-chevron-circle-left::before { - content: "\f137"; } - -.fa-house-chimney-window::before { - content: "\e00d"; } - -.fa-pen-nib::before { - content: "\f5ad"; } - -.fa-tent-arrow-turn-left::before { - content: "\e580"; } - -.fa-tents::before { - content: "\e582"; } - -.fa-wand-magic::before { - content: "\f0d0"; } - -.fa-magic::before { - content: "\f0d0"; } - -.fa-dog::before { - content: "\f6d3"; } - -.fa-carrot::before { - content: "\f787"; } - -.fa-moon::before { - content: "\f186"; } - -.fa-wine-glass-empty::before { - content: "\f5ce"; } - -.fa-wine-glass-alt::before { - content: "\f5ce"; } - -.fa-cheese::before { - content: "\f7ef"; } - -.fa-yin-yang::before { - content: "\f6ad"; } - -.fa-music::before { - content: "\f001"; } - -.fa-code-commit::before { - content: "\f386"; } - -.fa-temperature-low::before { - content: "\f76b"; } - -.fa-person-biking::before { - content: "\f84a"; } - -.fa-biking::before { - content: "\f84a"; } - -.fa-broom::before { - content: "\f51a"; } - -.fa-shield-heart::before { - content: "\e574"; } - -.fa-gopuram::before { - content: "\f664"; } - -.fa-earth-oceania::before { - content: "\e47b"; } - -.fa-globe-oceania::before { - content: "\e47b"; } - -.fa-square-xmark::before { - content: "\f2d3"; } - -.fa-times-square::before { - content: "\f2d3"; } - -.fa-xmark-square::before { - content: "\f2d3"; } - -.fa-hashtag::before { - content: "\23"; } - -.fa-up-right-and-down-left-from-center::before { - content: "\f424"; } - -.fa-expand-alt::before { - content: "\f424"; } - -.fa-oil-can::before { - content: "\f613"; } - -.fa-t::before { - content: "\54"; } - -.fa-hippo::before { - content: "\f6ed"; } - -.fa-chart-column::before { - content: "\e0e3"; } - -.fa-infinity::before { - content: "\f534"; } - -.fa-vial-circle-check::before { - content: "\e596"; } - -.fa-person-arrow-down-to-line::before { - content: "\e538"; } - -.fa-voicemail::before { - content: "\f897"; } - -.fa-fan::before { - content: "\f863"; } - -.fa-person-walking-luggage::before { - content: "\e554"; } - -.fa-up-down::before { - content: "\f338"; } - -.fa-arrows-alt-v::before { - content: "\f338"; } - -.fa-cloud-moon-rain::before { - content: "\f73c"; } - -.fa-calendar::before { - content: "\f133"; } - -.fa-trailer::before { - content: "\e041"; } - -.fa-bahai::before { - content: "\f666"; } - -.fa-haykal::before { - content: "\f666"; } - -.fa-sd-card::before { - content: "\f7c2"; } - -.fa-dragon::before { - content: "\f6d5"; } - -.fa-shoe-prints::before { - content: "\f54b"; } - -.fa-circle-plus::before { - content: "\f055"; } - -.fa-plus-circle::before { - content: "\f055"; } - -.fa-face-grin-tongue-wink::before { - content: "\f58b"; } - -.fa-grin-tongue-wink::before { - content: "\f58b"; } - -.fa-hand-holding::before { - content: "\f4bd"; } - -.fa-plug-circle-exclamation::before { - content: "\e55d"; } - -.fa-link-slash::before { - content: "\f127"; } - -.fa-chain-broken::before { - content: "\f127"; } - -.fa-chain-slash::before { - content: "\f127"; } - -.fa-unlink::before { - content: "\f127"; } - -.fa-clone::before { - content: "\f24d"; } - -.fa-person-walking-arrow-loop-left::before { - content: "\e551"; } - -.fa-arrow-up-z-a::before { - content: "\f882"; } - -.fa-sort-alpha-up-alt::before { - content: "\f882"; } - -.fa-fire-flame-curved::before { - content: "\f7e4"; } - -.fa-fire-alt::before { - content: "\f7e4"; } - -.fa-tornado::before { - content: "\f76f"; } - -.fa-file-circle-plus::before { - content: "\e494"; } - -.fa-book-quran::before { - content: "\f687"; } - -.fa-quran::before { - content: "\f687"; } - -.fa-anchor::before { - content: "\f13d"; } - -.fa-border-all::before { - content: "\f84c"; } - -.fa-face-angry::before { - content: "\f556"; } - -.fa-angry::before { - content: "\f556"; } - -.fa-cookie-bite::before { - content: "\f564"; } - -.fa-arrow-trend-down::before { - content: "\e097"; } - -.fa-rss::before { - content: "\f09e"; } - -.fa-feed::before { - content: "\f09e"; } - -.fa-draw-polygon::before { - content: "\f5ee"; } - -.fa-scale-balanced::before { - content: "\f24e"; } - -.fa-balance-scale::before { - content: "\f24e"; } - -.fa-gauge-simple-high::before { - content: "\f62a"; } - -.fa-tachometer::before { - content: "\f62a"; } - -.fa-tachometer-fast::before { - content: "\f62a"; } - -.fa-shower::before { - content: "\f2cc"; } - -.fa-desktop::before { - content: "\f390"; } - -.fa-desktop-alt::before { - content: "\f390"; } - -.fa-m::before { - content: "\4d"; } - -.fa-table-list::before { - content: "\f00b"; } - -.fa-th-list::before { - content: "\f00b"; } - -.fa-comment-sms::before { - content: "\f7cd"; } - -.fa-sms::before { - content: "\f7cd"; } - -.fa-book::before { - content: "\f02d"; } - -.fa-user-plus::before { - content: "\f234"; } - -.fa-check::before { - content: "\f00c"; } - -.fa-battery-three-quarters::before { - content: "\f241"; } - -.fa-battery-4::before { - content: "\f241"; } - -.fa-house-circle-check::before { - content: "\e509"; } - -.fa-angle-left::before { - content: "\f104"; } - -.fa-diagram-successor::before { - content: "\e47a"; } - -.fa-truck-arrow-right::before { - content: "\e58b"; } - -.fa-arrows-split-up-and-left::before { - content: "\e4bc"; } - -.fa-hand-fist::before { - content: "\f6de"; } - -.fa-fist-raised::before { - content: "\f6de"; } - -.fa-cloud-moon::before { - content: "\f6c3"; } - -.fa-briefcase::before { - content: "\f0b1"; } - -.fa-person-falling::before { - content: "\e546"; } - -.fa-image-portrait::before { - content: "\f3e0"; } - -.fa-portrait::before { - content: "\f3e0"; } - -.fa-user-tag::before { - content: "\f507"; } - -.fa-rug::before { - content: "\e569"; } - -.fa-earth-europe::before { - content: "\f7a2"; } - -.fa-globe-europe::before { - content: "\f7a2"; } - -.fa-cart-flatbed-suitcase::before { - content: "\f59d"; } - -.fa-luggage-cart::before { - content: "\f59d"; } - -.fa-rectangle-xmark::before { - content: "\f410"; } - -.fa-rectangle-times::before { - content: "\f410"; } - -.fa-times-rectangle::before { - content: "\f410"; } - -.fa-window-close::before { - content: "\f410"; } - -.fa-baht-sign::before { - content: "\e0ac"; } - -.fa-book-open::before { - content: "\f518"; } - -.fa-book-journal-whills::before { - content: "\f66a"; } - -.fa-journal-whills::before { - content: "\f66a"; } - -.fa-handcuffs::before { - content: "\e4f8"; } - -.fa-triangle-exclamation::before { - content: "\f071"; } - -.fa-exclamation-triangle::before { - content: "\f071"; } - -.fa-warning::before { - content: "\f071"; } - -.fa-database::before { - content: "\f1c0"; } - -.fa-share::before { - content: "\f064"; } - -.fa-arrow-turn-right::before { - content: "\f064"; } - -.fa-mail-forward::before { - content: "\f064"; } - -.fa-bottle-droplet::before { - content: "\e4c4"; } - -.fa-mask-face::before { - content: "\e1d7"; } - -.fa-hill-rockslide::before { - content: "\e508"; } - -.fa-right-left::before { - content: "\f362"; } - -.fa-exchange-alt::before { - content: "\f362"; } - -.fa-paper-plane::before { - content: "\f1d8"; } - -.fa-road-circle-exclamation::before { - content: "\e565"; } - -.fa-dungeon::before { - content: "\f6d9"; } - -.fa-align-right::before { - content: "\f038"; } - -.fa-money-bill-1-wave::before { - content: "\f53b"; } - -.fa-money-bill-wave-alt::before { - content: "\f53b"; } - -.fa-life-ring::before { - content: "\f1cd"; } - -.fa-hands::before { - content: "\f2a7"; } - -.fa-sign-language::before { - content: "\f2a7"; } - -.fa-signing::before { - content: "\f2a7"; } - -.fa-calendar-day::before { - content: "\f783"; } - -.fa-water-ladder::before { - content: "\f5c5"; } - -.fa-ladder-water::before { - content: "\f5c5"; } - -.fa-swimming-pool::before { - content: "\f5c5"; } - -.fa-arrows-up-down::before { - content: "\f07d"; } - -.fa-arrows-v::before { - content: "\f07d"; } - -.fa-face-grimace::before { - content: "\f57f"; } - -.fa-grimace::before { - content: "\f57f"; } - -.fa-wheelchair-move::before { - content: "\e2ce"; } - -.fa-wheelchair-alt::before { - content: "\e2ce"; } - -.fa-turn-down::before { - content: "\f3be"; } - -.fa-level-down-alt::before { - content: "\f3be"; } - -.fa-person-walking-arrow-right::before { - content: "\e552"; } - -.fa-square-envelope::before { - content: "\f199"; } - -.fa-envelope-square::before { - content: "\f199"; } - -.fa-dice::before { - content: "\f522"; } - -.fa-bowling-ball::before { - content: "\f436"; } - -.fa-brain::before { - content: "\f5dc"; } - -.fa-bandage::before { - content: "\f462"; } - -.fa-band-aid::before { - content: "\f462"; } - -.fa-calendar-minus::before { - content: "\f272"; } - -.fa-circle-xmark::before { - content: "\f057"; } - -.fa-times-circle::before { - content: "\f057"; } - -.fa-xmark-circle::before { - content: "\f057"; } - -.fa-gifts::before { - content: "\f79c"; } - -.fa-hotel::before { - content: "\f594"; } - -.fa-earth-asia::before { - content: "\f57e"; } - -.fa-globe-asia::before { - content: "\f57e"; } - -.fa-id-card-clip::before { - content: "\f47f"; } - -.fa-id-card-alt::before { - content: "\f47f"; } - -.fa-magnifying-glass-plus::before { - content: "\f00e"; } - -.fa-search-plus::before { - content: "\f00e"; } - -.fa-thumbs-up::before { - content: "\f164"; } - -.fa-user-clock::before { - content: "\f4fd"; } - -.fa-hand-dots::before { - content: "\f461"; } - -.fa-allergies::before { - content: "\f461"; } - -.fa-file-invoice::before { - content: "\f570"; } - -.fa-window-minimize::before { - content: "\f2d1"; } - -.fa-mug-saucer::before { - content: "\f0f4"; } - -.fa-coffee::before { - content: "\f0f4"; } - -.fa-brush::before { - content: "\f55d"; } - -.fa-mask::before { - content: "\f6fa"; } - -.fa-magnifying-glass-minus::before { - content: "\f010"; } - -.fa-search-minus::before { - content: "\f010"; } - -.fa-ruler-vertical::before { - content: "\f548"; } - -.fa-user-large::before { - content: "\f406"; } - -.fa-user-alt::before { - content: "\f406"; } - -.fa-train-tram::before { - content: "\e5b4"; } - -.fa-user-nurse::before { - content: "\f82f"; } - -.fa-syringe::before { - content: "\f48e"; } - -.fa-cloud-sun::before { - content: "\f6c4"; } - -.fa-stopwatch-20::before { - content: "\e06f"; } - -.fa-square-full::before { - content: "\f45c"; } - -.fa-magnet::before { - content: "\f076"; } - -.fa-jar::before { - content: "\e516"; } - -.fa-note-sticky::before { - content: "\f249"; } - -.fa-sticky-note::before { - content: "\f249"; } - -.fa-bug-slash::before { - content: "\e490"; } - -.fa-arrow-up-from-water-pump::before { - content: "\e4b6"; } - -.fa-bone::before { - content: "\f5d7"; } - -.fa-user-injured::before { - content: "\f728"; } - -.fa-face-sad-tear::before { - content: "\f5b4"; } - -.fa-sad-tear::before { - content: "\f5b4"; } - -.fa-plane::before { - content: "\f072"; } - -.fa-tent-arrows-down::before { - content: "\e581"; } - -.fa-exclamation::before { - content: "\21"; } - -.fa-arrows-spin::before { - content: "\e4bb"; } - -.fa-print::before { - content: "\f02f"; } - -.fa-turkish-lira-sign::before { - content: "\e2bb"; } - -.fa-try::before { - content: "\e2bb"; } - -.fa-turkish-lira::before { - content: "\e2bb"; } - -.fa-dollar-sign::before { - content: "\24"; } - -.fa-dollar::before { - content: "\24"; } - -.fa-usd::before { - content: "\24"; } - -.fa-x::before { - content: "\58"; } - -.fa-magnifying-glass-dollar::before { - content: "\f688"; } - -.fa-search-dollar::before { - content: "\f688"; } - -.fa-users-gear::before { - content: "\f509"; } - -.fa-users-cog::before { - content: "\f509"; } - -.fa-person-military-pointing::before { - content: "\e54a"; } - -.fa-building-columns::before { - content: "\f19c"; } - -.fa-bank::before { - content: "\f19c"; } - -.fa-institution::before { - content: "\f19c"; } - -.fa-museum::before { - content: "\f19c"; } - -.fa-university::before { - content: "\f19c"; } - -.fa-umbrella::before { - content: "\f0e9"; } - -.fa-trowel::before { - content: "\e589"; } - -.fa-d::before { - content: "\44"; } - -.fa-stapler::before { - content: "\e5af"; } - -.fa-masks-theater::before { - content: "\f630"; } - -.fa-theater-masks::before { - content: "\f630"; } - -.fa-kip-sign::before { - content: "\e1c4"; } - -.fa-hand-point-left::before { - content: "\f0a5"; } - -.fa-handshake-simple::before { - content: "\f4c6"; } - -.fa-handshake-alt::before { - content: "\f4c6"; } - -.fa-jet-fighter::before { - content: "\f0fb"; } - -.fa-fighter-jet::before { - content: "\f0fb"; } - -.fa-square-share-nodes::before { - content: "\f1e1"; } - -.fa-share-alt-square::before { - content: "\f1e1"; } - -.fa-barcode::before { - content: "\f02a"; } - -.fa-plus-minus::before { - content: "\e43c"; } - -.fa-video::before { - content: "\f03d"; } - -.fa-video-camera::before { - content: "\f03d"; } - -.fa-graduation-cap::before { - content: "\f19d"; } - -.fa-mortar-board::before { - content: "\f19d"; } - -.fa-hand-holding-medical::before { - content: "\e05c"; } - -.fa-person-circle-check::before { - content: "\e53e"; } - -.fa-turn-up::before { - content: "\f3bf"; } - -.fa-level-up-alt::before { - content: "\f3bf"; } - -.sr-only, -.fa-sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; } - -.sr-only-focusable:not(:focus), -.fa-sr-only-focusable:not(:focus) { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; } -/*! - * Glightbox v3.1.0 - * https://github.com/biati-digital/glightbox - * Released under the MIT license - */ - -.glightbox-container { - width: 100%; - height: 100%; - position: fixed; - top: 0; - left: 0; - z-index: 999999 !important; - overflow: hidden; - -ms-touch-action: none; - touch-action: none; - -webkit-text-size-adjust: 100%; - -moz-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; - text-size-adjust: 100%; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - outline: 0; - overflow: hidden; -} -.glightbox-container.inactive { - display: none; -} -.glightbox-container .gcontainer { - position: relative; - width: 100%; - height: 100%; - z-index: 9999; - overflow: hidden; -} -.glightbox-container .gslider { - -webkit-transition: -webkit-transform 0.4s ease; - transition: -webkit-transform 0.4s ease; - transition: transform 0.4s ease; - transition: transform 0.4s ease, -webkit-transform 0.4s ease; - height: 100%; - left: 0; - top: 0; - width: 100%; - position: relative; - overflow: hidden; - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); -} -.glightbox-container .gslide { - width: 100%; - position: absolute; - opacity: 1; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - opacity: 0; -} -.glightbox-container .gslide.current { - opacity: 1; - z-index: 99999; - position: relative; -} -.glightbox-container .gslide.prev { - opacity: 1; - z-index: 9999; -} -.glightbox-container .gslide-inner-content { - width: 100%; -} -.glightbox-container .ginner-container { - position: relative; - width: 100%; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - max-width: 100%; - margin: auto; - height: 100vh; -} -.glightbox-container .ginner-container.gvideo-container { - width: 100%; -} -.glightbox-container .ginner-container.desc-bottom, -.glightbox-container .ginner-container.desc-top { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; -} -.glightbox-container .ginner-container.desc-left, -.glightbox-container .ginner-container.desc-right { - max-width: 100% !important; -} -.gslide iframe, -.gslide video { - outline: 0 !important; - border: none; - min-height: 165px; - -webkit-overflow-scrolling: touch; - -ms-touch-action: auto; - touch-action: auto; -} -.gslide:not(.current) { - pointer-events: none; -} -.gslide-image { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} -.gslide-image img { - max-height: 100vh; - display: block; - padding: 0; - float: none; - outline: 0; - border: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - max-width: 100vw; - width: auto; - height: auto; - -o-object-fit: cover; - object-fit: cover; - -ms-touch-action: none; - touch-action: none; - margin: auto; - min-width: 200px; -} -.desc-bottom .gslide-image img, -.desc-top .gslide-image img { - width: auto; -} -.desc-left .gslide-image img, -.desc-right .gslide-image img { - width: auto; - max-width: 100%; -} -.gslide-image img.zoomable { - position: relative; -} -.gslide-image img.dragging { - cursor: -webkit-grabbing !important; - cursor: grabbing !important; - -webkit-transition: none; - transition: none; -} -.gslide-video { - position: relative; - max-width: 100vh; - width: 100% !important; -} -.gslide-video .gvideo-wrapper { - width: 100%; - margin: auto; -} -.gslide-video::before { - content: ""; - display: block; - position: absolute; - width: 100%; - height: 100%; - background: rgba(255, 0, 0, 0.34); - display: none; -} -.gslide-video.playing::before { - display: none; -} -.gslide-video.fullscreen { - max-width: 100% !important; - min-width: 100%; - height: 75vh; -} -.gslide-video.fullscreen video { - max-width: 100% !important; - width: 100% !important; -} -.gslide-inline { - background: #fff; - text-align: left; - max-height: calc(100vh - 40px); - overflow: auto; - max-width: 100%; -} -.gslide-inline .ginlined-content { - padding: 20px; - width: 100%; -} -.gslide-inline .dragging { - cursor: -webkit-grabbing !important; - cursor: grabbing !important; - -webkit-transition: none; - transition: none; -} -.ginlined-content { - overflow: auto; - display: block !important; - opacity: 1; -} -.gslide-external { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - width: 100%; - min-width: 100%; - background: #fff; - padding: 0; - overflow: auto; - max-height: 75vh; - height: 100%; -} -.gslide-media { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - width: auto; -} -.zoomed .gslide-media { - -webkit-box-shadow: none !important; - box-shadow: none !important; -} -.desc-bottom .gslide-media, -.desc-top .gslide-media { - margin: 0 auto; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; -} -.gslide-description { - position: relative; - -webkit-box-flex: 1; - -ms-flex: 1 0 100%; - flex: 1 0 100%; -} -.gslide-description.description-left, -.gslide-description.description-right { - max-width: 100%; -} -.gslide-description.description-bottom, -.gslide-description.description-top { - margin: 0 auto; - width: 100%; -} -.gslide-description p { - margin-bottom: 12px; -} -.gslide-description p:last-child { - margin-bottom: 0; -} -.zoomed .gslide-description { - display: none; -} -.glightbox-button-hidden { - display: none; -} -.glightbox-mobile .glightbox-container .gslide-description { - height: auto !important; - width: 100%; - background: 0 0; - position: absolute; - bottom: 0; - padding: 19px 11px; - max-width: 100vw !important; - -webkit-box-ordinal-group: 3 !important; - -ms-flex-order: 2 !important; - order: 2 !important; - max-height: 78vh; - overflow: auto !important; - background: -webkit-gradient( - linear, - left top, - left bottom, - from(rgba(0, 0, 0, 0)), - to(rgba(0, 0, 0, 0.75)) - ); - background: linear-gradient( - to bottom, - rgba(0, 0, 0, 0) 0, - rgba(0, 0, 0, 0.75) 100% - ); - -webkit-transition: opacity 0.3s linear; - transition: opacity 0.3s linear; - padding-bottom: 50px; -} -.glightbox-mobile .glightbox-container .gslide-title { - color: #fff; - font-size: 1em; -} -.glightbox-mobile .glightbox-container .gslide-desc { - color: #a1a1a1; -} -.glightbox-mobile .glightbox-container .gslide-desc a { - color: #fff; - font-weight: 700; -} -.glightbox-mobile .glightbox-container .gslide-desc * { - color: inherit; -} -.glightbox-mobile .glightbox-container .gslide-desc string { - color: #fff; -} -.glightbox-mobile .glightbox-container .gslide-desc .desc-more { - color: #fff; - opacity: 0.4; -} -.gdesc-open .gslide-media { - -webkit-transition: opacity 0.5s ease; - transition: opacity 0.5s ease; - opacity: 0.4; -} -.gdesc-open .gdesc-inner { - padding-bottom: 30px; -} -.gdesc-closed .gslide-media { - -webkit-transition: opacity 0.5s ease; - transition: opacity 0.5s ease; - opacity: 1; -} -.greset { - -webkit-transition: all 0.3s ease; - transition: all 0.3s ease; -} -.gabsolute { - position: absolute; -} -.grelative { - position: relative; -} -.glightbox-desc { - display: none !important; -} -.glightbox-open { - overflow: hidden; -} -.gloader { - height: 25px; - width: 25px; - -webkit-animation: lightboxLoader 0.8s infinite linear; - animation: lightboxLoader 0.8s infinite linear; - border: 2px solid #fff; - border-right-color: transparent; - border-radius: 50%; - position: absolute; - display: block; - z-index: 9999; - left: 0; - right: 0; - margin: 0 auto; - top: 47%; -} -.goverlay { - width: 100%; - height: calc(100vh + 1px); - position: fixed; - top: -1px; - left: 0; - background: #000; - will-change: opacity; -} -.glightbox-mobile .goverlay { - background: #000; -} -.gclose, -.gnext, -.gprev { - z-index: 99999; - cursor: pointer; - width: 26px; - height: 44px; - border: none; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; -} -.gclose svg, -.gnext svg, -.gprev svg { - display: block; - width: 25px; - height: auto; - margin: 0; - padding: 0; -} -.gclose.disabled, -.gnext.disabled, -.gprev.disabled { - opacity: 0.1; -} -.gclose .garrow, -.gnext .garrow, -.gprev .garrow { - stroke: #fff; -} -.gbtn.focused { - outline: 2px solid #0f3d81; -} -iframe.wait-autoplay { - opacity: 0; -} -.glightbox-closing .gclose, -.glightbox-closing .gnext, -.glightbox-closing .gprev { - opacity: 0 !important; -} -.glightbox-clean .gslide-description { - background: #fff; -} -.glightbox-clean .gdesc-inner { - padding: 22px 20px; -} -.glightbox-clean .gslide-title { - font-size: 1em; - font-weight: 400; - font-family: arial; - color: #000; - margin-bottom: 19px; - line-height: 1.4em; -} -.glightbox-clean .gslide-desc { - font-size: 0.86em; - margin-bottom: 0; - font-family: arial; - line-height: 1.4em; -} -.glightbox-clean .gslide-video { - background: #000; -} -.glightbox-clean .gclose, -.glightbox-clean .gnext, -.glightbox-clean .gprev { - background-color: rgba(0, 0, 0, 0.75); - border-radius: 4px; -} -.glightbox-clean .gclose path, -.glightbox-clean .gnext path, -.glightbox-clean .gprev path { - fill: #fff; -} -.glightbox-clean .gprev { - position: absolute; - top: -100%; - left: 30px; - width: 40px; - height: 50px; -} -.glightbox-clean .gnext { - position: absolute; - top: -100%; - right: 30px; - width: 40px; - height: 50px; -} -.glightbox-clean .gclose { - width: 35px; - height: 35px; - top: 15px; - right: 10px; - position: absolute; -} -.glightbox-clean .gclose svg { - width: 18px; - height: auto; -} -.glightbox-clean .gclose:hover { - opacity: 1; -} -.gfadeIn { - -webkit-animation: gfadeIn 0.5s ease; - animation: gfadeIn 0.5s ease; -} -.gfadeOut { - -webkit-animation: gfadeOut 0.5s ease; - animation: gfadeOut 0.5s ease; -} -.gslideOutLeft { - -webkit-animation: gslideOutLeft 0.3s ease; - animation: gslideOutLeft 0.3s ease; -} -.gslideInLeft { - -webkit-animation: gslideInLeft 0.3s ease; - animation: gslideInLeft 0.3s ease; -} -.gslideOutRight { - -webkit-animation: gslideOutRight 0.3s ease; - animation: gslideOutRight 0.3s ease; -} -.gslideInRight { - -webkit-animation: gslideInRight 0.3s ease; - animation: gslideInRight 0.3s ease; -} -.gzoomIn { - -webkit-animation: gzoomIn 0.5s ease; - animation: gzoomIn 0.5s ease; -} -.gzoomOut { - -webkit-animation: gzoomOut 0.5s ease; - animation: gzoomOut 0.5s ease; -} -@-webkit-keyframes lightboxLoader { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} -@keyframes lightboxLoader { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} -@-webkit-keyframes gfadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -@keyframes gfadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -@-webkit-keyframes gfadeOut { - from { - opacity: 1; - } - to { - opacity: 0; - } -} -@keyframes gfadeOut { - from { - opacity: 1; - } - to { - opacity: 0; - } -} -@-webkit-keyframes gslideInLeft { - from { - opacity: 0; - -webkit-transform: translate3d(-60%, 0, 0); - transform: translate3d(-60%, 0, 0); - } - to { - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - opacity: 1; - } -} -@keyframes gslideInLeft { - from { - opacity: 0; - -webkit-transform: translate3d(-60%, 0, 0); - transform: translate3d(-60%, 0, 0); - } - to { - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - opacity: 1; - } -} -@-webkit-keyframes gslideOutLeft { - from { - opacity: 1; - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - to { - -webkit-transform: translate3d(-60%, 0, 0); - transform: translate3d(-60%, 0, 0); - opacity: 0; - visibility: hidden; - } -} -@keyframes gslideOutLeft { - from { - opacity: 1; - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - to { - -webkit-transform: translate3d(-60%, 0, 0); - transform: translate3d(-60%, 0, 0); - opacity: 0; - visibility: hidden; - } -} -@-webkit-keyframes gslideInRight { - from { - opacity: 0; - visibility: visible; - -webkit-transform: translate3d(60%, 0, 0); - transform: translate3d(60%, 0, 0); - } - to { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - opacity: 1; - } -} -@keyframes gslideInRight { - from { - opacity: 0; - visibility: visible; - -webkit-transform: translate3d(60%, 0, 0); - transform: translate3d(60%, 0, 0); - } - to { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - opacity: 1; - } -} -@-webkit-keyframes gslideOutRight { - from { - opacity: 1; - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - to { - -webkit-transform: translate3d(60%, 0, 0); - transform: translate3d(60%, 0, 0); - opacity: 0; - } -} -@keyframes gslideOutRight { - from { - opacity: 1; - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - to { - -webkit-transform: translate3d(60%, 0, 0); - transform: translate3d(60%, 0, 0); - opacity: 0; - } -} -@-webkit-keyframes gzoomIn { - from { - opacity: 0; - -webkit-transform: scale3d(0.3, 0.3, 0.3); - transform: scale3d(0.3, 0.3, 0.3); - } - to { - opacity: 1; - } -} -@keyframes gzoomIn { - from { - opacity: 0; - -webkit-transform: scale3d(0.3, 0.3, 0.3); - transform: scale3d(0.3, 0.3, 0.3); - } - to { - opacity: 1; - } -} -@-webkit-keyframes gzoomOut { - from { - opacity: 1; - } - 50% { - opacity: 0; - -webkit-transform: scale3d(0.3, 0.3, 0.3); - transform: scale3d(0.3, 0.3, 0.3); - } - to { - opacity: 0; - } -} -@keyframes gzoomOut { - from { - opacity: 1; - } - 50% { - opacity: 0; - -webkit-transform: scale3d(0.3, 0.3, 0.3); - transform: scale3d(0.3, 0.3, 0.3); - } - to { - opacity: 0; - } -} -@media (min-width: 769px) { - .glightbox-container .ginner-container { - width: auto; - height: auto; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - } - .glightbox-container .ginner-container.desc-top .gslide-description { - -webkit-box-ordinal-group: 1; - -ms-flex-order: 0; - order: 0; - } - .glightbox-container .ginner-container.desc-top .gslide-image, - .glightbox-container .ginner-container.desc-top .gslide-image img { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1; - } - .glightbox-container .ginner-container.desc-left .gslide-description { - -webkit-box-ordinal-group: 1; - -ms-flex-order: 0; - order: 0; - } - .glightbox-container .ginner-container.desc-left .gslide-image { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1; - } - .gslide-image img { - max-height: 97vh; - max-width: 100%; - } - .gslide-image img.zoomable { - cursor: -webkit-zoom-in; - cursor: zoom-in; - } - .zoomed .gslide-image img.zoomable { - cursor: -webkit-grab; - cursor: grab; - } - .gslide-inline { - max-height: 95vh; - } - .gslide-external { - max-height: 100vh; - } - .gslide-description.description-left, - .gslide-description.description-right { - max-width: 275px; - } - .glightbox-open { - height: auto; - } - .goverlay { - background: rgba(0, 0, 0, 0.92); - } - .glightbox-clean .gslide-media { - -webkit-box-shadow: 1px 2px 9px 0 rgba(0, 0, 0, 0.65); - box-shadow: 1px 2px 9px 0 rgba(0, 0, 0, 0.65); - } - .glightbox-clean .description-left .gdesc-inner, - .glightbox-clean .description-right .gdesc-inner { - position: absolute; - height: 100%; - overflow-y: auto; - } - .glightbox-clean .gclose, - .glightbox-clean .gnext, - .glightbox-clean .gprev { - background-color: rgba(0, 0, 0, 0.32); - } - .glightbox-clean .gclose:hover, - .glightbox-clean .gnext:hover, - .glightbox-clean .gprev:hover { - background-color: rgba(0, 0, 0, 0.7); - } - .glightbox-clean .gprev { - top: 45%; - } - .glightbox-clean .gnext { - top: 45%; - } -} -@media (min-width: 992px) { - .glightbox-clean .gclose { - opacity: 0.7; - right: 20px; - } -} -@media screen and (max-height: 420px) { - .goverlay { - background: #000; - } -} -[data-aos][data-aos][data-aos-duration="50"], -body[data-aos-duration="50"] [data-aos] { - transition-duration: 50ms; -} -[data-aos][data-aos][data-aos-delay="50"], -body[data-aos-delay="50"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="50"].aos-animate, -body[data-aos-delay="50"] [data-aos].aos-animate { - transition-delay: 50ms; -} -[data-aos][data-aos][data-aos-duration="100"], -body[data-aos-duration="100"] [data-aos] { - transition-duration: 0.1s; -} -[data-aos][data-aos][data-aos-delay="100"], -body[data-aos-delay="100"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="100"].aos-animate, -body[data-aos-delay="100"] [data-aos].aos-animate { - transition-delay: 0.1s; -} -[data-aos][data-aos][data-aos-duration="150"], -body[data-aos-duration="150"] [data-aos] { - transition-duration: 0.15s; -} -[data-aos][data-aos][data-aos-delay="150"], -body[data-aos-delay="150"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="150"].aos-animate, -body[data-aos-delay="150"] [data-aos].aos-animate { - transition-delay: 0.15s; -} -[data-aos][data-aos][data-aos-duration="200"], -body[data-aos-duration="200"] [data-aos] { - transition-duration: 0.2s; -} -[data-aos][data-aos][data-aos-delay="200"], -body[data-aos-delay="200"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="200"].aos-animate, -body[data-aos-delay="200"] [data-aos].aos-animate { - transition-delay: 0.2s; -} -[data-aos][data-aos][data-aos-duration="250"], -body[data-aos-duration="250"] [data-aos] { - transition-duration: 0.25s; -} -[data-aos][data-aos][data-aos-delay="250"], -body[data-aos-delay="250"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="250"].aos-animate, -body[data-aos-delay="250"] [data-aos].aos-animate { - transition-delay: 0.25s; -} -[data-aos][data-aos][data-aos-duration="300"], -body[data-aos-duration="300"] [data-aos] { - transition-duration: 0.3s; -} -[data-aos][data-aos][data-aos-delay="300"], -body[data-aos-delay="300"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="300"].aos-animate, -body[data-aos-delay="300"] [data-aos].aos-animate { - transition-delay: 0.3s; -} -[data-aos][data-aos][data-aos-duration="350"], -body[data-aos-duration="350"] [data-aos] { - transition-duration: 0.35s; -} -[data-aos][data-aos][data-aos-delay="350"], -body[data-aos-delay="350"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="350"].aos-animate, -body[data-aos-delay="350"] [data-aos].aos-animate { - transition-delay: 0.35s; -} -[data-aos][data-aos][data-aos-duration="400"], -body[data-aos-duration="400"] [data-aos] { - transition-duration: 0.4s; -} -[data-aos][data-aos][data-aos-delay="400"], -body[data-aos-delay="400"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="400"].aos-animate, -body[data-aos-delay="400"] [data-aos].aos-animate { - transition-delay: 0.4s; -} -[data-aos][data-aos][data-aos-duration="450"], -body[data-aos-duration="450"] [data-aos] { - transition-duration: 0.45s; -} -[data-aos][data-aos][data-aos-delay="450"], -body[data-aos-delay="450"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="450"].aos-animate, -body[data-aos-delay="450"] [data-aos].aos-animate { - transition-delay: 0.45s; -} -[data-aos][data-aos][data-aos-duration="500"], -body[data-aos-duration="500"] [data-aos] { - transition-duration: 0.5s; -} -[data-aos][data-aos][data-aos-delay="500"], -body[data-aos-delay="500"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="500"].aos-animate, -body[data-aos-delay="500"] [data-aos].aos-animate { - transition-delay: 0.5s; -} -[data-aos][data-aos][data-aos-duration="550"], -body[data-aos-duration="550"] [data-aos] { - transition-duration: 0.55s; -} -[data-aos][data-aos][data-aos-delay="550"], -body[data-aos-delay="550"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="550"].aos-animate, -body[data-aos-delay="550"] [data-aos].aos-animate { - transition-delay: 0.55s; -} -[data-aos][data-aos][data-aos-duration="600"], -body[data-aos-duration="600"] [data-aos] { - transition-duration: 0.6s; -} -[data-aos][data-aos][data-aos-delay="600"], -body[data-aos-delay="600"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="600"].aos-animate, -body[data-aos-delay="600"] [data-aos].aos-animate { - transition-delay: 0.6s; -} -[data-aos][data-aos][data-aos-duration="650"], -body[data-aos-duration="650"] [data-aos] { - transition-duration: 0.65s; -} -[data-aos][data-aos][data-aos-delay="650"], -body[data-aos-delay="650"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="650"].aos-animate, -body[data-aos-delay="650"] [data-aos].aos-animate { - transition-delay: 0.65s; -} -[data-aos][data-aos][data-aos-duration="700"], -body[data-aos-duration="700"] [data-aos] { - transition-duration: 0.7s; -} -[data-aos][data-aos][data-aos-delay="700"], -body[data-aos-delay="700"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="700"].aos-animate, -body[data-aos-delay="700"] [data-aos].aos-animate { - transition-delay: 0.7s; -} -[data-aos][data-aos][data-aos-duration="750"], -body[data-aos-duration="750"] [data-aos] { - transition-duration: 0.75s; -} -[data-aos][data-aos][data-aos-delay="750"], -body[data-aos-delay="750"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="750"].aos-animate, -body[data-aos-delay="750"] [data-aos].aos-animate { - transition-delay: 0.75s; -} -[data-aos][data-aos][data-aos-duration="800"], -body[data-aos-duration="800"] [data-aos] { - transition-duration: 0.8s; -} -[data-aos][data-aos][data-aos-delay="800"], -body[data-aos-delay="800"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="800"].aos-animate, -body[data-aos-delay="800"] [data-aos].aos-animate { - transition-delay: 0.8s; -} -[data-aos][data-aos][data-aos-duration="850"], -body[data-aos-duration="850"] [data-aos] { - transition-duration: 0.85s; -} -[data-aos][data-aos][data-aos-delay="850"], -body[data-aos-delay="850"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="850"].aos-animate, -body[data-aos-delay="850"] [data-aos].aos-animate { - transition-delay: 0.85s; -} -[data-aos][data-aos][data-aos-duration="900"], -body[data-aos-duration="900"] [data-aos] { - transition-duration: 0.9s; -} -[data-aos][data-aos][data-aos-delay="900"], -body[data-aos-delay="900"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="900"].aos-animate, -body[data-aos-delay="900"] [data-aos].aos-animate { - transition-delay: 0.9s; -} -[data-aos][data-aos][data-aos-duration="950"], -body[data-aos-duration="950"] [data-aos] { - transition-duration: 0.95s; -} -[data-aos][data-aos][data-aos-delay="950"], -body[data-aos-delay="950"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="950"].aos-animate, -body[data-aos-delay="950"] [data-aos].aos-animate { - transition-delay: 0.95s; -} -[data-aos][data-aos][data-aos-duration="1000"], -body[data-aos-duration="1000"] [data-aos] { - transition-duration: 1s; -} -[data-aos][data-aos][data-aos-delay="1000"], -body[data-aos-delay="1000"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1000"].aos-animate, -body[data-aos-delay="1000"] [data-aos].aos-animate { - transition-delay: 1s; -} -[data-aos][data-aos][data-aos-duration="1050"], -body[data-aos-duration="1050"] [data-aos] { - transition-duration: 1.05s; -} -[data-aos][data-aos][data-aos-delay="1050"], -body[data-aos-delay="1050"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1050"].aos-animate, -body[data-aos-delay="1050"] [data-aos].aos-animate { - transition-delay: 1.05s; -} -[data-aos][data-aos][data-aos-duration="1100"], -body[data-aos-duration="1100"] [data-aos] { - transition-duration: 1.1s; -} -[data-aos][data-aos][data-aos-delay="1100"], -body[data-aos-delay="1100"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1100"].aos-animate, -body[data-aos-delay="1100"] [data-aos].aos-animate { - transition-delay: 1.1s; -} -[data-aos][data-aos][data-aos-duration="1150"], -body[data-aos-duration="1150"] [data-aos] { - transition-duration: 1.15s; -} -[data-aos][data-aos][data-aos-delay="1150"], -body[data-aos-delay="1150"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1150"].aos-animate, -body[data-aos-delay="1150"] [data-aos].aos-animate { - transition-delay: 1.15s; -} -[data-aos][data-aos][data-aos-duration="1200"], -body[data-aos-duration="1200"] [data-aos] { - transition-duration: 1.2s; -} -[data-aos][data-aos][data-aos-delay="1200"], -body[data-aos-delay="1200"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1200"].aos-animate, -body[data-aos-delay="1200"] [data-aos].aos-animate { - transition-delay: 1.2s; -} -[data-aos][data-aos][data-aos-duration="1250"], -body[data-aos-duration="1250"] [data-aos] { - transition-duration: 1.25s; -} -[data-aos][data-aos][data-aos-delay="1250"], -body[data-aos-delay="1250"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1250"].aos-animate, -body[data-aos-delay="1250"] [data-aos].aos-animate { - transition-delay: 1.25s; -} -[data-aos][data-aos][data-aos-duration="1300"], -body[data-aos-duration="1300"] [data-aos] { - transition-duration: 1.3s; -} -[data-aos][data-aos][data-aos-delay="1300"], -body[data-aos-delay="1300"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1300"].aos-animate, -body[data-aos-delay="1300"] [data-aos].aos-animate { - transition-delay: 1.3s; -} -[data-aos][data-aos][data-aos-duration="1350"], -body[data-aos-duration="1350"] [data-aos] { - transition-duration: 1.35s; -} -[data-aos][data-aos][data-aos-delay="1350"], -body[data-aos-delay="1350"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1350"].aos-animate, -body[data-aos-delay="1350"] [data-aos].aos-animate { - transition-delay: 1.35s; -} -[data-aos][data-aos][data-aos-duration="1400"], -body[data-aos-duration="1400"] [data-aos] { - transition-duration: 1.4s; -} -[data-aos][data-aos][data-aos-delay="1400"], -body[data-aos-delay="1400"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1400"].aos-animate, -body[data-aos-delay="1400"] [data-aos].aos-animate { - transition-delay: 1.4s; -} -[data-aos][data-aos][data-aos-duration="1450"], -body[data-aos-duration="1450"] [data-aos] { - transition-duration: 1.45s; -} -[data-aos][data-aos][data-aos-delay="1450"], -body[data-aos-delay="1450"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1450"].aos-animate, -body[data-aos-delay="1450"] [data-aos].aos-animate { - transition-delay: 1.45s; -} -[data-aos][data-aos][data-aos-duration="1500"], -body[data-aos-duration="1500"] [data-aos] { - transition-duration: 1.5s; -} -[data-aos][data-aos][data-aos-delay="1500"], -body[data-aos-delay="1500"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1500"].aos-animate, -body[data-aos-delay="1500"] [data-aos].aos-animate { - transition-delay: 1.5s; -} -[data-aos][data-aos][data-aos-duration="1550"], -body[data-aos-duration="1550"] [data-aos] { - transition-duration: 1.55s; -} -[data-aos][data-aos][data-aos-delay="1550"], -body[data-aos-delay="1550"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1550"].aos-animate, -body[data-aos-delay="1550"] [data-aos].aos-animate { - transition-delay: 1.55s; -} -[data-aos][data-aos][data-aos-duration="1600"], -body[data-aos-duration="1600"] [data-aos] { - transition-duration: 1.6s; -} -[data-aos][data-aos][data-aos-delay="1600"], -body[data-aos-delay="1600"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1600"].aos-animate, -body[data-aos-delay="1600"] [data-aos].aos-animate { - transition-delay: 1.6s; -} -[data-aos][data-aos][data-aos-duration="1650"], -body[data-aos-duration="1650"] [data-aos] { - transition-duration: 1.65s; -} -[data-aos][data-aos][data-aos-delay="1650"], -body[data-aos-delay="1650"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1650"].aos-animate, -body[data-aos-delay="1650"] [data-aos].aos-animate { - transition-delay: 1.65s; -} -[data-aos][data-aos][data-aos-duration="1700"], -body[data-aos-duration="1700"] [data-aos] { - transition-duration: 1.7s; -} -[data-aos][data-aos][data-aos-delay="1700"], -body[data-aos-delay="1700"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1700"].aos-animate, -body[data-aos-delay="1700"] [data-aos].aos-animate { - transition-delay: 1.7s; -} -[data-aos][data-aos][data-aos-duration="1750"], -body[data-aos-duration="1750"] [data-aos] { - transition-duration: 1.75s; -} -[data-aos][data-aos][data-aos-delay="1750"], -body[data-aos-delay="1750"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1750"].aos-animate, -body[data-aos-delay="1750"] [data-aos].aos-animate { - transition-delay: 1.75s; -} -[data-aos][data-aos][data-aos-duration="1800"], -body[data-aos-duration="1800"] [data-aos] { - transition-duration: 1.8s; -} -[data-aos][data-aos][data-aos-delay="1800"], -body[data-aos-delay="1800"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1800"].aos-animate, -body[data-aos-delay="1800"] [data-aos].aos-animate { - transition-delay: 1.8s; -} -[data-aos][data-aos][data-aos-duration="1850"], -body[data-aos-duration="1850"] [data-aos] { - transition-duration: 1.85s; -} -[data-aos][data-aos][data-aos-delay="1850"], -body[data-aos-delay="1850"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1850"].aos-animate, -body[data-aos-delay="1850"] [data-aos].aos-animate { - transition-delay: 1.85s; -} -[data-aos][data-aos][data-aos-duration="1900"], -body[data-aos-duration="1900"] [data-aos] { - transition-duration: 1.9s; -} -[data-aos][data-aos][data-aos-delay="1900"], -body[data-aos-delay="1900"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1900"].aos-animate, -body[data-aos-delay="1900"] [data-aos].aos-animate { - transition-delay: 1.9s; -} -[data-aos][data-aos][data-aos-duration="1950"], -body[data-aos-duration="1950"] [data-aos] { - transition-duration: 1.95s; -} -[data-aos][data-aos][data-aos-delay="1950"], -body[data-aos-delay="1950"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1950"].aos-animate, -body[data-aos-delay="1950"] [data-aos].aos-animate { - transition-delay: 1.95s; -} -[data-aos][data-aos][data-aos-duration="2000"], -body[data-aos-duration="2000"] [data-aos] { - transition-duration: 2s; -} -[data-aos][data-aos][data-aos-delay="2000"], -body[data-aos-delay="2000"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2000"].aos-animate, -body[data-aos-delay="2000"] [data-aos].aos-animate { - transition-delay: 2s; -} -[data-aos][data-aos][data-aos-duration="2050"], -body[data-aos-duration="2050"] [data-aos] { - transition-duration: 2.05s; -} -[data-aos][data-aos][data-aos-delay="2050"], -body[data-aos-delay="2050"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2050"].aos-animate, -body[data-aos-delay="2050"] [data-aos].aos-animate { - transition-delay: 2.05s; -} -[data-aos][data-aos][data-aos-duration="2100"], -body[data-aos-duration="2100"] [data-aos] { - transition-duration: 2.1s; -} -[data-aos][data-aos][data-aos-delay="2100"], -body[data-aos-delay="2100"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2100"].aos-animate, -body[data-aos-delay="2100"] [data-aos].aos-animate { - transition-delay: 2.1s; -} -[data-aos][data-aos][data-aos-duration="2150"], -body[data-aos-duration="2150"] [data-aos] { - transition-duration: 2.15s; -} -[data-aos][data-aos][data-aos-delay="2150"], -body[data-aos-delay="2150"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2150"].aos-animate, -body[data-aos-delay="2150"] [data-aos].aos-animate { - transition-delay: 2.15s; -} -[data-aos][data-aos][data-aos-duration="2200"], -body[data-aos-duration="2200"] [data-aos] { - transition-duration: 2.2s; -} -[data-aos][data-aos][data-aos-delay="2200"], -body[data-aos-delay="2200"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2200"].aos-animate, -body[data-aos-delay="2200"] [data-aos].aos-animate { - transition-delay: 2.2s; -} -[data-aos][data-aos][data-aos-duration="2250"], -body[data-aos-duration="2250"] [data-aos] { - transition-duration: 2.25s; -} -[data-aos][data-aos][data-aos-delay="2250"], -body[data-aos-delay="2250"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2250"].aos-animate, -body[data-aos-delay="2250"] [data-aos].aos-animate { - transition-delay: 2.25s; -} -[data-aos][data-aos][data-aos-duration="2300"], -body[data-aos-duration="2300"] [data-aos] { - transition-duration: 2.3s; -} -[data-aos][data-aos][data-aos-delay="2300"], -body[data-aos-delay="2300"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2300"].aos-animate, -body[data-aos-delay="2300"] [data-aos].aos-animate { - transition-delay: 2.3s; -} -[data-aos][data-aos][data-aos-duration="2350"], -body[data-aos-duration="2350"] [data-aos] { - transition-duration: 2.35s; -} -[data-aos][data-aos][data-aos-delay="2350"], -body[data-aos-delay="2350"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2350"].aos-animate, -body[data-aos-delay="2350"] [data-aos].aos-animate { - transition-delay: 2.35s; -} -[data-aos][data-aos][data-aos-duration="2400"], -body[data-aos-duration="2400"] [data-aos] { - transition-duration: 2.4s; -} -[data-aos][data-aos][data-aos-delay="2400"], -body[data-aos-delay="2400"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2400"].aos-animate, -body[data-aos-delay="2400"] [data-aos].aos-animate { - transition-delay: 2.4s; -} -[data-aos][data-aos][data-aos-duration="2450"], -body[data-aos-duration="2450"] [data-aos] { - transition-duration: 2.45s; -} -[data-aos][data-aos][data-aos-delay="2450"], -body[data-aos-delay="2450"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2450"].aos-animate, -body[data-aos-delay="2450"] [data-aos].aos-animate { - transition-delay: 2.45s; -} -[data-aos][data-aos][data-aos-duration="2500"], -body[data-aos-duration="2500"] [data-aos] { - transition-duration: 2.5s; -} -[data-aos][data-aos][data-aos-delay="2500"], -body[data-aos-delay="2500"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2500"].aos-animate, -body[data-aos-delay="2500"] [data-aos].aos-animate { - transition-delay: 2.5s; -} -[data-aos][data-aos][data-aos-duration="2550"], -body[data-aos-duration="2550"] [data-aos] { - transition-duration: 2.55s; -} -[data-aos][data-aos][data-aos-delay="2550"], -body[data-aos-delay="2550"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2550"].aos-animate, -body[data-aos-delay="2550"] [data-aos].aos-animate { - transition-delay: 2.55s; -} -[data-aos][data-aos][data-aos-duration="2600"], -body[data-aos-duration="2600"] [data-aos] { - transition-duration: 2.6s; -} -[data-aos][data-aos][data-aos-delay="2600"], -body[data-aos-delay="2600"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2600"].aos-animate, -body[data-aos-delay="2600"] [data-aos].aos-animate { - transition-delay: 2.6s; -} -[data-aos][data-aos][data-aos-duration="2650"], -body[data-aos-duration="2650"] [data-aos] { - transition-duration: 2.65s; -} -[data-aos][data-aos][data-aos-delay="2650"], -body[data-aos-delay="2650"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2650"].aos-animate, -body[data-aos-delay="2650"] [data-aos].aos-animate { - transition-delay: 2.65s; -} -[data-aos][data-aos][data-aos-duration="2700"], -body[data-aos-duration="2700"] [data-aos] { - transition-duration: 2.7s; -} -[data-aos][data-aos][data-aos-delay="2700"], -body[data-aos-delay="2700"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2700"].aos-animate, -body[data-aos-delay="2700"] [data-aos].aos-animate { - transition-delay: 2.7s; -} -[data-aos][data-aos][data-aos-duration="2750"], -body[data-aos-duration="2750"] [data-aos] { - transition-duration: 2.75s; -} -[data-aos][data-aos][data-aos-delay="2750"], -body[data-aos-delay="2750"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2750"].aos-animate, -body[data-aos-delay="2750"] [data-aos].aos-animate { - transition-delay: 2.75s; -} -[data-aos][data-aos][data-aos-duration="2800"], -body[data-aos-duration="2800"] [data-aos] { - transition-duration: 2.8s; -} -[data-aos][data-aos][data-aos-delay="2800"], -body[data-aos-delay="2800"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2800"].aos-animate, -body[data-aos-delay="2800"] [data-aos].aos-animate { - transition-delay: 2.8s; -} -[data-aos][data-aos][data-aos-duration="2850"], -body[data-aos-duration="2850"] [data-aos] { - transition-duration: 2.85s; -} -[data-aos][data-aos][data-aos-delay="2850"], -body[data-aos-delay="2850"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2850"].aos-animate, -body[data-aos-delay="2850"] [data-aos].aos-animate { - transition-delay: 2.85s; -} -[data-aos][data-aos][data-aos-duration="2900"], -body[data-aos-duration="2900"] [data-aos] { - transition-duration: 2.9s; -} -[data-aos][data-aos][data-aos-delay="2900"], -body[data-aos-delay="2900"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2900"].aos-animate, -body[data-aos-delay="2900"] [data-aos].aos-animate { - transition-delay: 2.9s; -} -[data-aos][data-aos][data-aos-duration="2950"], -body[data-aos-duration="2950"] [data-aos] { - transition-duration: 2.95s; -} -[data-aos][data-aos][data-aos-delay="2950"], -body[data-aos-delay="2950"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2950"].aos-animate, -body[data-aos-delay="2950"] [data-aos].aos-animate { - transition-delay: 2.95s; -} -[data-aos][data-aos][data-aos-duration="3000"], -body[data-aos-duration="3000"] [data-aos] { - transition-duration: 3s; -} -[data-aos][data-aos][data-aos-delay="3000"], -body[data-aos-delay="3000"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="3000"].aos-animate, -body[data-aos-delay="3000"] [data-aos].aos-animate { - transition-delay: 3s; -} -[data-aos][data-aos][data-aos-easing="linear"], -body[data-aos-easing="linear"] [data-aos] { - transition-timing-function: cubic-bezier(0.25, 0.25, 0.75, 0.75); -} -[data-aos][data-aos][data-aos-easing="ease"], -body[data-aos-easing="ease"] [data-aos] { - transition-timing-function: ease; -} -[data-aos][data-aos][data-aos-easing="ease-in"], -body[data-aos-easing="ease-in"] [data-aos] { - transition-timing-function: ease-in; -} -[data-aos][data-aos][data-aos-easing="ease-out"], -body[data-aos-easing="ease-out"] [data-aos] { - transition-timing-function: ease-out; -} -[data-aos][data-aos][data-aos-easing="ease-in-out"], -body[data-aos-easing="ease-in-out"] [data-aos] { - transition-timing-function: ease-in-out; -} -[data-aos][data-aos][data-aos-easing="ease-in-back"], -body[data-aos-easing="ease-in-back"] [data-aos] { - transition-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045); -} -[data-aos][data-aos][data-aos-easing="ease-out-back"], -body[data-aos-easing="ease-out-back"] [data-aos] { - transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275); -} -[data-aos][data-aos][data-aos-easing="ease-in-out-back"], -body[data-aos-easing="ease-in-out-back"] [data-aos] { - transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); -} -[data-aos][data-aos][data-aos-easing="ease-in-sine"], -body[data-aos-easing="ease-in-sine"] [data-aos] { - transition-timing-function: cubic-bezier(0.47, 0, 0.745, 0.715); -} -[data-aos][data-aos][data-aos-easing="ease-out-sine"], -body[data-aos-easing="ease-out-sine"] [data-aos] { - transition-timing-function: cubic-bezier(0.39, 0.575, 0.565, 1); -} -[data-aos][data-aos][data-aos-easing="ease-in-out-sine"], -body[data-aos-easing="ease-in-out-sine"] [data-aos] { - transition-timing-function: cubic-bezier(0.445, 0.05, 0.55, 0.95); -} -[data-aos][data-aos][data-aos-easing="ease-in-quad"], -body[data-aos-easing="ease-in-quad"] [data-aos] { - transition-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); -} -[data-aos][data-aos][data-aos-easing="ease-out-quad"], -body[data-aos-easing="ease-out-quad"] [data-aos] { - transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); -} -[data-aos][data-aos][data-aos-easing="ease-in-out-quad"], -body[data-aos-easing="ease-in-out-quad"] [data-aos] { - transition-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); -} -[data-aos][data-aos][data-aos-easing="ease-in-cubic"], -body[data-aos-easing="ease-in-cubic"] [data-aos] { - transition-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); -} -[data-aos][data-aos][data-aos-easing="ease-out-cubic"], -body[data-aos-easing="ease-out-cubic"] [data-aos] { - transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); -} -[data-aos][data-aos][data-aos-easing="ease-in-out-cubic"], -body[data-aos-easing="ease-in-out-cubic"] [data-aos] { - transition-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); -} -[data-aos][data-aos][data-aos-easing="ease-in-quart"], -body[data-aos-easing="ease-in-quart"] [data-aos] { - transition-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); -} -[data-aos][data-aos][data-aos-easing="ease-out-quart"], -body[data-aos-easing="ease-out-quart"] [data-aos] { - transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); -} -[data-aos][data-aos][data-aos-easing="ease-in-out-quart"], -body[data-aos-easing="ease-in-out-quart"] [data-aos] { - transition-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); -} -[data-aos^="fade"][data-aos^="fade"] { - opacity: 0; - transition-property: opacity, transform; -} -[data-aos^="fade"][data-aos^="fade"].aos-animate { - opacity: 1; - transform: translateZ(0); -} -[data-aos="fade-up"] { - transform: translate3d(0, 20px, 0); -} -[data-aos="fade-down"] { - transform: translate3d(0, -20px, 0); -} -[data-aos="fade-right"] { - transform: translate3d(-20px, 0, 0); -} -[data-aos="fade-left"] { - transform: translate3d(20px, 0, 0); -} -[data-aos="fade-up-right"] { - transform: translate3d(-20px, 20px, 0); -} -[data-aos="fade-up-left"] { - transform: translate3d(20px, 20px, 0); -} -[data-aos="fade-down-right"] { - transform: translate3d(-20px, -20px, 0); -} -[data-aos="fade-down-left"] { - transform: translate3d(20px, -20px, 0); -} -[data-aos^="slide"][data-aos^="slide"] { - transition-property: transform; -} -[data-aos^="slide"][data-aos^="slide"].aos-animate { - transform: translateZ(0); -} -[data-aos="slide-up"] { - transform: translate3d(0, 100%, 0); -} -[data-aos="slide-down"] { - transform: translate3d(0, -100%, 0); -} -[data-aos="slide-right"] { - transform: translate3d(-100%, 0, 0); -} -[data-aos="slide-left"] { - transform: translate3d(100%, 0, 0); -} -@charset "UTF-8"; -/*! - * Bootstrap v5.3.2 (https://getbootstrap.com/) - * Copyright 2011-2023 The Bootstrap Authors - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */ -:root, -[data-bs-theme="light"] { - --bs-blue: #0d6efd; - --bs-indigo: #6610f2; - --bs-purple: #6f42c1; - --bs-pink: #d63384; - --bs-red: #dc3545; - --bs-orange: #fd7e14; - --bs-yellow: #ffc107; - --bs-green: #198754; - --bs-teal: #20c997; - --bs-cyan: #0dcaf0; - --bs-black: #191f27; - --bs-white: #fff; - --bs-gray: #6c757d; - --bs-gray-dark: #343a40; - --bs-gray-100: #f8f9fa; - --bs-gray-200: #e9ecef; - --bs-gray-300: #dee2e6; - --bs-gray-400: #ced4da; - --bs-gray-500: #adb5bd; - --bs-gray-600: #6c757d; - --bs-gray-700: #495057; - --bs-gray-800: #343a40; - --bs-gray-900: #212529; - --bs-primary: #0d6efd; - --bs-secondary: #6c757d; - --bs-success: #198754; - --bs-info: #0dcaf0; - --bs-warning: #ffc107; - --bs-danger: #dc3545; - --bs-light: #eee; - --bs-dark: #222; - --bs-primary-rgb: 13, 110, 253; - --bs-secondary-rgb: 108, 117, 125; - --bs-success-rgb: 25, 135, 84; - --bs-info-rgb: 13, 202, 240; - --bs-warning-rgb: 255, 193, 7; - --bs-danger-rgb: 220, 53, 69; - --bs-light-rgb: 238, 238, 238; - --bs-dark-rgb: 34, 34, 34; - --bs-primary-text-emphasis: #052c65; - --bs-secondary-text-emphasis: #2b2f32; - --bs-success-text-emphasis: #0a3622; - --bs-info-text-emphasis: #055160; - --bs-warning-text-emphasis: #664d03; - --bs-danger-text-emphasis: #58151c; - --bs-light-text-emphasis: #495057; - --bs-dark-text-emphasis: #495057; - --bs-primary-bg-subtle: #cfe2ff; - --bs-secondary-bg-subtle: #e2e3e5; - --bs-success-bg-subtle: #d1e7dd; - --bs-info-bg-subtle: #cff4fc; - --bs-warning-bg-subtle: #fff3cd; - --bs-danger-bg-subtle: #f8d7da; - --bs-light-bg-subtle: #fcfcfd; - --bs-dark-bg-subtle: #ced4da; - --bs-primary-border-subtle: #9ec5fe; - --bs-secondary-border-subtle: #c4c8cb; - --bs-success-border-subtle: #a3cfbb; - --bs-info-border-subtle: #9eeaf9; - --bs-warning-border-subtle: #ffe69c; - --bs-danger-border-subtle: #f1aeb5; - --bs-light-border-subtle: #e9ecef; - --bs-dark-border-subtle: #adb5bd; - --bs-white-rgb: 255, 255, 255; - --bs-black-rgb: 25, 31, 39; - --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); - --bs-body-font-family: var(--bs-font-sans-serif); - --bs-body-font-size: 1rem; - --bs-body-font-weight: 400; - --bs-body-line-height: 1.5; - --bs-body-color: #212529; - --bs-body-color-rgb: 33, 37, 41; - --bs-body-bg: #0e1015; - --bs-body-bg-rgb: 14, 16, 21; - --bs-emphasis-color: #191f27; - --bs-emphasis-color-rgb: 25, 31, 39; - --bs-secondary-color: rgba(33, 37, 41, 0.75); - --bs-secondary-color-rgb: 33, 37, 41; - --bs-secondary-bg: #e9ecef; - --bs-secondary-bg-rgb: 233, 236, 239; - --bs-tertiary-color: rgba(33, 37, 41, 0.5); - --bs-tertiary-color-rgb: 33, 37, 41; - --bs-tertiary-bg: #f8f9fa; - --bs-tertiary-bg-rgb: 248, 249, 250; - --bs-heading-color: inherit; - --bs-link-color: #0d6efd; - --bs-link-color-rgb: 13, 110, 253; - --bs-link-decoration: underline; - --bs-link-hover-color: #0a58ca; - --bs-link-hover-color-rgb: 10, 88, 202; - --bs-code-color: #d63384; - --bs-highlight-color: #212529; - --bs-highlight-bg: #fff3cd; - --bs-border-width: 1px; - --bs-border-style: solid; - --bs-border-color: rgba(24, 176, 162, 0.15); - --bs-border-color-translucent: rgba(25, 31, 39, 0.175); - --bs-border-radius: 0.375rem; - --bs-border-radius-sm: 0.25rem; - --bs-border-radius-lg: 0.5rem; - --bs-border-radius-xl: 1rem; - --bs-border-radius-xxl: 2rem; - --bs-border-radius-2xl: var(--bs-border-radius-xxl); - --bs-border-radius-pill: 50rem; - --bs-box-shadow: 0 0.5rem 1rem rgba(25, 31, 39, 0.15); - --bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(25, 31, 39, 0.075); - --bs-box-shadow-lg: 0 1rem 3rem rgba(25, 31, 39, 0.175); - --bs-box-shadow-inset: inset 0 1px 2px rgba(25, 31, 39, 0.075); - --bs-focus-ring-width: 0.25rem; - --bs-focus-ring-opacity: 0.25; - --bs-focus-ring-color: rgba(13, 110, 253, 0.25); - --bs-form-valid-color: #198754; - --bs-form-valid-border-color: #198754; - --bs-form-invalid-color: #dc3545; - --bs-form-invalid-border-color: #dc3545; } - -[data-bs-theme="dark"] { - color-scheme: dark; - --bs-body-color: #dee2e6; - --bs-body-color-rgb: 222, 226, 230; - --bs-body-bg: #212529; - --bs-body-bg-rgb: 33, 37, 41; - --bs-emphasis-color: #fff; - --bs-emphasis-color-rgb: 255, 255, 255; - --bs-secondary-color: rgba(222, 226, 230, 0.75); - --bs-secondary-color-rgb: 222, 226, 230; - --bs-secondary-bg: #343a40; - --bs-secondary-bg-rgb: 52, 58, 64; - --bs-tertiary-color: rgba(222, 226, 230, 0.5); - --bs-tertiary-color-rgb: 222, 226, 230; - --bs-tertiary-bg: #2b3035; - --bs-tertiary-bg-rgb: 43, 48, 53; - --bs-primary-text-emphasis: #6ea8fe; - --bs-secondary-text-emphasis: #a7acb1; - --bs-success-text-emphasis: #75b798; - --bs-info-text-emphasis: #6edff6; - --bs-warning-text-emphasis: #ffda6a; - --bs-danger-text-emphasis: #ea868f; - --bs-light-text-emphasis: #f8f9fa; - --bs-dark-text-emphasis: #dee2e6; - --bs-primary-bg-subtle: #031633; - --bs-secondary-bg-subtle: #161719; - --bs-success-bg-subtle: #051b11; - --bs-info-bg-subtle: #032830; - --bs-warning-bg-subtle: #332701; - --bs-danger-bg-subtle: #2c0b0e; - --bs-light-bg-subtle: #343a40; - --bs-dark-bg-subtle: #272d34; - --bs-primary-border-subtle: #084298; - --bs-secondary-border-subtle: #41464b; - --bs-success-border-subtle: #0f5132; - --bs-info-border-subtle: #087990; - --bs-warning-border-subtle: #997404; - --bs-danger-border-subtle: #842029; - --bs-light-border-subtle: #495057; - --bs-dark-border-subtle: #343a40; - --bs-heading-color: inherit; - --bs-link-color: #6ea8fe; - --bs-link-hover-color: #8bb9fe; - --bs-link-color-rgb: 110, 168, 254; - --bs-link-hover-color-rgb: 139, 185, 254; - --bs-code-color: #e685b5; - --bs-highlight-color: #dee2e6; - --bs-highlight-bg: #664d03; - --bs-border-color: #495057; - --bs-border-color-translucent: rgba(255, 255, 255, 0.15); - --bs-form-valid-color: #75b798; - --bs-form-valid-border-color: #75b798; - --bs-form-invalid-color: #ea868f; - --bs-form-invalid-border-color: #ea868f; } - -*, -*::before, -*::after { - box-sizing: border-box; } - -@media (prefers-reduced-motion: no-preference) { - :root { - scroll-behavior: smooth; } } - -body { - margin: 0; - font-family: var(--bs-body-font-family); - font-size: var(--bs-body-font-size); - font-weight: var(--bs-body-font-weight); - line-height: var(--bs-body-line-height); - color: var(--bs-body-color); - text-align: var(--bs-body-text-align); - background-color: var(--bs-body-bg); - -webkit-text-size-adjust: 100%; - -webkit-tap-highlight-color: rgba(25, 31, 39, 0); } - -hr { - margin: 1rem 0; - color: inherit; - border: 0; - border-top: var(--bs-border-width) solid; - opacity: 0.25; } - - h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 { - margin-top: 0; - margin-bottom: 0.5rem; - font-weight: 500; - line-height: 1.2; - color: var(--bs-heading-color); } - -h1, .h1 { - font-size: calc(1.375rem + 1.5vw); } - @media (min-width: 1200px) { - h1, .h1 { - font-size: 2.5rem; } } -h2, .h2 { - font-size: calc(1.325rem + 0.9vw); } - @media (min-width: 1200px) { - h2, .h2 { - font-size: 2rem; } } -h3, .h3 { - font-size: calc(1.3rem + 0.6vw); } - @media (min-width: 1200px) { - h3, .h3 { - font-size: 1.75rem; } } -h4, .h4 { - font-size: calc(1.275rem + 0.3vw); } - @media (min-width: 1200px) { - h4, .h4 { - font-size: 1.5rem; } } -h5, .h5 { - font-size: 1.25rem; } - -p { - margin-top: 0; - margin-bottom: 1rem; } - -abbr[title] { - text-decoration: underline dotted; - cursor: help; - text-decoration-skip-ink: none; } - -address { - margin-bottom: 1rem; - font-style: normal; - line-height: inherit; } - -ol, -ul { - padding-left: 2rem; } - -ol, -ul, -dl { - margin-top: 0; - margin-bottom: 1rem; } - -ol ol, -ul ul, -ol ul, -ul ol { - margin-bottom: 0; } - -dt { - font-weight: 700; } - -dd { - margin-bottom: .5rem; - margin-left: 0; } - -blockquote { - margin: 0 0 1rem; } - -b, -strong { - font-weight: bolder; } - -small, .small { - font-size: 0.875em; } - -mark, .mark { - padding: 0.1875em; - color: var(--bs-highlight-color); - background-color: var(--bs-highlight-bg); } - -sub, -sup { - position: relative; - font-size: 0.75em; - line-height: 0; - vertical-align: baseline; } - -sub { - bottom: -.25em; } - -sup { - top: -.5em; } - -a { - color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1)); - text-decoration: underline; } - a:hover { - --bs-link-color-rgb: var(--bs-link-hover-color-rgb); } - -a:not([href]):not([class]), a:not([href]):not([class]):hover { - color: inherit; - text-decoration: none; } - -pre, -code, -kbd, -samp { - font-family: var(--bs-font-monospace); - font-size: 1em; } - -pre { - display: block; - margin-top: 0; - margin-bottom: 1rem; - overflow: auto; - font-size: 0.875em; } - pre code { - font-size: inherit; - color: inherit; - word-break: normal; } - -code { - font-size: 0.875em; - color: var(--bs-code-color); - word-wrap: break-word; } - a > code { - color: inherit; } - -kbd { - padding: 0.1875rem 0.375rem; - font-size: 0.875em; - color: var(--bs-body-bg); - background-color: var(--bs-body-color); - border-radius: 0.25rem; } - kbd kbd { - padding: 0; - font-size: 1em; } - -figure { - margin: 0 0 1rem; } - -img, -svg { - vertical-align: middle; } - -table { - caption-side: bottom; - border-collapse: collapse; } - -caption { - padding-top: 0.5rem; - padding-bottom: 0.5rem; - color: var(--bs-secondary-color); - text-align: left; } - -th { - text-align: inherit; - text-align: -webkit-match-parent; } - -thead, -tbody, -tfoot, -tr, -td, -th { - border-color: inherit; - border-style: solid; - border-width: 0; } - -label { - display: inline-block; } - -button { - border-radius: 0; } - -button:focus:not(:focus-visible) { - outline: 0; } - -input, -button, -select, -optgroup, -textarea { - margin: 0; - font-family: inherit; - font-size: inherit; - line-height: inherit; } - -button, -select { - text-transform: none; } - -[role="button"] { - cursor: pointer; } - -select { - word-wrap: normal; } - select:disabled { - opacity: 1; } - -[list]:not([type="date"]):not([type="datetime-local"]):not([type="month"]):not([type="week"]):not([type="time"])::-webkit-calendar-picker-indicator { - display: none !important; } - -button, -[type="button"], -[type="reset"], -[type="submit"] { - -webkit-appearance: button; } - button:not(:disabled), - [type="button"]:not(:disabled), - [type="reset"]:not(:disabled), - [type="submit"]:not(:disabled) { - cursor: pointer; } - -::-moz-focus-inner { - padding: 0; - border-style: none; } - -textarea { - resize: vertical; } - -fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0; } - -legend { - float: left; - width: 100%; - padding: 0; - margin-bottom: 0.5rem; - font-size: calc(1.275rem + 0.3vw); - line-height: inherit; } - @media (min-width: 1200px) { - legend { - font-size: 1.5rem; } } - legend + * { - clear: left; } - -::-webkit-datetime-edit-fields-wrapper, -::-webkit-datetime-edit-text, -::-webkit-datetime-edit-minute, -::-webkit-datetime-edit-hour-field, -::-webkit-datetime-edit-day-field, -::-webkit-datetime-edit-month-field, -::-webkit-datetime-edit-year-field { - padding: 0; } - -::-webkit-inner-spin-button { - height: auto; } - -[type="search"] { - -webkit-appearance: textfield; - outline-offset: -2px; } - -/* rtl:raw: -[type="tel"], -[type="url"], -[type="email"], -[type="number"] { - direction: ltr; -} -*/ -::-webkit-search-decoration { - -webkit-appearance: none; } - -::-webkit-color-swatch-wrapper { - padding: 0; } - -::file-selector-button { - font: inherit; - -webkit-appearance: button; } - -output { - display: inline-block; } - -iframe { - border: 0; } - -summary { - display: list-item; - cursor: pointer; } - -progress { - vertical-align: baseline; } - -[hidden] { - display: none !important; } - -.lead { - font-size: 1.25rem; - font-weight: 300; } - -.display-1 { - font-size: calc(1.625rem + 4.5vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-1 { - font-size: 5rem; } } -.display-2 { - font-size: calc(1.575rem + 3.9vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-2 { - font-size: 4.5rem; } } -.display-3 { - font-size: calc(1.525rem + 3.3vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-3 { - font-size: 4rem; } } -.display-4 { - font-size: calc(1.475rem + 2.7vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-4 { - font-size: 3.5rem; } } -.display-5 { - font-size: calc(1.425rem + 2.1vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-5 { - font-size: 3rem; } } -.display-6 { - font-size: calc(1.375rem + 1.5vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-6 { - font-size: 2.5rem; } } -.list-unstyled { - padding-left: 0; - list-style: none; } - -.list-inline { - padding-left: 0; - list-style: none; } - -.list-inline-item { - display: inline-block; } - .list-inline-item:not(:last-child) { - margin-right: 0.5rem; } - -.initialism { - font-size: 0.875em; - text-transform: uppercase; } - -.blockquote { - margin-bottom: 1rem; - font-size: 1.25rem; } - .blockquote > :last-child { - margin-bottom: 0; } - -.blockquote-footer { - margin-top: -1rem; - margin-bottom: 1rem; - font-size: 0.875em; - color: #6c757d; } - .blockquote-footer::before { - content: "\2014\00A0"; } - -.img-fluid { - max-width: 100%; - height: auto; } - -.img-thumbnail { - padding: 0.25rem; - background-color: var(--bs-body-bg); - border: var(--bs-border-width) solid var(--bs-border-color); - border-radius: var(--bs-border-radius); - max-width: 100%; - height: auto; } - -.figure { - display: inline-block; } - -.figure-img { - margin-bottom: 0.5rem; - line-height: 1; } - -.figure-caption { - font-size: 0.875em; - color: var(--bs-secondary-color); } - -.container, -.container-fluid, -.container-xxl, -.container-xl, -.container-lg, -.container-md, -.container-sm { - --bs-gutter-x: 1.5rem; - --bs-gutter-y: 0; - width: 100%; - padding-right: calc(var(--bs-gutter-x) * .5); - padding-left: calc(var(--bs-gutter-x) * .5); - margin-right: auto; - margin-left: auto; } - -@media (min-width: 576px) { - .container-sm, .container { - max-width: 540px; } } - -@media (min-width: 768px) { - .container-md, .container-sm, .container { - max-width: 720px; } } - -@media (min-width: 992px) { - .container-lg, .container-md, .container-sm, .container { - max-width: 960px; } } - -@media (min-width: 1200px) { - .container-xl, .container-lg, .container-md, .container-sm, .container { - max-width: 1140px; } } - -@media (min-width: 1400px) { - .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container { - max-width: 1320px; } } - -:root { - --bs-breakpoint-xs: 0; - --bs-breakpoint-sm: 576px; - --bs-breakpoint-md: 768px; - --bs-breakpoint-lg: 992px; - --bs-breakpoint-xl: 1200px; - --bs-breakpoint-xxl: 1400px; } - -.row { - --bs-gutter-x: 1.5rem; - --bs-gutter-y: 0; - display: flex; - flex-wrap: wrap; - margin-top: calc(-1 * var(--bs-gutter-y)); - margin-right: calc(-.5 * var(--bs-gutter-x)); - margin-left: calc(-.5 * var(--bs-gutter-x)); } - .row > * { - flex-shrink: 0; - width: 100%; - max-width: 100%; - padding-right: calc(var(--bs-gutter-x) * .5); - padding-left: calc(var(--bs-gutter-x) * .5); - margin-top: var(--bs-gutter-y); } - -.col { - flex: 1 0 0%; } - -.row-cols-auto > * { - flex: 0 0 auto; - width: auto; } - -.row-cols-1 > * { - flex: 0 0 auto; - width: 100%; } - -.row-cols-2 > * { - flex: 0 0 auto; - width: 50%; } - -.row-cols-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - -.row-cols-4 > * { - flex: 0 0 auto; - width: 25%; } - -.row-cols-5 > * { - flex: 0 0 auto; - width: 20%; } - -.row-cols-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - -.col-auto { - flex: 0 0 auto; - width: auto; } - -.col-1 { - flex: 0 0 auto; - width: 8.33333333%; } - -.col-2 { - flex: 0 0 auto; - width: 16.66666667%; } - -.col-3 { - flex: 0 0 auto; - width: 25%; } - -.col-4 { - flex: 0 0 auto; - width: 33.33333333%; } - -.col-5 { - flex: 0 0 auto; - width: 41.66666667%; } - -.col-6 { - flex: 0 0 auto; - width: 50%; } - -.col-7 { - flex: 0 0 auto; - width: 58.33333333%; } - -.col-8 { - flex: 0 0 auto; - width: 66.66666667%; } - -.col-9 { - flex: 0 0 auto; - width: 75%; } - -.col-10 { - flex: 0 0 auto; - width: 83.33333333%; } - -.col-11 { - flex: 0 0 auto; - width: 91.66666667%; } - -.col-12 { - flex: 0 0 auto; - width: 100%; } - -.offset-1 { - margin-left: 8.33333333%; } - -.offset-2 { - margin-left: 16.66666667%; } - -.offset-3 { - margin-left: 25%; } - -.offset-4 { - margin-left: 33.33333333%; } - -.offset-5 { - margin-left: 41.66666667%; } - -.offset-6 { - margin-left: 50%; } - -.offset-7 { - margin-left: 58.33333333%; } - -.offset-8 { - margin-left: 66.66666667%; } - -.offset-9 { - margin-left: 75%; } - -.offset-10 { - margin-left: 83.33333333%; } - -.offset-11 { - margin-left: 91.66666667%; } - - -.gx-0 { - --bs-gutter-x: 0; } - - -.gx-1 { - --bs-gutter-x: 0.25rem; } - - -.gx-2 { - --bs-gutter-x: 0.5rem; } - - -.gx-3 { - --bs-gutter-x: 1rem; } - - -.gx-4 { - --bs-gutter-x: 1.5rem; } - - -.gy-4 { - --bs-gutter-y: 1.5rem; } - - -.gx-5 { - --bs-gutter-x: 3rem; } - - -.gy-5 { - --bs-gutter-y: 3rem; } - -@media (min-width: 576px) { - .col-sm { - flex: 1 0 0%; } - .row-cols-sm-auto > * { - flex: 0 0 auto; - width: auto; } - .row-cols-sm-1 > * { - flex: 0 0 auto; - width: 100%; } - .row-cols-sm-2 > * { - flex: 0 0 auto; - width: 50%; } - .row-cols-sm-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - .row-cols-sm-4 > * { - flex: 0 0 auto; - width: 25%; } - .row-cols-sm-5 > * { - flex: 0 0 auto; - width: 20%; } - .row-cols-sm-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - .col-sm-auto { - flex: 0 0 auto; - width: auto; } - .col-sm-1 { - flex: 0 0 auto; - width: 8.33333333%; } - .col-sm-2 { - flex: 0 0 auto; - width: 16.66666667%; } - .col-sm-3 { - flex: 0 0 auto; - width: 25%; } - .col-sm-4 { - flex: 0 0 auto; - width: 33.33333333%; } - .col-sm-5 { - flex: 0 0 auto; - width: 41.66666667%; } - .col-sm-6 { - flex: 0 0 auto; - width: 50%; } - .col-sm-7 { - flex: 0 0 auto; - width: 58.33333333%; } - .col-sm-8 { - flex: 0 0 auto; - width: 66.66666667%; } - .col-sm-9 { - flex: 0 0 auto; - width: 75%; } - .col-sm-10 { - flex: 0 0 auto; - width: 83.33333333%; } - .col-sm-11 { - flex: 0 0 auto; - width: 91.66666667%; } - .col-sm-12 { - flex: 0 0 auto; - width: 100%; } - .offset-sm-0 { - margin-left: 0; } - .offset-sm-1 { - margin-left: 8.33333333%; } - .offset-sm-2 { - margin-left: 16.66666667%; } - .offset-sm-3 { - margin-left: 25%; } - .offset-sm-4 { - margin-left: 33.33333333%; } - .offset-sm-5 { - margin-left: 41.66666667%; } - .offset-sm-6 { - margin-left: 50%; } - .offset-sm-7 { - margin-left: 58.33333333%; } - .offset-sm-8 { - margin-left: 66.66666667%; } - .offset-sm-9 { - margin-left: 75%; } - .offset-sm-10 { - margin-left: 83.33333333%; } - .offset-sm-11 { - margin-left: 91.66666667%; } - .g-sm-0, - .gx-sm-0 { - --bs-gutter-x: 0; } - .g-sm-0, - .gy-sm-0 { - --bs-gutter-y: 0; } - .g-sm-1, - .gx-sm-1 { - --bs-gutter-x: 0.25rem; } - .g-sm-1, - .gy-sm-1 { - --bs-gutter-y: 0.25rem; } - .g-sm-2, - .gx-sm-2 { - --bs-gutter-x: 0.5rem; } - .g-sm-2, - .gy-sm-2 { - --bs-gutter-y: 0.5rem; } - .g-sm-3, - .gx-sm-3 { - --bs-gutter-x: 1rem; } - .g-sm-3, - .gy-sm-3 { - --bs-gutter-y: 1rem; } - .g-sm-4, - .gx-sm-4 { - --bs-gutter-x: 1.5rem; } - .g-sm-4, - .gy-sm-4 { - --bs-gutter-y: 1.5rem; } - .g-sm-5, - .gx-sm-5 { - --bs-gutter-x: 3rem; } - .g-sm-5, - .gy-sm-5 { - --bs-gutter-y: 3rem; } } - -@media (min-width: 768px) { - .col-md { - flex: 1 0 0%; } - .row-cols-md-auto > * { - flex: 0 0 auto; - width: auto; } - .row-cols-md-1 > * { - flex: 0 0 auto; - width: 100%; } - .row-cols-md-2 > * { - flex: 0 0 auto; - width: 50%; } - .row-cols-md-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - .row-cols-md-4 > * { - flex: 0 0 auto; - width: 25%; } - .row-cols-md-5 > * { - flex: 0 0 auto; - width: 20%; } - .row-cols-md-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - .col-md-auto { - flex: 0 0 auto; - width: auto; } - .col-md-1 { - flex: 0 0 auto; - width: 8.33333333%; } - .col-md-2 { - flex: 0 0 auto; - width: 16.66666667%; } - .col-md-3 { - flex: 0 0 auto; - width: 25%; } - .col-md-4 { - flex: 0 0 auto; - width: 33.33333333%; } - .col-md-5 { - flex: 0 0 auto; - width: 41.66666667%; } - .col-md-6 { - flex: 0 0 auto; - width: 50%; } - .col-md-7 { - flex: 0 0 auto; - width: 58.33333333%; } - .col-md-8 { - flex: 0 0 auto; - width: 66.66666667%; } - .col-md-9 { - flex: 0 0 auto; - width: 75%; } - .col-md-10 { - flex: 0 0 auto; - width: 83.33333333%; } - .col-md-11 { - flex: 0 0 auto; - width: 91.66666667%; } - .col-md-12 { - flex: 0 0 auto; - width: 100%; } - .offset-md-0 { - margin-left: 0; } - .offset-md-1 { - margin-left: 8.33333333%; } - .offset-md-2 { - margin-left: 16.66666667%; } - .offset-md-3 { - margin-left: 25%; } - .offset-md-4 { - margin-left: 33.33333333%; } - .offset-md-5 { - margin-left: 41.66666667%; } - .offset-md-6 { - margin-left: 50%; } - .offset-md-7 { - margin-left: 58.33333333%; } - .offset-md-8 { - margin-left: 66.66666667%; } - .offset-md-9 { - margin-left: 75%; } - .offset-md-10 { - margin-left: 83.33333333%; } - .offset-md-11 { - margin-left: 91.66666667%; } - .g-md-0, - .gx-md-0 { - --bs-gutter-x: 0; } - .g-md-0, - .gy-md-0 { - --bs-gutter-y: 0; } - .g-md-1, - .gx-md-1 { - --bs-gutter-x: 0.25rem; } - .g-md-1, - .gy-md-1 { - --bs-gutter-y: 0.25rem; } - .g-md-2, - .gx-md-2 { - --bs-gutter-x: 0.5rem; } - .g-md-2, - .gy-md-2 { - --bs-gutter-y: 0.5rem; } - .g-md-3, - .gx-md-3 { - --bs-gutter-x: 1rem; } - .g-md-3, - .gy-md-3 { - --bs-gutter-y: 1rem; } - .g-md-4, - .gx-md-4 { - --bs-gutter-x: 1.5rem; } - .g-md-4, - .gy-md-4 { - --bs-gutter-y: 1.5rem; } - .g-md-5, - .gx-md-5 { - --bs-gutter-x: 3rem; } - .g-md-5, - .gy-md-5 { - --bs-gutter-y: 3rem; } } - -@media (min-width: 992px) { - .col-lg { - flex: 1 0 0%; } - .row-cols-lg-auto > * { - flex: 0 0 auto; - width: auto; } - .row-cols-lg-1 > * { - flex: 0 0 auto; - width: 100%; } - .row-cols-lg-2 > * { - flex: 0 0 auto; - width: 50%; } - .row-cols-lg-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - .row-cols-lg-4 > * { - flex: 0 0 auto; - width: 25%; } - .row-cols-lg-5 > * { - flex: 0 0 auto; - width: 20%; } - .row-cols-lg-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - .col-lg-auto { - flex: 0 0 auto; - width: auto; } - .col-lg-1 { - flex: 0 0 auto; - width: 8.33333333%; } - .col-lg-2 { - flex: 0 0 auto; - width: 16.66666667%; } - .col-lg-3 { - flex: 0 0 auto; - width: 25%; } - .col-lg-4 { - flex: 0 0 auto; - width: 33.33333333%; } - .col-lg-5 { - flex: 0 0 auto; - width: 41.66666667%; } - .col-lg-6 { - flex: 0 0 auto; - width: 50%; } - .col-lg-7 { - flex: 0 0 auto; - width: 58.33333333%; } - .col-lg-8 { - flex: 0 0 auto; - width: 66.66666667%; } - .col-lg-9 { - flex: 0 0 auto; - width: 75%; } - .col-lg-10 { - flex: 0 0 auto; - width: 83.33333333%; } - .col-lg-11 { - flex: 0 0 auto; - width: 91.66666667%; } - .col-lg-12 { - flex: 0 0 auto; - width: 100%; } - .offset-lg-0 { - margin-left: 0; } - .offset-lg-1 { - margin-left: 8.33333333%; } - .offset-lg-2 { - margin-left: 16.66666667%; } - .offset-lg-3 { - margin-left: 25%; } - .offset-lg-4 { - margin-left: 33.33333333%; } - .offset-lg-5 { - margin-left: 41.66666667%; } - .offset-lg-6 { - margin-left: 50%; } - .offset-lg-7 { - margin-left: 58.33333333%; } - .offset-lg-8 { - margin-left: 66.66666667%; } - .offset-lg-9 { - margin-left: 75%; } - .offset-lg-10 { - margin-left: 83.33333333%; } - .offset-lg-11 { - margin-left: 91.66666667%; } - .g-lg-0, - .gx-lg-0 { - --bs-gutter-x: 0; } - .g-lg-0, - .gy-lg-0 { - --bs-gutter-y: 0; } - .g-lg-1, - .gx-lg-1 { - --bs-gutter-x: 0.25rem; } - .g-lg-1, - .gy-lg-1 { - --bs-gutter-y: 0.25rem; } - .g-lg-2, - .gx-lg-2 { - --bs-gutter-x: 0.5rem; } - .g-lg-2, - .gy-lg-2 { - --bs-gutter-y: 0.5rem; } - .g-lg-3, - .gx-lg-3 { - --bs-gutter-x: 1rem; } - .g-lg-3, - .gy-lg-3 { - --bs-gutter-y: 1rem; } - .g-lg-4, - .gx-lg-4 { - --bs-gutter-x: 1.5rem; } - .g-lg-4, - .gy-lg-4 { - --bs-gutter-y: 1.5rem; } - .g-lg-5, - .gx-lg-5 { - --bs-gutter-x: 3rem; } - .g-lg-5, - .gy-lg-5 { - --bs-gutter-y: 3rem; } } - -@media (min-width: 1200px) { - .col-xl { - flex: 1 0 0%; } - .row-cols-xl-auto > * { - flex: 0 0 auto; - width: auto; } - .row-cols-xl-1 > * { - flex: 0 0 auto; - width: 100%; } - .row-cols-xl-2 > * { - flex: 0 0 auto; - width: 50%; } - .row-cols-xl-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - .row-cols-xl-4 > * { - flex: 0 0 auto; - width: 25%; } - .row-cols-xl-5 > * { - flex: 0 0 auto; - width: 20%; } - .row-cols-xl-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - .col-xl-auto { - flex: 0 0 auto; - width: auto; } - .col-xl-1 { - flex: 0 0 auto; - width: 8.33333333%; } - .col-xl-2 { - flex: 0 0 auto; - width: 16.66666667%; } - .col-xl-3 { - flex: 0 0 auto; - width: 25%; } - .col-xl-4 { - flex: 0 0 auto; - width: 33.33333333%; } - .col-xl-5 { - flex: 0 0 auto; - width: 41.66666667%; } - .col-xl-6 { - flex: 0 0 auto; - width: 50%; } - .col-xl-7 { - flex: 0 0 auto; - width: 58.33333333%; } - .col-xl-8 { - flex: 0 0 auto; - width: 66.66666667%; } - .col-xl-9 { - flex: 0 0 auto; - width: 75%; } - .col-xl-10 { - flex: 0 0 auto; - width: 83.33333333%; } - .col-xl-11 { - flex: 0 0 auto; - width: 91.66666667%; } - .col-xl-12 { - flex: 0 0 auto; - width: 100%; } - .offset-xl-0 { - margin-left: 0; } - .offset-xl-1 { - margin-left: 8.33333333%; } - .offset-xl-2 { - margin-left: 16.66666667%; } - .offset-xl-3 { - margin-left: 25%; } - .offset-xl-4 { - margin-left: 33.33333333%; } - .offset-xl-5 { - margin-left: 41.66666667%; } - .offset-xl-6 { - margin-left: 50%; } - .offset-xl-7 { - margin-left: 58.33333333%; } - .offset-xl-8 { - margin-left: 66.66666667%; } - .offset-xl-9 { - margin-left: 75%; } - .offset-xl-10 { - margin-left: 83.33333333%; } - .offset-xl-11 { - margin-left: 91.66666667%; } - .g-xl-0, - .gx-xl-0 { - --bs-gutter-x: 0; } - .g-xl-0, - .gy-xl-0 { - --bs-gutter-y: 0; } - .g-xl-1, - .gx-xl-1 { - --bs-gutter-x: 0.25rem; } - .g-xl-1, - .gy-xl-1 { - --bs-gutter-y: 0.25rem; } - .g-xl-2, - .gx-xl-2 { - --bs-gutter-x: 0.5rem; } - .g-xl-2, - .gy-xl-2 { - --bs-gutter-y: 0.5rem; } - .g-xl-3, - .gx-xl-3 { - --bs-gutter-x: 1rem; } - .g-xl-3, - .gy-xl-3 { - --bs-gutter-y: 1rem; } - .g-xl-4, - .gx-xl-4 { - --bs-gutter-x: 1.5rem; } - .g-xl-4, - .gy-xl-4 { - --bs-gutter-y: 1.5rem; } - .g-xl-5, - .gx-xl-5 { - --bs-gutter-x: 3rem; } - .g-xl-5, - .gy-xl-5 { - --bs-gutter-y: 3rem; } } - -@media (min-width: 1400px) { - .col-xxl { - flex: 1 0 0%; } - .row-cols-xxl-auto > * { - flex: 0 0 auto; - width: auto; } - .row-cols-xxl-1 > * { - flex: 0 0 auto; - width: 100%; } - .row-cols-xxl-2 > * { - flex: 0 0 auto; - width: 50%; } - .row-cols-xxl-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - .row-cols-xxl-4 > * { - flex: 0 0 auto; - width: 25%; } - .row-cols-xxl-5 > * { - flex: 0 0 auto; - width: 20%; } - .row-cols-xxl-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - .col-xxl-auto { - flex: 0 0 auto; - width: auto; } - .col-xxl-1 { - flex: 0 0 auto; - width: 8.33333333%; } - .col-xxl-2 { - flex: 0 0 auto; - width: 16.66666667%; } - .col-xxl-3 { - flex: 0 0 auto; - width: 25%; } - .col-xxl-4 { - flex: 0 0 auto; - width: 33.33333333%; } - .col-xxl-5 { - flex: 0 0 auto; - width: 41.66666667%; } - .col-xxl-6 { - flex: 0 0 auto; - width: 50%; } - .col-xxl-7 { - flex: 0 0 auto; - width: 58.33333333%; } - .col-xxl-8 { - flex: 0 0 auto; - width: 66.66666667%; } - .col-xxl-9 { - flex: 0 0 auto; - width: 75%; } - .col-xxl-10 { - flex: 0 0 auto; - width: 83.33333333%; } - .col-xxl-11 { - flex: 0 0 auto; - width: 91.66666667%; } - .col-xxl-12 { - flex: 0 0 auto; - width: 100%; } - .offset-xxl-0 { - margin-left: 0; } - .offset-xxl-1 { - margin-left: 8.33333333%; } - .offset-xxl-2 { - margin-left: 16.66666667%; } - .offset-xxl-3 { - margin-left: 25%; } - .offset-xxl-4 { - margin-left: 33.33333333%; } - .offset-xxl-5 { - margin-left: 41.66666667%; } - .offset-xxl-6 { - margin-left: 50%; } - .offset-xxl-7 { - margin-left: 58.33333333%; } - .offset-xxl-8 { - margin-left: 66.66666667%; } - .offset-xxl-9 { - margin-left: 75%; } - .offset-xxl-10 { - margin-left: 83.33333333%; } - .offset-xxl-11 { - margin-left: 91.66666667%; } - .g-xxl-0, - .gx-xxl-0 { - --bs-gutter-x: 0; } - .g-xxl-0, - .gy-xxl-0 { - --bs-gutter-y: 0; } - .g-xxl-1, - .gx-xxl-1 { - --bs-gutter-x: 0.25rem; } - .g-xxl-1, - .gy-xxl-1 { - --bs-gutter-y: 0.25rem; } - .g-xxl-2, - .gx-xxl-2 { - --bs-gutter-x: 0.5rem; } - .g-xxl-2, - .gy-xxl-2 { - --bs-gutter-y: 0.5rem; } - .g-xxl-3, - .gx-xxl-3 { - --bs-gutter-x: 1rem; } - .g-xxl-3, - .gy-xxl-3 { - --bs-gutter-y: 1rem; } - .g-xxl-4, - .gx-xxl-4 { - --bs-gutter-x: 1.5rem; } - .g-xxl-4, - .gy-xxl-4 { - --bs-gutter-y: 1.5rem; } - .g-xxl-5, - .gx-xxl-5 { - --bs-gutter-x: 3rem; } - .g-xxl-5, - .gy-xxl-5 { - --bs-gutter-y: 3rem; } } - -.table { - --bs-table-color-type: initial; - --bs-table-bg-type: initial; - --bs-table-color-state: initial; - --bs-table-bg-state: initial; - --bs-table-color: var(--bs-emphasis-color); - --bs-table-bg: var(--bs-body-bg); - --bs-table-border-color: var(--bs-border-color); - --bs-table-accent-bg: transparent; - --bs-table-striped-color: var(--bs-emphasis-color); - --bs-table-striped-bg: rgba(var(--bs-emphasis-color-rgb), 0.05); - --bs-table-active-color: var(--bs-emphasis-color); - --bs-table-active-bg: rgba(var(--bs-emphasis-color-rgb), 0.1); - --bs-table-hover-color: var(--bs-emphasis-color); - --bs-table-hover-bg: rgba(var(--bs-emphasis-color-rgb), 0.075); - width: 100%; - margin-bottom: 1rem; - vertical-align: top; - border-color: var(--bs-table-border-color); } - .table > :not(caption) > * > * { - padding: 0.5rem 0.5rem; - color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color))); - background-color: var(--bs-table-bg); - border-bottom-width: var(--bs-border-width); - box-shadow: inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg))); } - .table > tbody { - vertical-align: inherit; } - .table > thead { - vertical-align: bottom; } - -.table-group-divider { - border-top: calc(var(--bs-border-width) * 2) solid currentcolor; } - -.caption-top { - caption-side: top; } - -.table-sm > :not(caption) > * > * { - padding: 0.25rem 0.25rem; } - -.table-bordered > :not(caption) > * { - border-width: var(--bs-border-width) 0; } - .table-bordered > :not(caption) > * > * { - border-width: 0 var(--bs-border-width); } - -.table-borderless > :not(caption) > * > * { - border-bottom-width: 0; } - -.table-borderless > :not(:first-child) { - border-top-width: 0; } - -.table-striped > tbody > tr:nth-of-type(odd) > * { - --bs-table-color-type: var(--bs-table-striped-color); - --bs-table-bg-type: var(--bs-table-striped-bg); } - -.table-striped-columns > :not(caption) > tr > :nth-child(even) { - --bs-table-color-type: var(--bs-table-striped-color); - --bs-table-bg-type: var(--bs-table-striped-bg); } - -.table-active { - --bs-table-color-state: var(--bs-table-active-color); - --bs-table-bg-state: var(--bs-table-active-bg); } - -.table-hover > tbody > tr:hover > * { - --bs-table-color-state: var(--bs-table-hover-color); - --bs-table-bg-state: var(--bs-table-hover-bg); } - -.table-primary { - --bs-table-color: #191f27; - --bs-table-bg: #cfe2ff; - --bs-table-border-color: #abbbd4; - --bs-table-striped-bg: #c6d8f4; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #bdcfe9; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #c1d3ef; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-secondary { - --bs-table-color: #191f27; - --bs-table-bg: #e2e3e5; - --bs-table-border-color: #babcbf; - --bs-table-striped-bg: #d8d9dc; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #cecfd2; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #d3d4d7; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-success { - --bs-table-color: #191f27; - --bs-table-bg: #d1e7dd; - --bs-table-border-color: #acbfb9; - --bs-table-striped-bg: #c8ddd4; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #bfd3cb; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #c3d8cf; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-info { - --bs-table-color: #191f27; - --bs-table-bg: #cff4fc; - --bs-table-border-color: #abc9d1; - --bs-table-striped-bg: #c6e9f1; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #bddfe7; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #c1e4ec; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-warning { - --bs-table-color: #191f27; - --bs-table-bg: #fff3cd; - --bs-table-border-color: #d1c9ac; - --bs-table-striped-bg: #f4e8c5; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #e8debc; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #eee3c1; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-danger { - --bs-table-color: #191f27; - --bs-table-bg: #f8d7da; - --bs-table-border-color: #cbb2b6; - --bs-table-striped-bg: #edced1; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #e2c5c8; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #e7c9cd; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-light { - --bs-table-color: #191f27; - --bs-table-bg: #eee; - --bs-table-border-color: #c3c5c6; - --bs-table-striped-bg: #e3e4e4; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #d9d9da; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #dededf; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-dark { - --bs-table-color: #fff; - --bs-table-bg: #222; - --bs-table-border-color: #4e4e4e; - --bs-table-striped-bg: #2d2d2d; - --bs-table-striped-color: #fff; - --bs-table-active-bg: #383838; - --bs-table-active-color: #fff; - --bs-table-hover-bg: #333333; - --bs-table-hover-color: #fff; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-responsive { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } - -@media (max-width: 575.98px) { - .table-responsive-sm { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } } - -@media (max-width: 767.98px) { - .table-responsive-md { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } } - -@media (max-width: 991.98px) { - .table-responsive-lg { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } } - -@media (max-width: 1199.98px) { - .table-responsive-xl { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } } - -@media (max-width: 1399.98px) { - .table-responsive-xxl { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } } - -.form-label { - margin-bottom: 0.5rem; } - -.col-form-label { - padding-top: calc(0.375rem + var(--bs-border-width)); - padding-bottom: calc(0.375rem + var(--bs-border-width)); - margin-bottom: 0; - font-size: inherit; - line-height: 1.5; } - -.col-form-label-lg { - padding-top: calc(0.5rem + var(--bs-border-width)); - padding-bottom: calc(0.5rem + var(--bs-border-width)); - font-size: 1.25rem; } - -.col-form-label-sm { - padding-top: calc(0.25rem + var(--bs-border-width)); - padding-bottom: calc(0.25rem + var(--bs-border-width)); - font-size: 0.875rem; } - -.form-text { - margin-top: 0.25rem; - font-size: 0.875em; - color: var(--bs-secondary-color); } - -.form-control { - display: block; - width: 100%; - padding: 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: var(--bs-body-color); - appearance: none; - background-color: var(--bs-body-bg); - background-clip: padding-box; - border: var(--bs-border-width) solid var(--bs-border-color); - border-radius: var(--bs-border-radius); - transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-control { - transition: none; } } - .form-control[type="file"] { - overflow: hidden; } - .form-control[type="file"]:not(:disabled):not([readonly]) { - cursor: pointer; } - .form-control:focus { - color: var(--bs-body-color); - background-color: var(--bs-body-bg); - border-color: #86b7fe; - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .form-control::-webkit-date-and-time-value { - min-width: 85px; - height: 1.5em; - margin: 0; } - .form-control::-webkit-datetime-edit { - display: block; - padding: 0; } - .form-control::placeholder { - color: var(--bs-secondary-color); - opacity: 1; } - .form-control:disabled { - background-color: var(--bs-secondary-bg); - opacity: 1; } - .form-control::file-selector-button { - padding: 0.375rem 0.75rem; - margin: -0.375rem -0.75rem; - margin-inline-end: 0.75rem; - color: var(--bs-body-color); - background-color: var(--bs-tertiary-bg); - pointer-events: none; - border-color: inherit; - border-style: solid; - border-width: 0; - border-inline-end-width: var(--bs-border-width); - border-radius: 0; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-control::file-selector-button { - transition: none; } } - .form-control:hover:not(:disabled):not([readonly])::file-selector-button { - background-color: var(--bs-secondary-bg); } - -.form-control-plaintext { - display: block; - width: 100%; - padding: 0.375rem 0; - margin-bottom: 0; - line-height: 1.5; - color: var(--bs-body-color); - background-color: transparent; - border: solid transparent; - border-width: var(--bs-border-width) 0; } - .form-control-plaintext:focus { - outline: 0; } - .form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { - padding-right: 0; - padding-left: 0; } - -.form-control-sm { - min-height: calc(1.5em + 0.5rem + calc(var(--bs-border-width) * 2)); - padding: 0.25rem 0.5rem; - font-size: 0.875rem; - border-radius: var(--bs-border-radius-sm); } - .form-control-sm::file-selector-button { - padding: 0.25rem 0.5rem; - margin: -0.25rem -0.5rem; - margin-inline-end: 0.5rem; } - -.form-control-lg { - min-height: calc(1.5em + 1rem + calc(var(--bs-border-width) * 2)); - padding: 0.5rem 1rem; - font-size: 1.25rem; - border-radius: var(--bs-border-radius-lg); } - .form-control-lg::file-selector-button { - padding: 0.5rem 1rem; - margin: -0.5rem -1rem; - margin-inline-end: 1rem; } - -textarea.form-control { - min-height: calc(1.5em + 0.75rem + calc(var(--bs-border-width) * 2)); } - -textarea.form-control-sm { - min-height: calc(1.5em + 0.5rem + calc(var(--bs-border-width) * 2)); } - -textarea.form-control-lg { - min-height: calc(1.5em + 1rem + calc(var(--bs-border-width) * 2)); } - -.form-control-color { - width: 3rem; - height: calc(1.5em + 0.75rem + calc(var(--bs-border-width) * 2)); - padding: 0.375rem; } - .form-control-color:not(:disabled):not([readonly]) { - cursor: pointer; } - .form-control-color::-moz-color-swatch { - border: 0 !important; - border-radius: var(--bs-border-radius); } - .form-control-color::-webkit-color-swatch { - border: 0 !important; - border-radius: var(--bs-border-radius); } - .form-control-color.form-control-sm { - height: calc(1.5em + 0.5rem + calc(var(--bs-border-width) * 2)); } - .form-control-color.form-control-lg { - height: calc(1.5em + 1rem + calc(var(--bs-border-width) * 2)); } - -.form-select { - --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); - display: block; - width: 100%; - padding: 0.375rem 2.25rem 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: var(--bs-body-color); - appearance: none; - background-color: var(--bs-body-bg); - background-image: var(--bs-form-select-bg-img), var(--bs-form-select-bg-icon, none); - background-repeat: no-repeat; - background-position: right 0.75rem center; - background-size: 16px 12px; - border: var(--bs-border-width) solid var(--bs-border-color); - border-radius: var(--bs-border-radius); - transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-select { - transition: none; } } - .form-select:focus { - border-color: #86b7fe; - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .form-select[multiple], .form-select[size]:not([size="1"]) { - padding-right: 0.75rem; - background-image: none; } - .form-select:disabled { - background-color: var(--bs-secondary-bg); } - .form-select:-moz-focusring { - color: transparent; - text-shadow: 0 0 0 var(--bs-body-color); } - -.form-select-sm { - padding-top: 0.25rem; - padding-bottom: 0.25rem; - padding-left: 0.5rem; - font-size: 0.875rem; - border-radius: var(--bs-border-radius-sm); } - -.form-select-lg { - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-left: 1rem; - font-size: 1.25rem; - border-radius: var(--bs-border-radius-lg); } - -[data-bs-theme="dark"] .form-select { - --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); } - -.form-check { - display: block; - min-height: 1.5rem; - padding-left: 1.5em; - margin-bottom: 0.125rem; } - .form-check .form-check-input { - float: left; - margin-left: -1.5em; } - -.form-check-reverse { - padding-right: 1.5em; - padding-left: 0; - text-align: right; } - .form-check-reverse .form-check-input { - float: right; - margin-right: -1.5em; - margin-left: 0; } - -.form-check-input { - --bs-form-check-bg: var(--bs-body-bg); - flex-shrink: 0; - width: 1em; - height: 1em; - margin-top: 0.25em; - vertical-align: top; - appearance: none; - background-color: var(--bs-form-check-bg); - background-image: var(--bs-form-check-bg-image); - background-repeat: no-repeat; - background-position: center; - background-size: contain; - border: var(--bs-border-width) solid var(--bs-border-color); - print-color-adjust: exact; } - .form-check-input[type="checkbox"] { - border-radius: 0.25em; } - .form-check-input[type="radio"] { - border-radius: 50%; } - .form-check-input:active { - filter: brightness(90%); } - .form-check-input:focus { - border-color: #86b7fe; - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .form-check-input:checked { - background-color: #0d6efd; - border-color: #0d6efd; } - .form-check-input:checked[type="checkbox"] { - --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e"); } - .form-check-input:checked[type="radio"] { - --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"); } - .form-check-input[type="checkbox"]:indeterminate { - background-color: #0d6efd; - border-color: #0d6efd; - --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"); } - .form-check-input:disabled { - pointer-events: none; - filter: none; - opacity: 0.5; } - .form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { - cursor: default; - opacity: 0.5; } - -.form-switch { - padding-left: 2.5em; } - .form-switch .form-check-input { - --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%2825, 31, 39, 0.25%29'/%3e%3c/svg%3e"); - width: 2em; - margin-left: -2.5em; - background-image: var(--bs-form-switch-bg); - background-position: left center; - border-radius: 2em; - transition: background-position 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-switch .form-check-input { - transition: none; } } - .form-switch .form-check-input:focus { - --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e"); } - .form-switch .form-check-input:checked { - background-position: right center; - --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); } - .form-switch.form-check-reverse { - padding-right: 2.5em; - padding-left: 0; } - .form-switch.form-check-reverse .form-check-input { - margin-right: -2.5em; - margin-left: 0; } - -.form-check-inline { - display: inline-block; - margin-right: 1rem; } - -.btn-check { - position: absolute; - clip: rect(0, 0, 0, 0); - pointer-events: none; } - .btn-check[disabled] + .btn, .btn-check:disabled + .btn { - pointer-events: none; - filter: none; - opacity: 0.65; } - -[data-bs-theme="dark"] .form-switch .form-check-input:not(:checked):not(:focus) { - --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e"); } - -.form-range { - width: 100%; - height: 1.5rem; - padding: 0; - appearance: none; - background-color: transparent; } - .form-range:focus { - outline: 0; } - .form-range:focus::-webkit-slider-thumb { - box-shadow: 0 0 0 1px #0e1015, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .form-range:focus::-moz-range-thumb { - box-shadow: 0 0 0 1px #0e1015, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .form-range::-moz-focus-outer { - border: 0; } - .form-range::-webkit-slider-thumb { - width: 1rem; - height: 1rem; - margin-top: -0.25rem; - appearance: none; - background-color: #0d6efd; - border: 0; - border-radius: 1rem; - transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-range::-webkit-slider-thumb { - transition: none; } } - .form-range::-webkit-slider-thumb:active { - background-color: #b6d4fe; } - .form-range::-webkit-slider-runnable-track { - width: 100%; - height: 0.5rem; - color: transparent; - cursor: pointer; - background-color: var(--bs-secondary-bg); - border-color: transparent; - border-radius: 1rem; } - .form-range::-moz-range-thumb { - width: 1rem; - height: 1rem; - appearance: none; - background-color: #0d6efd; - border: 0; - border-radius: 1rem; - transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-range::-moz-range-thumb { - transition: none; } } - .form-range::-moz-range-thumb:active { - background-color: #b6d4fe; } - .form-range::-moz-range-track { - width: 100%; - height: 0.5rem; - color: transparent; - cursor: pointer; - background-color: var(--bs-secondary-bg); - border-color: transparent; - border-radius: 1rem; } - .form-range:disabled { - pointer-events: none; } - .form-range:disabled::-webkit-slider-thumb { - background-color: var(--bs-secondary-color); } - .form-range:disabled::-moz-range-thumb { - background-color: var(--bs-secondary-color); } - -.form-floating { - position: relative; } - .form-floating > .form-control, - .form-floating > .form-control-plaintext, - .form-floating > .form-select { - height: calc(3.5rem + calc(var(--bs-border-width) * 2)); - min-height: calc(3.5rem + calc(var(--bs-border-width) * 2)); - line-height: 1.25; } - .form-floating > label { - position: absolute; - top: 0; - left: 0; - z-index: 2; - height: 100%; - padding: 1rem 0.75rem; - overflow: hidden; - text-align: start; - text-overflow: ellipsis; - white-space: nowrap; - pointer-events: none; - border: var(--bs-border-width) solid transparent; - transform-origin: 0 0; - transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-floating > label { - transition: none; } } - .form-floating > .form-control, - .form-floating > .form-control-plaintext { - padding: 1rem 0.75rem; } - .form-floating > .form-control::placeholder, - .form-floating > .form-control-plaintext::placeholder { - color: transparent; } - .form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown), - .form-floating > .form-control-plaintext:focus, - .form-floating > .form-control-plaintext:not(:placeholder-shown) { - padding-top: 1.625rem; - padding-bottom: 0.625rem; } - .form-floating > .form-control:-webkit-autofill, - .form-floating > .form-control-plaintext:-webkit-autofill { - padding-top: 1.625rem; - padding-bottom: 0.625rem; } - .form-floating > .form-select { - padding-top: 1.625rem; - padding-bottom: 0.625rem; } - .form-floating > .form-control:focus ~ label, - .form-floating > .form-control:not(:placeholder-shown) ~ label, - .form-floating > .form-control-plaintext ~ label, - .form-floating > .form-select ~ label { - color: rgba(var(--bs-body-color-rgb), 0.65); - transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); } - .form-floating > .form-control:focus ~ label::after, - .form-floating > .form-control:not(:placeholder-shown) ~ label::after, - .form-floating > .form-control-plaintext ~ label::after, - .form-floating > .form-select ~ label::after { - position: absolute; - inset: 1rem 0.375rem; - z-index: -1; - height: 1.5em; - content: ""; - background-color: var(--bs-body-bg); - border-radius: var(--bs-border-radius); } - .form-floating > .form-control:-webkit-autofill ~ label { - color: rgba(var(--bs-body-color-rgb), 0.65); - transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); } - .form-floating > .form-control-plaintext ~ label { - border-width: var(--bs-border-width) 0; } - .form-floating > :disabled ~ label, - .form-floating > .form-control:disabled ~ label { - color: #6c757d; } - .form-floating > :disabled ~ label::after, - .form-floating > .form-control:disabled ~ label::after { - background-color: var(--bs-secondary-bg); } - -.input-group { - position: relative; - display: flex; - flex-wrap: wrap; - align-items: stretch; - width: 100%; } - .input-group > .form-control, - .input-group > .form-select, - .input-group > .form-floating { - position: relative; - flex: 1 1 auto; - width: 1%; - min-width: 0; } - .input-group > .form-control:focus, - .input-group > .form-select:focus, - .input-group > .form-floating:focus-within { - z-index: 5; } - .input-group .btn { - position: relative; - z-index: 2; } - .input-group .btn:focus { - z-index: 5; } - -.input-group-text { - display: flex; - align-items: center; - padding: 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: var(--bs-body-color); - text-align: center; - white-space: nowrap; - background-color: var(--bs-tertiary-bg); - border: var(--bs-border-width) solid var(--bs-border-color); - border-radius: var(--bs-border-radius); } - -.input-group-lg > .form-control, -.input-group-lg > .form-select, -.input-group-lg > .input-group-text, -.input-group-lg > .btn { - padding: 0.5rem 1rem; - font-size: 1.25rem; - border-radius: var(--bs-border-radius-lg); } - -.input-group-sm > .form-control, -.input-group-sm > .form-select, -.input-group-sm > .input-group-text, -.input-group-sm > .btn { - padding: 0.25rem 0.5rem; - font-size: 0.875rem; - border-radius: var(--bs-border-radius-sm); } - -.input-group-lg > .form-select, -.input-group-sm > .form-select { - padding-right: 3rem; } - -.input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), -.input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n + 3), -.input-group:not(.has-validation) > .form-floating:not(:last-child) > .form-control, -.input-group:not(.has-validation) > .form-floating:not(:last-child) > .form-select { - border-top-right-radius: 0; - border-bottom-right-radius: 0; } - -.input-group.has-validation > :nth-last-child(n + 3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), -.input-group.has-validation > .dropdown-toggle:nth-last-child(n + 4), -.input-group.has-validation > .form-floating:nth-last-child(n + 3) > .form-control, -.input-group.has-validation > .form-floating:nth-last-child(n + 3) > .form-select { - border-top-right-radius: 0; - border-bottom-right-radius: 0; } - -.input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { - margin-left: calc(var(--bs-border-width) * -1); - border-top-left-radius: 0; - border-bottom-left-radius: 0; } - -.input-group > .form-floating:not(:first-child) > .form-control, -.input-group > .form-floating:not(:first-child) > .form-select { - border-top-left-radius: 0; - border-bottom-left-radius: 0; } - -.valid-feedback { - display: none; - width: 100%; - margin-top: 0.25rem; - font-size: 0.875em; - color: var(--bs-form-valid-color); } - -.valid-tooltip { - position: absolute; - top: 100%; - z-index: 5; - display: none; - max-width: 100%; - padding: 0.25rem 0.5rem; - margin-top: .1rem; - font-size: 0.875rem; - color: #fff; - background-color: var(--bs-success); - border-radius: var(--bs-border-radius); } - -.was-validated :valid ~ .valid-feedback, -.was-validated :valid ~ .valid-tooltip, -.is-valid ~ .valid-feedback, -.is-valid ~ .valid-tooltip { - display: block; } - -.was-validated .form-control:valid, .form-control.is-valid { - border-color: var(--bs-form-valid-border-color); - padding-right: calc(1.5em + 0.75rem); - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); - background-repeat: no-repeat; - background-position: right calc(0.375em + 0.1875rem) center; - background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } - .was-validated .form-control:valid:focus, .form-control.is-valid:focus { - border-color: var(--bs-form-valid-border-color); - box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); } - -.was-validated textarea.form-control:valid, textarea.form-control.is-valid { - padding-right: calc(1.5em + 0.75rem); - background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } - -.was-validated .form-select:valid, .form-select.is-valid { - border-color: var(--bs-form-valid-border-color); } - .was-validated .form-select:valid:not([multiple]):not([size]), .was-validated .form-select:valid:not([multiple])[size="1"], .form-select.is-valid:not([multiple]):not([size]), .form-select.is-valid:not([multiple])[size="1"] { - --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); - padding-right: 4.125rem; - background-position: right 0.75rem center, center right 2.25rem; - background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } - .was-validated .form-select:valid:focus, .form-select.is-valid:focus { - border-color: var(--bs-form-valid-border-color); - box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); } - -.was-validated .form-control-color:valid, .form-control-color.is-valid { - width: calc(3rem + calc(1.5em + 0.75rem)); } - -.was-validated .form-check-input:valid, .form-check-input.is-valid { - border-color: var(--bs-form-valid-border-color); } - .was-validated .form-check-input:valid:checked, .form-check-input.is-valid:checked { - background-color: var(--bs-form-valid-color); } - .was-validated .form-check-input:valid:focus, .form-check-input.is-valid:focus { - box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); } - .was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { - color: var(--bs-form-valid-color); } - -.form-check-inline .form-check-input ~ .valid-feedback { - margin-left: .5em; } - -.was-validated .input-group > .form-control:not(:focus):valid, .input-group > .form-control:not(:focus).is-valid, .was-validated .input-group > .form-select:not(:focus):valid, -.input-group > .form-select:not(:focus).is-valid, .was-validated .input-group > .form-floating:not(:focus-within):valid, -.input-group > .form-floating:not(:focus-within).is-valid { - z-index: 3; } - -.invalid-feedback { - display: none; - width: 100%; - margin-top: 0.25rem; - font-size: 0.875em; - color: var(--bs-form-invalid-color); } - -.invalid-tooltip { - position: absolute; - top: 100%; - z-index: 5; - display: none; - max-width: 100%; - padding: 0.25rem 0.5rem; - margin-top: .1rem; - font-size: 0.875rem; - color: #fff; - background-color: var(--bs-danger); - border-radius: var(--bs-border-radius); } - -.was-validated :invalid ~ .invalid-feedback, -.was-validated :invalid ~ .invalid-tooltip, -.is-invalid ~ .invalid-feedback, -.is-invalid ~ .invalid-tooltip { - display: block; } - -.was-validated .form-control:invalid, .form-control.is-invalid { - border-color: var(--bs-form-invalid-border-color); - padding-right: calc(1.5em + 0.75rem); - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); - background-repeat: no-repeat; - background-position: right calc(0.375em + 0.1875rem) center; - background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } - .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { - border-color: var(--bs-form-invalid-border-color); - box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); } - -.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { - padding-right: calc(1.5em + 0.75rem); - background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } - -.was-validated .form-select:invalid, .form-select.is-invalid { - border-color: var(--bs-form-invalid-border-color); } - .was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { - --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); - padding-right: 4.125rem; - background-position: right 0.75rem center, center right 2.25rem; - background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } - .was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { - border-color: var(--bs-form-invalid-border-color); - box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); } - -.was-validated .form-control-color:invalid, .form-control-color.is-invalid { - width: calc(3rem + calc(1.5em + 0.75rem)); } - -.was-validated .form-check-input:invalid, .form-check-input.is-invalid { - border-color: var(--bs-form-invalid-border-color); } - .was-validated .form-check-input:invalid:checked, .form-check-input.is-invalid:checked { - background-color: var(--bs-form-invalid-color); } - .was-validated .form-check-input:invalid:focus, .form-check-input.is-invalid:focus { - box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); } - .was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { - color: var(--bs-form-invalid-color); } - -.form-check-inline .form-check-input ~ .invalid-feedback { - margin-left: .5em; } - -.was-validated .input-group > .form-control:not(:focus):invalid, .input-group > .form-control:not(:focus).is-invalid, .was-validated .input-group > .form-select:not(:focus):invalid, -.input-group > .form-select:not(:focus).is-invalid, .was-validated .input-group > .form-floating:not(:focus-within):invalid, -.input-group > .form-floating:not(:focus-within).is-invalid { - z-index: 4; } - -.btn { - --bs-btn-padding-x: 0.75rem; - --bs-btn-padding-y: 0.375rem; - --bs-btn-font-family: ; - --bs-btn-font-size: 1rem; - --bs-btn-font-weight: 400; - --bs-btn-line-height: 1.5; - --bs-btn-color: var(--bs-body-color); - --bs-btn-bg: transparent; - --bs-btn-border-width: var(--bs-border-width); - --bs-btn-border-color: transparent; - --bs-btn-border-radius: var(--bs-border-radius); - --bs-btn-hover-border-color: transparent; - --bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(25, 31, 39, 0.075); - --bs-btn-disabled-opacity: 0.65; - --bs-btn-focus-box-shadow: 0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5); - display: inline-block; - padding: var(--bs-btn-padding-y) var(--bs-btn-padding-x); - font-family: var(--bs-btn-font-family); - font-size: var(--bs-btn-font-size); - font-weight: var(--bs-btn-font-weight); - line-height: var(--bs-btn-line-height); - color: var(--bs-btn-color); - text-align: center; - text-decoration: none; - vertical-align: middle; - cursor: pointer; - user-select: none; - border: var(--bs-btn-border-width) solid var(--bs-btn-border-color); - border-radius: var(--bs-btn-border-radius); - background-color: var(--bs-btn-bg); - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .btn { - transition: none; } } - .btn:hover { - color: var(--bs-btn-hover-color); - background-color: var(--bs-btn-hover-bg); - border-color: var(--bs-btn-hover-border-color); } - .btn-check + .btn:hover { - color: var(--bs-btn-color); - background-color: var(--bs-btn-bg); - border-color: var(--bs-btn-border-color); } - .btn:focus-visible { - color: var(--bs-btn-hover-color); - background-color: var(--bs-btn-hover-bg); - border-color: var(--bs-btn-hover-border-color); - outline: 0; - box-shadow: var(--bs-btn-focus-box-shadow); } - .btn-check:focus-visible + .btn { - border-color: var(--bs-btn-hover-border-color); - outline: 0; - box-shadow: var(--bs-btn-focus-box-shadow); } - .btn-check:checked + .btn, :not(.btn-check) + .btn:active, .btn:first-child:active, .btn.active, .btn.show { - color: var(--bs-btn-active-color); - background-color: var(--bs-btn-active-bg); - border-color: var(--bs-btn-active-border-color); } - .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { - box-shadow: var(--bs-btn-focus-box-shadow); } - .btn:disabled, .btn.disabled, fieldset:disabled .btn { - color: var(--bs-btn-disabled-color); - pointer-events: none; - background-color: var(--bs-btn-disabled-bg); - border-color: var(--bs-btn-disabled-border-color); - opacity: var(--bs-btn-disabled-opacity); } - -.btn-primary { - --bs-btn-color: #fff; - --bs-btn-bg: #0d6efd; - --bs-btn-border-color: #0d6efd; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #0b5ed7; - --bs-btn-hover-border-color: #0a58ca; - --bs-btn-focus-shadow-rgb: 49, 132, 253; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #0a58ca; - --bs-btn-active-border-color: #0a53be; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #fff; - --bs-btn-disabled-bg: #0d6efd; - --bs-btn-disabled-border-color: #0d6efd; } - -.btn-secondary { - --bs-btn-color: #fff; - --bs-btn-bg: #6c757d; - --bs-btn-border-color: #6c757d; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #5c636a; - --bs-btn-hover-border-color: #565e64; - --bs-btn-focus-shadow-rgb: 130, 138, 145; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #565e64; - --bs-btn-active-border-color: #51585e; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #fff; - --bs-btn-disabled-bg: #6c757d; - --bs-btn-disabled-border-color: #6c757d; } - -.btn-success { - --bs-btn-color: #fff; - --bs-btn-bg: #198754; - --bs-btn-border-color: #198754; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #157347; - --bs-btn-hover-border-color: #146c43; - --bs-btn-focus-shadow-rgb: 60, 153, 110; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #146c43; - --bs-btn-active-border-color: #13653f; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #fff; - --bs-btn-disabled-bg: #198754; - --bs-btn-disabled-border-color: #198754; } - -.btn-info { - --bs-btn-color: #191f27; - --bs-btn-bg: #0dcaf0; - --bs-btn-border-color: #0dcaf0; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #31d2f2; - --bs-btn-hover-border-color: #25cff2; - --bs-btn-focus-shadow-rgb: 15, 176, 210; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #3dd5f3; - --bs-btn-active-border-color: #25cff2; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #191f27; - --bs-btn-disabled-bg: #0dcaf0; - --bs-btn-disabled-border-color: #0dcaf0; } - -.btn-warning { - --bs-btn-color: #191f27; - --bs-btn-bg: #ffc107; - --bs-btn-border-color: #ffc107; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #ffca2c; - --bs-btn-hover-border-color: #ffc720; - --bs-btn-focus-shadow-rgb: 221, 169, 12; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #ffcd39; - --bs-btn-active-border-color: #ffc720; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #191f27; - --bs-btn-disabled-bg: #ffc107; - --bs-btn-disabled-border-color: #ffc107; } - -.btn-danger { - --bs-btn-color: #fff; - --bs-btn-bg: #dc3545; - --bs-btn-border-color: #dc3545; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #bb2d3b; - --bs-btn-hover-border-color: #b02a37; - --bs-btn-focus-shadow-rgb: 225, 83, 97; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #b02a37; - --bs-btn-active-border-color: #a52834; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #fff; - --bs-btn-disabled-bg: #dc3545; - --bs-btn-disabled-border-color: #dc3545; } - -.btn-light { - --bs-btn-color: #191f27; - --bs-btn-bg: #eee; - --bs-btn-border-color: #eee; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #cacaca; - --bs-btn-hover-border-color: #bebebe; - --bs-btn-focus-shadow-rgb: 206, 207, 208; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #bebebe; - --bs-btn-active-border-color: #b3b3b3; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #191f27; - --bs-btn-disabled-bg: #eee; - --bs-btn-disabled-border-color: #eee; } - -.btn-dark { - --bs-btn-color: #fff; - --bs-btn-bg: #222; - --bs-btn-border-color: #222; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #434343; - --bs-btn-hover-border-color: #383838; - --bs-btn-focus-shadow-rgb: 67, 67, 67; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #4e4e4e; - --bs-btn-active-border-color: #383838; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #fff; - --bs-btn-disabled-bg: #222; - --bs-btn-disabled-border-color: #222; } - -.btn-outline-primary { - --bs-btn-color: #0d6efd; - --bs-btn-border-color: #0d6efd; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #0d6efd; - --bs-btn-hover-border-color: #0d6efd; - --bs-btn-focus-shadow-rgb: 13, 110, 253; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #0d6efd; - --bs-btn-active-border-color: #0d6efd; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #0d6efd; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #0d6efd; - --bs-gradient: none; } - -.btn-outline-secondary { - --bs-btn-color: #6c757d; - --bs-btn-border-color: #6c757d; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #6c757d; - --bs-btn-hover-border-color: #6c757d; - --bs-btn-focus-shadow-rgb: 108, 117, 125; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #6c757d; - --bs-btn-active-border-color: #6c757d; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #6c757d; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #6c757d; - --bs-gradient: none; } - -.btn-outline-success { - --bs-btn-color: #198754; - --bs-btn-border-color: #198754; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #198754; - --bs-btn-hover-border-color: #198754; - --bs-btn-focus-shadow-rgb: 25, 135, 84; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #198754; - --bs-btn-active-border-color: #198754; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #198754; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #198754; - --bs-gradient: none; } - -.btn-outline-info { - --bs-btn-color: #0dcaf0; - --bs-btn-border-color: #0dcaf0; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #0dcaf0; - --bs-btn-hover-border-color: #0dcaf0; - --bs-btn-focus-shadow-rgb: 13, 202, 240; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #0dcaf0; - --bs-btn-active-border-color: #0dcaf0; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #0dcaf0; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #0dcaf0; - --bs-gradient: none; } - -.btn-outline-warning { - --bs-btn-color: #ffc107; - --bs-btn-border-color: #ffc107; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #ffc107; - --bs-btn-hover-border-color: #ffc107; - --bs-btn-focus-shadow-rgb: 255, 193, 7; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #ffc107; - --bs-btn-active-border-color: #ffc107; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #ffc107; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #ffc107; - --bs-gradient: none; } - -.btn-outline-danger { - --bs-btn-color: #dc3545; - --bs-btn-border-color: #dc3545; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #dc3545; - --bs-btn-hover-border-color: #dc3545; - --bs-btn-focus-shadow-rgb: 220, 53, 69; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #dc3545; - --bs-btn-active-border-color: #dc3545; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #dc3545; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #dc3545; - --bs-gradient: none; } - -.btn-outline-light { - --bs-btn-color: #eee; - --bs-btn-border-color: #eee; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #eee; - --bs-btn-hover-border-color: #eee; - --bs-btn-focus-shadow-rgb: 238, 238, 238; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #eee; - --bs-btn-active-border-color: #eee; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #eee; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #eee; - --bs-gradient: none; } - -.btn-outline-dark { - --bs-btn-color: #222; - --bs-btn-border-color: #222; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #222; - --bs-btn-hover-border-color: #222; - --bs-btn-focus-shadow-rgb: 34, 34, 34; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #222; - --bs-btn-active-border-color: #222; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #222; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #222; - --bs-gradient: none; } - -.btn-link { - --bs-btn-font-weight: 400; - --bs-btn-color: var(--bs-link-color); - --bs-btn-bg: transparent; - --bs-btn-border-color: transparent; - --bs-btn-hover-color: var(--bs-link-hover-color); - --bs-btn-hover-border-color: transparent; - --bs-btn-active-color: var(--bs-link-hover-color); - --bs-btn-active-border-color: transparent; - --bs-btn-disabled-color: #6c757d; - --bs-btn-disabled-border-color: transparent; - --bs-btn-box-shadow: 0 0 0 #000; - --bs-btn-focus-shadow-rgb: 49, 132, 253; - text-decoration: underline; } - .btn-link:focus-visible { - color: var(--bs-btn-color); } - .btn-link:hover { - color: var(--bs-btn-hover-color); } - -.btn-lg { - --bs-btn-padding-y: 0.5rem; - --bs-btn-padding-x: 1rem; - --bs-btn-font-size: 1.25rem; - --bs-btn-border-radius: var(--bs-border-radius-lg); } - -.btn-sm { - --bs-btn-padding-y: 0.25rem; - --bs-btn-padding-x: 0.5rem; - --bs-btn-font-size: 0.875rem; - --bs-btn-border-radius: var(--bs-border-radius-sm); } - -.fade { - transition: opacity 0.15s linear; } - @media (prefers-reduced-motion: reduce) { - .fade { - transition: none; } } - .fade:not(.show) { - opacity: 0; } - -.collapse:not(.show) { - display: none; } - -.collapsing { - height: 0; - overflow: hidden; - transition: height 0.35s ease; } - @media (prefers-reduced-motion: reduce) { - .collapsing { - transition: none; } } - .collapsing.collapse-horizontal { - width: 0; - height: auto; - transition: width 0.35s ease; } - @media (prefers-reduced-motion: reduce) { - .collapsing.collapse-horizontal { - transition: none; } } -.dropup, -.dropend, -.dropdown, -.dropstart, -.dropup-center, -.dropdown-center { - position: relative; } - -.dropdown-toggle { - white-space: nowrap; } - .dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0.3em solid; - border-right: 0.3em solid transparent; - border-bottom: 0; - border-left: 0.3em solid transparent; } - .dropdown-toggle:empty::after { - margin-left: 0; } - -.dropdown-menu { - --bs-dropdown-zindex: 1000; - --bs-dropdown-min-width: 10rem; - --bs-dropdown-padding-x: 0; - --bs-dropdown-padding-y: 0.5rem; - --bs-dropdown-spacer: 0.125rem; - --bs-dropdown-font-size: 1rem; - --bs-dropdown-color: var(--bs-body-color); - --bs-dropdown-bg: var(--bs-body-bg); - --bs-dropdown-border-color: var(--bs-border-color-translucent); - --bs-dropdown-border-radius: var(--bs-border-radius); - --bs-dropdown-border-width: var(--bs-border-width); - --bs-dropdown-inner-border-radius: calc(var(--bs-border-radius) - var(--bs-border-width)); - --bs-dropdown-divider-bg: var(--bs-border-color-translucent); - --bs-dropdown-divider-margin-y: 0.5rem; - --bs-dropdown-box-shadow: var(--bs-box-shadow); - --bs-dropdown-link-color: var(--bs-body-color); - --bs-dropdown-link-hover-color: var(--bs-body-color); - --bs-dropdown-link-hover-bg: var(--bs-tertiary-bg); - --bs-dropdown-link-active-color: #fff; - --bs-dropdown-link-active-bg: #0d6efd; - --bs-dropdown-link-disabled-color: var(--bs-tertiary-color); - --bs-dropdown-item-padding-x: 1rem; - --bs-dropdown-item-padding-y: 0.25rem; - --bs-dropdown-header-color: #6c757d; - --bs-dropdown-header-padding-x: 1rem; - --bs-dropdown-header-padding-y: 0.5rem; - position: absolute; - z-index: var(--bs-dropdown-zindex); - display: none; - min-width: var(--bs-dropdown-min-width); - padding: var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x); - margin: 0; - font-size: var(--bs-dropdown-font-size); - color: var(--bs-dropdown-color); - text-align: left; - list-style: none; - background-color: var(--bs-dropdown-bg); - background-clip: padding-box; - border: var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color); - border-radius: var(--bs-dropdown-border-radius); } - .dropdown-menu[data-bs-popper] { - top: 100%; - left: 0; - margin-top: var(--bs-dropdown-spacer); } - -.dropdown-menu-start { - --bs-position: start; } - .dropdown-menu-start[data-bs-popper] { - right: auto; - left: 0; } - -.dropdown-menu-end { - --bs-position: end; } - .dropdown-menu-end[data-bs-popper] { - right: 0; - left: auto; } - -@media (min-width: 576px) { - .dropdown-menu-sm-start { - --bs-position: start; } - .dropdown-menu-sm-start[data-bs-popper] { - right: auto; - left: 0; } - .dropdown-menu-sm-end { - --bs-position: end; } - .dropdown-menu-sm-end[data-bs-popper] { - right: 0; - left: auto; } } - -@media (min-width: 768px) { - .dropdown-menu-md-start { - --bs-position: start; } - .dropdown-menu-md-start[data-bs-popper] { - right: auto; - left: 0; } - .dropdown-menu-md-end { - --bs-position: end; } - .dropdown-menu-md-end[data-bs-popper] { - right: 0; - left: auto; } } - -@media (min-width: 992px) { - .dropdown-menu-lg-start { - --bs-position: start; } - .dropdown-menu-lg-start[data-bs-popper] { - right: auto; - left: 0; } - .dropdown-menu-lg-end { - --bs-position: end; } - .dropdown-menu-lg-end[data-bs-popper] { - right: 0; - left: auto; } } - -@media (min-width: 1200px) { - .dropdown-menu-xl-start { - --bs-position: start; } - .dropdown-menu-xl-start[data-bs-popper] { - right: auto; - left: 0; } - .dropdown-menu-xl-end { - --bs-position: end; } - .dropdown-menu-xl-end[data-bs-popper] { - right: 0; - left: auto; } } - -@media (min-width: 1400px) { - .dropdown-menu-xxl-start { - --bs-position: start; } - .dropdown-menu-xxl-start[data-bs-popper] { - right: auto; - left: 0; } - .dropdown-menu-xxl-end { - --bs-position: end; } - .dropdown-menu-xxl-end[data-bs-popper] { - right: 0; - left: auto; } } - -.dropup .dropdown-menu[data-bs-popper] { - top: auto; - bottom: 100%; - margin-top: 0; - margin-bottom: var(--bs-dropdown-spacer); } - -.dropup .dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0; - border-right: 0.3em solid transparent; - border-bottom: 0.3em solid; - border-left: 0.3em solid transparent; } - -.dropup .dropdown-toggle:empty::after { - margin-left: 0; } - -.dropend .dropdown-menu[data-bs-popper] { - top: 0; - right: auto; - left: 100%; - margin-top: 0; - margin-left: var(--bs-dropdown-spacer); } - -.dropend .dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0.3em solid transparent; - border-right: 0; - border-bottom: 0.3em solid transparent; - border-left: 0.3em solid; } - -.dropend .dropdown-toggle:empty::after { - margin-left: 0; } - -.dropend .dropdown-toggle::after { - vertical-align: 0; } - -.dropstart .dropdown-menu[data-bs-popper] { - top: 0; - right: 100%; - left: auto; - margin-top: 0; - margin-right: var(--bs-dropdown-spacer); } - -.dropstart .dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; } - -.dropstart .dropdown-toggle::after { - display: none; } - -.dropstart .dropdown-toggle::before { - display: inline-block; - margin-right: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0.3em solid transparent; - border-right: 0.3em solid; - border-bottom: 0.3em solid transparent; } - -.dropstart .dropdown-toggle:empty::after { - margin-left: 0; } - -.dropstart .dropdown-toggle::before { - vertical-align: 0; } - -.dropdown-divider { - height: 0; - margin: var(--bs-dropdown-divider-margin-y) 0; - overflow: hidden; - border-top: 1px solid var(--bs-dropdown-divider-bg); - opacity: 1; } - -.dropdown-item { - display: block; - width: 100%; - padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); - clear: both; - font-weight: 400; - color: var(--bs-dropdown-link-color); - text-align: inherit; - text-decoration: none; - white-space: nowrap; - background-color: transparent; - border: 0; - border-radius: var(--bs-dropdown-item-border-radius, 0); } - .dropdown-item:hover, .dropdown-item:focus { - color: var(--bs-dropdown-link-hover-color); - background-color: var(--bs-dropdown-link-hover-bg); } - .dropdown-item.active, .dropdown-item:active { - color: var(--bs-dropdown-link-active-color); - text-decoration: none; - background-color: var(--bs-dropdown-link-active-bg); } - .dropdown-item.disabled, .dropdown-item:disabled { - color: var(--bs-dropdown-link-disabled-color); - pointer-events: none; - background-color: transparent; } - -.dropdown-menu.show { - display: block; } - -.dropdown-header { - display: block; - padding: var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x); - margin-bottom: 0; - font-size: 0.875rem; - color: var(--bs-dropdown-header-color); - white-space: nowrap; } - -.dropdown-item-text { - display: block; - padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); - color: var(--bs-dropdown-link-color); } - -.dropdown-menu-dark { - --bs-dropdown-color: #dee2e6; - --bs-dropdown-bg: #343a40; - --bs-dropdown-border-color: var(--bs-border-color-translucent); - --bs-dropdown-box-shadow: ; - --bs-dropdown-link-color: #dee2e6; - --bs-dropdown-link-hover-color: #fff; - --bs-dropdown-divider-bg: var(--bs-border-color-translucent); - --bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.15); - --bs-dropdown-link-active-color: #fff; - --bs-dropdown-link-active-bg: #0d6efd; - --bs-dropdown-link-disabled-color: #adb5bd; - --bs-dropdown-header-color: #adb5bd; } - -.nav { - --bs-nav-link-padding-x: 1rem; - --bs-nav-link-padding-y: 0.5rem; - --bs-nav-link-font-weight: ; - --bs-nav-link-color: var(--bs-link-color); - --bs-nav-link-hover-color: var(--bs-link-hover-color); - --bs-nav-link-disabled-color: var(--bs-secondary-color); - display: flex; - flex-wrap: wrap; - padding-left: 0; - margin-bottom: 0; - list-style: none; } - -.nav-link { - display: block; - padding: var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x); - font-size: var(--bs-nav-link-font-size); - font-weight: var(--bs-nav-link-font-weight); - color: var(--bs-nav-link-color); - text-decoration: none; - background: none; - border: 0; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .nav-link { - transition: none; } } - .nav-link:hover, .nav-link:focus { - color: var(--bs-nav-link-hover-color); } - .nav-link:focus-visible { - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .nav-link.disabled, .nav-link:disabled { - color: var(--bs-nav-link-disabled-color); - pointer-events: none; - cursor: default; } - -.nav-tabs { - --bs-nav-tabs-border-width: var(--bs-border-width); - --bs-nav-tabs-border-color: var(--bs-border-color); - --bs-nav-tabs-border-radius: var(--bs-border-radius); - --bs-nav-tabs-link-hover-border-color: var(--bs-secondary-bg) var(--bs-secondary-bg) var(--bs-border-color); - --bs-nav-tabs-link-active-color: var(--bs-emphasis-color); - --bs-nav-tabs-link-active-bg: var(--bs-body-bg); - --bs-nav-tabs-link-active-border-color: var(--bs-border-color) var(--bs-border-color) var(--bs-body-bg); - border-bottom: var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color); } - .nav-tabs .nav-link { - margin-bottom: calc(-1 * var(--bs-nav-tabs-border-width)); - border: var(--bs-nav-tabs-border-width) solid transparent; - border-top-left-radius: var(--bs-nav-tabs-border-radius); - border-top-right-radius: var(--bs-nav-tabs-border-radius); } - .nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { - isolation: isolate; - border-color: var(--bs-nav-tabs-link-hover-border-color); } - .nav-tabs .nav-link.active, - .nav-tabs .nav-item.show .nav-link { - color: var(--bs-nav-tabs-link-active-color); - background-color: var(--bs-nav-tabs-link-active-bg); - border-color: var(--bs-nav-tabs-link-active-border-color); } - .nav-tabs .dropdown-menu { - margin-top: calc(-1 * var(--bs-nav-tabs-border-width)); - border-top-left-radius: 0; - border-top-right-radius: 0; } - -.nav-pills { - --bs-nav-pills-border-radius: var(--bs-border-radius); - --bs-nav-pills-link-active-color: #fff; - --bs-nav-pills-link-active-bg: #0d6efd; } - .nav-pills .nav-link { - border-radius: var(--bs-nav-pills-border-radius); } - .nav-pills .nav-link.active, - .nav-pills .show > .nav-link { - color: var(--bs-nav-pills-link-active-color); - background-color: var(--bs-nav-pills-link-active-bg); } - -.nav-underline { - --bs-nav-underline-gap: 1rem; - --bs-nav-underline-border-width: 0.125rem; - --bs-nav-underline-link-active-color: var(--bs-emphasis-color); - gap: var(--bs-nav-underline-gap); } - .nav-underline .nav-link { - padding-right: 0; - padding-left: 0; - border-bottom: var(--bs-nav-underline-border-width) solid transparent; } - .nav-underline .nav-link:hover, .nav-underline .nav-link:focus { - border-bottom-color: currentcolor; } - .nav-underline .nav-link.active, - .nav-underline .show > .nav-link { - font-weight: 700; - color: var(--bs-nav-underline-link-active-color); - border-bottom-color: currentcolor; } - -.nav-fill > .nav-link, -.nav-fill .nav-item { - flex: 1 1 auto; - text-align: center; } - -.nav-justified > .nav-link, -.nav-justified .nav-item { - flex-basis: 0; - flex-grow: 1; - text-align: center; } - -.nav-fill .nav-item .nav-link, -.nav-justified .nav-item .nav-link { - width: 100%; } - -.tab-content > .tab-pane { - display: none; } - -.tab-content > .active { - display: block; } - -.navbar { - --bs-navbar-padding-x: 0; - --bs-navbar-padding-y: 0.5rem; - --bs-navbar-color: rgba(var(--bs-emphasis-color-rgb), 0.65); - --bs-navbar-hover-color: rgba(var(--bs-emphasis-color-rgb), 0.8); - --bs-navbar-disabled-color: rgba(var(--bs-emphasis-color-rgb), 0.3); - --bs-navbar-active-color: rgba(var(--bs-emphasis-color-rgb), 1); - --bs-navbar-brand-padding-y: 0.3125rem; - --bs-navbar-brand-margin-end: 1rem; - --bs-navbar-brand-font-size: 1.25rem; - --bs-navbar-brand-color: rgba(var(--bs-emphasis-color-rgb), 1); - --bs-navbar-brand-hover-color: rgba(var(--bs-emphasis-color-rgb), 1); - --bs-navbar-nav-link-padding-x: 0.5rem; - --bs-navbar-toggler-padding-y: 0.25rem; - --bs-navbar-toggler-padding-x: 0.75rem; - --bs-navbar-toggler-font-size: 1.25rem; - --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2833, 37, 41, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); - --bs-navbar-toggler-border-color: rgba(var(--bs-emphasis-color-rgb), 0.15); - --bs-navbar-toggler-border-radius: var(--bs-border-radius); - --bs-navbar-toggler-focus-width: 0.25rem; - --bs-navbar-toggler-transition: box-shadow 0.15s ease-in-out; - position: relative; - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: space-between; - padding: var(--bs-navbar-padding-y) var(--bs-navbar-padding-x); } - .navbar > .container, - .navbar > .container-fluid, - .navbar > .container-sm, - .navbar > .container-md, - .navbar > .container-lg, - .navbar > .container-xl, - .navbar > .container-xxl { - display: flex; - flex-wrap: inherit; - align-items: center; - justify-content: space-between; } - -.navbar-brand { - padding-top: var(--bs-navbar-brand-padding-y); - padding-bottom: var(--bs-navbar-brand-padding-y); - margin-right: var(--bs-navbar-brand-margin-end); - font-size: var(--bs-navbar-brand-font-size); - color: var(--bs-navbar-brand-color); - text-decoration: none; - white-space: nowrap; } - .navbar-brand:hover, .navbar-brand:focus { - color: var(--bs-navbar-brand-hover-color); } - -.navbar-nav { - --bs-nav-link-padding-x: 0; - --bs-nav-link-padding-y: 0.5rem; - --bs-nav-link-font-weight: ; - --bs-nav-link-color: var(--bs-navbar-color); - --bs-nav-link-hover-color: var(--bs-navbar-hover-color); - --bs-nav-link-disabled-color: var(--bs-navbar-disabled-color); - display: flex; - flex-direction: column; - padding-left: 0; - margin-bottom: 0; - list-style: none; } - .navbar-nav .nav-link.active, .navbar-nav .nav-link.show { - color: var(--bs-navbar-active-color); } - .navbar-nav .dropdown-menu { - position: static; } - -.navbar-text { - padding-top: 0.5rem; - padding-bottom: 0.5rem; - color: var(--bs-navbar-color); } - .navbar-text a, - .navbar-text a:hover, - .navbar-text a:focus { - color: var(--bs-navbar-active-color); } - -.navbar-collapse { - flex-basis: 100%; - flex-grow: 1; - align-items: center; } - -.navbar-toggler { - padding: var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x); - font-size: var(--bs-navbar-toggler-font-size); - line-height: 1; - color: var(--bs-navbar-color); - background-color: transparent; - border: var(--bs-border-width) solid var(--bs-navbar-toggler-border-color); - border-radius: var(--bs-navbar-toggler-border-radius); - transition: var(--bs-navbar-toggler-transition); } - @media (prefers-reduced-motion: reduce) { - .navbar-toggler { - transition: none; } } - .navbar-toggler:hover { - text-decoration: none; } - .navbar-toggler:focus { - text-decoration: none; - outline: 0; - box-shadow: 0 0 0 var(--bs-navbar-toggler-focus-width); } - -.navbar-toggler-icon { - display: inline-block; - width: 1.5em; - height: 1.5em; - vertical-align: middle; - background-image: var(--bs-navbar-toggler-icon-bg); - background-repeat: no-repeat; - background-position: center; - background-size: 100%; } - -.navbar-nav-scroll { - max-height: var(--bs-scroll-height, 75vh); - overflow-y: auto; } - -@media (min-width: 576px) { - .navbar-expand-sm { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand-sm .navbar-nav { - flex-direction: row; } - .navbar-expand-sm .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand-sm .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand-sm .navbar-nav-scroll { - overflow: visible; } - .navbar-expand-sm .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand-sm .navbar-toggler { - display: none; } - .navbar-expand-sm .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand-sm .offcanvas .offcanvas-header { - display: none; } - .navbar-expand-sm .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } } - -@media (min-width: 768px) { - .navbar-expand-md { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand-md .navbar-nav { - flex-direction: row; } - .navbar-expand-md .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand-md .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand-md .navbar-nav-scroll { - overflow: visible; } - .navbar-expand-md .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand-md .navbar-toggler { - display: none; } - .navbar-expand-md .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand-md .offcanvas .offcanvas-header { - display: none; } - .navbar-expand-md .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } } - -@media (min-width: 992px) { - .navbar-expand-lg { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand-lg .navbar-nav { - flex-direction: row; } - .navbar-expand-lg .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand-lg .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand-lg .navbar-nav-scroll { - overflow: visible; } - .navbar-expand-lg .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand-lg .navbar-toggler { - display: none; } - .navbar-expand-lg .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand-lg .offcanvas .offcanvas-header { - display: none; } - .navbar-expand-lg .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } } - -@media (min-width: 1200px) { - .navbar-expand-xl { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand-xl .navbar-nav { - flex-direction: row; } - .navbar-expand-xl .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand-xl .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand-xl .navbar-nav-scroll { - overflow: visible; } - .navbar-expand-xl .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand-xl .navbar-toggler { - display: none; } - .navbar-expand-xl .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand-xl .offcanvas .offcanvas-header { - display: none; } - .navbar-expand-xl .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } } - -@media (min-width: 1400px) { - .navbar-expand-xxl { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand-xxl .navbar-nav { - flex-direction: row; } - .navbar-expand-xxl .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand-xxl .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand-xxl .navbar-nav-scroll { - overflow: visible; } - .navbar-expand-xxl .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand-xxl .navbar-toggler { - display: none; } - .navbar-expand-xxl .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand-xxl .offcanvas .offcanvas-header { - display: none; } - .navbar-expand-xxl .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } } - -.navbar-expand { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand .navbar-nav { - flex-direction: row; } - .navbar-expand .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand .navbar-nav-scroll { - overflow: visible; } - .navbar-expand .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand .navbar-toggler { - display: none; } - .navbar-expand .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand .offcanvas .offcanvas-header { - display: none; } - .navbar-expand .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } - -.navbar-dark, -.navbar[data-bs-theme="dark"] { - --bs-navbar-color: rgba(255, 255, 255, 0.55); - --bs-navbar-hover-color: rgba(255, 255, 255, 0.75); - --bs-navbar-disabled-color: rgba(255, 255, 255, 0.25); - --bs-navbar-active-color: #fff; - --bs-navbar-brand-color: #fff; - --bs-navbar-brand-hover-color: #fff; - --bs-navbar-toggler-border-color: rgba(255, 255, 255, 0.1); - --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); } - -[data-bs-theme="dark"] .navbar-toggler-icon { - --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); } - -.card { - --bs-card-spacer-y: 1rem; - --bs-card-spacer-x: 1rem; - --bs-card-title-spacer-y: 0.5rem; - --bs-card-title-color: ; - --bs-card-subtitle-color: ; - --bs-card-border-width: var(--bs-border-width); - --bs-card-border-color: var(--bs-border-color-translucent); - --bs-card-border-radius: var(--bs-border-radius); - --bs-card-box-shadow: ; - --bs-card-inner-border-radius: calc(var(--bs-border-radius) - (var(--bs-border-width))); - --bs-card-cap-padding-y: 0.5rem; - --bs-card-cap-padding-x: 1rem; - --bs-card-cap-bg: rgba(var(--bs-body-color-rgb), 0.03); - --bs-card-cap-color: ; - --bs-card-height: ; - --bs-card-color: ; - --bs-card-bg: var(--bs-body-bg); - --bs-card-img-overlay-padding: 1rem; - --bs-card-group-margin: 0.75rem; - position: relative; - display: flex; - flex-direction: column; - min-width: 0; - height: var(--bs-card-height); - color: var(--bs-body-color); - word-wrap: break-word; - background-color: var(--bs-card-bg); - background-clip: border-box; - border: var(--bs-card-border-width) solid var(--bs-card-border-color); - border-radius: var(--bs-card-border-radius); } - .card > hr { - margin-right: 0; - margin-left: 0; } - .card > .list-group { - border-top: inherit; - border-bottom: inherit; } - .card > .list-group:first-child { - border-top-width: 0; - border-top-left-radius: var(--bs-card-inner-border-radius); - border-top-right-radius: var(--bs-card-inner-border-radius); } - .card > .list-group:last-child { - border-bottom-width: 0; - border-bottom-right-radius: var(--bs-card-inner-border-radius); - border-bottom-left-radius: var(--bs-card-inner-border-radius); } - .card > .card-header + .list-group, - .card > .list-group + .card-footer { - border-top: 0; } - -.card-body { - flex: 1 1 auto; - padding: var(--bs-card-spacer-y) var(--bs-card-spacer-x); - color: var(--bs-card-color); } - -.card-title { - margin-bottom: var(--bs-card-title-spacer-y); - color: var(--bs-card-title-color); } - -.card-subtitle { - margin-top: calc(-.5 * var(--bs-card-title-spacer-y)); - margin-bottom: 0; - color: var(--bs-card-subtitle-color); } - -.card-text:last-child { - margin-bottom: 0; } - -.card-link + .card-link { - margin-left: var(--bs-card-spacer-x); } - -.card-header { - padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); - margin-bottom: 0; - color: var(--bs-card-cap-color); - background-color: var(--bs-card-cap-bg); - border-bottom: var(--bs-card-border-width) solid var(--bs-card-border-color); } - .card-header:first-child { - border-radius: var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0; } - -.card-footer { - padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); - color: var(--bs-card-cap-color); - background-color: var(--bs-card-cap-bg); - border-top: var(--bs-card-border-width) solid var(--bs-card-border-color); } - .card-footer:last-child { - border-radius: 0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius); } - -.card-header-tabs { - margin-right: calc(-.5 * var(--bs-card-cap-padding-x)); - margin-bottom: calc(-1 * var(--bs-card-cap-padding-y)); - margin-left: calc(-.5 * var(--bs-card-cap-padding-x)); - border-bottom: 0; } - .card-header-tabs .nav-link.active { - background-color: var(--bs-card-bg); - border-bottom-color: var(--bs-card-bg); } - -.card-header-pills { - margin-right: calc(-.5 * var(--bs-card-cap-padding-x)); - margin-left: calc(-.5 * var(--bs-card-cap-padding-x)); } - -.card-img-overlay { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - padding: var(--bs-card-img-overlay-padding); - border-radius: var(--bs-card-inner-border-radius); } - -.card-img, -.card-img-top, -.card-img-bottom { - width: 100%; } - -.card-img, -.card-img-top { - border-top-left-radius: var(--bs-card-inner-border-radius); - border-top-right-radius: var(--bs-card-inner-border-radius); } - -.card-img, -.card-img-bottom { - border-bottom-right-radius: var(--bs-card-inner-border-radius); - border-bottom-left-radius: var(--bs-card-inner-border-radius); } - -.card-group > .card { - margin-bottom: var(--bs-card-group-margin); } - -@media (min-width: 576px) { - .card-group { - display: flex; - flex-flow: row wrap; } - .card-group > .card { - flex: 1 0 0%; - margin-bottom: 0; } - .card-group > .card + .card { - margin-left: 0; - border-left: 0; } - .card-group > .card:not(:last-child) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; } - .card-group > .card:not(:last-child) .card-img-top, - .card-group > .card:not(:last-child) .card-header { - border-top-right-radius: 0; } - .card-group > .card:not(:last-child) .card-img-bottom, - .card-group > .card:not(:last-child) .card-footer { - border-bottom-right-radius: 0; } - .card-group > .card:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; } - .card-group > .card:not(:first-child) .card-img-top, - .card-group > .card:not(:first-child) .card-header { - border-top-left-radius: 0; } - .card-group > .card:not(:first-child) .card-img-bottom, - .card-group > .card:not(:first-child) .card-footer { - border-bottom-left-radius: 0; } } - -.accordion { - --bs-accordion-color: var(--bs-body-color); - --bs-accordion-bg: var(--bs-body-bg); - --bs-accordion-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease; - --bs-accordion-border-color: var(--bs-border-color); - --bs-accordion-border-width: var(--bs-border-width); - --bs-accordion-border-radius: var(--bs-border-radius); - --bs-accordion-inner-border-radius: calc(var(--bs-border-radius) - (var(--bs-border-width))); - --bs-accordion-btn-padding-x: 1.25rem; - --bs-accordion-btn-padding-y: 1rem; - --bs-accordion-btn-color: var(--bs-body-color); - --bs-accordion-btn-bg: var(--bs-accordion-bg); - --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); - --bs-accordion-btn-icon-width: 1.25rem; - --bs-accordion-btn-icon-transform: rotate(-180deg); - --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; - --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23052c65'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); - --bs-accordion-btn-focus-border-color: #86b7fe; - --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); - --bs-accordion-body-padding-x: 1.25rem; - --bs-accordion-body-padding-y: 1rem; - --bs-accordion-active-color: var(--bs-primary-text-emphasis); - --bs-accordion-active-bg: var(--bs-primary-bg-subtle); } - -.accordion-button { - position: relative; - display: flex; - align-items: center; - width: 100%; - padding: var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x); - font-size: 1rem; - color: var(--bs-accordion-btn-color); - text-align: left; - background-color: var(--bs-accordion-btn-bg); - border: 0; - border-radius: 0; - overflow-anchor: none; - transition: var(--bs-accordion-transition); } - @media (prefers-reduced-motion: reduce) { - .accordion-button { - transition: none; } } - .accordion-button:not(.collapsed) { - color: var(--bs-accordion-active-color); - background-color: var(--bs-accordion-active-bg); - box-shadow: inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color); } - .accordion-button:not(.collapsed)::after { - background-image: var(--bs-accordion-btn-active-icon); - transform: var(--bs-accordion-btn-icon-transform); } - .accordion-button::after { - flex-shrink: 0; - width: var(--bs-accordion-btn-icon-width); - height: var(--bs-accordion-btn-icon-width); - margin-left: auto; - content: ""; - background-image: var(--bs-accordion-btn-icon); - background-repeat: no-repeat; - background-size: var(--bs-accordion-btn-icon-width); - transition: var(--bs-accordion-btn-icon-transition); } - @media (prefers-reduced-motion: reduce) { - .accordion-button::after { - transition: none; } } - .accordion-button:hover { - z-index: 2; } - .accordion-button:focus { - z-index: 3; - border-color: var(--bs-accordion-btn-focus-border-color); - outline: 0; - box-shadow: var(--bs-accordion-btn-focus-box-shadow); } - -.accordion-header { - margin-bottom: 0; } - -.accordion-item { - color: var(--bs-accordion-color); - background-color: var(--bs-accordion-bg); - border: var(--bs-accordion-border-width) solid var(--bs-accordion-border-color); } - .accordion-item:first-of-type { - border-top-left-radius: var(--bs-accordion-border-radius); - border-top-right-radius: var(--bs-accordion-border-radius); } - .accordion-item:first-of-type .accordion-button { - border-top-left-radius: var(--bs-accordion-inner-border-radius); - border-top-right-radius: var(--bs-accordion-inner-border-radius); } - .accordion-item:not(:first-of-type) { - border-top: 0; } - .accordion-item:last-of-type { - border-bottom-right-radius: var(--bs-accordion-border-radius); - border-bottom-left-radius: var(--bs-accordion-border-radius); } - .accordion-item:last-of-type .accordion-button.collapsed { - border-bottom-right-radius: var(--bs-accordion-inner-border-radius); - border-bottom-left-radius: var(--bs-accordion-inner-border-radius); } - .accordion-item:last-of-type .accordion-collapse { - border-bottom-right-radius: var(--bs-accordion-border-radius); - border-bottom-left-radius: var(--bs-accordion-border-radius); } - -.accordion-body { - padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); } - -.accordion-flush .accordion-collapse { - border-width: 0; } - -.accordion-flush .accordion-item { - border-right: 0; - border-left: 0; - border-radius: 0; } - .accordion-flush .accordion-item:first-child { - border-top: 0; } - .accordion-flush .accordion-item:last-child { - border-bottom: 0; } - .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed { - border-radius: 0; } - -[data-bs-theme="dark"] .accordion-button::after { - --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); - --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); } - -.breadcrumb { - --bs-breadcrumb-padding-x: 0; - --bs-breadcrumb-padding-y: 0; - --bs-breadcrumb-margin-bottom: 1rem; - --bs-breadcrumb-bg: ; - --bs-breadcrumb-border-radius: ; - --bs-breadcrumb-divider-color: var(--bs-secondary-color); - --bs-breadcrumb-item-padding-x: 0.5rem; - --bs-breadcrumb-item-active-color: var(--bs-secondary-color); - display: flex; - flex-wrap: wrap; - padding: var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x); - margin-bottom: var(--bs-breadcrumb-margin-bottom); - font-size: var(--bs-breadcrumb-font-size); - list-style: none; - background-color: var(--bs-breadcrumb-bg); - border-radius: var(--bs-breadcrumb-border-radius); } - -.breadcrumb-item + .breadcrumb-item { - padding-left: var(--bs-breadcrumb-item-padding-x); } - .breadcrumb-item + .breadcrumb-item::before { - float: left; - padding-right: var(--bs-breadcrumb-item-padding-x); - color: var(--bs-breadcrumb-divider-color); - content: var(--bs-breadcrumb-divider, "/") /* rtl: var(--bs-breadcrumb-divider, "/") */; } - -.breadcrumb-item.active { - color: var(--bs-breadcrumb-item-active-color); } - -.pagination { - --bs-pagination-padding-x: 0.75rem; - --bs-pagination-padding-y: 0.375rem; - --bs-pagination-font-size: 1rem; - --bs-pagination-color: var(--bs-link-color); - --bs-pagination-bg: var(--bs-body-bg); - --bs-pagination-border-width: var(--bs-border-width); - --bs-pagination-border-color: var(--bs-border-color); - --bs-pagination-border-radius: var(--bs-border-radius); - --bs-pagination-hover-color: var(--bs-link-hover-color); - --bs-pagination-hover-bg: var(--bs-tertiary-bg); - --bs-pagination-hover-border-color: var(--bs-border-color); - --bs-pagination-focus-color: var(--bs-link-hover-color); - --bs-pagination-focus-bg: var(--bs-secondary-bg); - --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); - --bs-pagination-active-color: #fff; - --bs-pagination-active-bg: #0d6efd; - --bs-pagination-active-border-color: #0d6efd; - --bs-pagination-disabled-color: var(--bs-secondary-color); - --bs-pagination-disabled-bg: var(--bs-secondary-bg); - --bs-pagination-disabled-border-color: var(--bs-border-color); - display: flex; - padding-left: 0; - list-style: none; } - -.page-link { - position: relative; - display: block; - padding: var(--bs-pagination-padding-y) var(--bs-pagination-padding-x); - font-size: var(--bs-pagination-font-size); - color: var(--bs-pagination-color); - text-decoration: none; - background-color: var(--bs-pagination-bg); - border: var(--bs-pagination-border-width) solid var(--bs-pagination-border-color); - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .page-link { - transition: none; } } - .page-link:hover { - z-index: 2; - color: var(--bs-pagination-hover-color); - background-color: var(--bs-pagination-hover-bg); - border-color: var(--bs-pagination-hover-border-color); } - .page-link:focus { - z-index: 3; - color: var(--bs-pagination-focus-color); - background-color: var(--bs-pagination-focus-bg); - outline: 0; - box-shadow: var(--bs-pagination-focus-box-shadow); } - .page-link.active, .active > .page-link { - z-index: 3; - color: var(--bs-pagination-active-color); - background-color: var(--bs-pagination-active-bg); - border-color: var(--bs-pagination-active-border-color); } - .page-link.disabled, .disabled > .page-link { - color: var(--bs-pagination-disabled-color); - pointer-events: none; - background-color: var(--bs-pagination-disabled-bg); - border-color: var(--bs-pagination-disabled-border-color); } - -.page-item:not(:first-child) .page-link { - margin-left: calc(var(--bs-border-width) * -1); } - -.page-item:first-child .page-link { - border-top-left-radius: var(--bs-pagination-border-radius); - border-bottom-left-radius: var(--bs-pagination-border-radius); } - -.page-item:last-child .page-link { - border-top-right-radius: var(--bs-pagination-border-radius); - border-bottom-right-radius: var(--bs-pagination-border-radius); } - -.pagination-lg { - --bs-pagination-padding-x: 1.5rem; - --bs-pagination-padding-y: 0.75rem; - --bs-pagination-font-size: 1.25rem; - --bs-pagination-border-radius: var(--bs-border-radius-lg); } - -.pagination-sm { - --bs-pagination-padding-x: 0.5rem; - --bs-pagination-padding-y: 0.25rem; - --bs-pagination-font-size: 0.875rem; - --bs-pagination-border-radius: var(--bs-border-radius-sm); } - -.btn-close { - --bs-btn-close-color: #191f27; - --bs-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23191f27'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e"); - --bs-btn-close-opacity: 0.5; - --bs-btn-close-hover-opacity: 0.75; - --bs-btn-close-focus-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); - --bs-btn-close-focus-opacity: 1; - --bs-btn-close-disabled-opacity: 0.25; - --bs-btn-close-white-filter: invert(1) grayscale(100%) brightness(200%); - box-sizing: content-box; - width: 1em; - height: 1em; - padding: 0.25em 0.25em; - color: var(--bs-btn-close-color); - background: transparent var(--bs-btn-close-bg) center/1em auto no-repeat; - border: 0; - border-radius: 0.375rem; - opacity: var(--bs-btn-close-opacity); } - .btn-close:hover { - color: var(--bs-btn-close-color); - text-decoration: none; - opacity: var(--bs-btn-close-hover-opacity); } - .btn-close:focus { - outline: 0; - box-shadow: var(--bs-btn-close-focus-shadow); - opacity: var(--bs-btn-close-focus-opacity); } - .btn-close:disabled, .btn-close.disabled { - pointer-events: none; - user-select: none; - opacity: var(--bs-btn-close-disabled-opacity); } - -.btn-close-white { - filter: var(--bs-btn-close-white-filter); } - -[data-bs-theme="dark"] .btn-close { - filter: var(--bs-btn-close-white-filter); } - -.modal { - --bs-modal-zindex: 1055; - --bs-modal-width: 500px; - --bs-modal-padding: 1rem; - --bs-modal-margin: 0.5rem; - --bs-modal-color: ; - --bs-modal-bg: var(--bs-body-bg); - --bs-modal-border-color: var(--bs-border-color-translucent); - --bs-modal-border-width: var(--bs-border-width); - --bs-modal-border-radius: var(--bs-border-radius-lg); - --bs-modal-box-shadow: var(--bs-box-shadow-sm); - --bs-modal-inner-border-radius: calc(var(--bs-border-radius-lg) - (var(--bs-border-width))); - --bs-modal-header-padding-x: 1rem; - --bs-modal-header-padding-y: 1rem; - --bs-modal-header-padding: 1rem 1rem; - --bs-modal-header-border-color: var(--bs-border-color); - --bs-modal-header-border-width: var(--bs-border-width); - --bs-modal-title-line-height: 1.5; - --bs-modal-footer-gap: 0.5rem; - --bs-modal-footer-bg: ; - --bs-modal-footer-border-color: var(--bs-border-color); - --bs-modal-footer-border-width: var(--bs-border-width); - position: fixed; - top: 0; - left: 0; - z-index: var(--bs-modal-zindex); - display: none; - width: 100%; - height: 100%; - overflow-x: hidden; - overflow-y: auto; - outline: 0; } - -.modal-dialog { - position: relative; - width: auto; - margin: var(--bs-modal-margin); - pointer-events: none; } - .modal.fade .modal-dialog { - transition: transform 0.3s ease-out; - transform: translate(0, -50px); } - @media (prefers-reduced-motion: reduce) { - .modal.fade .modal-dialog { - transition: none; } } - .modal.show .modal-dialog { - transform: none; } - .modal.modal-static .modal-dialog { - transform: scale(1.02); } - -.modal-dialog-scrollable { - height: calc(100% - var(--bs-modal-margin) * 2); } - .modal-dialog-scrollable .modal-content { - max-height: 100%; - overflow: hidden; } - .modal-dialog-scrollable .modal-body { - overflow-y: auto; } - -.modal-dialog-centered { - display: flex; - align-items: center; - min-height: calc(100% - var(--bs-modal-margin) * 2); } - -.modal-content { - position: relative; - display: flex; - flex-direction: column; - width: 100%; - color: var(--bs-modal-color); - pointer-events: auto; - background-color: var(--bs-modal-bg); - background-clip: padding-box; - border: var(--bs-modal-border-width) solid var(--bs-modal-border-color); - border-radius: var(--bs-modal-border-radius); - outline: 0; } - -.modal-backdrop { - --bs-backdrop-zindex: 1050; - --bs-backdrop-bg: #191f27; - --bs-backdrop-opacity: 0.5; - position: fixed; - top: 0; - left: 0; - z-index: var(--bs-backdrop-zindex); - width: 100vw; - height: 100vh; - background-color: var(--bs-backdrop-bg); } - .modal-backdrop.fade { - opacity: 0; } - .modal-backdrop.show { - opacity: var(--bs-backdrop-opacity); } - -.modal-header { - display: flex; - flex-shrink: 0; - align-items: center; - justify-content: space-between; - padding: var(--bs-modal-header-padding); - border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); - border-top-left-radius: var(--bs-modal-inner-border-radius); - border-top-right-radius: var(--bs-modal-inner-border-radius); } - .modal-header .btn-close { - padding: calc(var(--bs-modal-header-padding-y) * .5) calc(var(--bs-modal-header-padding-x) * .5); - margin: calc(-.5 * var(--bs-modal-header-padding-y)) calc(-.5 * var(--bs-modal-header-padding-x)) calc(-.5 * var(--bs-modal-header-padding-y)) auto; } - -.modal-title { - margin-bottom: 0; - line-height: var(--bs-modal-title-line-height); } - -.modal-body { - position: relative; - flex: 1 1 auto; - padding: var(--bs-modal-padding); } - -.modal-footer { - display: flex; - flex-shrink: 0; - flex-wrap: wrap; - align-items: center; - justify-content: flex-end; - padding: calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * .5); - background-color: var(--bs-modal-footer-bg); - border-top: var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color); - border-bottom-right-radius: var(--bs-modal-inner-border-radius); - border-bottom-left-radius: var(--bs-modal-inner-border-radius); } - .modal-footer > * { - margin: calc(var(--bs-modal-footer-gap) * .5); } - -@media (min-width: 576px) { - .modal { - --bs-modal-margin: 1.75rem; - --bs-modal-box-shadow: var(--bs-box-shadow); } - .modal-dialog { - max-width: var(--bs-modal-width); - margin-right: auto; - margin-left: auto; } - .modal-sm { - --bs-modal-width: 300px; } } - -@media (min-width: 992px) { - .modal-lg, - .modal-xl { - --bs-modal-width: 800px; } } - -@media (min-width: 1200px) { - .modal-xl { - --bs-modal-width: 1140px; } } - -.modal-fullscreen { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen .modal-header, - .modal-fullscreen .modal-footer { - border-radius: 0; } - .modal-fullscreen .modal-body { - overflow-y: auto; } - -@media (max-width: 575.98px) { - .modal-fullscreen-sm-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen-sm-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen-sm-down .modal-header, - .modal-fullscreen-sm-down .modal-footer { - border-radius: 0; } - .modal-fullscreen-sm-down .modal-body { - overflow-y: auto; } } - -@media (max-width: 767.98px) { - .modal-fullscreen-md-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen-md-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen-md-down .modal-header, - .modal-fullscreen-md-down .modal-footer { - border-radius: 0; } - .modal-fullscreen-md-down .modal-body { - overflow-y: auto; } } - -@media (max-width: 991.98px) { - .modal-fullscreen-lg-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen-lg-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen-lg-down .modal-header, - .modal-fullscreen-lg-down .modal-footer { - border-radius: 0; } - .modal-fullscreen-lg-down .modal-body { - overflow-y: auto; } } - -@media (max-width: 1199.98px) { - .modal-fullscreen-xl-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen-xl-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen-xl-down .modal-header, - .modal-fullscreen-xl-down .modal-footer { - border-radius: 0; } - .modal-fullscreen-xl-down .modal-body { - overflow-y: auto; } } - -@media (max-width: 1399.98px) { - .modal-fullscreen-xxl-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen-xxl-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen-xxl-down .modal-header, - .modal-fullscreen-xxl-down .modal-footer { - border-radius: 0; } - .modal-fullscreen-xxl-down .modal-body { - overflow-y: auto; } } - -.clearfix::after { - display: block; - clear: both; - content: ""; } - -.text-bg-primary { - color: #fff !important; - background-color: RGBA(var(--bs-primary-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-secondary { - color: #fff !important; - background-color: RGBA(var(--bs-secondary-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-success { - color: #fff !important; - background-color: RGBA(var(--bs-success-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-info { - color: #191f27 !important; - background-color: RGBA(var(--bs-info-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-warning { - color: #191f27 !important; - background-color: RGBA(var(--bs-warning-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-danger { - color: #fff !important; - background-color: RGBA(var(--bs-danger-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-light { - color: #191f27 !important; - background-color: RGBA(var(--bs-light-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-dark { - color: #fff !important; - background-color: RGBA(var(--bs-dark-rgb), var(--bs-bg-opacity, 1)) !important; } - -.link-primary { - color: RGBA(var(--bs-primary-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-primary-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-primary:hover, .link-primary:focus { - color: RGBA(10, 88, 202, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(10, 88, 202, var(--bs-link-underline-opacity, 1)) !important; } - -.link-secondary { - color: RGBA(var(--bs-secondary-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-secondary-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-secondary:hover, .link-secondary:focus { - color: RGBA(86, 94, 100, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(86, 94, 100, var(--bs-link-underline-opacity, 1)) !important; } - -.link-success { - color: RGBA(var(--bs-success-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-success-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-success:hover, .link-success:focus { - color: RGBA(20, 108, 67, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(20, 108, 67, var(--bs-link-underline-opacity, 1)) !important; } - -.link-info { - color: RGBA(var(--bs-info-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-info-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-info:hover, .link-info:focus { - color: RGBA(61, 213, 243, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(61, 213, 243, var(--bs-link-underline-opacity, 1)) !important; } - -.link-warning { - color: RGBA(var(--bs-warning-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-warning-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-warning:hover, .link-warning:focus { - color: RGBA(255, 205, 57, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(255, 205, 57, var(--bs-link-underline-opacity, 1)) !important; } - -.link-danger { - color: RGBA(var(--bs-danger-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-danger:hover, .link-danger:focus { - color: RGBA(176, 42, 55, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(176, 42, 55, var(--bs-link-underline-opacity, 1)) !important; } - -.link-light { - color: RGBA(var(--bs-light-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-light:hover, .link-light:focus { - color: RGBA(241, 241, 241, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(241, 241, 241, var(--bs-link-underline-opacity, 1)) !important; } - -.link-dark { - color: RGBA(var(--bs-dark-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-dark-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-dark:hover, .link-dark:focus { - color: RGBA(27, 27, 27, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(27, 27, 27, var(--bs-link-underline-opacity, 1)) !important; } - -.link-body-emphasis { - color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-body-emphasis:hover, .link-body-emphasis:focus { - color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 0.75)) !important; - text-decoration-color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 0.75)) !important; } - -.focus-ring:focus { - outline: 0; - box-shadow: var(--bs-focus-ring-x, 0) var(--bs-focus-ring-y, 0) var(--bs-focus-ring-blur, 0) var(--bs-focus-ring-width) var(--bs-focus-ring-color); } - -.icon-link { - display: inline-flex; - gap: 0.375rem; - align-items: center; - text-decoration-color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 0.5)); - text-underline-offset: 0.25em; - backface-visibility: hidden; } - .icon-link > .bi { - flex-shrink: 0; - width: 1em; - height: 1em; - fill: currentcolor; - transition: 0.2s ease-in-out transform; } - @media (prefers-reduced-motion: reduce) { - .icon-link > .bi { - transition: none; } } -.icon-link-hover:hover > .bi, .icon-link-hover:focus-visible > .bi { - transform: var(--bs-icon-link-transform, translate3d(0.25em, 0, 0)); } - -.ratio { - position: relative; - width: 100%; } - .ratio::before { - display: block; - padding-top: var(--bs-aspect-ratio); - content: ""; } - .ratio > * { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; } - -.ratio-1x1 { - --bs-aspect-ratio: 100%; } - -.ratio-4x3 { - --bs-aspect-ratio: calc(3 / 4 * 100%); } - -.ratio-16x9 { - --bs-aspect-ratio: calc(9 / 16 * 100%); } - -.ratio-21x9 { - --bs-aspect-ratio: calc(9 / 21 * 100%); } - -.fixed-top { - position: fixed; - top: 0; - right: 0; - left: 0; - z-index: 1030; } - -.fixed-bottom { - position: fixed; - right: 0; - bottom: 0; - left: 0; - z-index: 1030; } - -.sticky-top { - position: sticky; - top: 0; - z-index: 1020; } - -.sticky-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } - -@media (min-width: 576px) { - .sticky-sm-top { - position: sticky; - top: 0; - z-index: 1020; } - .sticky-sm-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } } - -@media (min-width: 768px) { - .sticky-md-top { - position: sticky; - top: 0; - z-index: 1020; } - .sticky-md-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } } - -@media (min-width: 992px) { - .sticky-lg-top { - position: sticky; - top: 0; - z-index: 1020; } - .sticky-lg-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } } - -@media (min-width: 1200px) { - .sticky-xl-top { - position: sticky; - top: 0; - z-index: 1020; } - .sticky-xl-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } } - -@media (min-width: 1400px) { - .sticky-xxl-top { - position: sticky; - top: 0; - z-index: 1020; } - .sticky-xxl-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } } - -.hstack { - display: flex; - flex-direction: row; - align-items: center; - align-self: stretch; } - -.vstack { - display: flex; - flex: 1 1 auto; - flex-direction: column; - align-self: stretch; } - -.visually-hidden, -.visually-hidden-focusable:not(:focus):not(:focus-within) { - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; } - .visually-hidden:not(caption), - .visually-hidden-focusable:not(:focus):not(:focus-within):not(caption) { - position: absolute !important; } - -.stretched-link::after { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1; - content: ""; } - -.text-truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; } - -.vr { - display: inline-block; - align-self: stretch; - width: var(--bs-border-width); - min-height: 1em; - background-color: currentcolor; - opacity: 0.25; } - -.align-baseline { - vertical-align: baseline !important; } - -.align-top { - vertical-align: top !important; } - -.align-middle { - vertical-align: middle !important; } - -.align-bottom { - vertical-align: bottom !important; } - -.align-text-bottom { - vertical-align: text-bottom !important; } - -.align-text-top { - vertical-align: text-top !important; } - -.float-start { - float: left !important; } - -.float-end { - float: right !important; } - -.float-none { - float: none !important; } - -.object-fit-contain { - object-fit: contain !important; } - -.object-fit-cover { - object-fit: cover !important; } - -.object-fit-fill { - object-fit: fill !important; } - -.object-fit-scale { - object-fit: scale-down !important; } - -.object-fit-none { - object-fit: none !important; } - -.opacity-0 { - opacity: 0 !important; } - -.opacity-25 { - opacity: 0.25 !important; } - -.opacity-50 { - opacity: 0.5 !important; } - -.opacity-75 { - opacity: 0.75 !important; } - -.opacity-100 { - opacity: 1 !important; } - -.overflow-auto { - overflow: auto !important; } - -.overflow-hidden { - overflow: hidden !important; } - -.overflow-visible { - overflow: visible !important; } - -.overflow-scroll { - overflow: scroll !important; } - -.overflow-x-auto { - overflow-x: auto !important; } - -.overflow-x-hidden { - overflow-x: hidden !important; } - -.overflow-x-visible { - overflow-x: visible !important; } - -.overflow-x-scroll { - overflow-x: scroll !important; } - -.overflow-y-auto { - overflow-y: auto !important; } - -.overflow-y-hidden { - overflow-y: hidden !important; } - -.overflow-y-visible { - overflow-y: visible !important; } - -.overflow-y-scroll { - overflow-y: scroll !important; } - -.d-inline { - display: inline !important; } - -.d-inline-block { - display: inline-block !important; } - -.d-block { - display: block !important; } - -.d-grid { - display: grid !important; } - -.d-inline-grid { - display: inline-grid !important; } - -.d-table { - display: table !important; } - -.d-table-row { - display: table-row !important; } - -.d-table-cell { - display: table-cell !important; } - -.d-flex { - display: flex !important; } - -.d-inline-flex { - display: inline-flex !important; } - -.d-none { - display: none !important; } - -.shadow { - box-shadow: var(--bs-box-shadow) !important; } - -.shadow-sm { - box-shadow: var(--bs-box-shadow-sm) !important; } - -.shadow-lg { - box-shadow: var(--bs-box-shadow-lg) !important; } - -.shadow-none { - box-shadow: none !important; } - -.focus-ring-primary { - --bs-focus-ring-color: rgba(var(--bs-primary-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-secondary { - --bs-focus-ring-color: rgba(var(--bs-secondary-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-success { - --bs-focus-ring-color: rgba(var(--bs-success-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-info { - --bs-focus-ring-color: rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-warning { - --bs-focus-ring-color: rgba(var(--bs-warning-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-danger { - --bs-focus-ring-color: rgba(var(--bs-danger-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-light { - --bs-focus-ring-color: rgba(var(--bs-light-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-dark { - --bs-focus-ring-color: rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity)); } - -.position-static { - position: static !important; } - -.position-relative { - position: relative !important; } - -.position-absolute { - position: absolute !important; } - -.position-fixed { - position: fixed !important; } - -.position-sticky { - position: sticky !important; } - -.top-0 { - top: 0 !important; } - -.top-50 { - top: 50% !important; } - -.top-100 { - top: 100% !important; } - -.bottom-0 { - bottom: 0 !important; } - -.bottom-50 { - bottom: 50% !important; } - -.bottom-100 { - bottom: 100% !important; } - -.start-0 { - left: 0 !important; } - -.start-50 { - left: 50% !important; } - -.start-100 { - left: 100% !important; } - -.end-0 { - right: 0 !important; } - -.end-50 { - right: 50% !important; } - -.end-100 { - right: 100% !important; } - -.translate-middle { - transform: translate(-50%, -50%) !important; } - -.translate-middle-x { - transform: translateX(-50%) !important; } - -.translate-middle-y { - transform: translateY(-50%) !important; } - -.border { - border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } - -.border-0 { - border: 0 !important; } - -.border-top { - border-top: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } - -.border-top-0 { - border-top: 0 !important; } - -.border-end { - border-right: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } - -.border-end-0 { - border-right: 0 !important; } - -.border-bottom { - border-bottom: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } - -.border-bottom-0 { - border-bottom: 0 !important; } - -.border-start { - border-left: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } - -.border-start-0 { - border-left: 0 !important; } - -.border-primary { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-primary-rgb), var(--bs-border-opacity)) !important; } - -.border-secondary { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-secondary-rgb), var(--bs-border-opacity)) !important; } - -.border-success { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-success-rgb), var(--bs-border-opacity)) !important; } - -.border-info { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-info-rgb), var(--bs-border-opacity)) !important; } - -.border-warning { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-warning-rgb), var(--bs-border-opacity)) !important; } - -.border-danger { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-danger-rgb), var(--bs-border-opacity)) !important; } - -.border-light { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important; } - -.border-dark { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-dark-rgb), var(--bs-border-opacity)) !important; } - -.border-black { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-black-rgb), var(--bs-border-opacity)) !important; } - -.border-white { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-white-rgb), var(--bs-border-opacity)) !important; } - -.border-primary-subtle { - border-color: var(--bs-primary-border-subtle) !important; } - -.border-secondary-subtle { - border-color: var(--bs-secondary-border-subtle) !important; } - -.border-success-subtle { - border-color: var(--bs-success-border-subtle) !important; } - -.border-info-subtle { - border-color: var(--bs-info-border-subtle) !important; } - -.border-warning-subtle { - border-color: var(--bs-warning-border-subtle) !important; } - -.border-danger-subtle { - border-color: var(--bs-danger-border-subtle) !important; } - -.border-light-subtle { - border-color: var(--bs-light-border-subtle) !important; } - -.border-dark-subtle { - border-color: var(--bs-dark-border-subtle) !important; } - -.border-1 { - border-width: 1px !important; } - -.border-2 { - border-width: 2px !important; } - -.border-3 { - border-width: 3px !important; } - -.border-4 { - border-width: 4px !important; } - -.border-5 { - border-width: 5px !important; } - -.border-opacity-10 { - --bs-border-opacity: 0.1; } - -.border-opacity-25 { - --bs-border-opacity: 0.25; } - -.border-opacity-50 { - --bs-border-opacity: 0.5; } - -.border-opacity-75 { - --bs-border-opacity: 0.75; } - -.border-opacity-100 { - --bs-border-opacity: 1; } - -.w-100 { - width: 100% !important; } - -.w-auto { - width: auto !important; } - -.min-vw-100 { - min-width: 100vw !important; } - -.h-100 { - height: 100% !important; } - -.h-auto { - height: auto !important; } - -.vh-100 { - height: 100vh !important; } - -.min-vh-100 { - min-height: 100vh !important; } - -.flex-fill { - flex: 1 1 auto !important; } - -.flex-row { - flex-direction: row !important; } - -.flex-column { - flex-direction: column !important; } - -.flex-row-reverse { - flex-direction: row-reverse !important; } - -.flex-column-reverse { - flex-direction: column-reverse !important; } - -.flex-grow-0 { - flex-grow: 0 !important; } - -.flex-grow-1 { - flex-grow: 1 !important; } - -.flex-shrink-0 { - flex-shrink: 0 !important; } - -.flex-shrink-1 { - flex-shrink: 1 !important; } - -.flex-wrap { - flex-wrap: wrap !important; } - -.flex-nowrap { - flex-wrap: nowrap !important; } - -.flex-wrap-reverse { - flex-wrap: wrap-reverse !important; } - -.justify-content-start { - justify-content: flex-start !important; } - -.justify-content-end { - justify-content: flex-end !important; } - -.justify-content-center { - justify-content: center !important; } - -.justify-content-between { - justify-content: space-between !important; } - -.justify-content-around { - justify-content: space-around !important; } - -.justify-content-evenly { - justify-content: space-evenly !important; } - -.align-items-start { - align-items: flex-start !important; } - -.align-items-end { - align-items: flex-end !important; } - -.align-items-center { - align-items: center !important; } - -.align-items-baseline { - align-items: baseline !important; } - -.align-items-stretch { - align-items: stretch !important; } - -.align-content-start { - align-content: flex-start !important; } - -.align-content-end { - align-content: flex-end !important; } - -.align-content-center { - align-content: center !important; } - -.align-content-between { - align-content: space-between !important; } - -.align-content-around { - align-content: space-around !important; } - -.align-content-stretch { - align-content: stretch !important; } - -.align-self-auto { - align-self: auto !important; } - -.align-self-start { - align-self: flex-start !important; } - -.align-self-end { - align-self: flex-end !important; } - -.align-self-center { - align-self: center !important; } - -.align-self-baseline { - align-self: baseline !important; } - -.align-self-stretch { - align-self: stretch !important; } - -.order-first { - order: -1 !important; } - -.order-0 { - order: 0 !important; } - -.order-1 { - order: 1 !important; } - -.order-2 { - order: 2 !important; } - -.order-3 { - order: 3 !important; } - -.order-4 { - order: 4 !important; } - -.order-5 { - order: 5 !important; } - -.order-last { - order: 6 !important; } - -.m-auto { - margin: auto !important; } - -.mx-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - -.mx-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - -.mx-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - -.mx-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - -.mx-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - -.mx-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - -.mx-auto { - margin-right: auto !important; - margin-left: auto !important; } - -.my-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - -.my-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - -.mt-0 { - margin-top: 0 !important; } - -.mt-1 { - margin-top: 0.25rem !important; } - -.mt-2 { - margin-top: 0.5rem !important; } - -.mt-3 { - margin-top: 1rem !important; } - -.mt-4 { - margin-top: 1.5rem !important; } - -.mt-5 { - margin-top: 3rem !important; } - -.mt-auto { - margin-top: auto !important; } - -.me-0 { - margin-right: 0 !important; } - -.me-1 { - margin-right: 0.25rem !important; } - -.me-2 { - margin-right: 0.5rem !important; } - -.me-3 { - margin-right: 1rem !important; } - -.me-4 { - margin-right: 1.5rem !important; } - -.me-5 { - margin-right: 3rem !important; } - -.me-auto { - margin-right: auto !important; } - -.mb-0 { - margin-bottom: 0 !important; } - -.mb-1 { - margin-bottom: 0.25rem !important; } - -.mb-2 { - margin-bottom: 0.5rem !important; } - -.mb-3 { - margin-bottom: 1rem !important; } - -.mb-4 { - margin-bottom: 1.5rem !important; } - -.mb-5 { - margin-bottom: 3rem !important; } - -.mb-auto { - margin-bottom: auto !important; } - -.ms-0 { - margin-left: 0 !important; } - -.ms-1 { - margin-left: 0.25rem !important; } - -.ms-2 { - margin-left: 0.5rem !important; } - -.ms-3 { - margin-left: 1rem !important; } - -.ms-4 { - margin-left: 1.5rem !important; } - -.ms-5 { - margin-left: 3rem !important; } - -.ms-auto { - margin-left: auto !important; } - -.p-0 { - padding: 0 !important; } - -.p-1 { - padding: 0.25rem !important; } - -.p-2 { - padding: 0.5rem !important; } - -.p-3 { - padding: 1rem !important; } - -.p-4 { - padding: 1.5rem !important; } - -.p-5 { - padding: 3rem !important; } - -.px-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - -.px-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - -.px-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - -.px-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - -.px-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - -.px-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - -.py-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - -.py-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - -.py-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - -.py-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - -.py-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - -.py-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - -.pt-0 { - padding-top: 0 !important; } - -.pt-1 { - padding-top: 0.25rem !important; } - -.pt-2 { - padding-top: 0.5rem !important; } - -.pt-3 { - padding-top: 1rem !important; } - -.pt-4 { - padding-top: 1.5rem !important; } - -.pt-5 { - padding-top: 3rem !important; } - -.pe-0 { - padding-right: 0 !important; } - -.pe-1 { - padding-right: 0.25rem !important; } - -.pe-2 { - padding-right: 0.5rem !important; } - -.pe-3 { - padding-right: 1rem !important; } - -.pe-4 { - padding-right: 1.5rem !important; } - -.pe-5 { - padding-right: 3rem !important; } - -.pb-0 { - padding-bottom: 0 !important; } - -.pb-1 { - padding-bottom: 0.25rem !important; } - -.pb-2 { - padding-bottom: 0.5rem !important; } - -.pb-3 { - padding-bottom: 1rem !important; } - -.pb-4 { - padding-bottom: 1.5rem !important; } - -.pb-5 { - padding-bottom: 3rem !important; } - -.ps-0 { - padding-left: 0 !important; } - -.ps-1 { - padding-left: 0.25rem !important; } - -.ps-2 { - padding-left: 0.5rem !important; } - -.ps-3 { - padding-left: 1rem !important; } - -.ps-4 { - padding-left: 1.5rem !important; } - -.ps-5 { - padding-left: 3rem !important; } - -.gap-0 { - gap: 0 !important; } - -.gap-1 { - gap: 0.25rem !important; } - -.gap-2 { - gap: 0.5rem !important; } - -.gap-3 { - gap: 1rem !important; } - -.gap-4 { - gap: 1.5rem !important; } - -.gap-5 { - gap: 3rem !important; } - -.row-gap-0 { - row-gap: 0 !important; } - -.row-gap-1 { - row-gap: 0.25rem !important; } - -.row-gap-2 { - row-gap: 0.5rem !important; } - -.row-gap-3 { - row-gap: 1rem !important; } - -.row-gap-4 { - row-gap: 1.5rem !important; } - -.row-gap-5 { - row-gap: 3rem !important; } - -.column-gap-0 { - column-gap: 0 !important; } - -.column-gap-1 { - column-gap: 0.25rem !important; } - -.column-gap-2 { - column-gap: 0.5rem !important; } - -.column-gap-3 { - column-gap: 1rem !important; } - -.column-gap-4 { - column-gap: 1.5rem !important; } - -.column-gap-5 { - column-gap: 3rem !important; } - -.font-monospace { - font-family: var(--bs-font-monospace) !important; } - -.fs-1 { - font-size: calc(1.375rem + 1.5vw) !important; } - -.fs-2 { - font-size: calc(1.325rem + 0.9vw) !important; } - -.fs-3 { - font-size: calc(1.3rem + 0.6vw) !important; } - -.fs-4 { - font-size: calc(1.275rem + 0.3vw) !important; } - -.fs-5 { - font-size: 1.25rem !important; } - -.fs-6 { - font-size: 1rem !important; } - -.fst-italic { - font-style: italic !important; } - -.fst-normal { - font-style: normal !important; } - -.fw-lighter { - font-weight: lighter !important; } - -.fw-light { - font-weight: 300 !important; } - -.fw-normal { - font-weight: 400 !important; } - -.fw-medium { - font-weight: 500 !important; } - -.fw-semibold { - font-weight: 600 !important; } - -.fw-bold { - font-weight: 700 !important; } - -.fw-bolder { - font-weight: bolder !important; } - -.lh-1 { - line-height: 1 !important; } - -.lh-sm { - line-height: 1.25 !important; } - -.lh-base { - line-height: 1.5 !important; } - -.lh-lg { - line-height: 2 !important; } - -.text-start { - text-align: left !important; } - -.text-end { - text-align: right !important; } - -.text-center { - text-align: center !important; } - -.text-decoration-none { - text-decoration: none !important; } - -.text-decoration-underline { - text-decoration: underline !important; } - -.text-decoration-line-through { - text-decoration: line-through !important; } - -.text-lowercase { - text-transform: lowercase !important; } - -.text-uppercase { - text-transform: uppercase !important; } - -.text-capitalize { - text-transform: capitalize !important; } - -.text-wrap { - white-space: normal !important; } - -.text-nowrap { - white-space: nowrap !important; } - -/* rtl:begin:remove */ -.text-break { - word-wrap: break-word !important; - word-break: break-word !important; } - -/* rtl:end:remove */ -.text-primary { - --bs-text-opacity: 1; - color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important; } - -.text-secondary { - --bs-text-opacity: 1; - color: rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important; } - -.text-success { - --bs-text-opacity: 1; - color: rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important; } - -.text-info { - --bs-text-opacity: 1; - color: rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important; } - -.text-warning { - --bs-text-opacity: 1; - color: rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important; } - -.text-danger { - --bs-text-opacity: 1; - color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important; } - -.text-light { - --bs-text-opacity: 1; - color: rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important; } - -.text-dark { - --bs-text-opacity: 1; - color: rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important; } - -.text-black { - --bs-text-opacity: 1; - color: rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important; } - -.text-white { - --bs-text-opacity: 1; - color: rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important; } - -.text-body { - --bs-text-opacity: 1; - color: rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important; } - -.text-muted { - --bs-text-opacity: 1; - color: var(--bs-secondary-color) !important; } - -.text-black-50 { - --bs-text-opacity: 1; - color: rgba(25, 31, 39, 0.5) !important; } - -.text-white-50 { - --bs-text-opacity: 1; - color: rgba(255, 255, 255, 0.5) !important; } - -.text-body-secondary { - --bs-text-opacity: 1; - color: var(--bs-secondary-color) !important; } - -.text-body-tertiary { - --bs-text-opacity: 1; - color: var(--bs-tertiary-color) !important; } - -.text-body-emphasis { - --bs-text-opacity: 1; - color: var(--bs-emphasis-color) !important; } - -.text-reset { - --bs-text-opacity: 1; - color: inherit !important; } - -.text-opacity-25 { - --bs-text-opacity: 0.25; } - -.text-opacity-50 { - --bs-text-opacity: 0.5; } - -.text-opacity-75 { - --bs-text-opacity: 0.75; } - -.text-opacity-100 { - --bs-text-opacity: 1; } - -.text-primary-emphasis { - color: var(--bs-primary-text-emphasis) !important; } - -.text-secondary-emphasis { - color: var(--bs-secondary-text-emphasis) !important; } - -.text-success-emphasis { - color: var(--bs-success-text-emphasis) !important; } - -.text-info-emphasis { - color: var(--bs-info-text-emphasis) !important; } - -.text-warning-emphasis { - color: var(--bs-warning-text-emphasis) !important; } - -.text-danger-emphasis { - color: var(--bs-danger-text-emphasis) !important; } - -.text-light-emphasis { - color: var(--bs-light-text-emphasis) !important; } - -.text-dark-emphasis { - color: var(--bs-dark-text-emphasis) !important; } - -.link-opacity-10 { - --bs-link-opacity: 0.1; } - -.link-opacity-10-hover:hover { - --bs-link-opacity: 0.1; } - -.link-opacity-25 { - --bs-link-opacity: 0.25; } - -.link-opacity-25-hover:hover { - --bs-link-opacity: 0.25; } - -.link-opacity-50 { - --bs-link-opacity: 0.5; } - -.link-opacity-50-hover:hover { - --bs-link-opacity: 0.5; } - -.link-opacity-75 { - --bs-link-opacity: 0.75; } - -.link-opacity-75-hover:hover { - --bs-link-opacity: 0.75; } - -.link-opacity-100 { - --bs-link-opacity: 1; } - -.link-opacity-100-hover:hover { - --bs-link-opacity: 1; } - -.link-offset-1 { - text-underline-offset: 0.125em !important; } - -.link-offset-1-hover:hover { - text-underline-offset: 0.125em !important; } - -.link-offset-2 { - text-underline-offset: 0.25em !important; } - -.link-offset-2-hover:hover { - text-underline-offset: 0.25em !important; } - -.link-offset-3 { - text-underline-offset: 0.375em !important; } - -.link-offset-3-hover:hover { - text-underline-offset: 0.375em !important; } - -.link-underline-primary { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-primary-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-secondary { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-secondary-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-success { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-success-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-info { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-info-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-warning { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-warning-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-danger { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-danger-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-light { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-light-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-dark { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-dark-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-link-color-rgb), var(--bs-link-underline-opacity, 1)) !important; } - -.link-underline-opacity-0 { - --bs-link-underline-opacity: 0; } - -.link-underline-opacity-0-hover:hover { - --bs-link-underline-opacity: 0; } - -.link-underline-opacity-10 { - --bs-link-underline-opacity: 0.1; } - -.link-underline-opacity-10-hover:hover { - --bs-link-underline-opacity: 0.1; } - -.link-underline-opacity-25 { - --bs-link-underline-opacity: 0.25; } - -.link-underline-opacity-25-hover:hover { - --bs-link-underline-opacity: 0.25; } - -.link-underline-opacity-50 { - --bs-link-underline-opacity: 0.5; } - -.link-underline-opacity-50-hover:hover { - --bs-link-underline-opacity: 0.5; } - -.link-underline-opacity-75 { - --bs-link-underline-opacity: 0.75; } - -.link-underline-opacity-75-hover:hover { - --bs-link-underline-opacity: 0.75; } - -.link-underline-opacity-100 { - --bs-link-underline-opacity: 1; } - -.link-underline-opacity-100-hover:hover { - --bs-link-underline-opacity: 1; } - -.bg-primary { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important; } - -.bg-secondary { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important; } - -.bg-success { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important; } - -.bg-info { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important; } - -.bg-warning { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important; } - -.bg-danger { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important; } - -.bg-light { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; } - -.bg-dark { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important; } - -.bg-black { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important; } - -.bg-white { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important; } - -.bg-body { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important; } - -.bg-transparent { - --bs-bg-opacity: 1; - background-color: transparent !important; } - -.bg-body-secondary { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-secondary-bg-rgb), var(--bs-bg-opacity)) !important; } - -.bg-body-tertiary { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-tertiary-bg-rgb), var(--bs-bg-opacity)) !important; } - -.bg-opacity-10 { - --bs-bg-opacity: 0.1; } - -.bg-opacity-25 { - --bs-bg-opacity: 0.25; } - -.bg-opacity-50 { - --bs-bg-opacity: 0.5; } - -.bg-opacity-75 { - --bs-bg-opacity: 0.75; } - -.bg-opacity-100 { - --bs-bg-opacity: 1; } - -.bg-primary-subtle { - background-color: var(--bs-primary-bg-subtle) !important; } - -.bg-secondary-subtle { - background-color: var(--bs-secondary-bg-subtle) !important; } - -.bg-success-subtle { - background-color: var(--bs-success-bg-subtle) !important; } - -.bg-info-subtle { - background-color: var(--bs-info-bg-subtle) !important; } - -.bg-warning-subtle { - background-color: var(--bs-warning-bg-subtle) !important; } - -.bg-danger-subtle { - background-color: var(--bs-danger-bg-subtle) !important; } - -.bg-light-subtle { - background-color: var(--bs-light-bg-subtle) !important; } - -.bg-dark-subtle { - background-color: var(--bs-dark-bg-subtle) !important; } - -.bg-gradient { - background-image: var(--bs-gradient) !important; } - -.user-select-all { - user-select: all !important; } - -.user-select-auto { - user-select: auto !important; } - -.user-select-none { - user-select: none !important; } - -.pe-none { - pointer-events: none !important; } - -.pe-auto { - pointer-events: auto !important; } - -.rounded { - border-radius: var(--bs-border-radius) !important; } - -.rounded-0 { - border-radius: 0 !important; } - -.rounded-1 { - border-radius: var(--bs-border-radius-sm) !important; } - -.rounded-2, .content blockquote, .gallery-item img, .btn { - border-radius: var(--bs-border-radius) !important; } - -.rounded-3 { - border-radius: var(--bs-border-radius-lg) !important; } - -.rounded-4 { - border-radius: var(--bs-border-radius-xl) !important; } - -.rounded-5 { - border-radius: var(--bs-border-radius-xxl) !important; } - -.rounded-circle { - border-radius: 50% !important; } - -.rounded-pill { - border-radius: var(--bs-border-radius-pill) !important; } - -.rounded-top { - border-top-left-radius: var(--bs-border-radius) !important; - border-top-right-radius: var(--bs-border-radius) !important; } - -.rounded-top-0 { - border-top-left-radius: 0 !important; - border-top-right-radius: 0 !important; } - -.rounded-top-1 { - border-top-left-radius: var(--bs-border-radius-sm) !important; - border-top-right-radius: var(--bs-border-radius-sm) !important; } - -.rounded-top-2 { - border-top-left-radius: var(--bs-border-radius) !important; - border-top-right-radius: var(--bs-border-radius) !important; } - -.rounded-top-3 { - border-top-left-radius: var(--bs-border-radius-lg) !important; - border-top-right-radius: var(--bs-border-radius-lg) !important; } - -.rounded-top-4 { - border-top-left-radius: var(--bs-border-radius-xl) !important; - border-top-right-radius: var(--bs-border-radius-xl) !important; } - -.rounded-top-5 { - border-top-left-radius: var(--bs-border-radius-xxl) !important; - border-top-right-radius: var(--bs-border-radius-xxl) !important; } - -.rounded-top-circle { - border-top-left-radius: 50% !important; - border-top-right-radius: 50% !important; } - -.rounded-top-pill { - border-top-left-radius: var(--bs-border-radius-pill) !important; - border-top-right-radius: var(--bs-border-radius-pill) !important; } - -.rounded-end { - border-top-right-radius: var(--bs-border-radius) !important; - border-bottom-right-radius: var(--bs-border-radius) !important; } - -.rounded-end-0 { - border-top-right-radius: 0 !important; - border-bottom-right-radius: 0 !important; } - -.rounded-end-1 { - border-top-right-radius: var(--bs-border-radius-sm) !important; - border-bottom-right-radius: var(--bs-border-radius-sm) !important; } - -.rounded-end-2 { - border-top-right-radius: var(--bs-border-radius) !important; - border-bottom-right-radius: var(--bs-border-radius) !important; } - -.rounded-end-3 { - border-top-right-radius: var(--bs-border-radius-lg) !important; - border-bottom-right-radius: var(--bs-border-radius-lg) !important; } - -.rounded-end-4 { - border-top-right-radius: var(--bs-border-radius-xl) !important; - border-bottom-right-radius: var(--bs-border-radius-xl) !important; } - -.rounded-end-5 { - border-top-right-radius: var(--bs-border-radius-xxl) !important; - border-bottom-right-radius: var(--bs-border-radius-xxl) !important; } - -.rounded-end-circle { - border-top-right-radius: 50% !important; - border-bottom-right-radius: 50% !important; } - -.rounded-end-pill { - border-top-right-radius: var(--bs-border-radius-pill) !important; - border-bottom-right-radius: var(--bs-border-radius-pill) !important; } - -.rounded-bottom { - border-bottom-right-radius: var(--bs-border-radius) !important; - border-bottom-left-radius: var(--bs-border-radius) !important; } - -.rounded-bottom-0 { - border-bottom-right-radius: 0 !important; - border-bottom-left-radius: 0 !important; } - -.rounded-bottom-1 { - border-bottom-right-radius: var(--bs-border-radius-sm) !important; - border-bottom-left-radius: var(--bs-border-radius-sm) !important; } - -.rounded-bottom-2 { - border-bottom-right-radius: var(--bs-border-radius) !important; - border-bottom-left-radius: var(--bs-border-radius) !important; } - -.rounded-bottom-3 { - border-bottom-right-radius: var(--bs-border-radius-lg) !important; - border-bottom-left-radius: var(--bs-border-radius-lg) !important; } - -.rounded-bottom-4 { - border-bottom-right-radius: var(--bs-border-radius-xl) !important; - border-bottom-left-radius: var(--bs-border-radius-xl) !important; } - -.rounded-bottom-5 { - border-bottom-right-radius: var(--bs-border-radius-xxl) !important; - border-bottom-left-radius: var(--bs-border-radius-xxl) !important; } - -.rounded-bottom-circle { - border-bottom-right-radius: 50% !important; - border-bottom-left-radius: 50% !important; } - -.rounded-bottom-pill { - border-bottom-right-radius: var(--bs-border-radius-pill) !important; - border-bottom-left-radius: var(--bs-border-radius-pill) !important; } - -.rounded-start { - border-bottom-left-radius: var(--bs-border-radius) !important; - border-top-left-radius: var(--bs-border-radius) !important; } - -.rounded-start-0 { - border-bottom-left-radius: 0 !important; - border-top-left-radius: 0 !important; } - -.rounded-start-1 { - border-bottom-left-radius: var(--bs-border-radius-sm) !important; - border-top-left-radius: var(--bs-border-radius-sm) !important; } - -.rounded-start-2 { - border-bottom-left-radius: var(--bs-border-radius) !important; - border-top-left-radius: var(--bs-border-radius) !important; } - -.rounded-start-3 { - border-bottom-left-radius: var(--bs-border-radius-lg) !important; - border-top-left-radius: var(--bs-border-radius-lg) !important; } - -.rounded-start-4 { - border-bottom-left-radius: var(--bs-border-radius-xl) !important; - border-top-left-radius: var(--bs-border-radius-xl) !important; } - -.rounded-start-5 { - border-bottom-left-radius: var(--bs-border-radius-xxl) !important; - border-top-left-radius: var(--bs-border-radius-xxl) !important; } - -.rounded-start-circle { - border-bottom-left-radius: 50% !important; - border-top-left-radius: 50% !important; } - -.rounded-start-pill { - border-bottom-left-radius: var(--bs-border-radius-pill) !important; - border-top-left-radius: var(--bs-border-radius-pill) !important; } - -.visible { - visibility: visible !important; } - -.invisible { - visibility: hidden !important; } - -.z-n1 { - z-index: -1 !important; } - -@media (min-width: 576px) { - .float-sm-start { - float: left !important; } - .float-sm-end { - float: right !important; } - .float-sm-none { - float: none !important; } - .object-fit-sm-contain { - object-fit: contain !important; } - .object-fit-sm-cover { - object-fit: cover !important; } - .object-fit-sm-fill { - object-fit: fill !important; } - .object-fit-sm-scale { - object-fit: scale-down !important; } - .object-fit-sm-none { - object-fit: none !important; } - .d-sm-inline { - display: inline !important; } - .d-sm-inline-block { - display: inline-block !important; } - .d-sm-block { - display: block !important; } - .d-sm-grid { - display: grid !important; } - .d-sm-inline-grid { - display: inline-grid !important; } - .d-sm-table { - display: table !important; } - .d-sm-table-row { - display: table-row !important; } - .d-sm-table-cell { - display: table-cell !important; } - .d-sm-flex { - display: flex !important; } - .d-sm-inline-flex { - display: inline-flex !important; } - .d-sm-none { - display: none !important; } - .flex-sm-fill { - flex: 1 1 auto !important; } - .flex-sm-row { - flex-direction: row !important; } - .flex-sm-column { - flex-direction: column !important; } - .flex-sm-row-reverse { - flex-direction: row-reverse !important; } - .flex-sm-column-reverse { - flex-direction: column-reverse !important; } - .flex-sm-grow-0 { - flex-grow: 0 !important; } - .flex-sm-grow-1 { - flex-grow: 1 !important; } - .flex-sm-shrink-0 { - flex-shrink: 0 !important; } - .flex-sm-shrink-1 { - flex-shrink: 1 !important; } - .flex-sm-wrap { - flex-wrap: wrap !important; } - .flex-sm-nowrap { - flex-wrap: nowrap !important; } - .flex-sm-wrap-reverse { - flex-wrap: wrap-reverse !important; } - .justify-content-sm-start { - justify-content: flex-start !important; } - .justify-content-sm-end { - justify-content: flex-end !important; } - .justify-content-sm-center { - justify-content: center !important; } - .justify-content-sm-between { - justify-content: space-between !important; } - .justify-content-sm-around { - justify-content: space-around !important; } - .justify-content-sm-evenly { - justify-content: space-evenly !important; } - .align-items-sm-start { - align-items: flex-start !important; } - .align-items-sm-end { - align-items: flex-end !important; } - .align-items-sm-center { - align-items: center !important; } - .align-items-sm-baseline { - align-items: baseline !important; } - .align-items-sm-stretch { - align-items: stretch !important; } - .align-content-sm-start { - align-content: flex-start !important; } - .align-content-sm-end { - align-content: flex-end !important; } - .align-content-sm-center { - align-content: center !important; } - .align-content-sm-between { - align-content: space-between !important; } - .align-content-sm-around { - align-content: space-around !important; } - .align-content-sm-stretch { - align-content: stretch !important; } - .align-self-sm-auto { - align-self: auto !important; } - .align-self-sm-start { - align-self: flex-start !important; } - .align-self-sm-end { - align-self: flex-end !important; } - .align-self-sm-center { - align-self: center !important; } - .align-self-sm-baseline { - align-self: baseline !important; } - .align-self-sm-stretch { - align-self: stretch !important; } - .order-sm-first { - order: -1 !important; } - .order-sm-0 { - order: 0 !important; } - .order-sm-1 { - order: 1 !important; } - .order-sm-2 { - order: 2 !important; } - .order-sm-3 { - order: 3 !important; } - .order-sm-4 { - order: 4 !important; } - .order-sm-5 { - order: 5 !important; } - .order-sm-last { - order: 6 !important; } - .m-sm-0 { - margin: 0 !important; } - .m-sm-1 { - margin: 0.25rem !important; } - .m-sm-2 { - margin: 0.5rem !important; } - .m-sm-3 { - margin: 1rem !important; } - .m-sm-4 { - margin: 1.5rem !important; } - .m-sm-5 { - margin: 3rem !important; } - .m-sm-auto { - margin: auto !important; } - .mx-sm-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - .mx-sm-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - .mx-sm-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - .mx-sm-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - .mx-sm-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - .mx-sm-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - .mx-sm-auto { - margin-right: auto !important; - margin-left: auto !important; } - .my-sm-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; } - .my-sm-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; } - .my-sm-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; } - .my-sm-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; } - .my-sm-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - .my-sm-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; } - .my-sm-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - .mt-sm-0 { - margin-top: 0 !important; } - .mt-sm-1 { - margin-top: 0.25rem !important; } - .mt-sm-2 { - margin-top: 0.5rem !important; } - .mt-sm-3 { - margin-top: 1rem !important; } - .mt-sm-4 { - margin-top: 1.5rem !important; } - .mt-sm-5 { - margin-top: 3rem !important; } - .mt-sm-auto { - margin-top: auto !important; } - .me-sm-0 { - margin-right: 0 !important; } - .me-sm-1 { - margin-right: 0.25rem !important; } - .me-sm-2 { - margin-right: 0.5rem !important; } - .me-sm-3 { - margin-right: 1rem !important; } - .me-sm-4 { - margin-right: 1.5rem !important; } - .me-sm-5 { - margin-right: 3rem !important; } - .me-sm-auto { - margin-right: auto !important; } - .mb-sm-0 { - margin-bottom: 0 !important; } - .mb-sm-1 { - margin-bottom: 0.25rem !important; } - .mb-sm-2 { - margin-bottom: 0.5rem !important; } - .mb-sm-3 { - margin-bottom: 1rem !important; } - .mb-sm-4 { - margin-bottom: 1.5rem !important; } - .mb-sm-5 { - margin-bottom: 3rem !important; } - .mb-sm-auto { - margin-bottom: auto !important; } - .ms-sm-0 { - margin-left: 0 !important; } - .ms-sm-1 { - margin-left: 0.25rem !important; } - .ms-sm-2 { - margin-left: 0.5rem !important; } - .ms-sm-3 { - margin-left: 1rem !important; } - .ms-sm-4 { - margin-left: 1.5rem !important; } - .ms-sm-5 { - margin-left: 3rem !important; } - .ms-sm-auto { - margin-left: auto !important; } - .p-sm-0 { - padding: 0 !important; } - .p-sm-1 { - padding: 0.25rem !important; } - .p-sm-2 { - padding: 0.5rem !important; } - .p-sm-3 { - padding: 1rem !important; } - .p-sm-4 { - padding: 1.5rem !important; } - .p-sm-5 { - padding: 3rem !important; } - .px-sm-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - .px-sm-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - .px-sm-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - .px-sm-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - .px-sm-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - .px-sm-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - .py-sm-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - .py-sm-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - .py-sm-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - .py-sm-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - .py-sm-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - .py-sm-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - .pt-sm-0 { - padding-top: 0 !important; } - .pt-sm-1 { - padding-top: 0.25rem !important; } - .pt-sm-2 { - padding-top: 0.5rem !important; } - .pt-sm-3 { - padding-top: 1rem !important; } - .pt-sm-4 { - padding-top: 1.5rem !important; } - .pt-sm-5 { - padding-top: 3rem !important; } - .pe-sm-0 { - padding-right: 0 !important; } - .pe-sm-1 { - padding-right: 0.25rem !important; } - .pe-sm-2 { - padding-right: 0.5rem !important; } - .pe-sm-3 { - padding-right: 1rem !important; } - .pe-sm-4 { - padding-right: 1.5rem !important; } - .pe-sm-5 { - padding-right: 3rem !important; } - .pb-sm-0 { - padding-bottom: 0 !important; } - .pb-sm-1 { - padding-bottom: 0.25rem !important; } - .pb-sm-2 { - padding-bottom: 0.5rem !important; } - .pb-sm-3 { - padding-bottom: 1rem !important; } - .pb-sm-4 { - padding-bottom: 1.5rem !important; } - .pb-sm-5 { - padding-bottom: 3rem !important; } - .ps-sm-0 { - padding-left: 0 !important; } - .ps-sm-1 { - padding-left: 0.25rem !important; } - .ps-sm-2 { - padding-left: 0.5rem !important; } - .ps-sm-3 { - padding-left: 1rem !important; } - .ps-sm-4 { - padding-left: 1.5rem !important; } - .ps-sm-5 { - padding-left: 3rem !important; } - .gap-sm-0 { - gap: 0 !important; } - .gap-sm-1 { - gap: 0.25rem !important; } - .gap-sm-2 { - gap: 0.5rem !important; } - .gap-sm-3 { - gap: 1rem !important; } - .gap-sm-4 { - gap: 1.5rem !important; } - .gap-sm-5 { - gap: 3rem !important; } - .row-gap-sm-0 { - row-gap: 0 !important; } - .row-gap-sm-1 { - row-gap: 0.25rem !important; } - .row-gap-sm-2 { - row-gap: 0.5rem !important; } - .row-gap-sm-3 { - row-gap: 1rem !important; } - .row-gap-sm-4 { - row-gap: 1.5rem !important; } - .row-gap-sm-5 { - row-gap: 3rem !important; } - .column-gap-sm-0 { - column-gap: 0 !important; } - .column-gap-sm-1 { - column-gap: 0.25rem !important; } - .column-gap-sm-2 { - column-gap: 0.5rem !important; } - .column-gap-sm-3 { - column-gap: 1rem !important; } - .column-gap-sm-4 { - column-gap: 1.5rem !important; } - .column-gap-sm-5 { - column-gap: 3rem !important; } - .text-sm-start { - text-align: left !important; } - .text-sm-end { - text-align: right !important; } - .text-sm-center { - text-align: center !important; } } - -@media (min-width: 768px) { - .float-md-start { - float: left !important; } - .float-md-end { - float: right !important; } - .float-md-none { - float: none !important; } - .object-fit-md-contain { - object-fit: contain !important; } - .object-fit-md-cover { - object-fit: cover !important; } - .object-fit-md-fill { - object-fit: fill !important; } - .object-fit-md-scale { - object-fit: scale-down !important; } - .object-fit-md-none { - object-fit: none !important; } - .d-md-inline { - display: inline !important; } - .d-md-inline-block { - display: inline-block !important; } - .d-md-block { - display: block !important; } - .d-md-grid { - display: grid !important; } - .d-md-inline-grid { - display: inline-grid !important; } - .d-md-table { - display: table !important; } - .d-md-table-row { - display: table-row !important; } - .d-md-table-cell { - display: table-cell !important; } - .d-md-flex { - display: flex !important; } - .d-md-inline-flex { - display: inline-flex !important; } - .d-md-none { - display: none !important; } - .flex-md-fill { - flex: 1 1 auto !important; } - .flex-md-row { - flex-direction: row !important; } - .flex-md-column { - flex-direction: column !important; } - .flex-md-row-reverse { - flex-direction: row-reverse !important; } - .flex-md-column-reverse { - flex-direction: column-reverse !important; } - .flex-md-grow-0 { - flex-grow: 0 !important; } - .flex-md-grow-1 { - flex-grow: 1 !important; } - .flex-md-shrink-0 { - flex-shrink: 0 !important; } - .flex-md-shrink-1 { - flex-shrink: 1 !important; } - .flex-md-wrap { - flex-wrap: wrap !important; } - .flex-md-nowrap { - flex-wrap: nowrap !important; } - .flex-md-wrap-reverse { - flex-wrap: wrap-reverse !important; } - .justify-content-md-start { - justify-content: flex-start !important; } - .justify-content-md-end { - justify-content: flex-end !important; } - .justify-content-md-center { - justify-content: center !important; } - .justify-content-md-between { - justify-content: space-between !important; } - .justify-content-md-around { - justify-content: space-around !important; } - .justify-content-md-evenly { - justify-content: space-evenly !important; } - .align-items-md-start { - align-items: flex-start !important; } - .align-items-md-end { - align-items: flex-end !important; } - .align-items-md-center { - align-items: center !important; } - .align-items-md-baseline { - align-items: baseline !important; } - .align-items-md-stretch { - align-items: stretch !important; } - .align-content-md-start { - align-content: flex-start !important; } - .align-content-md-end { - align-content: flex-end !important; } - .align-content-md-center { - align-content: center !important; } - .align-content-md-between { - align-content: space-between !important; } - .align-content-md-around { - align-content: space-around !important; } - .align-content-md-stretch { - align-content: stretch !important; } - .align-self-md-auto { - align-self: auto !important; } - .align-self-md-start { - align-self: flex-start !important; } - .align-self-md-end { - align-self: flex-end !important; } - .align-self-md-center { - align-self: center !important; } - .align-self-md-baseline { - align-self: baseline !important; } - .align-self-md-stretch { - align-self: stretch !important; } - .order-md-first { - order: -1 !important; } - .order-md-0 { - order: 0 !important; } - .order-md-1 { - order: 1 !important; } - .order-md-2 { - order: 2 !important; } - .order-md-3 { - order: 3 !important; } - .order-md-4 { - order: 4 !important; } - .order-md-5 { - order: 5 !important; } - .order-md-last { - order: 6 !important; } - .m-md-0 { - margin: 0 !important; } - .m-md-1 { - margin: 0.25rem !important; } - .m-md-2 { - margin: 0.5rem !important; } - .m-md-3 { - margin: 1rem !important; } - .m-md-4 { - margin: 1.5rem !important; } - .m-md-5 { - margin: 3rem !important; } - .m-md-auto { - margin: auto !important; } - .mx-md-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - .mx-md-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - .mx-md-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - .mx-md-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - .mx-md-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - .mx-md-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - .mx-md-auto { - margin-right: auto !important; - margin-left: auto !important; } - .my-md-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; } - .my-md-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; } - .my-md-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; } - .my-md-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; } - .my-md-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - .my-md-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; } - .my-md-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - .mt-md-0 { - margin-top: 0 !important; } - .mt-md-1 { - margin-top: 0.25rem !important; } - .mt-md-2 { - margin-top: 0.5rem !important; } - .mt-md-3 { - margin-top: 1rem !important; } - .mt-md-4 { - margin-top: 1.5rem !important; } - .mt-md-5 { - margin-top: 3rem !important; } - .mt-md-auto { - margin-top: auto !important; } - .me-md-0 { - margin-right: 0 !important; } - .me-md-1 { - margin-right: 0.25rem !important; } - .me-md-2 { - margin-right: 0.5rem !important; } - .me-md-3 { - margin-right: 1rem !important; } - .me-md-4 { - margin-right: 1.5rem !important; } - .me-md-5 { - margin-right: 3rem !important; } - .me-md-auto { - margin-right: auto !important; } - .mb-md-0 { - margin-bottom: 0 !important; } - .mb-md-1 { - margin-bottom: 0.25rem !important; } - .mb-md-2 { - margin-bottom: 0.5rem !important; } - .mb-md-3 { - margin-bottom: 1rem !important; } - .mb-md-4 { - margin-bottom: 1.5rem !important; } - .mb-md-5 { - margin-bottom: 3rem !important; } - .mb-md-auto { - margin-bottom: auto !important; } - .ms-md-0 { - margin-left: 0 !important; } - .ms-md-1 { - margin-left: 0.25rem !important; } - .ms-md-2 { - margin-left: 0.5rem !important; } - .ms-md-3 { - margin-left: 1rem !important; } - .ms-md-4 { - margin-left: 1.5rem !important; } - .ms-md-5 { - margin-left: 3rem !important; } - .ms-md-auto { - margin-left: auto !important; } - .p-md-0 { - padding: 0 !important; } - .p-md-1 { - padding: 0.25rem !important; } - .p-md-2 { - padding: 0.5rem !important; } - .p-md-3 { - padding: 1rem !important; } - .p-md-4 { - padding: 1.5rem !important; } - .p-md-5 { - padding: 3rem !important; } - .px-md-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - .px-md-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - .px-md-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - .px-md-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - .px-md-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - .px-md-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - .py-md-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - .py-md-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - .py-md-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - .py-md-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - .py-md-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - .py-md-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - .pt-md-0 { - padding-top: 0 !important; } - .pt-md-1 { - padding-top: 0.25rem !important; } - .pt-md-2 { - padding-top: 0.5rem !important; } - .pt-md-3 { - padding-top: 1rem !important; } - .pt-md-4 { - padding-top: 1.5rem !important; } - .pt-md-5 { - padding-top: 3rem !important; } - .pe-md-0 { - padding-right: 0 !important; } - .pe-md-1 { - padding-right: 0.25rem !important; } - .pe-md-2 { - padding-right: 0.5rem !important; } - .pe-md-3 { - padding-right: 1rem !important; } - .pe-md-4 { - padding-right: 1.5rem !important; } - .pe-md-5 { - padding-right: 3rem !important; } - .pb-md-0 { - padding-bottom: 0 !important; } - .pb-md-1 { - padding-bottom: 0.25rem !important; } - .pb-md-2 { - padding-bottom: 0.5rem !important; } - .pb-md-3 { - padding-bottom: 1rem !important; } - .pb-md-4 { - padding-bottom: 1.5rem !important; } - .pb-md-5 { - padding-bottom: 3rem !important; } - .ps-md-0 { - padding-left: 0 !important; } - .ps-md-1 { - padding-left: 0.25rem !important; } - .ps-md-2 { - padding-left: 0.5rem !important; } - .ps-md-3 { - padding-left: 1rem !important; } - .ps-md-4 { - padding-left: 1.5rem !important; } - .ps-md-5 { - padding-left: 3rem !important; } - .gap-md-0 { - gap: 0 !important; } - .gap-md-1 { - gap: 0.25rem !important; } - .gap-md-2 { - gap: 0.5rem !important; } - .gap-md-3 { - gap: 1rem !important; } - .gap-md-4 { - gap: 1.5rem !important; } - .gap-md-5 { - gap: 3rem !important; } - .row-gap-md-0 { - row-gap: 0 !important; } - .row-gap-md-1 { - row-gap: 0.25rem !important; } - .row-gap-md-2 { - row-gap: 0.5rem !important; } - .row-gap-md-3 { - row-gap: 1rem !important; } - .row-gap-md-4 { - row-gap: 1.5rem !important; } - .row-gap-md-5 { - row-gap: 3rem !important; } - .column-gap-md-0 { - column-gap: 0 !important; } - .column-gap-md-1 { - column-gap: 0.25rem !important; } - .column-gap-md-2 { - column-gap: 0.5rem !important; } - .column-gap-md-3 { - column-gap: 1rem !important; } - .column-gap-md-4 { - column-gap: 1.5rem !important; } - .column-gap-md-5 { - column-gap: 3rem !important; } - .text-md-start { - text-align: left !important; } - .text-md-end { - text-align: right !important; } - .text-md-center { - text-align: center !important; } } - -@media (min-width: 992px) { - .float-lg-start { - float: left !important; } - .float-lg-end { - float: right !important; } - .float-lg-none { - float: none !important; } - .object-fit-lg-contain { - object-fit: contain !important; } - .object-fit-lg-cover { - object-fit: cover !important; } - .object-fit-lg-fill { - object-fit: fill !important; } - .object-fit-lg-scale { - object-fit: scale-down !important; } - .object-fit-lg-none { - object-fit: none !important; } - .d-lg-inline { - display: inline !important; } - .d-lg-inline-block { - display: inline-block !important; } - .d-lg-block { - display: block !important; } - .d-lg-grid { - display: grid !important; } - .d-lg-inline-grid { - display: inline-grid !important; } - .d-lg-table { - display: table !important; } - .d-lg-table-row { - display: table-row !important; } - .d-lg-table-cell { - display: table-cell !important; } - .d-lg-flex { - display: flex !important; } - .d-lg-inline-flex { - display: inline-flex !important; } - .d-lg-none { - display: none !important; } - .flex-lg-fill { - flex: 1 1 auto !important; } - .flex-lg-row { - flex-direction: row !important; } - .flex-lg-column { - flex-direction: column !important; } - .flex-lg-row-reverse { - flex-direction: row-reverse !important; } - .flex-lg-column-reverse { - flex-direction: column-reverse !important; } - .flex-lg-grow-0 { - flex-grow: 0 !important; } - .flex-lg-grow-1 { - flex-grow: 1 !important; } - .flex-lg-shrink-0 { - flex-shrink: 0 !important; } - .flex-lg-shrink-1 { - flex-shrink: 1 !important; } - .flex-lg-wrap { - flex-wrap: wrap !important; } - .flex-lg-nowrap { - flex-wrap: nowrap !important; } - .flex-lg-wrap-reverse { - flex-wrap: wrap-reverse !important; } - .justify-content-lg-start { - justify-content: flex-start !important; } - .justify-content-lg-end { - justify-content: flex-end !important; } - .justify-content-lg-center { - justify-content: center !important; } - .justify-content-lg-between { - justify-content: space-between !important; } - .justify-content-lg-around { - justify-content: space-around !important; } - .justify-content-lg-evenly { - justify-content: space-evenly !important; } - .align-items-lg-start { - align-items: flex-start !important; } - .align-items-lg-end { - align-items: flex-end !important; } - .align-items-lg-center { - align-items: center !important; } - .align-items-lg-baseline { - align-items: baseline !important; } - .align-items-lg-stretch { - align-items: stretch !important; } - .align-content-lg-start { - align-content: flex-start !important; } - .align-content-lg-end { - align-content: flex-end !important; } - .align-content-lg-center { - align-content: center !important; } - .align-content-lg-between { - align-content: space-between !important; } - .align-content-lg-around { - align-content: space-around !important; } - .align-content-lg-stretch { - align-content: stretch !important; } - .align-self-lg-auto { - align-self: auto !important; } - .align-self-lg-start { - align-self: flex-start !important; } - .align-self-lg-end { - align-self: flex-end !important; } - .align-self-lg-center { - align-self: center !important; } - .align-self-lg-baseline { - align-self: baseline !important; } - .align-self-lg-stretch { - align-self: stretch !important; } - .order-lg-first { - order: -1 !important; } - .order-lg-0 { - order: 0 !important; } - .order-lg-1 { - order: 1 !important; } - .order-lg-2 { - order: 2 !important; } - .order-lg-3 { - order: 3 !important; } - .order-lg-4 { - order: 4 !important; } - .order-lg-5 { - order: 5 !important; } - .order-lg-last { - order: 6 !important; } - .m-lg-0 { - margin: 0 !important; } - .m-lg-1 { - margin: 0.25rem !important; } - .m-lg-2 { - margin: 0.5rem !important; } - .m-lg-3 { - margin: 1rem !important; } - .m-lg-4 { - margin: 1.5rem !important; } - .m-lg-5 { - margin: 3rem !important; } - .m-lg-auto { - margin: auto !important; } - .mx-lg-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - .mx-lg-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - .mx-lg-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - .mx-lg-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - .mx-lg-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - .mx-lg-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - .mx-lg-auto { - margin-right: auto !important; - margin-left: auto !important; } - .my-lg-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; } - .my-lg-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; } - .my-lg-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; } - .my-lg-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; } - .my-lg-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - .my-lg-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; } - .my-lg-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - .mt-lg-0 { - margin-top: 0 !important; } - .mt-lg-1 { - margin-top: 0.25rem !important; } - .mt-lg-2 { - margin-top: 0.5rem !important; } - .mt-lg-3 { - margin-top: 1rem !important; } - .mt-lg-4 { - margin-top: 1.5rem !important; } - .mt-lg-5 { - margin-top: 3rem !important; } - .mt-lg-auto { - margin-top: auto !important; } - .me-lg-0 { - margin-right: 0 !important; } - .me-lg-1 { - margin-right: 0.25rem !important; } - .me-lg-2 { - margin-right: 0.5rem !important; } - .me-lg-3 { - margin-right: 1rem !important; } - .me-lg-4 { - margin-right: 1.5rem !important; } - .me-lg-5 { - margin-right: 3rem !important; } - .me-lg-auto { - margin-right: auto !important; } - .mb-lg-0 { - margin-bottom: 0 !important; } - .mb-lg-1 { - margin-bottom: 0.25rem !important; } - .mb-lg-2 { - margin-bottom: 0.5rem !important; } - .mb-lg-3 { - margin-bottom: 1rem !important; } - .mb-lg-4 { - margin-bottom: 1.5rem !important; } - .mb-lg-5 { - margin-bottom: 3rem !important; } - .mb-lg-auto { - margin-bottom: auto !important; } - .ms-lg-0 { - margin-left: 0 !important; } - .ms-lg-1 { - margin-left: 0.25rem !important; } - .ms-lg-2 { - margin-left: 0.5rem !important; } - .ms-lg-3 { - margin-left: 1rem !important; } - .ms-lg-4 { - margin-left: 1.5rem !important; } - .ms-lg-5 { - margin-left: 3rem !important; } - .ms-lg-auto { - margin-left: auto !important; } - .p-lg-0 { - padding: 0 !important; } - .p-lg-1 { - padding: 0.25rem !important; } - .p-lg-2 { - padding: 0.5rem !important; } - .p-lg-3 { - padding: 1rem !important; } - .p-lg-4 { - padding: 1.5rem !important; } - .p-lg-5 { - padding: 3rem !important; } - .px-lg-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - .px-lg-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - .px-lg-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - .px-lg-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - .px-lg-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - .px-lg-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - .py-lg-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - .py-lg-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - .py-lg-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - .py-lg-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - .py-lg-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - .py-lg-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - .pt-lg-0 { - padding-top: 0 !important; } - .pt-lg-1 { - padding-top: 0.25rem !important; } - .pt-lg-2 { - padding-top: 0.5rem !important; } - .pt-lg-3 { - padding-top: 1rem !important; } - .pt-lg-4 { - padding-top: 1.5rem !important; } - .pt-lg-5 { - padding-top: 3rem !important; } - .pe-lg-0 { - padding-right: 0 !important; } - .pe-lg-1 { - padding-right: 0.25rem !important; } - .pe-lg-2 { - padding-right: 0.5rem !important; } - .pe-lg-3 { - padding-right: 1rem !important; } - .pe-lg-4 { - padding-right: 1.5rem !important; } - .pe-lg-5 { - padding-right: 3rem !important; } - .pb-lg-0 { - padding-bottom: 0 !important; } - .pb-lg-1 { - padding-bottom: 0.25rem !important; } - .pb-lg-2 { - padding-bottom: 0.5rem !important; } - .pb-lg-3 { - padding-bottom: 1rem !important; } - .pb-lg-4 { - padding-bottom: 1.5rem !important; } - .pb-lg-5 { - padding-bottom: 3rem !important; } - .ps-lg-0 { - padding-left: 0 !important; } - .ps-lg-1 { - padding-left: 0.25rem !important; } - .ps-lg-2 { - padding-left: 0.5rem !important; } - .ps-lg-3 { - padding-left: 1rem !important; } - .ps-lg-4 { - padding-left: 1.5rem !important; } - .ps-lg-5 { - padding-left: 3rem !important; } - .gap-lg-0 { - gap: 0 !important; } - .gap-lg-1 { - gap: 0.25rem !important; } - .gap-lg-2 { - gap: 0.5rem !important; } - .gap-lg-3 { - gap: 1rem !important; } - .gap-lg-4 { - gap: 1.5rem !important; } - .gap-lg-5 { - gap: 3rem !important; } - .row-gap-lg-0 { - row-gap: 0 !important; } - .row-gap-lg-1 { - row-gap: 0.25rem !important; } - .row-gap-lg-2 { - row-gap: 0.5rem !important; } - .row-gap-lg-3 { - row-gap: 1rem !important; } - .row-gap-lg-4 { - row-gap: 1.5rem !important; } - .row-gap-lg-5 { - row-gap: 3rem !important; } - .column-gap-lg-0 { - column-gap: 0 !important; } - .column-gap-lg-1 { - column-gap: 0.25rem !important; } - .column-gap-lg-2 { - column-gap: 0.5rem !important; } - .column-gap-lg-3 { - column-gap: 1rem !important; } - .column-gap-lg-4 { - column-gap: 1.5rem !important; } - .column-gap-lg-5 { - column-gap: 3rem !important; } - .text-lg-start { - text-align: left !important; } - .text-lg-end { - text-align: right !important; } - .text-lg-center { - text-align: center !important; } } - -@media (min-width: 1200px) { - .float-xl-start { - float: left !important; } - .float-xl-end { - float: right !important; } - .float-xl-none { - float: none !important; } - .object-fit-xl-contain { - object-fit: contain !important; } - .object-fit-xl-cover { - object-fit: cover !important; } - .object-fit-xl-fill { - object-fit: fill !important; } - .object-fit-xl-scale { - object-fit: scale-down !important; } - .object-fit-xl-none { - object-fit: none !important; } - .d-xl-inline { - display: inline !important; } - .d-xl-inline-block { - display: inline-block !important; } - .d-xl-block { - display: block !important; } - .d-xl-grid { - display: grid !important; } - .d-xl-inline-grid { - display: inline-grid !important; } - .d-xl-table { - display: table !important; } - .d-xl-table-row { - display: table-row !important; } - .d-xl-table-cell { - display: table-cell !important; } - .d-xl-flex { - display: flex !important; } - .d-xl-inline-flex { - display: inline-flex !important; } - .d-xl-none { - display: none !important; } - .flex-xl-fill { - flex: 1 1 auto !important; } - .flex-xl-row { - flex-direction: row !important; } - .flex-xl-column { - flex-direction: column !important; } - .flex-xl-row-reverse { - flex-direction: row-reverse !important; } - .flex-xl-column-reverse { - flex-direction: column-reverse !important; } - .flex-xl-grow-0 { - flex-grow: 0 !important; } - .flex-xl-grow-1 { - flex-grow: 1 !important; } - .flex-xl-shrink-0 { - flex-shrink: 0 !important; } - .flex-xl-shrink-1 { - flex-shrink: 1 !important; } - .flex-xl-wrap { - flex-wrap: wrap !important; } - .flex-xl-nowrap { - flex-wrap: nowrap !important; } - .flex-xl-wrap-reverse { - flex-wrap: wrap-reverse !important; } - .justify-content-xl-start { - justify-content: flex-start !important; } - .justify-content-xl-end { - justify-content: flex-end !important; } - .justify-content-xl-center { - justify-content: center !important; } - .justify-content-xl-between { - justify-content: space-between !important; } - .justify-content-xl-around { - justify-content: space-around !important; } - .justify-content-xl-evenly { - justify-content: space-evenly !important; } - .align-items-xl-start { - align-items: flex-start !important; } - .align-items-xl-end { - align-items: flex-end !important; } - .align-items-xl-center { - align-items: center !important; } - .align-items-xl-baseline { - align-items: baseline !important; } - .align-items-xl-stretch { - align-items: stretch !important; } - .align-content-xl-start { - align-content: flex-start !important; } - .align-content-xl-end { - align-content: flex-end !important; } - .align-content-xl-center { - align-content: center !important; } - .align-content-xl-between { - align-content: space-between !important; } - .align-content-xl-around { - align-content: space-around !important; } - .align-content-xl-stretch { - align-content: stretch !important; } - .align-self-xl-auto { - align-self: auto !important; } - .align-self-xl-start { - align-self: flex-start !important; } - .align-self-xl-end { - align-self: flex-end !important; } - .align-self-xl-center { - align-self: center !important; } - .align-self-xl-baseline { - align-self: baseline !important; } - .align-self-xl-stretch { - align-self: stretch !important; } - .order-xl-first { - order: -1 !important; } - .order-xl-0 { - order: 0 !important; } - .order-xl-1 { - order: 1 !important; } - .order-xl-2 { - order: 2 !important; } - .order-xl-3 { - order: 3 !important; } - .order-xl-4 { - order: 4 !important; } - .order-xl-5 { - order: 5 !important; } - .order-xl-last { - order: 6 !important; } - .m-xl-0 { - margin: 0 !important; } - .m-xl-1 { - margin: 0.25rem !important; } - .m-xl-2 { - margin: 0.5rem !important; } - .m-xl-3 { - margin: 1rem !important; } - .m-xl-4 { - margin: 1.5rem !important; } - .m-xl-5 { - margin: 3rem !important; } - .m-xl-auto { - margin: auto !important; } - .mx-xl-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - .mx-xl-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - .mx-xl-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - .mx-xl-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - .mx-xl-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - .mx-xl-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - .mx-xl-auto { - margin-right: auto !important; - margin-left: auto !important; } - .my-xl-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; } - .my-xl-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; } - .my-xl-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; } - .my-xl-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; } - .my-xl-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - .my-xl-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; } - .my-xl-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - .mt-xl-0 { - margin-top: 0 !important; } - .mt-xl-1 { - margin-top: 0.25rem !important; } - .mt-xl-2 { - margin-top: 0.5rem !important; } - .mt-xl-3 { - margin-top: 1rem !important; } - .mt-xl-4 { - margin-top: 1.5rem !important; } - .mt-xl-5 { - margin-top: 3rem !important; } - .mt-xl-auto { - margin-top: auto !important; } - .me-xl-0 { - margin-right: 0 !important; } - .me-xl-1 { - margin-right: 0.25rem !important; } - .me-xl-2 { - margin-right: 0.5rem !important; } - .me-xl-3 { - margin-right: 1rem !important; } - .me-xl-4 { - margin-right: 1.5rem !important; } - .me-xl-5 { - margin-right: 3rem !important; } - .me-xl-auto { - margin-right: auto !important; } - .mb-xl-0 { - margin-bottom: 0 !important; } - .mb-xl-1 { - margin-bottom: 0.25rem !important; } - .mb-xl-2 { - margin-bottom: 0.5rem !important; } - .mb-xl-3 { - margin-bottom: 1rem !important; } - .mb-xl-4 { - margin-bottom: 1.5rem !important; } - .mb-xl-5 { - margin-bottom: 3rem !important; } - .mb-xl-auto { - margin-bottom: auto !important; } - .ms-xl-0 { - margin-left: 0 !important; } - .ms-xl-1 { - margin-left: 0.25rem !important; } - .ms-xl-2 { - margin-left: 0.5rem !important; } - .ms-xl-3 { - margin-left: 1rem !important; } - .ms-xl-4 { - margin-left: 1.5rem !important; } - .ms-xl-5 { - margin-left: 3rem !important; } - .ms-xl-auto { - margin-left: auto !important; } - .p-xl-0 { - padding: 0 !important; } - .p-xl-1 { - padding: 0.25rem !important; } - .p-xl-2 { - padding: 0.5rem !important; } - .p-xl-3 { - padding: 1rem !important; } - .p-xl-4 { - padding: 1.5rem !important; } - .p-xl-5 { - padding: 3rem !important; } - .px-xl-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - .px-xl-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - .px-xl-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - .px-xl-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - .px-xl-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - .px-xl-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - .py-xl-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - .py-xl-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - .py-xl-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - .py-xl-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - .py-xl-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - .py-xl-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - .pt-xl-0 { - padding-top: 0 !important; } - .pt-xl-1 { - padding-top: 0.25rem !important; } - .pt-xl-2 { - padding-top: 0.5rem !important; } - .pt-xl-3 { - padding-top: 1rem !important; } - .pt-xl-4 { - padding-top: 1.5rem !important; } - .pt-xl-5 { - padding-top: 3rem !important; } - .pe-xl-0 { - padding-right: 0 !important; } - .pe-xl-1 { - padding-right: 0.25rem !important; } - .pe-xl-2 { - padding-right: 0.5rem !important; } - .pe-xl-3 { - padding-right: 1rem !important; } - .pe-xl-4 { - padding-right: 1.5rem !important; } - .pe-xl-5 { - padding-right: 3rem !important; } - .pb-xl-0 { - padding-bottom: 0 !important; } - .pb-xl-1 { - padding-bottom: 0.25rem !important; } - .pb-xl-2 { - padding-bottom: 0.5rem !important; } - .pb-xl-3 { - padding-bottom: 1rem !important; } - .pb-xl-4 { - padding-bottom: 1.5rem !important; } - .pb-xl-5 { - padding-bottom: 3rem !important; } - .ps-xl-0 { - padding-left: 0 !important; } - .ps-xl-1 { - padding-left: 0.25rem !important; } - .ps-xl-2 { - padding-left: 0.5rem !important; } - .ps-xl-3 { - padding-left: 1rem !important; } - .ps-xl-4 { - padding-left: 1.5rem !important; } - .ps-xl-5 { - padding-left: 3rem !important; } - .gap-xl-0 { - gap: 0 !important; } - .gap-xl-1 { - gap: 0.25rem !important; } - .gap-xl-2 { - gap: 0.5rem !important; } - .gap-xl-3 { - gap: 1rem !important; } - .gap-xl-4 { - gap: 1.5rem !important; } - .gap-xl-5 { - gap: 3rem !important; } - .row-gap-xl-0 { - row-gap: 0 !important; } - .row-gap-xl-1 { - row-gap: 0.25rem !important; } - .row-gap-xl-2 { - row-gap: 0.5rem !important; } - .row-gap-xl-3 { - row-gap: 1rem !important; } - .row-gap-xl-4 { - row-gap: 1.5rem !important; } - .row-gap-xl-5 { - row-gap: 3rem !important; } - .column-gap-xl-0 { - column-gap: 0 !important; } - .column-gap-xl-1 { - column-gap: 0.25rem !important; } - .column-gap-xl-2 { - column-gap: 0.5rem !important; } - .column-gap-xl-3 { - column-gap: 1rem !important; } - .column-gap-xl-4 { - column-gap: 1.5rem !important; } - .column-gap-xl-5 { - column-gap: 3rem !important; } - .text-xl-start { - text-align: left !important; } - .text-xl-end { - text-align: right !important; } - .text-xl-center { - text-align: center !important; } } - -@media (min-width: 1400px) { - .float-xxl-start { - float: left !important; } - .float-xxl-end { - float: right !important; } - .float-xxl-none { - float: none !important; } - .object-fit-xxl-contain { - object-fit: contain !important; } - .object-fit-xxl-cover { - object-fit: cover !important; } - .object-fit-xxl-fill { - object-fit: fill !important; } - .object-fit-xxl-scale { - object-fit: scale-down !important; } - .object-fit-xxl-none { - object-fit: none !important; } - .d-xxl-inline { - display: inline !important; } - .d-xxl-inline-block { - display: inline-block !important; } - .d-xxl-block { - display: block !important; } - .d-xxl-grid { - display: grid !important; } - .d-xxl-inline-grid { - display: inline-grid !important; } - .d-xxl-table { - display: table !important; } - .d-xxl-table-row { - display: table-row !important; } - .d-xxl-table-cell { - display: table-cell !important; } - .d-xxl-flex { - display: flex !important; } - .d-xxl-inline-flex { - display: inline-flex !important; } - .d-xxl-none { - display: none !important; } - .flex-xxl-fill { - flex: 1 1 auto !important; } - .flex-xxl-row { - flex-direction: row !important; } - .flex-xxl-column { - flex-direction: column !important; } - .flex-xxl-row-reverse { - flex-direction: row-reverse !important; } - .flex-xxl-column-reverse { - flex-direction: column-reverse !important; } - .flex-xxl-grow-0 { - flex-grow: 0 !important; } - .flex-xxl-grow-1 { - flex-grow: 1 !important; } - .flex-xxl-shrink-0 { - flex-shrink: 0 !important; } - .flex-xxl-shrink-1 { - flex-shrink: 1 !important; } - .flex-xxl-wrap { - flex-wrap: wrap !important; } - .flex-xxl-nowrap { - flex-wrap: nowrap !important; } - .flex-xxl-wrap-reverse { - flex-wrap: wrap-reverse !important; } - .justify-content-xxl-start { - justify-content: flex-start !important; } - .justify-content-xxl-end { - justify-content: flex-end !important; } - .justify-content-xxl-center { - justify-content: center !important; } - .justify-content-xxl-between { - justify-content: space-between !important; } - .justify-content-xxl-around { - justify-content: space-around !important; } - .justify-content-xxl-evenly { - justify-content: space-evenly !important; } - .align-items-xxl-start { - align-items: flex-start !important; } - .align-items-xxl-end { - align-items: flex-end !important; } - .align-items-xxl-center { - align-items: center !important; } - .align-items-xxl-baseline { - align-items: baseline !important; } - .align-items-xxl-stretch { - align-items: stretch !important; } - .align-content-xxl-start { - align-content: flex-start !important; } - .align-content-xxl-end { - align-content: flex-end !important; } - .align-content-xxl-center { - align-content: center !important; } - .align-content-xxl-between { - align-content: space-between !important; } - .align-content-xxl-around { - align-content: space-around !important; } - .align-content-xxl-stretch { - align-content: stretch !important; } - .align-self-xxl-auto { - align-self: auto !important; } - .align-self-xxl-start { - align-self: flex-start !important; } - .align-self-xxl-end { - align-self: flex-end !important; } - .align-self-xxl-center { - align-self: center !important; } - .align-self-xxl-baseline { - align-self: baseline !important; } - .align-self-xxl-stretch { - align-self: stretch !important; } - .order-xxl-first { - order: -1 !important; } - .order-xxl-0 { - order: 0 !important; } - .order-xxl-1 { - order: 1 !important; } - .order-xxl-2 { - order: 2 !important; } - .order-xxl-3 { - order: 3 !important; } - .order-xxl-4 { - order: 4 !important; } - .order-xxl-5 { - order: 5 !important; } - .order-xxl-last { - order: 6 !important; } - .m-xxl-0 { - margin: 0 !important; } - .m-xxl-1 { - margin: 0.25rem !important; } - .m-xxl-2 { - margin: 0.5rem !important; } - .m-xxl-3 { - margin: 1rem !important; } - .m-xxl-4 { - margin: 1.5rem !important; } - .m-xxl-5 { - margin: 3rem !important; } - .m-xxl-auto { - margin: auto !important; } - .mx-xxl-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - .mx-xxl-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - .mx-xxl-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - .mx-xxl-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - .mx-xxl-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - .mx-xxl-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - .mx-xxl-auto { - margin-right: auto !important; - margin-left: auto !important; } - .my-xxl-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; } - .my-xxl-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; } - .my-xxl-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; } - .my-xxl-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; } - .my-xxl-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - .my-xxl-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; } - .my-xxl-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - .mt-xxl-0 { - margin-top: 0 !important; } - .mt-xxl-1 { - margin-top: 0.25rem !important; } - .mt-xxl-2 { - margin-top: 0.5rem !important; } - .mt-xxl-3 { - margin-top: 1rem !important; } - .mt-xxl-4 { - margin-top: 1.5rem !important; } - .mt-xxl-5 { - margin-top: 3rem !important; } - .mt-xxl-auto { - margin-top: auto !important; } - .me-xxl-0 { - margin-right: 0 !important; } - .me-xxl-1 { - margin-right: 0.25rem !important; } - .me-xxl-2 { - margin-right: 0.5rem !important; } - .me-xxl-3 { - margin-right: 1rem !important; } - .me-xxl-4 { - margin-right: 1.5rem !important; } - .me-xxl-5 { - margin-right: 3rem !important; } - .me-xxl-auto { - margin-right: auto !important; } - .mb-xxl-0 { - margin-bottom: 0 !important; } - .mb-xxl-1 { - margin-bottom: 0.25rem !important; } - .mb-xxl-2 { - margin-bottom: 0.5rem !important; } - .mb-xxl-3 { - margin-bottom: 1rem !important; } - .mb-xxl-4 { - margin-bottom: 1.5rem !important; } - .mb-xxl-5 { - margin-bottom: 3rem !important; } - .mb-xxl-auto { - margin-bottom: auto !important; } - .ms-xxl-0 { - margin-left: 0 !important; } - .ms-xxl-1 { - margin-left: 0.25rem !important; } - .ms-xxl-2 { - margin-left: 0.5rem !important; } - .ms-xxl-3 { - margin-left: 1rem !important; } - .ms-xxl-4 { - margin-left: 1.5rem !important; } - .ms-xxl-5 { - margin-left: 3rem !important; } - .ms-xxl-auto { - margin-left: auto !important; } - .p-xxl-0 { - padding: 0 !important; } - .p-xxl-1 { - padding: 0.25rem !important; } - .p-xxl-2 { - padding: 0.5rem !important; } - .p-xxl-3 { - padding: 1rem !important; } - .p-xxl-4 { - padding: 1.5rem !important; } - .p-xxl-5 { - padding: 3rem !important; } - .px-xxl-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - .px-xxl-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - .px-xxl-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - .px-xxl-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - .px-xxl-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - .px-xxl-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - .py-xxl-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - .py-xxl-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - .py-xxl-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - .py-xxl-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - .py-xxl-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - .py-xxl-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - .pt-xxl-0 { - padding-top: 0 !important; } - .pt-xxl-1 { - padding-top: 0.25rem !important; } - .pt-xxl-2 { - padding-top: 0.5rem !important; } - .pt-xxl-3 { - padding-top: 1rem !important; } - .pt-xxl-4 { - padding-top: 1.5rem !important; } - .pt-xxl-5 { - padding-top: 3rem !important; } - .pe-xxl-0 { - padding-right: 0 !important; } - .pe-xxl-1 { - padding-right: 0.25rem !important; } - .pe-xxl-2 { - padding-right: 0.5rem !important; } - .pe-xxl-3 { - padding-right: 1rem !important; } - .pe-xxl-4 { - padding-right: 1.5rem !important; } - .pe-xxl-5 { - padding-right: 3rem !important; } - .pb-xxl-0 { - padding-bottom: 0 !important; } - .pb-xxl-1 { - padding-bottom: 0.25rem !important; } - .pb-xxl-2 { - padding-bottom: 0.5rem !important; } - .pb-xxl-3 { - padding-bottom: 1rem !important; } - .pb-xxl-4 { - padding-bottom: 1.5rem !important; } - .pb-xxl-5 { - padding-bottom: 3rem !important; } - .ps-xxl-0 { - padding-left: 0 !important; } - .ps-xxl-1 { - padding-left: 0.25rem !important; } - .ps-xxl-2 { - padding-left: 0.5rem !important; } - .ps-xxl-3 { - padding-left: 1rem !important; } - .ps-xxl-4 { - padding-left: 1.5rem !important; } - .ps-xxl-5 { - padding-left: 3rem !important; } - .gap-xxl-0 { - gap: 0 !important; } - .gap-xxl-1 { - gap: 0.25rem !important; } - .gap-xxl-2 { - gap: 0.5rem !important; } - .gap-xxl-3 { - gap: 1rem !important; } - .gap-xxl-4 { - gap: 1.5rem !important; } - .gap-xxl-5 { - gap: 3rem !important; } - .row-gap-xxl-0 { - row-gap: 0 !important; } - .row-gap-xxl-1 { - row-gap: 0.25rem !important; } - .row-gap-xxl-2 { - row-gap: 0.5rem !important; } - .row-gap-xxl-3 { - row-gap: 1rem !important; } - .row-gap-xxl-4 { - row-gap: 1.5rem !important; } - .row-gap-xxl-5 { - row-gap: 3rem !important; } - .column-gap-xxl-0 { - column-gap: 0 !important; } - .column-gap-xxl-1 { - column-gap: 0.25rem !important; } - .column-gap-xxl-2 { - column-gap: 0.5rem !important; } - .column-gap-xxl-3 { - column-gap: 1rem !important; } - .column-gap-xxl-4 { - column-gap: 1.5rem !important; } - .column-gap-xxl-5 { - column-gap: 3rem !important; } - .text-xxl-start { - text-align: left !important; } - .text-xxl-end { - text-align: right !important; } - .text-xxl-center { - text-align: center !important; } } - -@media (min-width: 1200px) { - .fs-1 { - font-size: 2.5rem !important; } - .fs-2 { - font-size: 2rem !important; } - .fs-3 { - font-size: 1.75rem !important; } - .fs-4 { - font-size: 1.5rem !important; } } - -@media print { - .d-print-inline { - display: inline !important; } - .d-print-inline-block { - display: inline-block !important; } - .d-print-block { - display: block !important; } - .d-print-grid { - display: grid !important; } - .d-print-inline-grid { - display: inline-grid !important; } - .d-print-table { - display: table !important; } - .d-print-table-row { - display: table-row !important; } - .d-print-table-cell { - display: table-cell !important; } - .d-print-flex { - display: flex !important; } - .d-print-inline-flex { - display: inline-flex !important; } - .d-print-none { - display: none !important; } } - -html { - font-family: "Poppins", sans-serif; - font-size: 1.125rem; - font-weight: 400; - line-height: 1.75; - scroll-behavior: smooth; } - @media (max-width: 991px) { - html { - font-size: 1rem; } } -body { - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; } - -p { - margin-bottom: 0.25rem; } - -ul { - margin-bottom: 0; } - -a, -a:hover, -a:focus { - text-decoration: none; } - -a, -button, -select { - cursor: pointer; - transition: 0.2s ease; } - a:focus, - button:focus, - select:focus { - outline: 0; } - -a:hover { - color: #18b0a2; } - -h1, .h1, -h2, -.h2, -h3, -.h3, -h4, -.h4, -h5, -.h5 { - font-family: "Poppins", sans-serif; - font-weight: 700; - color: #fff; } - -small, -.small { - font-size: 85%; } -h5, -.h5 { - font-size: 25.4016px; - line-height: calc(2px + 2ex + 2px); - margin-bottom: 0.65em; } - @media (max-width: 991px) { - h5:not(h5, .h5, h6, .h6), - .h5:not(h5, .h5, h6, .h6) { - font-size: calc(25.4016px * 0.9); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h5:not(h5, .h5, h6, .h6), - .h5:not(h5, .h5, h6, .h6) { - font-size: calc(25.4016px * 0.8); } } - @media (max-width: 991px) { - h5, - .h5 { - font-size: calc(25.4016px * 0.95); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h5, - .h5 { - font-size: calc(25.4016px * 0.9); } } -h4, -.h4 { - font-size: 32.006016px; - line-height: calc(2px + 2ex + 2px); - margin-bottom: 0.65em; } - @media (max-width: 991px) { - h4:not(h5, .h5, h6, .h6), - .h4:not(h5, .h5, h6, .h6) { - font-size: calc(32.006016px * 0.9); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h4:not(h5, .h5, h6, .h6), - .h4:not(h5, .h5, h6, .h6) { - font-size: calc(32.006016px * 0.8); } } - @media (max-width: 991px) { - h4, - .h4 { - font-size: calc(32.006016px * 0.95); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h4, - .h4 { - font-size: calc(32.006016px * 0.9); } } -h3, -.h3 { - font-size: 40.32758016px; - line-height: calc(2px + 2ex + 2px); - margin-bottom: 0.65em; } - @media (max-width: 991px) { - h3:not(h5, .h5, h6, .h6), - .h3:not(h5, .h5, h6, .h6) { - font-size: calc(40.32758016px * 0.9); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h3:not(h5, .h5, h6, .h6), - .h3:not(h5, .h5, h6, .h6) { - font-size: calc(40.32758016px * 0.8); } } - @media (max-width: 991px) { - h3, - .h3 { - font-size: calc(40.32758016px * 0.95); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h3, - .h3 { - font-size: calc(40.32758016px * 0.9); } } -h2, -.h2 { - font-size: 50.812751px; - line-height: calc(2px + 2ex + 2px); - margin-bottom: 0.65em; } - @media (max-width: 991px) { - h2:not(h5, .h5, h6, .h6), - .h2:not(h5, .h5, h6, .h6) { - font-size: calc(50.812751px * 0.9); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h2:not(h5, .h5, h6, .h6), - .h2:not(h5, .h5, h6, .h6) { - font-size: calc(50.812751px * 0.8); } } - @media (max-width: 991px) { - h2, - .h2 { - font-size: calc(50.812751px * 0.95); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h2, - .h2 { - font-size: calc(50.812751px * 0.9); } } -h1, -.h1 { - font-size: 64.02406626px; - line-height: calc(2px + 2ex + 2px); - margin-bottom: 0.65em; } - @media (max-width: 991px) { - h1:not(h5, .h5, h6, .h6), - .h1:not(h5, .h5, h6, .h6) { - font-size: calc(64.02406626px * 0.9); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h1:not(h5, .h5, h6, .h6), - .h1:not(h5, .h5, h6, .h6) { - font-size: calc(64.02406626px * 0.8); } } - @media (max-width: 991px) { - h1, - .h1 { - font-size: calc(64.02406626px * 0.95); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h1, - .h1 { - font-size: calc(64.02406626px * 0.9); } } -html.light { - color: #555; } - html.light h1, html.light .h1, - html.light h2, - html.light .h2, - html.light h3, - html.light .h3, - html.light h4, - html.light .h4, - html.light h5, - html.light .h5 { - color: #222222; } - -/* Button style */ -.btn { - font-size: 0.9rem; - padding: 0.7rem 1.25rem; - position: relative; - overflow: hidden; - z-index: 1; - transition: 0.3s; } - .btn:hover, .btn:active, .btn.active, .btn:focus, .btn.focus { - outline: 0; - box-shadow: none !important; - background-color: transparent !important; } - -.btn-primary { - color: #fff; - border-color: #18b0a2 !important; - background-color: #18b0a2; } - .btn-primary:hover, .btn-primary:active, .btn-primary.active, .btn-primary:focus, .btn-primary.focus { - color: #fff; - border-color: #18b0a2 !important; - background-color: #18b0a2 !important; } - .btn-primary:hover::before, .btn-primary:active::before, .btn-primary.active::before, .btn-primary:focus::before, .btn-primary.focus::before { - height: 200%; - bottom: -25px; } - .btn-primary::before { - content: ""; - width: 100%; - height: 100%; - position: absolute; - bottom: -70px; - left: 0; - z-index: -1; - transition: 0.35s cubic-bezier(0.65, 0.05, 0.36, 1); - background-color: rgba(25, 31, 39, 0.2); - transform: skewY(10deg); } - -.btn-outline-primary { - background-color: transparent; - color: #18b0a2; - border-color: rgba(24, 176, 162, 0.2) !important; } - .btn-outline-primary:hover, .btn-outline-primary:active, .btn-outline-primary.active, .btn-outline-primary:focus, .btn-outline-primary.focus { - color: #18b0a2 !important; - border-color: rgba(24, 176, 162, 0.4) !important; } - .btn-outline-primary:hover::before, .btn-outline-primary:active::before, .btn-outline-primary.active::before, .btn-outline-primary:focus::before, .btn-outline-primary.focus::before { - height: 200%; - bottom: -25px; } - .btn-outline-primary::before { - content: ""; - width: 100%; - height: 100%; - position: absolute; - bottom: -70px; - left: 0; - z-index: -1; - transition: 0.35s cubic-bezier(0.65, 0.05, 0.36, 1); - background-color: rgba(24, 176, 162, 0.1); - transform: skewY(10deg); } - -.dark { - color-scheme: dark; } - -.light { - color-scheme: light; } - -::-webkit-scrollbar { - width: 10px; } - -::-webkit-scrollbar-track { - background: transparent; } - -::-webkit-scrollbar-thumb { - background: #313847; - border-radius: 8px; } - -::-webkit-scrollbar-thumb:hover { - background: #3f4759; } - -.dark body { - color: #bbb; - background-color: #0e1015; } - -.light body { - color: #555 !important; - background-color: #FFFFFF; } - -main { - width: calc(100% - 320px); - margin-left: auto; } - @media (max-width: 1199px) { - main { - width: 100%; } } - @media (max-width: 991px) { - main { - width: auto; } } -footer { - padding-top: 2rem; } - -.section { - padding-top: 4rem; - padding-bottom: 4rem; } - @media (max-width: 767px) { - .section { - padding-top: 3rem; - padding-bottom: 3rem; } } -.section-title { - margin-bottom: 4rem; } - @media (max-width: 767px) { - .section-title { - margin-bottom: 2.5rem; } } - .section-title h1 strong, .section-title .h1 strong, - .section-title h2 strong, - .section-title .h2 strong, - .section-title h3 strong, - .section-title .h3 strong { - color: #18b0a2; } - .section-title h2, .section-title .h2 { - margin: auto; - width: fit-content; - text-align: center; - position: relative; - font-weight: 500; } - @media (max-width: 767px) { - .section-title h2, .section-title .h2 { - padding-left: 40px; - font-size: 1.6rem !important; - text-align: start; - margin: 0; } } - .section-title h2::before, .section-title .h2::before, .section-title h2::after, .section-title .h2::after { - content: "⭓"; - font-weight: bold; - position: absolute; - color: #18b0a2; - letter-spacing: 2px; - left: -55px; - top: 50%; - line-height: 0; - font-size: 85%; } - @media (max-width: 767px) { - .section-title h2::before, .section-title .h2::before, .section-title h2::after, .section-title .h2::after { - left: 0; } } - .section-title h2::after, .section-title .h2::after { - left: auto; - right: -55px; } - @media (max-width: 767px) { - .section-title h2::after, .section-title .h2::after { - display: none; } } - .section-title .sub-title { - font-size: 1rem; - padding: 20px 0px; - margin-top: 10px; - text-align: center; } - @media (max-width: 575px) { - .section-title .sub-title { - text-align: start; } } -.social-links a { - width: 40px; - height: 40px; - line-height: 40px; - text-align: center; - background-color: transparent !important; - color: #eee !important; - border: 1px solid rgba(24, 176, 162, 0.15) !important; - transition: all 0.3s; } - .social-links a:hover { - background-color: #18b0a2 !important; - color: #fff !important; - border-color: transparent !important; } - -.light .social-links a { - color: #222 !important; } - .light .social-links a:hover { - color: #fff !important; } - -.fw-medium { - font-weight: 500; } - -.bg-dark { - background-color: #151923 !important; } - -.text-primary { - color: #18b0a2 !important; } - -.bg-primary { - background-color: #18b0a2 !important; } - -.bg-primary-soft { - background-color: rgba(24, 176, 162, 0.2) !important; } - -.light .text-white { - color: #222 !important; } - -.light .bg-primary-soft { - background-color: rgba(24, 176, 162, 0.1) !important; } - -.light .bg-dark { - background-color: #f6f6f6 !important; } - -.form-control { - padding: 0.6rem 1rem !important; - color: #fff !important; - border: 1px solid rgba(24, 176, 162, 0.15) !important; - box-shadow: none !important; - background-color: #191f27 !important; } - .form-control:focus { - border-color: rgba(24, 176, 162, 0.8) !important; } - -.light .form-control { - color: #222 !important; - background-color: #eee !important; } - -textarea { - resize: none; } - -.back-to-top { - position: fixed; - right: 25px; - bottom: 15px; - width: 46px; - height: 46px; - z-index: 50; - visibility: visible; - transform: translateY(30px); - transition: all 0.2s ease-out; - background-color: rgba(255, 255, 255, 0.1); - opacity: 0; - color: #fff; } - @media (max-width: 991px) { - .back-to-top { - background-color: #18b0a2; } } - @media (max-width: 767px) { - .back-to-top { - right: 10px; } } - .back-to-top.active { - transform: translateY(-10px); - opacity: 1; } - .back-to-top:hover { - background-color: rgba(24, 176, 162, 0.15) !important; } - -.light .back-to-top { - background-color: rgba(34, 34, 34, 0.1); - color: #222; } - @media (max-width: 991px) { - .light .back-to-top { - color: #fff; - background-color: #18b0a2; } } -.content h1, -.content .h1, -.content h2, -.content .h2, -.content h3, -.content .h3, -.content h4, -.content .h4, -.content h5, -.content .h5 { - font-weight: 400; } - -.content p { - margin-bottom: 1rem !important; } - -.content a { - color: #959595; } - .content a:hover { - color: #18b0a2; } - -.content img { - border-radius: 6px; } - -.content ol, -.content ul { - padding-left: 1.5rem; } - .content ol li, - .content ul li { - margin-bottom: 0.7rem; } - -.content ul { - padding-left: 0; - margin-bottom: 1.5rem; - list-style-type: none; } - .content ul li { - padding-left: 1.5rem; - position: relative; } - .content ul li::before { - position: absolute; - content: ""; - height: 0.5rem; - width: 0.5rem; - border-radius: 50%; - background-color: #18b0a2; - left: 3px; - top: 0.5rem; } - -.content table { - width: 100%; - max-width: 100%; - margin-bottom: 1rem; - border-radius: 6px; - overflow: hidden; } - -.content table td, -.content table th { - padding: 0.75rem; - vertical-align: top; - margin-bottom: 0; } - -.content tr:not(:last-child) { - border-bottom: 1px solid rgba(24, 176, 162, 0.15); } - -.content th { - font-weight: 500; } - -.content thead { - background-color: #191f27; - margin-bottom: 0; } - .content thead tr { - border-bottom: 1px solid rgba(24, 176, 162, 0.15); } - -.content tbody { - background-color: #151923; - margin-bottom: 0; } - -.content .notices p { - border-radius: 5px; - color: #191f27; } - .content .notices p::before { - content: "⭓"; - border: 0px !important; } - -.content .accordion-item { - border: 0; } - -.content .accordion-button { - padding: 0.7rem 1.25rem; - color: #bbb; - background-color: #eee; } - .content .accordion-button::after { - background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 16 16%22 fill=%22%23000000%22%3E%3Cpath fill-rule=%22evenodd%22 d=%22M1.646 4.646a.5.5.0 01.708.0L8 10.293l5.646-5.647a.5.5.0 01.708.708l-6 6a.5.5.0 01-.708.0l-6-6a.5.5.0 010-.708z%22/%3E%3C/svg%3E"); } - .content .accordion-button:focus { - border-color: inherit; - box-shadow: none; } - .content .accordion-button:not(.collapsed) { - color: #bbb; - box-shadow: none; } - -.content blockquote { - color: #eee; - padding: 1.2rem 30px; - border: 1px solid rgba(24, 176, 162, 0.4); - border-left: 3px solid rgba(24, 176, 162, 0.8); - margin: 2rem 0; - background: transparent; - font-weight: 400; } - .content blockquote p { - margin-bottom: 0 !important; } - .content blockquote cite { - display: inline-block; - margin-top: 1rem; } - -.content pre { - display: block; - padding: 20px; - margin: 0.7rem 0; - white-space: pre-wrap; - border-radius: 6px; } - -.content code { - margin-bottom: 0 !important; - font-size: 100%; } - -.content iframe { - border-radius: 6px; } - -.light .content thead { - background-color: #eee; } - -.light .content tbody { - background-color: #f6f6f6; } - -.dark .card { - color: #bbb; } - -.light .card { - color: #555; } - -#sidebarContent { - background-color: #191f27; - padding: 45px 45px 0 45px; - max-width: 320px; - overflow-y: auto; } - #sidebarContent::-webkit-scrollbar-thumb { - background: transparent; } - #sidebarContent:hover::-webkit-scrollbar-thumb { - background: #2b313e; } - @media (max-width: 1199px) { - #sidebarContent.hidden { - top: 0px; - max-width: 100%; - left: -100%; - max-width: 300px; - padding-left: 20px; - transition: all 0.4s ease-out; - z-index: 777; } - #sidebarContent.hidden.active { - left: 0px; } } - #sidebarContent .navbar-nav .nav-item a { - font-weight: 400; - font-size: 1.1rem; - margin-bottom: 10px; - color: rgba(255, 255, 255, 0.75); - transition: color 0.3s; } - #sidebarContent .navbar-nav .nav-item a i { - font-size: 0.9em; - color: rgba(255, 255, 255, 0.5); - transition: 0.3s; } - #sidebarContent .navbar-nav .nav-item a.nav-link.active, - #sidebarContent .navbar-nav .nav-item a.nav-link:hover { - color: #fff; } - #sidebarContent .navbar-nav .nav-item a.nav-link.active i, - #sidebarContent .navbar-nav .nav-item a.nav-link:hover i { - color: #fff; } - -.theme-switcher { - position: relative; } - .theme-switcher span { - position: absolute; - height: 30px; - width: 50px; - border-radius: 30px; - background-color: #222; - cursor: pointer; - z-index: 99; - transform: rotateZ(180deg) rotateX(180deg); - transform-origin: center; } - .theme-switcher span::before { - position: absolute; - left: 5px; - bottom: 5px; - height: 20px; - width: 20px; - content: ""; - border-radius: 50%; - background-color: #fff; - transition: 0.3s; } - .theme-switcher #toggler { - opacity: 0; - display: none; - touch-action: none; } - .theme-switcher #toggler:checked ~ span { - background-color: #2d3846; } - .theme-switcher #toggler:checked ~ span::before { - background-color: #2d3846; - box-shadow: inset -8px -3px 0 0px #fff; - transform: translate(18px, 0px); } - -.navbar-toggler { - background-color: rgba(255, 255, 255, 0.2); - transition: background-color 0.3s; - padding: 2px; - position: fixed; - top: 30px; - right: 25px; - z-index: 9999; } - @media (max-width: 991px) { - .navbar-toggler { - background-color: #18b0a2; } } - @media (max-width: 767px) { - .navbar-toggler { - right: 10px; } } - .navbar-toggler:focus { - box-shadow: none; } - .navbar-toggler label { - display: block; - cursor: pointer; - position: absolute; - width: 40px; - height: 40px; - bottom: 0; - right: 0; } - .navbar-toggler label svg { - transform: scale(1.5); } - .navbar-toggler.active .line--1, - .navbar-toggler.active .line--3 { - stroke-dasharray: 22.627416998 126.64183044433594; } - .navbar-toggler.active .line--2 { - stroke-dasharray: 0 126.64183044433594; } - .navbar-toggler.active .line--1, - .navbar-toggler.active .line--3 { - stroke-dashoffset: -94.1149185097; } - .navbar-toggler.active .line--2 { - stroke-dashoffset: -50; } - .navbar-toggler path { - fill: none; - stroke: white; - stroke-width: 3; - stroke-linecap: round; - stroke-linejoin: round; - stroke-dasharray: 24 126.64183044433594; - stroke-dashoffset: -38; - transition: all 0.4s cubic-bezier(0.645, 0.045, 0.355, 1); } - -.navbar-show { - overflow-y: hidden; } - -.tf-backdrop { - display: none !important; } - @media (max-width: 1199px) { - .tf-backdrop { - display: block !important; } } -html.light #sidebarContent { - background-color: rgba(188, 188, 188, 0.2) !important; } - html.light #sidebarContent:hover::-webkit-scrollbar-thumb { - background: rgba(188, 188, 188, 0.7); } - -html.light .navbar-nav .nav-item a { - color: rgba(34, 34, 34, 0.6) !important; } - html.light .navbar-nav .nav-item a i { - color: rgba(34, 34, 34, 0.4) !important; } - -html.light .navbar-nav .nav-item a.nav-link.active, -html.light .navbar-nav .nav-item a.nav-link:hover { - color: #222 !important; } - html.light .navbar-nav .nav-item a.nav-link.active i, - html.light .navbar-nav .nav-item a.nav-link:hover i { - color: #222 !important; } - -#banner { - padding: 8rem 0; } - @media (max-width: 767px) { - #banner { - padding-top: 5rem; - padding-bottom: 5rem; } } - #banner::after { - content: ""; - position: absolute; - width: 690px; - height: 690px; - left: 5%; - top: -30%; - background: linear-gradient(180deg, rgba(250, 209, 65, 0.5) 0%, rgba(0, 71, 255, 0.2) 33.85%, rgba(24, 176, 162, 0.7) 67.71%, rgba(233, 65, 0, 0.5) 100%); - opacity: 0.4; - filter: blur(75px); - z-index: -1; } - -.image-block { - border: 1px solid rgba(24, 176, 162, 0.2); - padding: 20px; } - @media (max-width: 1199px) { - .image-block { - padding: 10px; } } - @media (max-width: 991px) { - .image-block { - border: 0; - padding: 0; } - .image-block img { - padding: 0; - height: 160px; - width: 150px !important; - object-fit: cover; - object-position: top; } } -.additional-info { - margin-bottom: 35px; } - .additional-info tr { - display: block; - margin-bottom: 7px; } - .additional-info tr td { - position: relative; - vertical-align: top; } - .additional-info tr td:first-child { - width: 130px; } - .additional-info tr td:last-child { - padding-left: 30px; } - @media (max-width: 400px) { - .additional-info tr td { - word-break: break-word; - font-size: 0.9rem; } } - .additional-info tr td:nth-child(2)::before { - content: ":"; - position: absolute; - left: 0px; - font-weight: bold; - opacity: 0.75; } - -#skill { - z-index: 1; } - #skill::before { - content: ""; - position: absolute; - width: 600px; - height: 400px; - right: -10%; - bottom: 30%; - background: linear-gradient(180deg, rgba(250, 209, 65, 0.5) 0%, rgba(0, 71, 255, 0.2) 33.85%, #18b0a2 67.71%, rgba(233, 65, 0, 0.5) 100%); - opacity: 0.4; - filter: blur(200px); - z-index: -1; - pointer-events: none; } - #skill .progress-item > div > span:last-child { - color: #18b0a2; } - #skill .progress-item .progress { - height: 10px; - background-color: rgba(24, 176, 162, 0.3); } - #skill .progress-item .progress .progress-bar { - background-color: #18b0a2; - height: 100%; - line-height: 10px; - font-size: 0; - padding: 0; } - @media (max-width: 400px) { - #skill .progress-item .progress { - height: 10px; } } -#resume { - z-index: 1; } - #resume::before { - content: ""; - position: absolute; - width: 400px; - height: 400px; - left: 5%; - bottom: 30%; - background-color: #18b0a2; - background-image: radial-gradient(at 81% 18%, #eedc77 0px, transparent 50%), radial-gradient(at 71% 74%, #ede882 0px, transparent 50%), radial-gradient(at 63% 28%, #da5885 0px, transparent 50%), radial-gradient(at 26% 98%, #96bbe9 0px, transparent 50%), radial-gradient(at 99% 53%, #9191e3 0px, transparent 50%), radial-gradient(at 78% 85%, #bd8ced 0px, transparent 50%), radial-gradient(at 15% 55%, #4ef4a6 0px, transparent 50%); - opacity: 0.4; - filter: blur(200px); - z-index: -1; - pointer-events: none; } - #resume .divider { - padding: 0; - position: absolute; - width: 1px; - height: calc(100% - 180px); - background-color: rgba(24, 176, 162, 0.2); - bottom: 40px; - left: 50%; } - #resume .divider::after, #resume .divider::before { - content: ""; - position: absolute; - width: 20px; - height: 20px; - border: 1px solid rgba(24, 176, 162, 0.3); - border-radius: 50%; - bottom: -30px; - left: -10px; } - #resume .divider::before { - bottom: auto; - top: -30px; } - #resume .card { - padding: 30px; - color: #bbb; } - #resume .card .icon { - height: 50px; - width: 50px; - text-align: center; - line-height: 50px; - color: #18b0a2; - background-color: rgba(24, 176, 162, 0.15); - border-top-left-radius: 0 !important; - border-top-right-radius: 0 !important; } - #resume .card .card-body p { - font-size: 1rem; } - #resume .card .card-body strong { - font-weight: normal; - color: #18b0a2; } - -.projects, -.blog-wrapper { - column-count: 3; - column-gap: 1.5rem; } - @media (max-width: 991px) { - .projects, - .blog-wrapper { - column-count: 2; } } - @media (max-width: 767px) { - .projects, - .blog-wrapper { - column-count: 1; } } -.meta-link:hover { - color: #18b0a2 !important; - text-decoration: underline !important; } - -.project-item .card, -.blog-post .card { - border: 1px solid rgba(24, 176, 162, 0.15); - overflow: hidden; } - .project-item .card > a:first-child img, - .blog-post .card > a:first-child img { - transition: all 0.2s; - display: block; - border: none; } - .project-item .card > a:first-child:hover img, - .blog-post .card > a:first-child:hover img { - transform: scale(1.02); } - .project-item .card .card-title, - .blog-post .card .card-title { - margin-bottom: 0.8rem; } - .project-item .card .card-title a, - .blog-post .card .card-title a { - text-decoration-color: #18b0a2; } - .project-item .card .card-title a:hover, - .blog-post .card .card-title a:hover { - text-decoration: underline; - text-decoration-color: #18b0a2; } - .project-item .card .card-text, - .blog-post .card .card-text { - font-size: 1rem; - font-weight: 300; - line-height: 160%; } - .project-item .card .card-btn i, - .blog-post .card .card-btn i { - transition: all 0.4s; - font-size: 14px; - text-align: center; - line-height: 12px; - margin-left: 5px; } - .project-item .card .card-btn:hover i, - .blog-post .card .card-btn:hover i { - transform: translateX(5px); - color: #18b0a2 !important; } - -.blog-post .post-meta li:not(:first-child)::before { - content: "-"; - font-size: 10px; - margin-right: 5px; } - -.blog-post .post-meta a, -.blog-post .post-meta li { - font-size: 0.875rem; - color: rgba(255, 255, 255, 0.7); } - -.blog-post .post-meta span { - font-size: 0.875rem; - color: rgba(255, 255, 255, 0.7); } - -.blog-post .card > a:first-child { - border-radius: 10px 10px 0px 0px; } - -.blog-post .card .card-btn { - color: #fff; } - .blog-post .card .card-btn img { - transition: all 0.4s; } - .blog-post .card .card-btn:hover { - color: #18b0a2 !important; } - .blog-post .card .card-btn:hover img { - margin-left: 15px; } - .blog-post .card .card-btn img { - margin-left: 10px; } - -.light .blog-post .post-meta a, -.light .blog-post .post-meta li { - color: rgba(34, 34, 34, 0.7) !important; } - -.post-meta a, -.post-meta li, -.post-meta span { - font-size: 0.975rem; - color: rgba(255, 255, 255, 0.7); } - -.post-meta li:not(:first-child)::before { - content: "-"; - font-size: 10px; - margin-right: 5px; } - -.featured-image { - max-height: 600px; - object-fit: cover; } - -#blog { - position: relative; } - #blog::before { - content: ""; - position: absolute; - z-index: -1; - width: 1159px; - height: 644px; - left: -60%; - top: 10%; - background: #34d71b; - opacity: 0.1; - filter: blur(200px); - transform: rotate(30deg); } - @media (max-width: 991px) { - #blog::before { - display: none; } } -#contact::before { - content: ""; - position: absolute; - width: 1058.89px; - height: 540.7px; - left: -60%; - bottom: 30%; - background-color: #24ff00; - opacity: 0.1; - filter: blur(200px); - transform: rotate(30deg); - z-index: -1; } - @media (max-width: 1399px) { - #contact::before { - display: none; } } -#contact::after { - content: ""; - position: absolute; - width: 561px; - height: 683px; - left: 1359px; - top: 0px; - background: linear-gradient(180deg, rgba(250, 209, 65, 0.5) 0%, rgba(0, 71, 255, 0.5) 33.85%, rgba(0, 255, 56, 0.5) 67.71%, rgba(233, 65, 0, 0.5) 100%); - opacity: 0.4; - filter: blur(175px); - z-index: -1; } - @media (max-width: 1399px) { - #contact::after { - display: none; } } -#contact form { - z-index: 1; - border: 1px solid rgba(24, 176, 162, 0.15); } - -footer a, -footer p { - color: rgba(255, 255, 255, 0.7); } - -footer p { - font-size: 0.9375rem; - line-height: 140%; } - -footer .list-inline { - text-align: center; } - footer .list-inline li a { - width: 40px; - height: 40px; - transition: all 0.3s; - border: 1px solid rgba(24, 176, 162, 0.15); - color: rgba(255, 255, 255, 0.7); } - footer .list-inline li a:hover { - background-color: rgba(24, 176, 162, 0.2); } - footer .list-inline li a i { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); } - -footer .contact-list img { - width: 25px; - height: 25px; - object-fit: contain; - object-position: center; } - -footer .copyright-info { - border-top: 1px solid rgba(24, 176, 162, 0.15); } - -.light footer a, -.light footer p { - color: rgba(34, 34, 34, 0.7) !important; } - -.notice { - margin-bottom: 1.5rem; - border: 1px solid #e5e7eb; - padding: 1.5rem; } - -.notice-head { - display: flex; - align-items: center; } - -.notice-head svg { - margin-right: 0.75rem; } - -.notice-head p { - font-size: 1.25rem; - font-weight: 600; - color: #1f2937; - margin: 0; - line-height: 1; } - -.notice-body { - margin-top: 0.75rem; } - -.notice-body p { - margin: 0; } - -.notice.note { - color: #1b83e2; - border-color: currentColor; } - -.notice.tip { - color: #40d294; - border-color: currentColor; } - -.notice.info { - color: #e3a72c; - border-color: currentColor; } - -.notice.warning { - color: #db2c23; - border-color: currentColor; } - -.dark .notice-head p { - color: #d1d5db; } - -.tab-nav { - list-style: none; - padding: 0; - margin: 0 !important; - list-style-type: none !important; - display: flex; - border-bottom: 1px solid #aaa; - overflow-x: auto; } - .tab-nav::-webkit-scrollbar { - width: 2px; } - -.tab-nav-item { - padding: 0.5rem 1rem !important; - cursor: pointer; - opacity: 0.8; - margin: 0 !important; - white-space: nowrap; } - -.tab-nav-item::before { - display: none !important; } - -.tab-nav-item.active { - border-bottom: 3px solid #aaa; - opacity: 1; } - -.tab-content .tab-content-panel { - display: none; - padding: 1rem 0.5rem; } - -.tab-content .tab-content-panel p { - margin-bottom: 0 !important; } - -.tab-content .tab-content-panel.active { - display: block; } - -.img { - max-width: 100%; - height: auto; } - -.img-light { - display: initial; } - -.img-dark { - display: none; } - -.dark .img-light { - display: none; } - -.dark .img-dark { - display: initial; } - -.content img { - max-width: 100%; - margin-bottom: 1.5rem; - height: auto; - display: inline-block; } - .content img.glightbox { - cursor: pointer; } - .content img.img-center { - display: block; - margin-left: auto; - margin-right: auto; } - .content img.img-left { - display: block; - margin-left: 0; - margin-right: auto; } - .content img.img-right { - display: block; - margin-left: auto; - margin-right: 0; } - .content img.img-float-left { - float: left; - margin-right: 1.5rem; } - .content img.img-float-right { - float: right; - margin-left: 1.5rem; } - -.content figure { - display: inline-block; - margin-bottom: 1.5rem; } - .content figure img { - margin-bottom: 0.7rem; } - .content figure.img-center { - display: block; - text-align: center; } - .content figure.img-left { - display: block; - text-align: left; } - .content figure.img-right { - display: block; - text-align: right; } - .content figure.img-float-left { - float: left; - margin-right: 1.5rem; } - .content figure.img-float-right { - float: right; - margin-left: 1.5rem; } - -.img { - max-width: 100%; - height: auto; } - -/*! - * Justified gallery style - */ -.gallery { - display: flex; - flex-wrap: wrap; - margin-left: -10px; - margin-right: -10px; } - -.gallery .gallery-item { - margin: 0 10px; - margin-bottom: 20px; - overflow: hidden; - max-width: calc(100% - 20px); } - -.gallery .gallery-item img { - user-select: none; - width: 100%; - vertical-align: middle; - transition: 0.3s; } - -.gallery.zoomable .gallery-item:hover img { - transform: scale(1.05); - cursor: zoom-in; } - -.gallery::after { - content: ""; - flex-grow: 99999; - min-width: calc(100vw / 3); } - -@media (max-width: 460px) { - .gallery { - flex-direction: column; } - .gallery .gallery-item { - width: calc(100% - 20px) !important; } } - -.gallery-slider .swiper-slide img { - width: 100%; } - -.gallery-slider .swiper-button-prev, -.gallery-slider .swiper-button-next { - color: white; - opacity: 0; - transition: 0.3s; } - -.gallery-slider:hover .swiper-button-prev, -.gallery-slider:hover .swiper-button-next { - opacity: 1; } - -.gallery-slider:hover .swiper-button-prev { - left: 30px; } - -.gallery-slider:hover .swiper-button-next { - right: 30px; } - -.table-of-content { - margin: 1rem 0 1.5rem; } - .table-of-content summary { - font-size: 18px; - color: #fff; - background-color: #555; - padding: 5px 20px; - margin-bottom: 0 !important; } - .table-of-content ul li::before { - display: none; } - .table-of-content #TableOfContents { - padding: 10px; - background-color: #f7f7f7; } - .table-of-content #TableOfContents li, - .table-of-content #TableOfContents a { - color: #333 !important; } - .table-of-content #TableOfContents a { - text-decoration: none; } - .table-of-content #TableOfContents a:hover { - text-decoration: underline; } - -.content .table-of-content ul li, -.content .table-of-content ol li { - margin-bottom: 6px !important; } - -.dark #TableOfContents { - background-color: #333; } - .dark #TableOfContents li, - .dark #TableOfContents a { - color: #fff !important; } diff --git a/public/css/style.css b/public/css/style.css deleted file mode 100644 index 14edfb6..0000000 --- a/public/css/style.css +++ /dev/null @@ -1,18693 +0,0 @@ -/*! - * Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - * Copyright 2023 Fonticons, Inc. - */ -:root, -:host { - --fa-font-brands: normal 400 1em/1 "Font Awesome 6 Brands"; -} - -@font-face { - font-family: "Font Awesome 6 Brands"; - font-style: normal; - font-weight: 400; - font-display: block; - src: url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/webfonts/fa-brands-400.woff2") - format("woff2"), - url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/webfonts/fa-brands-400.ttf") - format("truetype"); -} - -.fab, -.fa-brands { - font-weight: 400; } - -.fa-monero:before { - content: "\f3d0"; } - -.fa-hooli:before { - content: "\f427"; } - -.fa-yelp:before { - content: "\f1e9"; } - -.fa-cc-visa:before { - content: "\f1f0"; } - -.fa-lastfm:before { - content: "\f202"; } - -.fa-shopware:before { - content: "\f5b5"; } - -.fa-creative-commons-nc:before { - content: "\f4e8"; } - -.fa-aws:before { - content: "\f375"; } - -.fa-redhat:before { - content: "\f7bc"; } - -.fa-yoast:before { - content: "\f2b1"; } - -.fa-cloudflare:before { - content: "\e07d"; } - -.fa-ups:before { - content: "\f7e0"; } - -.fa-wpexplorer:before { - content: "\f2de"; } - -.fa-dyalog:before { - content: "\f399"; } - -.fa-bity:before { - content: "\f37a"; } - -.fa-stackpath:before { - content: "\f842"; } - -.fa-buysellads:before { - content: "\f20d"; } - -.fa-first-order:before { - content: "\f2b0"; } - -.fa-modx:before { - content: "\f285"; } - -.fa-guilded:before { - content: "\e07e"; } - -.fa-vnv:before { - content: "\f40b"; } - -.fa-square-js:before { - content: "\f3b9"; } - -.fa-js-square:before { - content: "\f3b9"; } - -.fa-microsoft:before { - content: "\f3ca"; } - -.fa-qq:before { - content: "\f1d6"; } - -.fa-orcid:before { - content: "\f8d2"; } - -.fa-java:before { - content: "\f4e4"; } - -.fa-invision:before { - content: "\f7b0"; } - -.fa-creative-commons-pd-alt:before { - content: "\f4ed"; } - -.fa-centercode:before { - content: "\f380"; } - -.fa-glide-g:before { - content: "\f2a6"; } - -.fa-drupal:before { - content: "\f1a9"; } - -.fa-hire-a-helper:before { - content: "\f3b0"; } - -.fa-creative-commons-by:before { - content: "\f4e7"; } - -.fa-unity:before { - content: "\e049"; } - -.fa-whmcs:before { - content: "\f40d"; } - -.fa-rocketchat:before { - content: "\f3e8"; } - -.fa-vk:before { - content: "\f189"; } - -.fa-untappd:before { - content: "\f405"; } - -.fa-mailchimp:before { - content: "\f59e"; } - -.fa-css3-alt:before { - content: "\f38b"; } - -.fa-square-reddit:before { - content: "\f1a2"; } - -.fa-reddit-square:before { - content: "\f1a2"; } - -.fa-vimeo-v:before { - content: "\f27d"; } - -.fa-contao:before { - content: "\f26d"; } - -.fa-square-font-awesome:before { - content: "\e5ad"; } - -.fa-deskpro:before { - content: "\f38f"; } - -.fa-sistrix:before { - content: "\f3ee"; } - -.fa-square-instagram:before { - content: "\e055"; } - -.fa-instagram-square:before { - content: "\e055"; } - -.fa-battle-net:before { - content: "\f835"; } - -.fa-the-red-yeti:before { - content: "\f69d"; } - -.fa-square-hacker-news:before { - content: "\f3af"; } - -.fa-hacker-news-square:before { - content: "\f3af"; } - -.fa-edge:before { - content: "\f282"; } - -.fa-threads:before { - content: "\e618"; } - -.fa-napster:before { - content: "\f3d2"; } - -.fa-square-snapchat:before { - content: "\f2ad"; } - -.fa-snapchat-square:before { - content: "\f2ad"; } - -.fa-google-plus-g:before { - content: "\f0d5"; } - -.fa-artstation:before { - content: "\f77a"; } - -.fa-markdown:before { - content: "\f60f"; } - -.fa-sourcetree:before { - content: "\f7d3"; } - -.fa-google-plus:before { - content: "\f2b3"; } - -.fa-diaspora:before { - content: "\f791"; } - -.fa-foursquare:before { - content: "\f180"; } - -.fa-stack-overflow:before { - content: "\f16c"; } - -.fa-github-alt:before { - content: "\f113"; } - -.fa-phoenix-squadron:before { - content: "\f511"; } - -.fa-pagelines:before { - content: "\f18c"; } - -.fa-algolia:before { - content: "\f36c"; } - -.fa-red-river:before { - content: "\f3e3"; } - -.fa-creative-commons-sa:before { - content: "\f4ef"; } - -.fa-safari:before { - content: "\f267"; } - -.fa-google:before { - content: "\f1a0"; } - -.fa-square-font-awesome-stroke:before { - content: "\f35c"; } - -.fa-font-awesome-alt:before { - content: "\f35c"; } - -.fa-atlassian:before { - content: "\f77b"; } - -.fa-linkedin-in:before { - content: "\f0e1"; } - -.fa-digital-ocean:before { - content: "\f391"; } - -.fa-nimblr:before { - content: "\f5a8"; } - -.fa-chromecast:before { - content: "\f838"; } - -.fa-evernote:before { - content: "\f839"; } - -.fa-hacker-news:before { - content: "\f1d4"; } - -.fa-creative-commons-sampling:before { - content: "\f4f0"; } - -.fa-adversal:before { - content: "\f36a"; } - -.fa-creative-commons:before { - content: "\f25e"; } - -.fa-watchman-monitoring:before { - content: "\e087"; } - -.fa-fonticons:before { - content: "\f280"; } - -.fa-weixin:before { - content: "\f1d7"; } - -.fa-shirtsinbulk:before { - content: "\f214"; } - -.fa-codepen:before { - content: "\f1cb"; } - -.fa-git-alt:before { - content: "\f841"; } - -.fa-lyft:before { - content: "\f3c3"; } - -.fa-rev:before { - content: "\f5b2"; } - -.fa-windows:before { - content: "\f17a"; } - -.fa-wizards-of-the-coast:before { - content: "\f730"; } - -.fa-square-viadeo:before { - content: "\f2aa"; } - -.fa-viadeo-square:before { - content: "\f2aa"; } - -.fa-meetup:before { - content: "\f2e0"; } - -.fa-centos:before { - content: "\f789"; } - -.fa-adn:before { - content: "\f170"; } - -.fa-cloudsmith:before { - content: "\f384"; } - -.fa-pied-piper-alt:before { - content: "\f1a8"; } - -.fa-square-dribbble:before { - content: "\f397"; } - -.fa-dribbble-square:before { - content: "\f397"; } - -.fa-codiepie:before { - content: "\f284"; } - -.fa-node:before { - content: "\f419"; } - -.fa-mix:before { - content: "\f3cb"; } - -.fa-steam:before { - content: "\f1b6"; } - -.fa-cc-apple-pay:before { - content: "\f416"; } - -.fa-scribd:before { - content: "\f28a"; } - -.fa-debian:before { - content: "\e60b"; } - -.fa-openid:before { - content: "\f19b"; } - -.fa-instalod:before { - content: "\e081"; } - -.fa-expeditedssl:before { - content: "\f23e"; } - -.fa-sellcast:before { - content: "\f2da"; } - -.fa-square-twitter:before { - content: "\f081"; } - -.fa-twitter-square:before { - content: "\f081"; } - -.fa-r-project:before { - content: "\f4f7"; } - -.fa-delicious:before { - content: "\f1a5"; } - -.fa-freebsd:before { - content: "\f3a4"; } - -.fa-vuejs:before { - content: "\f41f"; } - -.fa-accusoft:before { - content: "\f369"; } - -.fa-ioxhost:before { - content: "\f208"; } - -.fa-fonticons-fi:before { - content: "\f3a2"; } - -.fa-app-store:before { - content: "\f36f"; } - -.fa-cc-mastercard:before { - content: "\f1f1"; } - -.fa-itunes-note:before { - content: "\f3b5"; } - -.fa-golang:before { - content: "\e40f"; } - -.fa-kickstarter:before { - content: "\f3bb"; } - -.fa-grav:before { - content: "\f2d6"; } - -.fa-weibo:before { - content: "\f18a"; } - -.fa-uncharted:before { - content: "\e084"; } - -.fa-firstdraft:before { - content: "\f3a1"; } - -.fa-square-youtube:before { - content: "\f431"; } - -.fa-youtube-square:before { - content: "\f431"; } - -.fa-wikipedia-w:before { - content: "\f266"; } - -.fa-wpressr:before { - content: "\f3e4"; } - -.fa-rendact:before { - content: "\f3e4"; } - -.fa-angellist:before { - content: "\f209"; } - -.fa-galactic-republic:before { - content: "\f50c"; } - -.fa-nfc-directional:before { - content: "\e530"; } - -.fa-skype:before { - content: "\f17e"; } - -.fa-joget:before { - content: "\f3b7"; } - -.fa-fedora:before { - content: "\f798"; } - -.fa-stripe-s:before { - content: "\f42a"; } - -.fa-meta:before { - content: "\e49b"; } - -.fa-laravel:before { - content: "\f3bd"; } - -.fa-hotjar:before { - content: "\f3b1"; } - -.fa-bluetooth-b:before { - content: "\f294"; } - -.fa-sticker-mule:before { - content: "\f3f7"; } - -.fa-creative-commons-zero:before { - content: "\f4f3"; } - -.fa-hips:before { - content: "\f452"; } - -.fa-behance:before { - content: "\f1b4"; } - -.fa-reddit:before { - content: "\f1a1"; } - -.fa-discord:before { - content: "\f392"; } - -.fa-chrome:before { - content: "\f268"; } - -.fa-app-store-ios:before { - content: "\f370"; } - -.fa-cc-discover:before { - content: "\f1f2"; } - -.fa-wpbeginner:before { - content: "\f297"; } - -.fa-confluence:before { - content: "\f78d"; } - -.fa-mdb:before { - content: "\f8ca"; } - -.fa-dochub:before { - content: "\f394"; } - -.fa-accessible-icon:before { - content: "\f368"; } - -.fa-ebay:before { - content: "\f4f4"; } - -.fa-amazon:before { - content: "\f270"; } - -.fa-unsplash:before { - content: "\e07c"; } - -.fa-yarn:before { - content: "\f7e3"; } - -.fa-square-steam:before { - content: "\f1b7"; } - -.fa-steam-square:before { - content: "\f1b7"; } - -.fa-500px:before { - content: "\f26e"; } - -.fa-square-vimeo:before { - content: "\f194"; } - -.fa-vimeo-square:before { - content: "\f194"; } - -.fa-asymmetrik:before { - content: "\f372"; } - -.fa-font-awesome:before { - content: "\f2b4"; } - -.fa-font-awesome-flag:before { - content: "\f2b4"; } - -.fa-font-awesome-logo-full:before { - content: "\f2b4"; } - -.fa-gratipay:before { - content: "\f184"; } - -.fa-apple:before { - content: "\f179"; } - -.fa-hive:before { - content: "\e07f"; } - -.fa-gitkraken:before { - content: "\f3a6"; } - -.fa-keybase:before { - content: "\f4f5"; } - -.fa-apple-pay:before { - content: "\f415"; } - -.fa-padlet:before { - content: "\e4a0"; } - -.fa-amazon-pay:before { - content: "\f42c"; } - -.fa-square-github:before { - content: "\f092"; } - -.fa-github-square:before { - content: "\f092"; } - -.fa-stumbleupon:before { - content: "\f1a4"; } - -.fa-fedex:before { - content: "\f797"; } - -.fa-phoenix-framework:before { - content: "\f3dc"; } - -.fa-shopify:before { - content: "\e057"; } - -.fa-neos:before { - content: "\f612"; } - -.fa-square-threads:before { - content: "\e619"; } - -.fa-hackerrank:before { - content: "\f5f7"; } - -.fa-researchgate:before { - content: "\f4f8"; } - -.fa-swift:before { - content: "\f8e1"; } - -.fa-angular:before { - content: "\f420"; } - -.fa-speakap:before { - content: "\f3f3"; } - -.fa-angrycreative:before { - content: "\f36e"; } - -.fa-y-combinator:before { - content: "\f23b"; } - -.fa-empire:before { - content: "\f1d1"; } - -.fa-envira:before { - content: "\f299"; } - -.fa-square-gitlab:before { - content: "\e5ae"; } - -.fa-gitlab-square:before { - content: "\e5ae"; } - -.fa-studiovinari:before { - content: "\f3f8"; } - -.fa-pied-piper:before { - content: "\f2ae"; } - -.fa-wordpress:before { - content: "\f19a"; } - -.fa-product-hunt:before { - content: "\f288"; } - -.fa-firefox:before { - content: "\f269"; } - -.fa-linode:before { - content: "\f2b8"; } - -.fa-goodreads:before { - content: "\f3a8"; } - -.fa-square-odnoklassniki:before { - content: "\f264"; } - -.fa-odnoklassniki-square:before { - content: "\f264"; } - -.fa-jsfiddle:before { - content: "\f1cc"; } - -.fa-sith:before { - content: "\f512"; } - -.fa-themeisle:before { - content: "\f2b2"; } - -.fa-page4:before { - content: "\f3d7"; } - -.fa-hashnode:before { - content: "\e499"; } - -.fa-react:before { - content: "\f41b"; } - -.fa-cc-paypal:before { - content: "\f1f4"; } - -.fa-squarespace:before { - content: "\f5be"; } - -.fa-cc-stripe:before { - content: "\f1f5"; } - -.fa-creative-commons-share:before { - content: "\f4f2"; } - -.fa-bitcoin:before { - content: "\f379"; } - -.fa-keycdn:before { - content: "\f3ba"; } - -.fa-opera:before { - content: "\f26a"; } - -.fa-itch-io:before { - content: "\f83a"; } - -.fa-umbraco:before { - content: "\f8e8"; } - -.fa-galactic-senate:before { - content: "\f50d"; } - -.fa-ubuntu:before { - content: "\f7df"; } - -.fa-draft2digital:before { - content: "\f396"; } - -.fa-stripe:before { - content: "\f429"; } - -.fa-houzz:before { - content: "\f27c"; } - -.fa-gg:before { - content: "\f260"; } - -.fa-dhl:before { - content: "\f790"; } - -.fa-square-pinterest:before { - content: "\f0d3"; } - -.fa-pinterest-square:before { - content: "\f0d3"; } - -.fa-xing:before { - content: "\f168"; } - -.fa-blackberry:before { - content: "\f37b"; } - -.fa-creative-commons-pd:before { - content: "\f4ec"; } - -.fa-playstation:before { - content: "\f3df"; } - -.fa-quinscape:before { - content: "\f459"; } - -.fa-less:before { - content: "\f41d"; } - -.fa-blogger-b:before { - content: "\f37d"; } - -.fa-opencart:before { - content: "\f23d"; } - -.fa-vine:before { - content: "\f1ca"; } - -.fa-paypal:before { - content: "\f1ed"; } - -.fa-gitlab:before { - content: "\f296"; } - -.fa-typo3:before { - content: "\f42b"; } - -.fa-reddit-alien:before { - content: "\f281"; } - -.fa-yahoo:before { - content: "\f19e"; } - -.fa-dailymotion:before { - content: "\e052"; } - -.fa-affiliatetheme:before { - content: "\f36b"; } - -.fa-pied-piper-pp:before { - content: "\f1a7"; } - -.fa-bootstrap:before { - content: "\f836"; } - -.fa-odnoklassniki:before { - content: "\f263"; } - -.fa-nfc-symbol:before { - content: "\e531"; } - -.fa-ethereum:before { - content: "\f42e"; } - -.fa-speaker-deck:before { - content: "\f83c"; } - -.fa-creative-commons-nc-eu:before { - content: "\f4e9"; } - -.fa-patreon:before { - content: "\f3d9"; } - -.fa-avianex:before { - content: "\f374"; } - -.fa-ello:before { - content: "\f5f1"; } - -.fa-gofore:before { - content: "\f3a7"; } - -.fa-bimobject:before { - content: "\f378"; } - -.fa-facebook-f:before { - content: "\f39e"; } - -.fa-square-google-plus:before { - content: "\f0d4"; } - -.fa-google-plus-square:before { - content: "\f0d4"; } - -.fa-mandalorian:before { - content: "\f50f"; } - -.fa-first-order-alt:before { - content: "\f50a"; } - -.fa-osi:before { - content: "\f41a"; } - -.fa-google-wallet:before { - content: "\f1ee"; } - -.fa-d-and-d-beyond:before { - content: "\f6ca"; } - -.fa-periscope:before { - content: "\f3da"; } - -.fa-fulcrum:before { - content: "\f50b"; } - -.fa-cloudscale:before { - content: "\f383"; } - -.fa-forumbee:before { - content: "\f211"; } - -.fa-mizuni:before { - content: "\f3cc"; } - -.fa-schlix:before { - content: "\f3ea"; } - -.fa-square-xing:before { - content: "\f169"; } - -.fa-xing-square:before { - content: "\f169"; } - -.fa-bandcamp:before { - content: "\f2d5"; } - -.fa-wpforms:before { - content: "\f298"; } - -.fa-cloudversify:before { - content: "\f385"; } - -.fa-usps:before { - content: "\f7e1"; } - -.fa-megaport:before { - content: "\f5a3"; } - -.fa-magento:before { - content: "\f3c4"; } - -.fa-spotify:before { - content: "\f1bc"; } - -.fa-optin-monster:before { - content: "\f23c"; } - -.fa-fly:before { - content: "\f417"; } - -.fa-aviato:before { - content: "\f421"; } - -.fa-itunes:before { - content: "\f3b4"; } - -.fa-cuttlefish:before { - content: "\f38c"; } - -.fa-blogger:before { - content: "\f37c"; } - -.fa-flickr:before { - content: "\f16e"; } - -.fa-viber:before { - content: "\f409"; } - -.fa-soundcloud:before { - content: "\f1be"; } - -.fa-digg:before { - content: "\f1a6"; } - -.fa-tencent-weibo:before { - content: "\f1d5"; } - -.fa-symfony:before { - content: "\f83d"; } - -.fa-maxcdn:before { - content: "\f136"; } - -.fa-etsy:before { - content: "\f2d7"; } - -.fa-facebook-messenger:before { - content: "\f39f"; } - -.fa-audible:before { - content: "\f373"; } - -.fa-think-peaks:before { - content: "\f731"; } - -.fa-bilibili:before { - content: "\e3d9"; } - -.fa-erlang:before { - content: "\f39d"; } - -.fa-x-twitter:before { - content: "\e61b"; } - -.fa-cotton-bureau:before { - content: "\f89e"; } - -.fa-dashcube:before { - content: "\f210"; } - -.fa-42-group:before { - content: "\e080"; } - -.fa-innosoft:before { - content: "\e080"; } - -.fa-stack-exchange:before { - content: "\f18d"; } - -.fa-elementor:before { - content: "\f430"; } - -.fa-square-pied-piper:before { - content: "\e01e"; } - -.fa-pied-piper-square:before { - content: "\e01e"; } - -.fa-creative-commons-nd:before { - content: "\f4eb"; } - -.fa-palfed:before { - content: "\f3d8"; } - -.fa-superpowers:before { - content: "\f2dd"; } - -.fa-resolving:before { - content: "\f3e7"; } - -.fa-xbox:before { - content: "\f412"; } - -.fa-searchengin:before { - content: "\f3eb"; } - -.fa-tiktok:before { - content: "\e07b"; } - -.fa-square-facebook:before { - content: "\f082"; } - -.fa-facebook-square:before { - content: "\f082"; } - -.fa-renren:before { - content: "\f18b"; } - -.fa-linux:before { - content: "\f17c"; } - -.fa-glide:before { - content: "\f2a5"; } - -.fa-linkedin:before { - content: "\f08c"; } - -.fa-hubspot:before { - content: "\f3b2"; } - -.fa-deploydog:before { - content: "\f38e"; } - -.fa-twitch:before { - content: "\f1e8"; } - -.fa-ravelry:before { - content: "\f2d9"; } - -.fa-mixer:before { - content: "\e056"; } - -.fa-square-lastfm:before { - content: "\f203"; } - -.fa-lastfm-square:before { - content: "\f203"; } - -.fa-vimeo:before { - content: "\f40a"; } - -.fa-mendeley:before { - content: "\f7b3"; } - -.fa-uniregistry:before { - content: "\f404"; } - -.fa-figma:before { - content: "\f799"; } - -.fa-creative-commons-remix:before { - content: "\f4ee"; } - -.fa-cc-amazon-pay:before { - content: "\f42d"; } - -.fa-dropbox:before { - content: "\f16b"; } - -.fa-instagram:before { - content: "\f16d"; } - -.fa-cmplid:before { - content: "\e360"; } - -.fa-facebook:before { - content: "\f09a"; } - -.fa-gripfire:before { - content: "\f3ac"; } - -.fa-jedi-order:before { - content: "\f50e"; } - -.fa-uikit:before { - content: "\f403"; } - -.fa-fort-awesome-alt:before { - content: "\f3a3"; } - -.fa-phabricator:before { - content: "\f3db"; } - -.fa-ussunnah:before { - content: "\f407"; } - -.fa-earlybirds:before { - content: "\f39a"; } - -.fa-trade-federation:before { - content: "\f513"; } - -.fa-autoprefixer:before { - content: "\f41c"; } - -.fa-whatsapp:before { - content: "\f232"; } - -.fa-slideshare:before { - content: "\f1e7"; } - -.fa-google-play:before { - content: "\f3ab"; } - -.fa-viadeo:before { - content: "\f2a9"; } - -.fa-line:before { - content: "\f3c0"; } - -.fa-google-drive:before { - content: "\f3aa"; } - -.fa-servicestack:before { - content: "\f3ec"; } - -.fa-simplybuilt:before { - content: "\f215"; } - -.fa-bitbucket:before { - content: "\f171"; } - -.fa-imdb:before { - content: "\f2d8"; } - -.fa-deezer:before { - content: "\e077"; } - -.fa-raspberry-pi:before { - content: "\f7bb"; } - -.fa-jira:before { - content: "\f7b1"; } - -.fa-docker:before { - content: "\f395"; } - -.fa-screenpal:before { - content: "\e570"; } - -.fa-bluetooth:before { - content: "\f293"; } - -.fa-gitter:before { - content: "\f426"; } - -.fa-d-and-d:before { - content: "\f38d"; } - -.fa-microblog:before { - content: "\e01a"; } - -.fa-cc-diners-club:before { - content: "\f24c"; } - -.fa-gg-circle:before { - content: "\f261"; } - -.fa-pied-piper-hat:before { - content: "\f4e5"; } - -.fa-kickstarter-k:before { - content: "\f3bc"; } - -.fa-yandex:before { - content: "\f413"; } - -.fa-readme:before { - content: "\f4d5"; } - -.fa-html5:before { - content: "\f13b"; } - -.fa-sellsy:before { - content: "\f213"; } - -.fa-sass:before { - content: "\f41e"; } - -.fa-wirsindhandwerk:before { - content: "\e2d0"; } - -.fa-wsh:before { - content: "\e2d0"; } - -.fa-buromobelexperte:before { - content: "\f37f"; } - -.fa-salesforce:before { - content: "\f83b"; } - -.fa-octopus-deploy:before { - content: "\e082"; } - -.fa-medapps:before { - content: "\f3c6"; } - -.fa-ns8:before { - content: "\f3d5"; } - -.fa-pinterest-p:before { - content: "\f231"; } - -.fa-apper:before { - content: "\f371"; } - -.fa-fort-awesome:before { - content: "\f286"; } - -.fa-waze:before { - content: "\f83f"; } - -.fa-cc-jcb:before { - content: "\f24b"; } - -.fa-snapchat:before { - content: "\f2ab"; } - -.fa-snapchat-ghost:before { - content: "\f2ab"; } - -.fa-fantasy-flight-games:before { - content: "\f6dc"; } - -.fa-rust:before { - content: "\e07a"; } - -.fa-wix:before { - content: "\f5cf"; } - -.fa-square-behance:before { - content: "\f1b5"; } - -.fa-behance-square:before { - content: "\f1b5"; } - -.fa-supple:before { - content: "\f3f9"; } - -.fa-rebel:before { - content: "\f1d0"; } - -.fa-css3:before { - content: "\f13c"; } - -.fa-staylinked:before { - content: "\f3f5"; } - -.fa-kaggle:before { - content: "\f5fa"; } - -.fa-space-awesome:before { - content: "\e5ac"; } - -.fa-deviantart:before { - content: "\f1bd"; } - -.fa-cpanel:before { - content: "\f388"; } - -.fa-goodreads-g:before { - content: "\f3a9"; } - -.fa-square-git:before { - content: "\f1d2"; } - -.fa-git-square:before { - content: "\f1d2"; } - -.fa-square-tumblr:before { - content: "\f174"; } - -.fa-tumblr-square:before { - content: "\f174"; } - -.fa-trello:before { - content: "\f181"; } - -.fa-creative-commons-nc-jp:before { - content: "\f4ea"; } - -.fa-get-pocket:before { - content: "\f265"; } - -.fa-perbyte:before { - content: "\e083"; } - -.fa-grunt:before { - content: "\f3ad"; } - -.fa-weebly:before { - content: "\f5cc"; } - -.fa-connectdevelop:before { - content: "\f20e"; } - -.fa-leanpub:before { - content: "\f212"; } - -.fa-black-tie:before { - content: "\f27e"; } - -.fa-themeco:before { - content: "\f5c6"; } - -.fa-python:before { - content: "\f3e2"; } - -.fa-android:before { - content: "\f17b"; } - -.fa-bots:before { - content: "\e340"; } - -.fa-free-code-camp:before { - content: "\f2c5"; } - -.fa-hornbill:before { - content: "\f592"; } - -.fa-js:before { - content: "\f3b8"; } - -.fa-ideal:before { - content: "\e013"; } - -.fa-git:before { - content: "\f1d3"; } - -.fa-dev:before { - content: "\f6cc"; } - -.fa-sketch:before { - content: "\f7c6"; } - -.fa-yandex-international:before { - content: "\f414"; } - -.fa-cc-amex:before { - content: "\f1f3"; } - -.fa-uber:before { - content: "\f402"; } - -.fa-github:before { - content: "\f09b"; } - -.fa-php:before { - content: "\f457"; } - -.fa-alipay:before { - content: "\f642"; } - -.fa-youtube:before { - content: "\f167"; } - -.fa-skyatlas:before { - content: "\f216"; } - -.fa-firefox-browser:before { - content: "\e007"; } - -.fa-replyd:before { - content: "\f3e6"; } - -.fa-suse:before { - content: "\f7d6"; } - -.fa-jenkins:before { - content: "\f3b6"; } - -.fa-twitter:before { - content: "\f099"; } - -.fa-rockrms:before { - content: "\f3e9"; } - -.fa-pinterest:before { - content: "\f0d2"; } - -.fa-buffer:before { - content: "\f837"; } - -.fa-npm:before { - content: "\f3d4"; } - -.fa-yammer:before { - content: "\f840"; } - -.fa-btc:before { - content: "\f15a"; } - -.fa-dribbble:before { - content: "\f17d"; } - -.fa-stumbleupon-circle:before { - content: "\f1a3"; } - -.fa-internet-explorer:before { - content: "\f26b"; } - -.fa-stubber:before { - content: "\e5c7"; } - -.fa-telegram:before { - content: "\f2c6"; } - -.fa-telegram-plane:before { - content: "\f2c6"; } - -.fa-old-republic:before { - content: "\f510"; } - -.fa-odysee:before { - content: "\e5c6"; } - -.fa-square-whatsapp:before { - content: "\f40c"; } - -.fa-whatsapp-square:before { - content: "\f40c"; } - -.fa-node-js:before { - content: "\f3d3"; } - -.fa-edge-legacy:before { - content: "\e078"; } - -.fa-slack:before { - content: "\f198"; } - -.fa-slack-hash:before { - content: "\f198"; } - -.fa-medrt:before { - content: "\f3c8"; } - -.fa-usb:before { - content: "\f287"; } - -.fa-tumblr:before { - content: "\f173"; } - -.fa-vaadin:before { - content: "\f408"; } - -.fa-quora:before { - content: "\f2c4"; } - -.fa-square-x-twitter:before { - content: "\e61a"; } - -.fa-reacteurope:before { - content: "\f75d"; } - -.fa-medium:before { - content: "\f23a"; } - -.fa-medium-m:before { - content: "\f23a"; } - -.fa-amilia:before { - content: "\f36d"; } - -.fa-mixcloud:before { - content: "\f289"; } - -.fa-flipboard:before { - content: "\f44d"; } - -.fa-viacoin:before { - content: "\f237"; } - -.fa-critical-role:before { - content: "\f6c9"; } - -.fa-sitrox:before { - content: "\e44a"; } - -.fa-discourse:before { - content: "\f393"; } - -.fa-joomla:before { - content: "\f1aa"; } - -.fa-mastodon:before { - content: "\f4f6"; } - -.fa-airbnb:before { - content: "\f834"; } - -.fa-wolf-pack-battalion:before { - content: "\f514"; } - -.fa-buy-n-large:before { - content: "\f8a6"; } - -.fa-gulp:before { - content: "\f3ae"; } - -.fa-creative-commons-sampling-plus:before { - content: "\f4f1"; } - -.fa-strava:before { - content: "\f428"; } - -.fa-ember:before { - content: "\f423"; } - -.fa-canadian-maple-leaf:before { - content: "\f785"; } - -.fa-teamspeak:before { - content: "\f4f9"; } - -.fa-pushed:before { - content: "\f3e1"; } - -.fa-wordpress-simple:before { - content: "\f411"; } - -.fa-nutritionix:before { - content: "\f3d6"; } - -.fa-wodu:before { - content: "\e088"; } - -.fa-google-pay:before { - content: "\e079"; } - -.fa-intercom:before { - content: "\f7af"; } - -.fa-zhihu:before { - content: "\f63f"; } - -.fa-korvue:before { - content: "\f42f"; } - -.fa-pix:before { - content: "\e43a"; } - -.fa-steam-symbol:before { - content: "\f3f6"; }/*! - * Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - * Copyright 2023 Fonticons, Inc. - */ - :root, :host { - --fa-style-family-classic: 'Font Awesome 6 Free'; - --fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; } - -@font-face { - font-family: 'Font Awesome 6 Free'; - font-style: normal; - font-weight: 900; - font-display: block; - src: url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/webfonts/fa-solid-900.woff2") - format("woff2"), - url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/webfonts/fa-solid-900.ttf") - format("truetype"); } - -.fas, -.fa-solid { - font-weight: 900; } -/*! - * Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - * Copyright 2023 Fonticons, Inc. - */ - .fa { - font-family: var(--fa-style-family, "Font Awesome 6 Free"); - font-weight: var(--fa-style, 900); } - -.fa, -.fa-classic, -.fa-sharp, -.fas, -.fa-solid, -.far, -.fa-regular, -.fab, -.fa-brands { - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - display: var(--fa-display, inline-block); - font-style: normal; - font-variant: normal; - line-height: 1; - text-rendering: auto; } - -.fas, -.fa-classic, -.fa-solid, -.far, -.fa-regular { - font-family: 'Font Awesome 6 Free'; } - -.fab, -.fa-brands { - font-family: 'Font Awesome 6 Brands'; } - -.fa-1x { - font-size: 1em; } - -.fa-2x { - font-size: 2em; } - -.fa-3x { - font-size: 3em; } - -.fa-4x { - font-size: 4em; } - -.fa-5x { - font-size: 5em; } - -.fa-6x { - font-size: 6em; } - -.fa-7x { - font-size: 7em; } - -.fa-8x { - font-size: 8em; } - -.fa-9x { - font-size: 9em; } - -.fa-10x { - font-size: 10em; } - -.fa-2xs { - font-size: 0.625em; - line-height: 0.1em; - vertical-align: 0.225em; } - -.fa-xs { - font-size: 0.75em; - line-height: 0.08333em; - vertical-align: 0.125em; } - -.fa-sm { - font-size: 0.875em; - line-height: 0.07143em; - vertical-align: 0.05357em; } - -.fa-lg { - font-size: 1.25em; - line-height: 0.05em; - vertical-align: -0.075em; } - -.fa-xl { - font-size: 1.5em; - line-height: 0.04167em; - vertical-align: -0.125em; } - -.fa-2xl { - font-size: 2em; - line-height: 0.03125em; - vertical-align: -0.1875em; } - -.fa-fw { - text-align: center; - width: 1.25em; } - -.fa-ul { - list-style-type: none; - margin-left: var(--fa-li-margin, 2.5em); - padding-left: 0; } - .fa-ul > li { - position: relative; } - -.fa-li { - left: calc(var(--fa-li-width, 2em) * -1); - position: absolute; - text-align: center; - width: var(--fa-li-width, 2em); - line-height: inherit; } - -.fa-border { - border-color: var(--fa-border-color, #eee); - border-radius: var(--fa-border-radius, 0.1em); - border-style: var(--fa-border-style, solid); - border-width: var(--fa-border-width, 0.08em); - padding: var(--fa-border-padding, 0.2em 0.25em 0.15em); } - -.fa-pull-left { - float: left; - margin-right: var(--fa-pull-margin, 0.3em); } - -.fa-pull-right { - float: right; - margin-left: var(--fa-pull-margin, 0.3em); } - -.fa-beat { - -webkit-animation-name: fa-beat; - animation-name: fa-beat; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out); - animation-timing-function: var(--fa-animation-timing, ease-in-out); } - -.fa-bounce { - -webkit-animation-name: fa-bounce; - animation-name: fa-bounce; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); - animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); } - -.fa-fade { - -webkit-animation-name: fa-fade; - animation-name: fa-fade; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); - animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); } - -.fa-beat-fade { - -webkit-animation-name: fa-beat-fade; - animation-name: fa-beat-fade; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); - animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); } - -.fa-flip { - -webkit-animation-name: fa-flip; - animation-name: fa-flip; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out); - animation-timing-function: var(--fa-animation-timing, ease-in-out); } - -.fa-shake { - -webkit-animation-name: fa-shake; - animation-name: fa-shake; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, linear); - animation-timing-function: var(--fa-animation-timing, linear); } - -.fa-spin { - -webkit-animation-name: fa-spin; - animation-name: fa-spin; - -webkit-animation-delay: var(--fa-animation-delay, 0s); - animation-delay: var(--fa-animation-delay, 0s); - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 2s); - animation-duration: var(--fa-animation-duration, 2s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, linear); - animation-timing-function: var(--fa-animation-timing, linear); } - -.fa-spin-reverse { - --fa-animation-direction: reverse; } - -.fa-pulse, -.fa-spin-pulse { - -webkit-animation-name: fa-spin; - animation-name: fa-spin; - -webkit-animation-direction: var(--fa-animation-direction, normal); - animation-direction: var(--fa-animation-direction, normal); - -webkit-animation-duration: var(--fa-animation-duration, 1s); - animation-duration: var(--fa-animation-duration, 1s); - -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - -webkit-animation-timing-function: var(--fa-animation-timing, steps(8)); - animation-timing-function: var(--fa-animation-timing, steps(8)); } - -@media (prefers-reduced-motion: reduce) { - .fa-beat, - .fa-bounce, - .fa-fade, - .fa-beat-fade, - .fa-flip, - .fa-pulse, - .fa-shake, - .fa-spin, - .fa-spin-pulse { - -webkit-animation-delay: -1ms; - animation-delay: -1ms; - -webkit-animation-duration: 1ms; - animation-duration: 1ms; - -webkit-animation-iteration-count: 1; - animation-iteration-count: 1; - -webkit-transition-delay: 0s; - transition-delay: 0s; - -webkit-transition-duration: 0s; - transition-duration: 0s; } } - -@-webkit-keyframes fa-beat { - 0%, 90% { - -webkit-transform: scale(1); - transform: scale(1); } - 45% { - -webkit-transform: scale(var(--fa-beat-scale, 1.25)); - transform: scale(var(--fa-beat-scale, 1.25)); } } - -@keyframes fa-beat { - 0%, 90% { - -webkit-transform: scale(1); - transform: scale(1); } - 45% { - -webkit-transform: scale(var(--fa-beat-scale, 1.25)); - transform: scale(var(--fa-beat-scale, 1.25)); } } - -@-webkit-keyframes fa-bounce { - 0% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } - 10% { - -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); - transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); } - 30% { - -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); - transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); } - 50% { - -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); - transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); } - 57% { - -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); - transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); } - 64% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } - 100% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } } - -@keyframes fa-bounce { - 0% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } - 10% { - -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); - transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); } - 30% { - -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); - transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); } - 50% { - -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); - transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); } - 57% { - -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); - transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); } - 64% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } - 100% { - -webkit-transform: scale(1, 1) translateY(0); - transform: scale(1, 1) translateY(0); } } - -@-webkit-keyframes fa-fade { - 50% { - opacity: var(--fa-fade-opacity, 0.4); } } - -@keyframes fa-fade { - 50% { - opacity: var(--fa-fade-opacity, 0.4); } } - -@-webkit-keyframes fa-beat-fade { - 0%, 100% { - opacity: var(--fa-beat-fade-opacity, 0.4); - -webkit-transform: scale(1); - transform: scale(1); } - 50% { - opacity: 1; - -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125)); - transform: scale(var(--fa-beat-fade-scale, 1.125)); } } - -@keyframes fa-beat-fade { - 0%, 100% { - opacity: var(--fa-beat-fade-opacity, 0.4); - -webkit-transform: scale(1); - transform: scale(1); } - 50% { - opacity: 1; - -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125)); - transform: scale(var(--fa-beat-fade-scale, 1.125)); } } - -@-webkit-keyframes fa-flip { - 50% { - -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); - transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } } - -@keyframes fa-flip { - 50% { - -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); - transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } } - -@-webkit-keyframes fa-shake { - 0% { - -webkit-transform: rotate(-15deg); - transform: rotate(-15deg); } - 4% { - -webkit-transform: rotate(15deg); - transform: rotate(15deg); } - 8%, 24% { - -webkit-transform: rotate(-18deg); - transform: rotate(-18deg); } - 12%, 28% { - -webkit-transform: rotate(18deg); - transform: rotate(18deg); } - 16% { - -webkit-transform: rotate(-22deg); - transform: rotate(-22deg); } - 20% { - -webkit-transform: rotate(22deg); - transform: rotate(22deg); } - 32% { - -webkit-transform: rotate(-12deg); - transform: rotate(-12deg); } - 36% { - -webkit-transform: rotate(12deg); - transform: rotate(12deg); } - 40%, 100% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); } } - -@keyframes fa-shake { - 0% { - -webkit-transform: rotate(-15deg); - transform: rotate(-15deg); } - 4% { - -webkit-transform: rotate(15deg); - transform: rotate(15deg); } - 8%, 24% { - -webkit-transform: rotate(-18deg); - transform: rotate(-18deg); } - 12%, 28% { - -webkit-transform: rotate(18deg); - transform: rotate(18deg); } - 16% { - -webkit-transform: rotate(-22deg); - transform: rotate(-22deg); } - 20% { - -webkit-transform: rotate(22deg); - transform: rotate(22deg); } - 32% { - -webkit-transform: rotate(-12deg); - transform: rotate(-12deg); } - 36% { - -webkit-transform: rotate(12deg); - transform: rotate(12deg); } - 40%, 100% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); } } - -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); } } - -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); } } - -.fa-rotate-90 { - -webkit-transform: rotate(90deg); - transform: rotate(90deg); } - -.fa-rotate-180 { - -webkit-transform: rotate(180deg); - transform: rotate(180deg); } - -.fa-rotate-270 { - -webkit-transform: rotate(270deg); - transform: rotate(270deg); } - -.fa-flip-horizontal { - -webkit-transform: scale(-1, 1); - transform: scale(-1, 1); } - -.fa-flip-vertical { - -webkit-transform: scale(1, -1); - transform: scale(1, -1); } - -.fa-flip-both, -.fa-flip-horizontal.fa-flip-vertical { - -webkit-transform: scale(-1, -1); - transform: scale(-1, -1); } - -.fa-rotate-by { - -webkit-transform: rotate(var(--fa-rotate-angle, none)); - transform: rotate(var(--fa-rotate-angle, none)); } - -.fa-stack { - display: inline-block; - height: 2em; - line-height: 2em; - position: relative; - vertical-align: middle; - width: 2.5em; } - -.fa-stack-1x, -.fa-stack-2x { - left: 0; - position: absolute; - text-align: center; - width: 100%; - z-index: var(--fa-stack-z-index, auto); } - -.fa-stack-1x { - line-height: inherit; } - -.fa-stack-2x { - font-size: 2em; } - -.fa-inverse { - color: var(--fa-inverse, #fff); } - -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen -readers do not read off random characters that represent icons */ - -.fa-0::before { - content: "\30"; } - -.fa-1::before { - content: "\31"; } - -.fa-2::before { - content: "\32"; } - -.fa-3::before { - content: "\33"; } - -.fa-4::before { - content: "\34"; } - -.fa-5::before { - content: "\35"; } - -.fa-6::before { - content: "\36"; } - -.fa-7::before { - content: "\37"; } - -.fa-8::before { - content: "\38"; } - -.fa-9::before { - content: "\39"; } - -.fa-fill-drip::before { - content: "\f576"; } - -.fa-arrows-to-circle::before { - content: "\e4bd"; } - -.fa-circle-chevron-right::before { - content: "\f138"; } - -.fa-chevron-circle-right::before { - content: "\f138"; } - -.fa-at::before { - content: "\40"; } - -.fa-trash-can::before { - content: "\f2ed"; } - -.fa-trash-alt::before { - content: "\f2ed"; } - -.fa-text-height::before { - content: "\f034"; } - -.fa-user-xmark::before { - content: "\f235"; } - -.fa-user-times::before { - content: "\f235"; } - -.fa-stethoscope::before { - content: "\f0f1"; } - -.fa-message::before { - content: "\f27a"; } - -.fa-comment-alt::before { - content: "\f27a"; } - -.fa-info::before { - content: "\f129"; } - -.fa-down-left-and-up-right-to-center::before { - content: "\f422"; } - -.fa-compress-alt::before { - content: "\f422"; } - -.fa-explosion::before { - content: "\e4e9"; } - -.fa-file-lines::before { - content: "\f15c"; } - -.fa-file-alt::before { - content: "\f15c"; } - -.fa-file-text::before { - content: "\f15c"; } - -.fa-wave-square::before { - content: "\f83e"; } - -.fa-ring::before { - content: "\f70b"; } - -.fa-building-un::before { - content: "\e4d9"; } - -.fa-dice-three::before { - content: "\f527"; } - -.fa-calendar-days::before { - content: "\f073"; } - -.fa-calendar-alt::before { - content: "\f073"; } - -.fa-anchor-circle-check::before { - content: "\e4aa"; } - -.fa-building-circle-arrow-right::before { - content: "\e4d1"; } - -.fa-volleyball::before { - content: "\f45f"; } - -.fa-volleyball-ball::before { - content: "\f45f"; } - -.fa-arrows-up-to-line::before { - content: "\e4c2"; } - -.fa-sort-down::before { - content: "\f0dd"; } - -.fa-sort-desc::before { - content: "\f0dd"; } - -.fa-circle-minus::before { - content: "\f056"; } - -.fa-minus-circle::before { - content: "\f056"; } - -.fa-door-open::before { - content: "\f52b"; } - -.fa-right-from-bracket::before { - content: "\f2f5"; } - -.fa-sign-out-alt::before { - content: "\f2f5"; } - -.fa-atom::before { - content: "\f5d2"; } - -.fa-soap::before { - content: "\e06e"; } - -.fa-icons::before { - content: "\f86d"; } - -.fa-heart-music-camera-bolt::before { - content: "\f86d"; } - -.fa-microphone-lines-slash::before { - content: "\f539"; } - -.fa-microphone-alt-slash::before { - content: "\f539"; } - -.fa-bridge-circle-check::before { - content: "\e4c9"; } - -.fa-pump-medical::before { - content: "\e06a"; } - -.fa-fingerprint::before { - content: "\f577"; } - -.fa-hand-point-right::before { - content: "\f0a4"; } - -.fa-magnifying-glass-location::before { - content: "\f689"; } - -.fa-search-location::before { - content: "\f689"; } - -.fa-forward-step::before { - content: "\f051"; } - -.fa-step-forward::before { - content: "\f051"; } - -.fa-face-smile-beam::before { - content: "\f5b8"; } - -.fa-smile-beam::before { - content: "\f5b8"; } - -.fa-flag-checkered::before { - content: "\f11e"; } - -.fa-football::before { - content: "\f44e"; } - -.fa-football-ball::before { - content: "\f44e"; } - -.fa-school-circle-exclamation::before { - content: "\e56c"; } - -.fa-crop::before { - content: "\f125"; } - -.fa-angles-down::before { - content: "\f103"; } - -.fa-angle-double-down::before { - content: "\f103"; } - -.fa-users-rectangle::before { - content: "\e594"; } - -.fa-people-roof::before { - content: "\e537"; } - -.fa-people-line::before { - content: "\e534"; } - -.fa-beer-mug-empty::before { - content: "\f0fc"; } - -.fa-beer::before { - content: "\f0fc"; } - -.fa-diagram-predecessor::before { - content: "\e477"; } - -.fa-arrow-up-long::before { - content: "\f176"; } - -.fa-long-arrow-up::before { - content: "\f176"; } - -.fa-fire-flame-simple::before { - content: "\f46a"; } - -.fa-burn::before { - content: "\f46a"; } - -.fa-person::before { - content: "\f183"; } - -.fa-male::before { - content: "\f183"; } - -.fa-laptop::before { - content: "\f109"; } - -.fa-file-csv::before { - content: "\f6dd"; } - -.fa-menorah::before { - content: "\f676"; } - -.fa-truck-plane::before { - content: "\e58f"; } - -.fa-record-vinyl::before { - content: "\f8d9"; } - -.fa-face-grin-stars::before { - content: "\f587"; } - -.fa-grin-stars::before { - content: "\f587"; } - -.fa-bong::before { - content: "\f55c"; } - -.fa-spaghetti-monster-flying::before { - content: "\f67b"; } - -.fa-pastafarianism::before { - content: "\f67b"; } - -.fa-arrow-down-up-across-line::before { - content: "\e4af"; } - -.fa-spoon::before { - content: "\f2e5"; } - -.fa-utensil-spoon::before { - content: "\f2e5"; } - -.fa-jar-wheat::before { - content: "\e517"; } - -.fa-envelopes-bulk::before { - content: "\f674"; } - -.fa-mail-bulk::before { - content: "\f674"; } - -.fa-file-circle-exclamation::before { - content: "\e4eb"; } - -.fa-circle-h::before { - content: "\f47e"; } - -.fa-hospital-symbol::before { - content: "\f47e"; } - -.fa-pager::before { - content: "\f815"; } - -.fa-address-book::before { - content: "\f2b9"; } - -.fa-contact-book::before { - content: "\f2b9"; } - -.fa-strikethrough::before { - content: "\f0cc"; } - -.fa-k::before { - content: "\4b"; } - -.fa-landmark-flag::before { - content: "\e51c"; } - -.fa-pencil::before { - content: "\f303"; } - -.fa-pencil-alt::before { - content: "\f303"; } - -.fa-backward::before { - content: "\f04a"; } - -.fa-caret-right::before { - content: "\f0da"; } - -.fa-comments::before { - content: "\f086"; } - -.fa-paste::before { - content: "\f0ea"; } - -.fa-file-clipboard::before { - content: "\f0ea"; } - -.fa-code-pull-request::before { - content: "\e13c"; } - -.fa-clipboard-list::before { - content: "\f46d"; } - -.fa-truck-ramp-box::before { - content: "\f4de"; } - -.fa-truck-loading::before { - content: "\f4de"; } - -.fa-user-check::before { - content: "\f4fc"; } - -.fa-vial-virus::before { - content: "\e597"; } - -.fa-sheet-plastic::before { - content: "\e571"; } - -.fa-blog::before { - content: "\f781"; } - -.fa-user-ninja::before { - content: "\f504"; } - -.fa-person-arrow-up-from-line::before { - content: "\e539"; } - -.fa-scroll-torah::before { - content: "\f6a0"; } - -.fa-torah::before { - content: "\f6a0"; } - -.fa-broom-ball::before { - content: "\f458"; } - -.fa-quidditch::before { - content: "\f458"; } - -.fa-quidditch-broom-ball::before { - content: "\f458"; } - -.fa-toggle-off::before { - content: "\f204"; } - -.fa-box-archive::before { - content: "\f187"; } - -.fa-archive::before { - content: "\f187"; } - -.fa-person-drowning::before { - content: "\e545"; } - -.fa-arrow-down-9-1::before { - content: "\f886"; } - -.fa-sort-numeric-desc::before { - content: "\f886"; } - -.fa-sort-numeric-down-alt::before { - content: "\f886"; } - -.fa-face-grin-tongue-squint::before { - content: "\f58a"; } - -.fa-grin-tongue-squint::before { - content: "\f58a"; } - -.fa-spray-can::before { - content: "\f5bd"; } - -.fa-truck-monster::before { - content: "\f63b"; } - -.fa-w::before { - content: "\57"; } - -.fa-earth-africa::before { - content: "\f57c"; } - -.fa-globe-africa::before { - content: "\f57c"; } - -.fa-rainbow::before { - content: "\f75b"; } - -.fa-circle-notch::before { - content: "\f1ce"; } - -.fa-tablet-screen-button::before { - content: "\f3fa"; } - -.fa-tablet-alt::before { - content: "\f3fa"; } - -.fa-paw::before { - content: "\f1b0"; } - -.fa-cloud::before { - content: "\f0c2"; } - -.fa-trowel-bricks::before { - content: "\e58a"; } - -.fa-face-flushed::before { - content: "\f579"; } - -.fa-flushed::before { - content: "\f579"; } - -.fa-hospital-user::before { - content: "\f80d"; } - -.fa-tent-arrow-left-right::before { - content: "\e57f"; } - -.fa-gavel::before { - content: "\f0e3"; } - -.fa-legal::before { - content: "\f0e3"; } - -.fa-binoculars::before { - content: "\f1e5"; } - -.fa-microphone-slash::before { - content: "\f131"; } - -.fa-box-tissue::before { - content: "\e05b"; } - -.fa-motorcycle::before { - content: "\f21c"; } - -.fa-bell-concierge::before { - content: "\f562"; } - -.fa-concierge-bell::before { - content: "\f562"; } - -.fa-pen-ruler::before { - content: "\f5ae"; } - -.fa-pencil-ruler::before { - content: "\f5ae"; } - -.fa-people-arrows::before { - content: "\e068"; } - -.fa-people-arrows-left-right::before { - content: "\e068"; } - -.fa-mars-and-venus-burst::before { - content: "\e523"; } - -.fa-square-caret-right::before { - content: "\f152"; } - -.fa-caret-square-right::before { - content: "\f152"; } - -.fa-scissors::before { - content: "\f0c4"; } - -.fa-cut::before { - content: "\f0c4"; } - -.fa-sun-plant-wilt::before { - content: "\e57a"; } - -.fa-toilets-portable::before { - content: "\e584"; } - -.fa-hockey-puck::before { - content: "\f453"; } - -.fa-table::before { - content: "\f0ce"; } - -.fa-magnifying-glass-arrow-right::before { - content: "\e521"; } - -.fa-tachograph-digital::before { - content: "\f566"; } - -.fa-digital-tachograph::before { - content: "\f566"; } - -.fa-users-slash::before { - content: "\e073"; } - -.fa-clover::before { - content: "\e139"; } - -.fa-reply::before { - content: "\f3e5"; } - -.fa-mail-reply::before { - content: "\f3e5"; } - -.fa-star-and-crescent::before { - content: "\f699"; } - -.fa-house-fire::before { - content: "\e50c"; } - -.fa-square-minus::before { - content: "\f146"; } - -.fa-minus-square::before { - content: "\f146"; } - -.fa-helicopter::before { - content: "\f533"; } - -.fa-compass::before { - content: "\f14e"; } - -.fa-square-caret-down::before { - content: "\f150"; } - -.fa-caret-square-down::before { - content: "\f150"; } - -.fa-file-circle-question::before { - content: "\e4ef"; } - -.fa-laptop-code::before { - content: "\f5fc"; } - -.fa-swatchbook::before { - content: "\f5c3"; } - -.fa-prescription-bottle::before { - content: "\f485"; } - -.fa-bars::before { - content: "\f0c9"; } - -.fa-navicon::before { - content: "\f0c9"; } - -.fa-people-group::before { - content: "\e533"; } - -.fa-hourglass-end::before { - content: "\f253"; } - -.fa-hourglass-3::before { - content: "\f253"; } - -.fa-heart-crack::before { - content: "\f7a9"; } - -.fa-heart-broken::before { - content: "\f7a9"; } - -.fa-square-up-right::before { - content: "\f360"; } - -.fa-external-link-square-alt::before { - content: "\f360"; } - -.fa-face-kiss-beam::before { - content: "\f597"; } - -.fa-kiss-beam::before { - content: "\f597"; } - -.fa-film::before { - content: "\f008"; } - -.fa-ruler-horizontal::before { - content: "\f547"; } - -.fa-people-robbery::before { - content: "\e536"; } - -.fa-lightbulb::before { - content: "\f0eb"; } - -.fa-caret-left::before { - content: "\f0d9"; } - -.fa-circle-exclamation::before { - content: "\f06a"; } - -.fa-exclamation-circle::before { - content: "\f06a"; } - -.fa-school-circle-xmark::before { - content: "\e56d"; } - -.fa-arrow-right-from-bracket::before { - content: "\f08b"; } - -.fa-sign-out::before { - content: "\f08b"; } - -.fa-circle-chevron-down::before { - content: "\f13a"; } - -.fa-chevron-circle-down::before { - content: "\f13a"; } - -.fa-unlock-keyhole::before { - content: "\f13e"; } - -.fa-unlock-alt::before { - content: "\f13e"; } - -.fa-cloud-showers-heavy::before { - content: "\f740"; } - -.fa-headphones-simple::before { - content: "\f58f"; } - -.fa-headphones-alt::before { - content: "\f58f"; } - -.fa-sitemap::before { - content: "\f0e8"; } - -.fa-circle-dollar-to-slot::before { - content: "\f4b9"; } - -.fa-donate::before { - content: "\f4b9"; } - -.fa-memory::before { - content: "\f538"; } - -.fa-road-spikes::before { - content: "\e568"; } - -.fa-fire-burner::before { - content: "\e4f1"; } - -.fa-flag::before { - content: "\f024"; } - -.fa-hanukiah::before { - content: "\f6e6"; } - -.fa-feather::before { - content: "\f52d"; } - -.fa-volume-low::before { - content: "\f027"; } - -.fa-volume-down::before { - content: "\f027"; } - -.fa-comment-slash::before { - content: "\f4b3"; } - -.fa-cloud-sun-rain::before { - content: "\f743"; } - -.fa-compress::before { - content: "\f066"; } - -.fa-wheat-awn::before { - content: "\e2cd"; } - -.fa-wheat-alt::before { - content: "\e2cd"; } - -.fa-ankh::before { - content: "\f644"; } - -.fa-hands-holding-child::before { - content: "\e4fa"; } - -.fa-asterisk::before { - content: "\2a"; } - -.fa-square-check::before { - content: "\f14a"; } - -.fa-check-square::before { - content: "\f14a"; } - -.fa-peseta-sign::before { - content: "\e221"; } - -.fa-heading::before { - content: "\f1dc"; } - -.fa-header::before { - content: "\f1dc"; } - -.fa-ghost::before { - content: "\f6e2"; } - -.fa-list::before { - content: "\f03a"; } - -.fa-list-squares::before { - content: "\f03a"; } - -.fa-square-phone-flip::before { - content: "\f87b"; } - -.fa-phone-square-alt::before { - content: "\f87b"; } - -.fa-cart-plus::before { - content: "\f217"; } - -.fa-gamepad::before { - content: "\f11b"; } - -.fa-circle-dot::before { - content: "\f192"; } - -.fa-dot-circle::before { - content: "\f192"; } - -.fa-face-dizzy::before { - content: "\f567"; } - -.fa-dizzy::before { - content: "\f567"; } - -.fa-egg::before { - content: "\f7fb"; } - -.fa-house-medical-circle-xmark::before { - content: "\e513"; } - -.fa-campground::before { - content: "\f6bb"; } - -.fa-folder-plus::before { - content: "\f65e"; } - -.fa-futbol::before { - content: "\f1e3"; } - -.fa-futbol-ball::before { - content: "\f1e3"; } - -.fa-soccer-ball::before { - content: "\f1e3"; } - -.fa-paintbrush::before { - content: "\f1fc"; } - -.fa-paint-brush::before { - content: "\f1fc"; } - -.fa-lock::before { - content: "\f023"; } - -.fa-gas-pump::before { - content: "\f52f"; } - -.fa-hot-tub-person::before { - content: "\f593"; } - -.fa-hot-tub::before { - content: "\f593"; } - -.fa-map-location::before { - content: "\f59f"; } - -.fa-map-marked::before { - content: "\f59f"; } - -.fa-house-flood-water::before { - content: "\e50e"; } - -.fa-tree::before { - content: "\f1bb"; } - -.fa-bridge-lock::before { - content: "\e4cc"; } - -.fa-sack-dollar::before { - content: "\f81d"; } - -.fa-pen-to-square::before { - content: "\f044"; } - -.fa-edit::before { - content: "\f044"; } - -.fa-car-side::before { - content: "\f5e4"; } - -.fa-share-nodes::before { - content: "\f1e0"; } - -.fa-share-alt::before { - content: "\f1e0"; } - -.fa-heart-circle-minus::before { - content: "\e4ff"; } - -.fa-hourglass-half::before { - content: "\f252"; } - -.fa-hourglass-2::before { - content: "\f252"; } - -.fa-microscope::before { - content: "\f610"; } - -.fa-sink::before { - content: "\e06d"; } - -.fa-bag-shopping::before { - content: "\f290"; } - -.fa-shopping-bag::before { - content: "\f290"; } - -.fa-arrow-down-z-a::before { - content: "\f881"; } - -.fa-sort-alpha-desc::before { - content: "\f881"; } - -.fa-sort-alpha-down-alt::before { - content: "\f881"; } - -.fa-mitten::before { - content: "\f7b5"; } - -.fa-person-rays::before { - content: "\e54d"; } - -.fa-users::before { - content: "\f0c0"; } - -.fa-eye-slash::before { - content: "\f070"; } - -.fa-flask-vial::before { - content: "\e4f3"; } - -.fa-hand::before { - content: "\f256"; } - -.fa-hand-paper::before { - content: "\f256"; } - -.fa-om::before { - content: "\f679"; } - -.fa-worm::before { - content: "\e599"; } - -.fa-house-circle-xmark::before { - content: "\e50b"; } - -.fa-plug::before { - content: "\f1e6"; } - -.fa-chevron-up::before { - content: "\f077"; } - -.fa-hand-spock::before { - content: "\f259"; } - -.fa-stopwatch::before { - content: "\f2f2"; } - -.fa-face-kiss::before { - content: "\f596"; } - -.fa-kiss::before { - content: "\f596"; } - -.fa-bridge-circle-xmark::before { - content: "\e4cb"; } - -.fa-face-grin-tongue::before { - content: "\f589"; } - -.fa-grin-tongue::before { - content: "\f589"; } - -.fa-chess-bishop::before { - content: "\f43a"; } - -.fa-face-grin-wink::before { - content: "\f58c"; } - -.fa-grin-wink::before { - content: "\f58c"; } - -.fa-ear-deaf::before { - content: "\f2a4"; } - -.fa-deaf::before { - content: "\f2a4"; } - -.fa-deafness::before { - content: "\f2a4"; } - -.fa-hard-of-hearing::before { - content: "\f2a4"; } - -.fa-road-circle-check::before { - content: "\e564"; } - -.fa-dice-five::before { - content: "\f523"; } - -.fa-square-rss::before { - content: "\f143"; } - -.fa-rss-square::before { - content: "\f143"; } - -.fa-land-mine-on::before { - content: "\e51b"; } - -.fa-i-cursor::before { - content: "\f246"; } - -.fa-stamp::before { - content: "\f5bf"; } - -.fa-stairs::before { - content: "\e289"; } - -.fa-i::before { - content: "\49"; } - -.fa-hryvnia-sign::before { - content: "\f6f2"; } - -.fa-hryvnia::before { - content: "\f6f2"; } - -.fa-pills::before { - content: "\f484"; } - -.fa-face-grin-wide::before { - content: "\f581"; } - -.fa-grin-alt::before { - content: "\f581"; } - -.fa-tooth::before { - content: "\f5c9"; } - -.fa-v::before { - content: "\56"; } - -.fa-bangladeshi-taka-sign::before { - content: "\e2e6"; } - -.fa-bicycle::before { - content: "\f206"; } - -.fa-staff-snake::before { - content: "\e579"; } - -.fa-rod-asclepius::before { - content: "\e579"; } - -.fa-rod-snake::before { - content: "\e579"; } - -.fa-staff-aesculapius::before { - content: "\e579"; } - -.fa-head-side-cough-slash::before { - content: "\e062"; } - -.fa-truck-medical::before { - content: "\f0f9"; } - -.fa-ambulance::before { - content: "\f0f9"; } - -.fa-wheat-awn-circle-exclamation::before { - content: "\e598"; } - -.fa-snowman::before { - content: "\f7d0"; } - -.fa-mortar-pestle::before { - content: "\f5a7"; } - -.fa-road-barrier::before { - content: "\e562"; } - -.fa-school::before { - content: "\f549"; } - -.fa-igloo::before { - content: "\f7ae"; } - -.fa-joint::before { - content: "\f595"; } - -.fa-angle-right::before { - content: "\f105"; } - -.fa-horse::before { - content: "\f6f0"; } - -.fa-q::before { - content: "\51"; } - -.fa-g::before { - content: "\47"; } - -.fa-notes-medical::before { - content: "\f481"; } - -.fa-temperature-half::before { - content: "\f2c9"; } - -.fa-temperature-2::before { - content: "\f2c9"; } - -.fa-thermometer-2::before { - content: "\f2c9"; } - -.fa-thermometer-half::before { - content: "\f2c9"; } - -.fa-dong-sign::before { - content: "\e169"; } - -.fa-capsules::before { - content: "\f46b"; } - -.fa-poo-storm::before { - content: "\f75a"; } - -.fa-poo-bolt::before { - content: "\f75a"; } - -.fa-face-frown-open::before { - content: "\f57a"; } - -.fa-frown-open::before { - content: "\f57a"; } - -.fa-hand-point-up::before { - content: "\f0a6"; } - -.fa-money-bill::before { - content: "\f0d6"; } - -.fa-bookmark::before { - content: "\f02e"; } - -.fa-align-justify::before { - content: "\f039"; } - -.fa-umbrella-beach::before { - content: "\f5ca"; } - -.fa-helmet-un::before { - content: "\e503"; } - -.fa-bullseye::before { - content: "\f140"; } - -.fa-bacon::before { - content: "\f7e5"; } - -.fa-hand-point-down::before { - content: "\f0a7"; } - -.fa-arrow-up-from-bracket::before { - content: "\e09a"; } - -.fa-folder::before { - content: "\f07b"; } - -.fa-folder-blank::before { - content: "\f07b"; } - -.fa-file-waveform::before { - content: "\f478"; } - -.fa-file-medical-alt::before { - content: "\f478"; } - -.fa-radiation::before { - content: "\f7b9"; } - -.fa-chart-simple::before { - content: "\e473"; } - -.fa-mars-stroke::before { - content: "\f229"; } - -.fa-vial::before { - content: "\f492"; } - -.fa-gauge::before { - content: "\f624"; } - -.fa-dashboard::before { - content: "\f624"; } - -.fa-gauge-med::before { - content: "\f624"; } - -.fa-tachometer-alt-average::before { - content: "\f624"; } - -.fa-wand-magic-sparkles::before { - content: "\e2ca"; } - -.fa-magic-wand-sparkles::before { - content: "\e2ca"; } - -.fa-e::before { - content: "\45"; } - -.fa-pen-clip::before { - content: "\f305"; } - -.fa-pen-alt::before { - content: "\f305"; } - -.fa-bridge-circle-exclamation::before { - content: "\e4ca"; } - -.fa-user::before { - content: "\f007"; } - -.fa-school-circle-check::before { - content: "\e56b"; } - -.fa-dumpster::before { - content: "\f793"; } - -.fa-van-shuttle::before { - content: "\f5b6"; } - -.fa-shuttle-van::before { - content: "\f5b6"; } - -.fa-building-user::before { - content: "\e4da"; } - -.fa-square-caret-left::before { - content: "\f191"; } - -.fa-caret-square-left::before { - content: "\f191"; } - -.fa-highlighter::before { - content: "\f591"; } - -.fa-key::before { - content: "\f084"; } - -.fa-bullhorn::before { - content: "\f0a1"; } - -.fa-globe::before { - content: "\f0ac"; } - -.fa-synagogue::before { - content: "\f69b"; } - -.fa-person-half-dress::before { - content: "\e548"; } - -.fa-road-bridge::before { - content: "\e563"; } - -.fa-location-arrow::before { - content: "\f124"; } - -.fa-c::before { - content: "\43"; } - -.fa-tablet-button::before { - content: "\f10a"; } - -.fa-building-lock::before { - content: "\e4d6"; } - -.fa-pizza-slice::before { - content: "\f818"; } - -.fa-money-bill-wave::before { - content: "\f53a"; } - -.fa-chart-area::before { - content: "\f1fe"; } - -.fa-area-chart::before { - content: "\f1fe"; } - -.fa-house-flag::before { - content: "\e50d"; } - -.fa-person-circle-minus::before { - content: "\e540"; } - -.fa-ban::before { - content: "\f05e"; } - -.fa-cancel::before { - content: "\f05e"; } - -.fa-camera-rotate::before { - content: "\e0d8"; } - -.fa-spray-can-sparkles::before { - content: "\f5d0"; } - -.fa-air-freshener::before { - content: "\f5d0"; } - -.fa-star::before { - content: "\f005"; } - -.fa-repeat::before { - content: "\f363"; } - -.fa-cross::before { - content: "\f654"; } - -.fa-box::before { - content: "\f466"; } - -.fa-venus-mars::before { - content: "\f228"; } - -.fa-arrow-pointer::before { - content: "\f245"; } - -.fa-mouse-pointer::before { - content: "\f245"; } - -.fa-maximize::before { - content: "\f31e"; } - -.fa-expand-arrows-alt::before { - content: "\f31e"; } - -.fa-charging-station::before { - content: "\f5e7"; } - -.fa-shapes::before { - content: "\f61f"; } - -.fa-triangle-circle-square::before { - content: "\f61f"; } - -.fa-shuffle::before { - content: "\f074"; } - -.fa-random::before { - content: "\f074"; } - -.fa-person-running::before { - content: "\f70c"; } - -.fa-running::before { - content: "\f70c"; } - -.fa-mobile-retro::before { - content: "\e527"; } - -.fa-grip-lines-vertical::before { - content: "\f7a5"; } - -.fa-spider::before { - content: "\f717"; } - -.fa-hands-bound::before { - content: "\e4f9"; } - -.fa-file-invoice-dollar::before { - content: "\f571"; } - -.fa-plane-circle-exclamation::before { - content: "\e556"; } - -.fa-x-ray::before { - content: "\f497"; } - -.fa-spell-check::before { - content: "\f891"; } - -.fa-slash::before { - content: "\f715"; } - -.fa-computer-mouse::before { - content: "\f8cc"; } - -.fa-mouse::before { - content: "\f8cc"; } - -.fa-arrow-right-to-bracket::before { - content: "\f090"; } - -.fa-sign-in::before { - content: "\f090"; } - -.fa-shop-slash::before { - content: "\e070"; } - -.fa-store-alt-slash::before { - content: "\e070"; } - -.fa-server::before { - content: "\f233"; } - -.fa-virus-covid-slash::before { - content: "\e4a9"; } - -.fa-shop-lock::before { - content: "\e4a5"; } - -.fa-hourglass-start::before { - content: "\f251"; } - -.fa-hourglass-1::before { - content: "\f251"; } - -.fa-blender-phone::before { - content: "\f6b6"; } - -.fa-building-wheat::before { - content: "\e4db"; } - -.fa-person-breastfeeding::before { - content: "\e53a"; } - -.fa-right-to-bracket::before { - content: "\f2f6"; } - -.fa-sign-in-alt::before { - content: "\f2f6"; } - -.fa-venus::before { - content: "\f221"; } - -.fa-passport::before { - content: "\f5ab"; } - -.fa-heart-pulse::before { - content: "\f21e"; } - -.fa-heartbeat::before { - content: "\f21e"; } - -.fa-people-carry-box::before { - content: "\f4ce"; } - -.fa-people-carry::before { - content: "\f4ce"; } - -.fa-temperature-high::before { - content: "\f769"; } - -.fa-microchip::before { - content: "\f2db"; } - -.fa-crown::before { - content: "\f521"; } - -.fa-weight-hanging::before { - content: "\f5cd"; } - -.fa-xmarks-lines::before { - content: "\e59a"; } - -.fa-file-prescription::before { - content: "\f572"; } - -.fa-weight-scale::before { - content: "\f496"; } - -.fa-weight::before { - content: "\f496"; } - -.fa-user-group::before { - content: "\f500"; } - -.fa-user-friends::before { - content: "\f500"; } - -.fa-arrow-up-a-z::before { - content: "\f15e"; } - -.fa-sort-alpha-up::before { - content: "\f15e"; } - -.fa-chess-knight::before { - content: "\f441"; } - -.fa-face-laugh-squint::before { - content: "\f59b"; } - -.fa-laugh-squint::before { - content: "\f59b"; } - -.fa-wheelchair::before { - content: "\f193"; } - -.fa-circle-arrow-up::before { - content: "\f0aa"; } - -.fa-arrow-circle-up::before { - content: "\f0aa"; } - -.fa-toggle-on::before { - content: "\f205"; } - -.fa-person-walking::before { - content: "\f554"; } - -.fa-walking::before { - content: "\f554"; } - -.fa-l::before { - content: "\4c"; } - -.fa-fire::before { - content: "\f06d"; } - -.fa-bed-pulse::before { - content: "\f487"; } - -.fa-procedures::before { - content: "\f487"; } - -.fa-shuttle-space::before { - content: "\f197"; } - -.fa-space-shuttle::before { - content: "\f197"; } - -.fa-face-laugh::before { - content: "\f599"; } - -.fa-laugh::before { - content: "\f599"; } - -.fa-folder-open::before { - content: "\f07c"; } - -.fa-heart-circle-plus::before { - content: "\e500"; } - -.fa-code-fork::before { - content: "\e13b"; } - -.fa-city::before { - content: "\f64f"; } - -.fa-microphone-lines::before { - content: "\f3c9"; } - -.fa-microphone-alt::before { - content: "\f3c9"; } - -.fa-pepper-hot::before { - content: "\f816"; } - -.fa-unlock::before { - content: "\f09c"; } - -.fa-colon-sign::before { - content: "\e140"; } - -.fa-headset::before { - content: "\f590"; } - -.fa-store-slash::before { - content: "\e071"; } - -.fa-road-circle-xmark::before { - content: "\e566"; } - -.fa-user-minus::before { - content: "\f503"; } - -.fa-mars-stroke-up::before { - content: "\f22a"; } - -.fa-mars-stroke-v::before { - content: "\f22a"; } - -.fa-champagne-glasses::before { - content: "\f79f"; } - -.fa-glass-cheers::before { - content: "\f79f"; } - -.fa-clipboard::before { - content: "\f328"; } - -.fa-house-circle-exclamation::before { - content: "\e50a"; } - -.fa-file-arrow-up::before { - content: "\f574"; } - -.fa-file-upload::before { - content: "\f574"; } - -.fa-wifi::before { - content: "\f1eb"; } - -.fa-wifi-3::before { - content: "\f1eb"; } - -.fa-wifi-strong::before { - content: "\f1eb"; } - -.fa-bath::before { - content: "\f2cd"; } - -.fa-bathtub::before { - content: "\f2cd"; } - -.fa-underline::before { - content: "\f0cd"; } - -.fa-user-pen::before { - content: "\f4ff"; } - -.fa-user-edit::before { - content: "\f4ff"; } - -.fa-signature::before { - content: "\f5b7"; } - -.fa-stroopwafel::before { - content: "\f551"; } - -.fa-bold::before { - content: "\f032"; } - -.fa-anchor-lock::before { - content: "\e4ad"; } - -.fa-building-ngo::before { - content: "\e4d7"; } - -.fa-manat-sign::before { - content: "\e1d5"; } - -.fa-not-equal::before { - content: "\f53e"; } - -.fa-border-top-left::before { - content: "\f853"; } - -.fa-border-style::before { - content: "\f853"; } - -.fa-map-location-dot::before { - content: "\f5a0"; } - -.fa-map-marked-alt::before { - content: "\f5a0"; } - -.fa-jedi::before { - content: "\f669"; } - -.fa-square-poll-vertical::before { - content: "\f681"; } - -.fa-poll::before { - content: "\f681"; } - -.fa-mug-hot::before { - content: "\f7b6"; } - -.fa-car-battery::before { - content: "\f5df"; } - -.fa-battery-car::before { - content: "\f5df"; } - -.fa-gift::before { - content: "\f06b"; } - -.fa-dice-two::before { - content: "\f528"; } - -.fa-chess-queen::before { - content: "\f445"; } - -.fa-glasses::before { - content: "\f530"; } - -.fa-chess-board::before { - content: "\f43c"; } - -.fa-building-circle-check::before { - content: "\e4d2"; } - -.fa-person-chalkboard::before { - content: "\e53d"; } - -.fa-mars-stroke-right::before { - content: "\f22b"; } - -.fa-mars-stroke-h::before { - content: "\f22b"; } - -.fa-hand-back-fist::before { - content: "\f255"; } - -.fa-hand-rock::before { - content: "\f255"; } - -.fa-square-caret-up::before { - content: "\f151"; } - -.fa-caret-square-up::before { - content: "\f151"; } - -.fa-cloud-showers-water::before { - content: "\e4e4"; } - -.fa-chart-bar::before { - content: "\f080"; } - -.fa-bar-chart::before { - content: "\f080"; } - -.fa-hands-bubbles::before { - content: "\e05e"; } - -.fa-hands-wash::before { - content: "\e05e"; } - -.fa-less-than-equal::before { - content: "\f537"; } - -.fa-train::before { - content: "\f238"; } - -.fa-eye-low-vision::before { - content: "\f2a8"; } - -.fa-low-vision::before { - content: "\f2a8"; } - -.fa-crow::before { - content: "\f520"; } - -.fa-sailboat::before { - content: "\e445"; } - -.fa-window-restore::before { - content: "\f2d2"; } - -.fa-square-plus::before { - content: "\f0fe"; } - -.fa-plus-square::before { - content: "\f0fe"; } - -.fa-torii-gate::before { - content: "\f6a1"; } - -.fa-frog::before { - content: "\f52e"; } - -.fa-bucket::before { - content: "\e4cf"; } - -.fa-image::before { - content: "\f03e"; } - -.fa-microphone::before { - content: "\f130"; } - -.fa-cow::before { - content: "\f6c8"; } - -.fa-caret-up::before { - content: "\f0d8"; } - -.fa-screwdriver::before { - content: "\f54a"; } - -.fa-folder-closed::before { - content: "\e185"; } - -.fa-house-tsunami::before { - content: "\e515"; } - -.fa-square-nfi::before { - content: "\e576"; } - -.fa-arrow-up-from-ground-water::before { - content: "\e4b5"; } - -.fa-martini-glass::before { - content: "\f57b"; } - -.fa-glass-martini-alt::before { - content: "\f57b"; } - -.fa-rotate-left::before { - content: "\f2ea"; } - -.fa-rotate-back::before { - content: "\f2ea"; } - -.fa-rotate-backward::before { - content: "\f2ea"; } - -.fa-undo-alt::before { - content: "\f2ea"; } - -.fa-table-columns::before { - content: "\f0db"; } - -.fa-columns::before { - content: "\f0db"; } - -.fa-lemon::before { - content: "\f094"; } - -.fa-head-side-mask::before { - content: "\e063"; } - -.fa-handshake::before { - content: "\f2b5"; } - -.fa-gem::before { - content: "\f3a5"; } - -.fa-dolly::before { - content: "\f472"; } - -.fa-dolly-box::before { - content: "\f472"; } - -.fa-smoking::before { - content: "\f48d"; } - -.fa-minimize::before { - content: "\f78c"; } - -.fa-compress-arrows-alt::before { - content: "\f78c"; } - -.fa-monument::before { - content: "\f5a6"; } - -.fa-snowplow::before { - content: "\f7d2"; } - -.fa-angles-right::before { - content: "\f101"; } - -.fa-angle-double-right::before { - content: "\f101"; } - -.fa-cannabis::before { - content: "\f55f"; } - -.fa-circle-play::before { - content: "\f144"; } - -.fa-play-circle::before { - content: "\f144"; } - -.fa-tablets::before { - content: "\f490"; } - -.fa-ethernet::before { - content: "\f796"; } - -.fa-euro-sign::before { - content: "\f153"; } - -.fa-eur::before { - content: "\f153"; } - -.fa-euro::before { - content: "\f153"; } - -.fa-chair::before { - content: "\f6c0"; } - -.fa-circle-check::before { - content: "\f058"; } - -.fa-check-circle::before { - content: "\f058"; } - -.fa-circle-stop::before { - content: "\f28d"; } - -.fa-stop-circle::before { - content: "\f28d"; } - -.fa-compass-drafting::before { - content: "\f568"; } - -.fa-drafting-compass::before { - content: "\f568"; } - -.fa-plate-wheat::before { - content: "\e55a"; } - -.fa-icicles::before { - content: "\f7ad"; } - -.fa-person-shelter::before { - content: "\e54f"; } - -.fa-neuter::before { - content: "\f22c"; } - -.fa-id-badge::before { - content: "\f2c1"; } - -.fa-marker::before { - content: "\f5a1"; } - -.fa-face-laugh-beam::before { - content: "\f59a"; } - -.fa-laugh-beam::before { - content: "\f59a"; } - -.fa-helicopter-symbol::before { - content: "\e502"; } - -.fa-universal-access::before { - content: "\f29a"; } - -.fa-circle-chevron-up::before { - content: "\f139"; } - -.fa-chevron-circle-up::before { - content: "\f139"; } - -.fa-lari-sign::before { - content: "\e1c8"; } - -.fa-volcano::before { - content: "\f770"; } - -.fa-person-walking-dashed-line-arrow-right::before { - content: "\e553"; } - -.fa-sterling-sign::before { - content: "\f154"; } - -.fa-gbp::before { - content: "\f154"; } - -.fa-pound-sign::before { - content: "\f154"; } - -.fa-viruses::before { - content: "\e076"; } - -.fa-square-person-confined::before { - content: "\e577"; } - -.fa-user-tie::before { - content: "\f508"; } - -.fa-arrow-down-long::before { - content: "\f175"; } - -.fa-long-arrow-down::before { - content: "\f175"; } - -.fa-tent-arrow-down-to-line::before { - content: "\e57e"; } - -.fa-certificate::before { - content: "\f0a3"; } - -.fa-reply-all::before { - content: "\f122"; } - -.fa-mail-reply-all::before { - content: "\f122"; } - -.fa-suitcase::before { - content: "\f0f2"; } - -.fa-person-skating::before { - content: "\f7c5"; } - -.fa-skating::before { - content: "\f7c5"; } - -.fa-filter-circle-dollar::before { - content: "\f662"; } - -.fa-funnel-dollar::before { - content: "\f662"; } - -.fa-camera-retro::before { - content: "\f083"; } - -.fa-circle-arrow-down::before { - content: "\f0ab"; } - -.fa-arrow-circle-down::before { - content: "\f0ab"; } - -.fa-file-import::before { - content: "\f56f"; } - -.fa-arrow-right-to-file::before { - content: "\f56f"; } - -.fa-square-arrow-up-right::before { - content: "\f14c"; } - -.fa-external-link-square::before { - content: "\f14c"; } - -.fa-box-open::before { - content: "\f49e"; } - -.fa-scroll::before { - content: "\f70e"; } - -.fa-spa::before { - content: "\f5bb"; } - -.fa-location-pin-lock::before { - content: "\e51f"; } - -.fa-pause::before { - content: "\f04c"; } - -.fa-hill-avalanche::before { - content: "\e507"; } - -.fa-temperature-empty::before { - content: "\f2cb"; } - -.fa-temperature-0::before { - content: "\f2cb"; } - -.fa-thermometer-0::before { - content: "\f2cb"; } - -.fa-thermometer-empty::before { - content: "\f2cb"; } - -.fa-bomb::before { - content: "\f1e2"; } - -.fa-registered::before { - content: "\f25d"; } - -.fa-address-card::before { - content: "\f2bb"; } - -.fa-contact-card::before { - content: "\f2bb"; } - -.fa-vcard::before { - content: "\f2bb"; } - -.fa-scale-unbalanced-flip::before { - content: "\f516"; } - -.fa-balance-scale-right::before { - content: "\f516"; } - -.fa-subscript::before { - content: "\f12c"; } - -.fa-diamond-turn-right::before { - content: "\f5eb"; } - -.fa-directions::before { - content: "\f5eb"; } - -.fa-burst::before { - content: "\e4dc"; } - -.fa-house-laptop::before { - content: "\e066"; } - -.fa-laptop-house::before { - content: "\e066"; } - -.fa-face-tired::before { - content: "\f5c8"; } - -.fa-tired::before { - content: "\f5c8"; } - -.fa-money-bills::before { - content: "\e1f3"; } - -.fa-smog::before { - content: "\f75f"; } - -.fa-crutch::before { - content: "\f7f7"; } - -.fa-cloud-arrow-up::before { - content: "\f0ee"; } - -.fa-cloud-upload::before { - content: "\f0ee"; } - -.fa-cloud-upload-alt::before { - content: "\f0ee"; } - -.fa-palette::before { - content: "\f53f"; } - -.fa-arrows-turn-right::before { - content: "\e4c0"; } - -.fa-vest::before { - content: "\e085"; } - -.fa-ferry::before { - content: "\e4ea"; } - -.fa-arrows-down-to-people::before { - content: "\e4b9"; } - -.fa-seedling::before { - content: "\f4d8"; } - -.fa-sprout::before { - content: "\f4d8"; } - -.fa-left-right::before { - content: "\f337"; } - -.fa-arrows-alt-h::before { - content: "\f337"; } - -.fa-boxes-packing::before { - content: "\e4c7"; } - -.fa-circle-arrow-left::before { - content: "\f0a8"; } - -.fa-arrow-circle-left::before { - content: "\f0a8"; } - -.fa-group-arrows-rotate::before { - content: "\e4f6"; } - -.fa-bowl-food::before { - content: "\e4c6"; } - -.fa-candy-cane::before { - content: "\f786"; } - -.fa-arrow-down-wide-short::before { - content: "\f160"; } - -.fa-sort-amount-asc::before { - content: "\f160"; } - -.fa-sort-amount-down::before { - content: "\f160"; } - -.fa-cloud-bolt::before { - content: "\f76c"; } - -.fa-thunderstorm::before { - content: "\f76c"; } - -.fa-text-slash::before { - content: "\f87d"; } - -.fa-remove-format::before { - content: "\f87d"; } - -.fa-face-smile-wink::before { - content: "\f4da"; } - -.fa-smile-wink::before { - content: "\f4da"; } - -.fa-file-word::before { - content: "\f1c2"; } - -.fa-file-powerpoint::before { - content: "\f1c4"; } - -.fa-arrows-left-right::before { - content: "\f07e"; } - -.fa-arrows-h::before { - content: "\f07e"; } - -.fa-house-lock::before { - content: "\e510"; } - -.fa-cloud-arrow-down::before { - content: "\f0ed"; } - -.fa-cloud-download::before { - content: "\f0ed"; } - -.fa-cloud-download-alt::before { - content: "\f0ed"; } - -.fa-children::before { - content: "\e4e1"; } - -.fa-chalkboard::before { - content: "\f51b"; } - -.fa-blackboard::before { - content: "\f51b"; } - -.fa-user-large-slash::before { - content: "\f4fa"; } - -.fa-user-alt-slash::before { - content: "\f4fa"; } - -.fa-envelope-open::before { - content: "\f2b6"; } - -.fa-handshake-simple-slash::before { - content: "\e05f"; } - -.fa-handshake-alt-slash::before { - content: "\e05f"; } - -.fa-mattress-pillow::before { - content: "\e525"; } - -.fa-guarani-sign::before { - content: "\e19a"; } - -.fa-arrows-rotate::before { - content: "\f021"; } - -.fa-refresh::before { - content: "\f021"; } - -.fa-sync::before { - content: "\f021"; } - -.fa-fire-extinguisher::before { - content: "\f134"; } - -.fa-cruzeiro-sign::before { - content: "\e152"; } - -.fa-greater-than-equal::before { - content: "\f532"; } - -.fa-shield-halved::before { - content: "\f3ed"; } - -.fa-shield-alt::before { - content: "\f3ed"; } - -.fa-book-atlas::before { - content: "\f558"; } - -.fa-atlas::before { - content: "\f558"; } - -.fa-virus::before { - content: "\e074"; } - -.fa-envelope-circle-check::before { - content: "\e4e8"; } - -.fa-layer-group::before { - content: "\f5fd"; } - -.fa-arrows-to-dot::before { - content: "\e4be"; } - -.fa-archway::before { - content: "\f557"; } - -.fa-heart-circle-check::before { - content: "\e4fd"; } - -.fa-house-chimney-crack::before { - content: "\f6f1"; } - -.fa-house-damage::before { - content: "\f6f1"; } - -.fa-file-zipper::before { - content: "\f1c6"; } - -.fa-file-archive::before { - content: "\f1c6"; } - -.fa-square::before { - content: "\f0c8"; } - -.fa-martini-glass-empty::before { - content: "\f000"; } - -.fa-glass-martini::before { - content: "\f000"; } - -.fa-couch::before { - content: "\f4b8"; } - -.fa-cedi-sign::before { - content: "\e0df"; } - -.fa-italic::before { - content: "\f033"; } - -.fa-church::before { - content: "\f51d"; } - -.fa-comments-dollar::before { - content: "\f653"; } - -.fa-democrat::before { - content: "\f747"; } - -.fa-z::before { - content: "\5a"; } - -.fa-person-skiing::before { - content: "\f7c9"; } - -.fa-skiing::before { - content: "\f7c9"; } - -.fa-road-lock::before { - content: "\e567"; } - -.fa-a::before { - content: "\41"; } - -.fa-temperature-arrow-down::before { - content: "\e03f"; } - -.fa-temperature-down::before { - content: "\e03f"; } - -.fa-feather-pointed::before { - content: "\f56b"; } - -.fa-feather-alt::before { - content: "\f56b"; } - -.fa-p::before { - content: "\50"; } - -.fa-snowflake::before { - content: "\f2dc"; } - -.fa-newspaper::before { - content: "\f1ea"; } - -.fa-rectangle-ad::before { - content: "\f641"; } - -.fa-ad::before { - content: "\f641"; } - -.fa-circle-arrow-right::before { - content: "\f0a9"; } - -.fa-arrow-circle-right::before { - content: "\f0a9"; } - -.fa-filter-circle-xmark::before { - content: "\e17b"; } - -.fa-locust::before { - content: "\e520"; } - -.fa-sort::before { - content: "\f0dc"; } - -.fa-unsorted::before { - content: "\f0dc"; } - -.fa-list-ol::before { - content: "\f0cb"; } - -.fa-list-1-2::before { - content: "\f0cb"; } - -.fa-list-numeric::before { - content: "\f0cb"; } - -.fa-person-dress-burst::before { - content: "\e544"; } - -.fa-money-check-dollar::before { - content: "\f53d"; } - -.fa-money-check-alt::before { - content: "\f53d"; } - -.fa-vector-square::before { - content: "\f5cb"; } - -.fa-bread-slice::before { - content: "\f7ec"; } - -.fa-language::before { - content: "\f1ab"; } - -.fa-face-kiss-wink-heart::before { - content: "\f598"; } - -.fa-kiss-wink-heart::before { - content: "\f598"; } - -.fa-filter::before { - content: "\f0b0"; } - -.fa-question::before { - content: "\3f"; } - -.fa-file-signature::before { - content: "\f573"; } - -.fa-up-down-left-right::before { - content: "\f0b2"; } - -.fa-arrows-alt::before { - content: "\f0b2"; } - -.fa-house-chimney-user::before { - content: "\e065"; } - -.fa-hand-holding-heart::before { - content: "\f4be"; } - -.fa-puzzle-piece::before { - content: "\f12e"; } - -.fa-money-check::before { - content: "\f53c"; } - -.fa-star-half-stroke::before { - content: "\f5c0"; } - -.fa-star-half-alt::before { - content: "\f5c0"; } - -.fa-code::before { - content: "\f121"; } - -.fa-whiskey-glass::before { - content: "\f7a0"; } - -.fa-glass-whiskey::before { - content: "\f7a0"; } - -.fa-building-circle-exclamation::before { - content: "\e4d3"; } - -.fa-magnifying-glass-chart::before { - content: "\e522"; } - -.fa-arrow-up-right-from-square::before { - content: "\f08e"; } - -.fa-external-link::before { - content: "\f08e"; } - -.fa-cubes-stacked::before { - content: "\e4e6"; } - -.fa-won-sign::before { - content: "\f159"; } - -.fa-krw::before { - content: "\f159"; } - -.fa-won::before { - content: "\f159"; } - -.fa-virus-covid::before { - content: "\e4a8"; } - -.fa-austral-sign::before { - content: "\e0a9"; } - -.fa-f::before { - content: "\46"; } - -.fa-leaf::before { - content: "\f06c"; } - -.fa-road::before { - content: "\f018"; } - -.fa-taxi::before { - content: "\f1ba"; } - -.fa-cab::before { - content: "\f1ba"; } - -.fa-person-circle-plus::before { - content: "\e541"; } - -.fa-chart-pie::before { - content: "\f200"; } - -.fa-pie-chart::before { - content: "\f200"; } - -.fa-bolt-lightning::before { - content: "\e0b7"; } - -.fa-sack-xmark::before { - content: "\e56a"; } - -.fa-file-excel::before { - content: "\f1c3"; } - -.fa-file-contract::before { - content: "\f56c"; } - -.fa-fish-fins::before { - content: "\e4f2"; } - -.fa-building-flag::before { - content: "\e4d5"; } - -.fa-face-grin-beam::before { - content: "\f582"; } - -.fa-grin-beam::before { - content: "\f582"; } - -.fa-object-ungroup::before { - content: "\f248"; } - -.fa-poop::before { - content: "\f619"; } - -.fa-location-pin::before { - content: "\f041"; } - -.fa-map-marker::before { - content: "\f041"; } - -.fa-kaaba::before { - content: "\f66b"; } - -.fa-toilet-paper::before { - content: "\f71e"; } - -.fa-helmet-safety::before { - content: "\f807"; } - -.fa-hard-hat::before { - content: "\f807"; } - -.fa-hat-hard::before { - content: "\f807"; } - -.fa-eject::before { - content: "\f052"; } - -.fa-circle-right::before { - content: "\f35a"; } - -.fa-arrow-alt-circle-right::before { - content: "\f35a"; } - -.fa-plane-circle-check::before { - content: "\e555"; } - -.fa-face-rolling-eyes::before { - content: "\f5a5"; } - -.fa-meh-rolling-eyes::before { - content: "\f5a5"; } - -.fa-object-group::before { - content: "\f247"; } - -.fa-chart-line::before { - content: "\f201"; } - -.fa-line-chart::before { - content: "\f201"; } - -.fa-mask-ventilator::before { - content: "\e524"; } - -.fa-arrow-right::before { - content: "\f061"; } - -.fa-signs-post::before { - content: "\f277"; } - -.fa-map-signs::before { - content: "\f277"; } - -.fa-cash-register::before { - content: "\f788"; } - -.fa-person-circle-question::before { - content: "\e542"; } - -.fa-h::before { - content: "\48"; } - -.fa-tarp::before { - content: "\e57b"; } - -.fa-screwdriver-wrench::before { - content: "\f7d9"; } - -.fa-tools::before { - content: "\f7d9"; } - -.fa-arrows-to-eye::before { - content: "\e4bf"; } - -.fa-plug-circle-bolt::before { - content: "\e55b"; } - -.fa-heart::before { - content: "\f004"; } - -.fa-mars-and-venus::before { - content: "\f224"; } - -.fa-house-user::before { - content: "\e1b0"; } - -.fa-home-user::before { - content: "\e1b0"; } - -.fa-dumpster-fire::before { - content: "\f794"; } - -.fa-house-crack::before { - content: "\e3b1"; } - -.fa-martini-glass-citrus::before { - content: "\f561"; } - -.fa-cocktail::before { - content: "\f561"; } - -.fa-face-surprise::before { - content: "\f5c2"; } - -.fa-surprise::before { - content: "\f5c2"; } - -.fa-bottle-water::before { - content: "\e4c5"; } - -.fa-circle-pause::before { - content: "\f28b"; } - -.fa-pause-circle::before { - content: "\f28b"; } - -.fa-toilet-paper-slash::before { - content: "\e072"; } - -.fa-apple-whole::before { - content: "\f5d1"; } - -.fa-apple-alt::before { - content: "\f5d1"; } - -.fa-kitchen-set::before { - content: "\e51a"; } - -.fa-r::before { - content: "\52"; } - -.fa-temperature-quarter::before { - content: "\f2ca"; } - -.fa-temperature-1::before { - content: "\f2ca"; } - -.fa-thermometer-1::before { - content: "\f2ca"; } - -.fa-thermometer-quarter::before { - content: "\f2ca"; } - -.fa-cube::before { - content: "\f1b2"; } - -.fa-bitcoin-sign::before { - content: "\e0b4"; } - -.fa-shield-dog::before { - content: "\e573"; } - -.fa-solar-panel::before { - content: "\f5ba"; } - -.fa-lock-open::before { - content: "\f3c1"; } - -.fa-elevator::before { - content: "\e16d"; } - -.fa-money-bill-transfer::before { - content: "\e528"; } - -.fa-money-bill-trend-up::before { - content: "\e529"; } - -.fa-house-flood-water-circle-arrow-right::before { - content: "\e50f"; } - -.fa-square-poll-horizontal::before { - content: "\f682"; } - -.fa-poll-h::before { - content: "\f682"; } - -.fa-circle::before { - content: "\f111"; } - -.fa-backward-fast::before { - content: "\f049"; } - -.fa-fast-backward::before { - content: "\f049"; } - -.fa-recycle::before { - content: "\f1b8"; } - -.fa-user-astronaut::before { - content: "\f4fb"; } - -.fa-plane-slash::before { - content: "\e069"; } - -.fa-trademark::before { - content: "\f25c"; } - -.fa-basketball::before { - content: "\f434"; } - -.fa-basketball-ball::before { - content: "\f434"; } - -.fa-satellite-dish::before { - content: "\f7c0"; } - -.fa-circle-up::before { - content: "\f35b"; } - -.fa-arrow-alt-circle-up::before { - content: "\f35b"; } - -.fa-mobile-screen-button::before { - content: "\f3cd"; } - -.fa-mobile-alt::before { - content: "\f3cd"; } - -.fa-volume-high::before { - content: "\f028"; } - -.fa-volume-up::before { - content: "\f028"; } - -.fa-users-rays::before { - content: "\e593"; } - -.fa-wallet::before { - content: "\f555"; } - -.fa-clipboard-check::before { - content: "\f46c"; } - -.fa-file-audio::before { - content: "\f1c7"; } - -.fa-burger::before { - content: "\f805"; } - -.fa-hamburger::before { - content: "\f805"; } - -.fa-wrench::before { - content: "\f0ad"; } - -.fa-bugs::before { - content: "\e4d0"; } - -.fa-rupee-sign::before { - content: "\f156"; } - -.fa-rupee::before { - content: "\f156"; } - -.fa-file-image::before { - content: "\f1c5"; } - -.fa-circle-question::before { - content: "\f059"; } - -.fa-question-circle::before { - content: "\f059"; } - -.fa-plane-departure::before { - content: "\f5b0"; } - -.fa-handshake-slash::before { - content: "\e060"; } - -.fa-book-bookmark::before { - content: "\e0bb"; } - -.fa-code-branch::before { - content: "\f126"; } - -.fa-hat-cowboy::before { - content: "\f8c0"; } - -.fa-bridge::before { - content: "\e4c8"; } - -.fa-phone-flip::before { - content: "\f879"; } - -.fa-phone-alt::before { - content: "\f879"; } - -.fa-truck-front::before { - content: "\e2b7"; } - -.fa-cat::before { - content: "\f6be"; } - -.fa-anchor-circle-exclamation::before { - content: "\e4ab"; } - -.fa-truck-field::before { - content: "\e58d"; } - -.fa-route::before { - content: "\f4d7"; } - -.fa-clipboard-question::before { - content: "\e4e3"; } - -.fa-panorama::before { - content: "\e209"; } - -.fa-comment-medical::before { - content: "\f7f5"; } - -.fa-teeth-open::before { - content: "\f62f"; } - -.fa-file-circle-minus::before { - content: "\e4ed"; } - -.fa-tags::before { - content: "\f02c"; } - -.fa-wine-glass::before { - content: "\f4e3"; } - -.fa-forward-fast::before { - content: "\f050"; } - -.fa-fast-forward::before { - content: "\f050"; } - -.fa-face-meh-blank::before { - content: "\f5a4"; } - -.fa-meh-blank::before { - content: "\f5a4"; } - -.fa-square-parking::before { - content: "\f540"; } - -.fa-parking::before { - content: "\f540"; } - -.fa-house-signal::before { - content: "\e012"; } - -.fa-bars-progress::before { - content: "\f828"; } - -.fa-tasks-alt::before { - content: "\f828"; } - -.fa-faucet-drip::before { - content: "\e006"; } - -.fa-cart-flatbed::before { - content: "\f474"; } - -.fa-dolly-flatbed::before { - content: "\f474"; } - -.fa-ban-smoking::before { - content: "\f54d"; } - -.fa-smoking-ban::before { - content: "\f54d"; } - -.fa-terminal::before { - content: "\f120"; } - -.fa-mobile-button::before { - content: "\f10b"; } - -.fa-house-medical-flag::before { - content: "\e514"; } - -.fa-basket-shopping::before { - content: "\f291"; } - -.fa-shopping-basket::before { - content: "\f291"; } - -.fa-tape::before { - content: "\f4db"; } - -.fa-bus-simple::before { - content: "\f55e"; } - -.fa-bus-alt::before { - content: "\f55e"; } - -.fa-eye::before { - content: "\f06e"; } - -.fa-face-sad-cry::before { - content: "\f5b3"; } - -.fa-sad-cry::before { - content: "\f5b3"; } - -.fa-audio-description::before { - content: "\f29e"; } - -.fa-person-military-to-person::before { - content: "\e54c"; } - -.fa-file-shield::before { - content: "\e4f0"; } - -.fa-user-slash::before { - content: "\f506"; } - -.fa-pen::before { - content: "\f304"; } - -.fa-tower-observation::before { - content: "\e586"; } - -.fa-file-code::before { - content: "\f1c9"; } - -.fa-signal::before { - content: "\f012"; } - -.fa-signal-5::before { - content: "\f012"; } - -.fa-signal-perfect::before { - content: "\f012"; } - -.fa-bus::before { - content: "\f207"; } - -.fa-heart-circle-xmark::before { - content: "\e501"; } - -.fa-house-chimney::before { - content: "\e3af"; } - -.fa-home-lg::before { - content: "\e3af"; } - -.fa-window-maximize::before { - content: "\f2d0"; } - -.fa-face-frown::before { - content: "\f119"; } - -.fa-frown::before { - content: "\f119"; } - -.fa-prescription::before { - content: "\f5b1"; } - -.fa-shop::before { - content: "\f54f"; } - -.fa-store-alt::before { - content: "\f54f"; } - -.fa-floppy-disk::before { - content: "\f0c7"; } - -.fa-save::before { - content: "\f0c7"; } - -.fa-vihara::before { - content: "\f6a7"; } - -.fa-scale-unbalanced::before { - content: "\f515"; } - -.fa-balance-scale-left::before { - content: "\f515"; } - -.fa-sort-up::before { - content: "\f0de"; } - -.fa-sort-asc::before { - content: "\f0de"; } - -.fa-comment-dots::before { - content: "\f4ad"; } - -.fa-commenting::before { - content: "\f4ad"; } - -.fa-plant-wilt::before { - content: "\e5aa"; } - -.fa-diamond::before { - content: "\f219"; } - -.fa-face-grin-squint::before { - content: "\f585"; } - -.fa-grin-squint::before { - content: "\f585"; } - -.fa-hand-holding-dollar::before { - content: "\f4c0"; } - -.fa-hand-holding-usd::before { - content: "\f4c0"; } - -.fa-bacterium::before { - content: "\e05a"; } - -.fa-hand-pointer::before { - content: "\f25a"; } - -.fa-drum-steelpan::before { - content: "\f56a"; } - -.fa-hand-scissors::before { - content: "\f257"; } - -.fa-hands-praying::before { - content: "\f684"; } - -.fa-praying-hands::before { - content: "\f684"; } - -.fa-arrow-rotate-right::before { - content: "\f01e"; } - -.fa-arrow-right-rotate::before { - content: "\f01e"; } - -.fa-arrow-rotate-forward::before { - content: "\f01e"; } - -.fa-redo::before { - content: "\f01e"; } - -.fa-biohazard::before { - content: "\f780"; } - -.fa-location-crosshairs::before { - content: "\f601"; } - -.fa-location::before { - content: "\f601"; } - -.fa-mars-double::before { - content: "\f227"; } - -.fa-child-dress::before { - content: "\e59c"; } - -.fa-users-between-lines::before { - content: "\e591"; } - -.fa-lungs-virus::before { - content: "\e067"; } - -.fa-face-grin-tears::before { - content: "\f588"; } - -.fa-grin-tears::before { - content: "\f588"; } - -.fa-phone::before { - content: "\f095"; } - -.fa-calendar-xmark::before { - content: "\f273"; } - -.fa-calendar-times::before { - content: "\f273"; } - -.fa-child-reaching::before { - content: "\e59d"; } - -.fa-head-side-virus::before { - content: "\e064"; } - -.fa-user-gear::before { - content: "\f4fe"; } - -.fa-user-cog::before { - content: "\f4fe"; } - -.fa-arrow-up-1-9::before { - content: "\f163"; } - -.fa-sort-numeric-up::before { - content: "\f163"; } - -.fa-door-closed::before { - content: "\f52a"; } - -.fa-shield-virus::before { - content: "\e06c"; } - -.fa-dice-six::before { - content: "\f526"; } - -.fa-mosquito-net::before { - content: "\e52c"; } - -.fa-bridge-water::before { - content: "\e4ce"; } - -.fa-person-booth::before { - content: "\f756"; } - -.fa-text-width::before { - content: "\f035"; } - -.fa-hat-wizard::before { - content: "\f6e8"; } - -.fa-pen-fancy::before { - content: "\f5ac"; } - -.fa-person-digging::before { - content: "\f85e"; } - -.fa-digging::before { - content: "\f85e"; } - -.fa-trash::before { - content: "\f1f8"; } - -.fa-gauge-simple::before { - content: "\f629"; } - -.fa-gauge-simple-med::before { - content: "\f629"; } - -.fa-tachometer-average::before { - content: "\f629"; } - -.fa-book-medical::before { - content: "\f7e6"; } - -.fa-poo::before { - content: "\f2fe"; } - -.fa-quote-right::before { - content: "\f10e"; } - -.fa-quote-right-alt::before { - content: "\f10e"; } - -.fa-shirt::before { - content: "\f553"; } - -.fa-t-shirt::before { - content: "\f553"; } - -.fa-tshirt::before { - content: "\f553"; } - -.fa-cubes::before { - content: "\f1b3"; } - -.fa-divide::before { - content: "\f529"; } - -.fa-tenge-sign::before { - content: "\f7d7"; } - -.fa-tenge::before { - content: "\f7d7"; } - -.fa-headphones::before { - content: "\f025"; } - -.fa-hands-holding::before { - content: "\f4c2"; } - -.fa-hands-clapping::before { - content: "\e1a8"; } - -.fa-republican::before { - content: "\f75e"; } - -.fa-arrow-left::before { - content: "\f060"; } - -.fa-person-circle-xmark::before { - content: "\e543"; } - -.fa-ruler::before { - content: "\f545"; } - -.fa-align-left::before { - content: "\f036"; } - -.fa-dice-d6::before { - content: "\f6d1"; } - -.fa-restroom::before { - content: "\f7bd"; } - -.fa-j::before { - content: "\4a"; } - -.fa-users-viewfinder::before { - content: "\e595"; } - -.fa-file-video::before { - content: "\f1c8"; } - -.fa-up-right-from-square::before { - content: "\f35d"; } - -.fa-external-link-alt::before { - content: "\f35d"; } - -.fa-table-cells::before { - content: "\f00a"; } - -.fa-th::before { - content: "\f00a"; } - -.fa-file-pdf::before { - content: "\f1c1"; } - -.fa-book-bible::before { - content: "\f647"; } - -.fa-bible::before { - content: "\f647"; } - -.fa-o::before { - content: "\4f"; } - -.fa-suitcase-medical::before { - content: "\f0fa"; } - -.fa-medkit::before { - content: "\f0fa"; } - -.fa-user-secret::before { - content: "\f21b"; } - -.fa-otter::before { - content: "\f700"; } - -.fa-person-dress::before { - content: "\f182"; } - -.fa-female::before { - content: "\f182"; } - -.fa-comment-dollar::before { - content: "\f651"; } - -.fa-business-time::before { - content: "\f64a"; } - -.fa-briefcase-clock::before { - content: "\f64a"; } - -.fa-table-cells-large::before { - content: "\f009"; } - -.fa-th-large::before { - content: "\f009"; } - -.fa-book-tanakh::before { - content: "\f827"; } - -.fa-tanakh::before { - content: "\f827"; } - -.fa-phone-volume::before { - content: "\f2a0"; } - -.fa-volume-control-phone::before { - content: "\f2a0"; } - -.fa-hat-cowboy-side::before { - content: "\f8c1"; } - -.fa-clipboard-user::before { - content: "\f7f3"; } - -.fa-child::before { - content: "\f1ae"; } - -.fa-lira-sign::before { - content: "\f195"; } - -.fa-satellite::before { - content: "\f7bf"; } - -.fa-plane-lock::before { - content: "\e558"; } - -.fa-tag::before { - content: "\f02b"; } - -.fa-comment::before { - content: "\f075"; } - -.fa-cake-candles::before { - content: "\f1fd"; } - -.fa-birthday-cake::before { - content: "\f1fd"; } - -.fa-cake::before { - content: "\f1fd"; } - -.fa-envelope::before { - content: "\f0e0"; } - -.fa-angles-up::before { - content: "\f102"; } - -.fa-angle-double-up::before { - content: "\f102"; } - -.fa-paperclip::before { - content: "\f0c6"; } - -.fa-arrow-right-to-city::before { - content: "\e4b3"; } - -.fa-ribbon::before { - content: "\f4d6"; } - -.fa-lungs::before { - content: "\f604"; } - -.fa-arrow-up-9-1::before { - content: "\f887"; } - -.fa-sort-numeric-up-alt::before { - content: "\f887"; } - -.fa-litecoin-sign::before { - content: "\e1d3"; } - -.fa-border-none::before { - content: "\f850"; } - -.fa-circle-nodes::before { - content: "\e4e2"; } - -.fa-parachute-box::before { - content: "\f4cd"; } - -.fa-indent::before { - content: "\f03c"; } - -.fa-truck-field-un::before { - content: "\e58e"; } - -.fa-hourglass::before { - content: "\f254"; } - -.fa-hourglass-empty::before { - content: "\f254"; } - -.fa-mountain::before { - content: "\f6fc"; } - -.fa-user-doctor::before { - content: "\f0f0"; } - -.fa-user-md::before { - content: "\f0f0"; } - -.fa-circle-info::before { - content: "\f05a"; } - -.fa-info-circle::before { - content: "\f05a"; } - -.fa-cloud-meatball::before { - content: "\f73b"; } - -.fa-camera::before { - content: "\f030"; } - -.fa-camera-alt::before { - content: "\f030"; } - -.fa-square-virus::before { - content: "\e578"; } - -.fa-meteor::before { - content: "\f753"; } - -.fa-car-on::before { - content: "\e4dd"; } - -.fa-sleigh::before { - content: "\f7cc"; } - -.fa-arrow-down-1-9::before { - content: "\f162"; } - -.fa-sort-numeric-asc::before { - content: "\f162"; } - -.fa-sort-numeric-down::before { - content: "\f162"; } - -.fa-hand-holding-droplet::before { - content: "\f4c1"; } - -.fa-hand-holding-water::before { - content: "\f4c1"; } - -.fa-water::before { - content: "\f773"; } - -.fa-calendar-check::before { - content: "\f274"; } - -.fa-braille::before { - content: "\f2a1"; } - -.fa-prescription-bottle-medical::before { - content: "\f486"; } - -.fa-prescription-bottle-alt::before { - content: "\f486"; } - -.fa-landmark::before { - content: "\f66f"; } - -.fa-truck::before { - content: "\f0d1"; } - -.fa-crosshairs::before { - content: "\f05b"; } - -.fa-person-cane::before { - content: "\e53c"; } - -.fa-tent::before { - content: "\e57d"; } - -.fa-vest-patches::before { - content: "\e086"; } - -.fa-check-double::before { - content: "\f560"; } - -.fa-arrow-down-a-z::before { - content: "\f15d"; } - -.fa-sort-alpha-asc::before { - content: "\f15d"; } - -.fa-sort-alpha-down::before { - content: "\f15d"; } - -.fa-money-bill-wheat::before { - content: "\e52a"; } - -.fa-cookie::before { - content: "\f563"; } - -.fa-arrow-rotate-left::before { - content: "\f0e2"; } - -.fa-arrow-left-rotate::before { - content: "\f0e2"; } - -.fa-arrow-rotate-back::before { - content: "\f0e2"; } - -.fa-arrow-rotate-backward::before { - content: "\f0e2"; } - -.fa-undo::before { - content: "\f0e2"; } - -.fa-hard-drive::before { - content: "\f0a0"; } - -.fa-hdd::before { - content: "\f0a0"; } - -.fa-face-grin-squint-tears::before { - content: "\f586"; } - -.fa-grin-squint-tears::before { - content: "\f586"; } - -.fa-dumbbell::before { - content: "\f44b"; } - -.fa-rectangle-list::before { - content: "\f022"; } - -.fa-list-alt::before { - content: "\f022"; } - -.fa-tarp-droplet::before { - content: "\e57c"; } - -.fa-house-medical-circle-check::before { - content: "\e511"; } - -.fa-person-skiing-nordic::before { - content: "\f7ca"; } - -.fa-skiing-nordic::before { - content: "\f7ca"; } - -.fa-calendar-plus::before { - content: "\f271"; } - -.fa-plane-arrival::before { - content: "\f5af"; } - -.fa-circle-left::before { - content: "\f359"; } - -.fa-arrow-alt-circle-left::before { - content: "\f359"; } - -.fa-train-subway::before { - content: "\f239"; } - -.fa-subway::before { - content: "\f239"; } - -.fa-chart-gantt::before { - content: "\e0e4"; } - -.fa-indian-rupee-sign::before { - content: "\e1bc"; } - -.fa-indian-rupee::before { - content: "\e1bc"; } - -.fa-inr::before { - content: "\e1bc"; } - -.fa-crop-simple::before { - content: "\f565"; } - -.fa-crop-alt::before { - content: "\f565"; } - -.fa-money-bill-1::before { - content: "\f3d1"; } - -.fa-money-bill-alt::before { - content: "\f3d1"; } - -.fa-left-long::before { - content: "\f30a"; } - -.fa-long-arrow-alt-left::before { - content: "\f30a"; } - -.fa-dna::before { - content: "\f471"; } - -.fa-virus-slash::before { - content: "\e075"; } - -.fa-minus::before { - content: "\f068"; } - -.fa-subtract::before { - content: "\f068"; } - -.fa-chess::before { - content: "\f439"; } - -.fa-arrow-left-long::before { - content: "\f177"; } - -.fa-long-arrow-left::before { - content: "\f177"; } - -.fa-plug-circle-check::before { - content: "\e55c"; } - -.fa-street-view::before { - content: "\f21d"; } - -.fa-franc-sign::before { - content: "\e18f"; } - -.fa-volume-off::before { - content: "\f026"; } - -.fa-hands-asl-interpreting::before { - content: "\f2a3"; } - -.fa-american-sign-language-interpreting::before { - content: "\f2a3"; } - -.fa-asl-interpreting::before { - content: "\f2a3"; } - -.fa-hands-american-sign-language-interpreting::before { - content: "\f2a3"; } - -.fa-gear::before { - content: "\f013"; } - -.fa-cog::before { - content: "\f013"; } - -.fa-droplet-slash::before { - content: "\f5c7"; } - -.fa-tint-slash::before { - content: "\f5c7"; } - -.fa-mosque::before { - content: "\f678"; } - -.fa-mosquito::before { - content: "\e52b"; } - -.fa-star-of-david::before { - content: "\f69a"; } - -.fa-person-military-rifle::before { - content: "\e54b"; } - -.fa-cart-shopping::before { - content: "\f07a"; } - -.fa-shopping-cart::before { - content: "\f07a"; } - -.fa-vials::before { - content: "\f493"; } - -.fa-plug-circle-plus::before { - content: "\e55f"; } - -.fa-place-of-worship::before { - content: "\f67f"; } - -.fa-grip-vertical::before { - content: "\f58e"; } - -.fa-arrow-turn-up::before { - content: "\f148"; } - -.fa-level-up::before { - content: "\f148"; } - -.fa-u::before { - content: "\55"; } - -.fa-square-root-variable::before { - content: "\f698"; } - -.fa-square-root-alt::before { - content: "\f698"; } - -.fa-clock::before { - content: "\f017"; } - -.fa-clock-four::before { - content: "\f017"; } - -.fa-backward-step::before { - content: "\f048"; } - -.fa-step-backward::before { - content: "\f048"; } - -.fa-pallet::before { - content: "\f482"; } - -.fa-faucet::before { - content: "\e005"; } - -.fa-baseball-bat-ball::before { - content: "\f432"; } - -.fa-s::before { - content: "\53"; } - -.fa-timeline::before { - content: "\e29c"; } - -.fa-keyboard::before { - content: "\f11c"; } - -.fa-caret-down::before { - content: "\f0d7"; } - -.fa-house-chimney-medical::before { - content: "\f7f2"; } - -.fa-clinic-medical::before { - content: "\f7f2"; } - -.fa-temperature-three-quarters::before { - content: "\f2c8"; } - -.fa-temperature-3::before { - content: "\f2c8"; } - -.fa-thermometer-3::before { - content: "\f2c8"; } - -.fa-thermometer-three-quarters::before { - content: "\f2c8"; } - -.fa-mobile-screen::before { - content: "\f3cf"; } - -.fa-mobile-android-alt::before { - content: "\f3cf"; } - -.fa-plane-up::before { - content: "\e22d"; } - -.fa-piggy-bank::before { - content: "\f4d3"; } - -.fa-battery-half::before { - content: "\f242"; } - -.fa-battery-3::before { - content: "\f242"; } - -.fa-mountain-city::before { - content: "\e52e"; } - -.fa-coins::before { - content: "\f51e"; } - -.fa-khanda::before { - content: "\f66d"; } - -.fa-sliders::before { - content: "\f1de"; } - -.fa-sliders-h::before { - content: "\f1de"; } - -.fa-folder-tree::before { - content: "\f802"; } - -.fa-network-wired::before { - content: "\f6ff"; } - -.fa-map-pin::before { - content: "\f276"; } - -.fa-hamsa::before { - content: "\f665"; } - -.fa-cent-sign::before { - content: "\e3f5"; } - -.fa-flask::before { - content: "\f0c3"; } - -.fa-person-pregnant::before { - content: "\e31e"; } - -.fa-wand-sparkles::before { - content: "\f72b"; } - -.fa-ellipsis-vertical::before { - content: "\f142"; } - -.fa-ellipsis-v::before { - content: "\f142"; } - -.fa-ticket::before { - content: "\f145"; } - -.fa-power-off::before { - content: "\f011"; } - -.fa-right-long::before { - content: "\f30b"; } - -.fa-long-arrow-alt-right::before { - content: "\f30b"; } - -.fa-flag-usa::before { - content: "\f74d"; } - -.fa-laptop-file::before { - content: "\e51d"; } - -.fa-tty::before { - content: "\f1e4"; } - -.fa-teletype::before { - content: "\f1e4"; } - -.fa-diagram-next::before { - content: "\e476"; } - -.fa-person-rifle::before { - content: "\e54e"; } - -.fa-house-medical-circle-exclamation::before { - content: "\e512"; } - -.fa-closed-captioning::before { - content: "\f20a"; } - -.fa-person-hiking::before { - content: "\f6ec"; } - -.fa-hiking::before { - content: "\f6ec"; } - -.fa-venus-double::before { - content: "\f226"; } - -.fa-images::before { - content: "\f302"; } - -.fa-calculator::before { - content: "\f1ec"; } - -.fa-people-pulling::before { - content: "\e535"; } - -.fa-n::before { - content: "\4e"; } - -.fa-cable-car::before { - content: "\f7da"; } - -.fa-tram::before { - content: "\f7da"; } - -.fa-cloud-rain::before { - content: "\f73d"; } - -.fa-building-circle-xmark::before { - content: "\e4d4"; } - -.fa-ship::before { - content: "\f21a"; } - -.fa-arrows-down-to-line::before { - content: "\e4b8"; } - -.fa-download::before { - content: "\f019"; } - -.fa-face-grin::before { - content: "\f580"; } - -.fa-grin::before { - content: "\f580"; } - -.fa-delete-left::before { - content: "\f55a"; } - -.fa-backspace::before { - content: "\f55a"; } - -.fa-eye-dropper::before { - content: "\f1fb"; } - -.fa-eye-dropper-empty::before { - content: "\f1fb"; } - -.fa-eyedropper::before { - content: "\f1fb"; } - -.fa-file-circle-check::before { - content: "\e5a0"; } - -.fa-forward::before { - content: "\f04e"; } - -.fa-mobile::before { - content: "\f3ce"; } - -.fa-mobile-android::before { - content: "\f3ce"; } - -.fa-mobile-phone::before { - content: "\f3ce"; } - -.fa-face-meh::before { - content: "\f11a"; } - -.fa-meh::before { - content: "\f11a"; } - -.fa-align-center::before { - content: "\f037"; } - -.fa-book-skull::before { - content: "\f6b7"; } - -.fa-book-dead::before { - content: "\f6b7"; } - -.fa-id-card::before { - content: "\f2c2"; } - -.fa-drivers-license::before { - content: "\f2c2"; } - -.fa-outdent::before { - content: "\f03b"; } - -.fa-dedent::before { - content: "\f03b"; } - -.fa-heart-circle-exclamation::before { - content: "\e4fe"; } - -.fa-house::before { - content: "\f015"; } - -.fa-home::before { - content: "\f015"; } - -.fa-home-alt::before { - content: "\f015"; } - -.fa-home-lg-alt::before { - content: "\f015"; } - -.fa-calendar-week::before { - content: "\f784"; } - -.fa-laptop-medical::before { - content: "\f812"; } - -.fa-b::before { - content: "\42"; } - -.fa-file-medical::before { - content: "\f477"; } - -.fa-dice-one::before { - content: "\f525"; } - -.fa-kiwi-bird::before { - content: "\f535"; } - -.fa-arrow-right-arrow-left::before { - content: "\f0ec"; } - -.fa-exchange::before { - content: "\f0ec"; } - -.fa-rotate-right::before { - content: "\f2f9"; } - -.fa-redo-alt::before { - content: "\f2f9"; } - -.fa-rotate-forward::before { - content: "\f2f9"; } - -.fa-utensils::before { - content: "\f2e7"; } - -.fa-cutlery::before { - content: "\f2e7"; } - -.fa-arrow-up-wide-short::before { - content: "\f161"; } - -.fa-sort-amount-up::before { - content: "\f161"; } - -.fa-mill-sign::before { - content: "\e1ed"; } - -.fa-bowl-rice::before { - content: "\e2eb"; } - -.fa-skull::before { - content: "\f54c"; } - -.fa-tower-broadcast::before { - content: "\f519"; } - -.fa-broadcast-tower::before { - content: "\f519"; } - -.fa-truck-pickup::before { - content: "\f63c"; } - -.fa-up-long::before { - content: "\f30c"; } - -.fa-long-arrow-alt-up::before { - content: "\f30c"; } - -.fa-stop::before { - content: "\f04d"; } - -.fa-code-merge::before { - content: "\f387"; } - -.fa-upload::before { - content: "\f093"; } - -.fa-hurricane::before { - content: "\f751"; } - -.fa-mound::before { - content: "\e52d"; } - -.fa-toilet-portable::before { - content: "\e583"; } - -.fa-compact-disc::before { - content: "\f51f"; } - -.fa-file-arrow-down::before { - content: "\f56d"; } - -.fa-file-download::before { - content: "\f56d"; } - -.fa-caravan::before { - content: "\f8ff"; } - -.fa-shield-cat::before { - content: "\e572"; } - -.fa-bolt::before { - content: "\f0e7"; } - -.fa-zap::before { - content: "\f0e7"; } - -.fa-glass-water::before { - content: "\e4f4"; } - -.fa-oil-well::before { - content: "\e532"; } - -.fa-vault::before { - content: "\e2c5"; } - -.fa-mars::before { - content: "\f222"; } - -.fa-toilet::before { - content: "\f7d8"; } - -.fa-plane-circle-xmark::before { - content: "\e557"; } - -.fa-yen-sign::before { - content: "\f157"; } - -.fa-cny::before { - content: "\f157"; } - -.fa-jpy::before { - content: "\f157"; } - -.fa-rmb::before { - content: "\f157"; } - -.fa-yen::before { - content: "\f157"; } - -.fa-ruble-sign::before { - content: "\f158"; } - -.fa-rouble::before { - content: "\f158"; } - -.fa-rub::before { - content: "\f158"; } - -.fa-ruble::before { - content: "\f158"; } - -.fa-sun::before { - content: "\f185"; } - -.fa-guitar::before { - content: "\f7a6"; } - -.fa-face-laugh-wink::before { - content: "\f59c"; } - -.fa-laugh-wink::before { - content: "\f59c"; } - -.fa-horse-head::before { - content: "\f7ab"; } - -.fa-bore-hole::before { - content: "\e4c3"; } - -.fa-industry::before { - content: "\f275"; } - -.fa-circle-down::before { - content: "\f358"; } - -.fa-arrow-alt-circle-down::before { - content: "\f358"; } - -.fa-arrows-turn-to-dots::before { - content: "\e4c1"; } - -.fa-florin-sign::before { - content: "\e184"; } - -.fa-arrow-down-short-wide::before { - content: "\f884"; } - -.fa-sort-amount-desc::before { - content: "\f884"; } - -.fa-sort-amount-down-alt::before { - content: "\f884"; } - -.fa-less-than::before { - content: "\3c"; } - -.fa-angle-down::before { - content: "\f107"; } - -.fa-car-tunnel::before { - content: "\e4de"; } - -.fa-head-side-cough::before { - content: "\e061"; } - -.fa-grip-lines::before { - content: "\f7a4"; } - -.fa-thumbs-down::before { - content: "\f165"; } - -.fa-user-lock::before { - content: "\f502"; } - -.fa-arrow-right-long::before { - content: "\f178"; } - -.fa-long-arrow-right::before { - content: "\f178"; } - -.fa-anchor-circle-xmark::before { - content: "\e4ac"; } - -.fa-ellipsis::before { - content: "\f141"; } - -.fa-ellipsis-h::before { - content: "\f141"; } - -.fa-chess-pawn::before { - content: "\f443"; } - -.fa-kit-medical::before { - content: "\f479"; } - -.fa-first-aid::before { - content: "\f479"; } - -.fa-person-through-window::before { - content: "\e5a9"; } - -.fa-toolbox::before { - content: "\f552"; } - -.fa-hands-holding-circle::before { - content: "\e4fb"; } - -.fa-bug::before { - content: "\f188"; } - -.fa-credit-card::before { - content: "\f09d"; } - -.fa-credit-card-alt::before { - content: "\f09d"; } - -.fa-car::before { - content: "\f1b9"; } - -.fa-automobile::before { - content: "\f1b9"; } - -.fa-hand-holding-hand::before { - content: "\e4f7"; } - -.fa-book-open-reader::before { - content: "\f5da"; } - -.fa-book-reader::before { - content: "\f5da"; } - -.fa-mountain-sun::before { - content: "\e52f"; } - -.fa-arrows-left-right-to-line::before { - content: "\e4ba"; } - -.fa-dice-d20::before { - content: "\f6cf"; } - -.fa-truck-droplet::before { - content: "\e58c"; } - -.fa-file-circle-xmark::before { - content: "\e5a1"; } - -.fa-temperature-arrow-up::before { - content: "\e040"; } - -.fa-temperature-up::before { - content: "\e040"; } - -.fa-medal::before { - content: "\f5a2"; } - -.fa-bed::before { - content: "\f236"; } - -.fa-square-h::before { - content: "\f0fd"; } - -.fa-h-square::before { - content: "\f0fd"; } - -.fa-podcast::before { - content: "\f2ce"; } - -.fa-temperature-full::before { - content: "\f2c7"; } - -.fa-temperature-4::before { - content: "\f2c7"; } - -.fa-thermometer-4::before { - content: "\f2c7"; } - -.fa-thermometer-full::before { - content: "\f2c7"; } - -.fa-bell::before { - content: "\f0f3"; } - -.fa-superscript::before { - content: "\f12b"; } - -.fa-plug-circle-xmark::before { - content: "\e560"; } - -.fa-star-of-life::before { - content: "\f621"; } - -.fa-phone-slash::before { - content: "\f3dd"; } - -.fa-paint-roller::before { - content: "\f5aa"; } - -.fa-handshake-angle::before { - content: "\f4c4"; } - -.fa-hands-helping::before { - content: "\f4c4"; } - -.fa-location-dot::before { - content: "\f3c5"; } - -.fa-map-marker-alt::before { - content: "\f3c5"; } - -.fa-file::before { - content: "\f15b"; } - -.fa-greater-than::before { - content: "\3e"; } - -.fa-person-swimming::before { - content: "\f5c4"; } - -.fa-swimmer::before { - content: "\f5c4"; } - -.fa-arrow-down::before { - content: "\f063"; } - -.fa-droplet::before { - content: "\f043"; } - -.fa-tint::before { - content: "\f043"; } - -.fa-eraser::before { - content: "\f12d"; } - -.fa-earth-americas::before { - content: "\f57d"; } - -.fa-earth::before { - content: "\f57d"; } - -.fa-earth-america::before { - content: "\f57d"; } - -.fa-globe-americas::before { - content: "\f57d"; } - -.fa-person-burst::before { - content: "\e53b"; } - -.fa-dove::before { - content: "\f4ba"; } - -.fa-battery-empty::before { - content: "\f244"; } - -.fa-battery-0::before { - content: "\f244"; } - -.fa-socks::before { - content: "\f696"; } - -.fa-inbox::before { - content: "\f01c"; } - -.fa-section::before { - content: "\e447"; } - -.fa-gauge-high::before { - content: "\f625"; } - -.fa-tachometer-alt::before { - content: "\f625"; } - -.fa-tachometer-alt-fast::before { - content: "\f625"; } - -.fa-envelope-open-text::before { - content: "\f658"; } - -.fa-hospital::before { - content: "\f0f8"; } - -.fa-hospital-alt::before { - content: "\f0f8"; } - -.fa-hospital-wide::before { - content: "\f0f8"; } - -.fa-wine-bottle::before { - content: "\f72f"; } - -.fa-chess-rook::before { - content: "\f447"; } - -.fa-bars-staggered::before { - content: "\f550"; } - -.fa-reorder::before { - content: "\f550"; } - -.fa-stream::before { - content: "\f550"; } - -.fa-dharmachakra::before { - content: "\f655"; } - -.fa-hotdog::before { - content: "\f80f"; } - -.fa-person-walking-with-cane::before { - content: "\f29d"; } - -.fa-blind::before { - content: "\f29d"; } - -.fa-drum::before { - content: "\f569"; } - -.fa-ice-cream::before { - content: "\f810"; } - -.fa-heart-circle-bolt::before { - content: "\e4fc"; } - -.fa-fax::before { - content: "\f1ac"; } - -.fa-paragraph::before { - content: "\f1dd"; } - -.fa-check-to-slot::before { - content: "\f772"; } - -.fa-vote-yea::before { - content: "\f772"; } - -.fa-star-half::before { - content: "\f089"; } - -.fa-boxes-stacked::before { - content: "\f468"; } - -.fa-boxes::before { - content: "\f468"; } - -.fa-boxes-alt::before { - content: "\f468"; } - -.fa-link::before { - content: "\f0c1"; } - -.fa-chain::before { - content: "\f0c1"; } - -.fa-ear-listen::before { - content: "\f2a2"; } - -.fa-assistive-listening-systems::before { - content: "\f2a2"; } - -.fa-tree-city::before { - content: "\e587"; } - -.fa-play::before { - content: "\f04b"; } - -.fa-font::before { - content: "\f031"; } - -.fa-rupiah-sign::before { - content: "\e23d"; } - -.fa-magnifying-glass::before { - content: "\f002"; } - -.fa-search::before { - content: "\f002"; } - -.fa-table-tennis-paddle-ball::before { - content: "\f45d"; } - -.fa-ping-pong-paddle-ball::before { - content: "\f45d"; } - -.fa-table-tennis::before { - content: "\f45d"; } - -.fa-person-dots-from-line::before { - content: "\f470"; } - -.fa-diagnoses::before { - content: "\f470"; } - -.fa-trash-can-arrow-up::before { - content: "\f82a"; } - -.fa-trash-restore-alt::before { - content: "\f82a"; } - -.fa-naira-sign::before { - content: "\e1f6"; } - -.fa-cart-arrow-down::before { - content: "\f218"; } - -.fa-walkie-talkie::before { - content: "\f8ef"; } - -.fa-file-pen::before { - content: "\f31c"; } - -.fa-file-edit::before { - content: "\f31c"; } - -.fa-receipt::before { - content: "\f543"; } - -.fa-square-pen::before { - content: "\f14b"; } - -.fa-pen-square::before { - content: "\f14b"; } - -.fa-pencil-square::before { - content: "\f14b"; } - -.fa-suitcase-rolling::before { - content: "\f5c1"; } - -.fa-person-circle-exclamation::before { - content: "\e53f"; } - -.fa-chevron-down::before { - content: "\f078"; } - -.fa-battery-full::before { - content: "\f240"; } - -.fa-battery::before { - content: "\f240"; } - -.fa-battery-5::before { - content: "\f240"; } - -.fa-skull-crossbones::before { - content: "\f714"; } - -.fa-code-compare::before { - content: "\e13a"; } - -.fa-list-ul::before { - content: "\f0ca"; } - -.fa-list-dots::before { - content: "\f0ca"; } - -.fa-school-lock::before { - content: "\e56f"; } - -.fa-tower-cell::before { - content: "\e585"; } - -.fa-down-long::before { - content: "\f309"; } - -.fa-long-arrow-alt-down::before { - content: "\f309"; } - -.fa-ranking-star::before { - content: "\e561"; } - -.fa-chess-king::before { - content: "\f43f"; } - -.fa-person-harassing::before { - content: "\e549"; } - -.fa-brazilian-real-sign::before { - content: "\e46c"; } - -.fa-landmark-dome::before { - content: "\f752"; } - -.fa-landmark-alt::before { - content: "\f752"; } - -.fa-arrow-up::before { - content: "\f062"; } - -.fa-tv::before { - content: "\f26c"; } - -.fa-television::before { - content: "\f26c"; } - -.fa-tv-alt::before { - content: "\f26c"; } - -.fa-shrimp::before { - content: "\e448"; } - -.fa-list-check::before { - content: "\f0ae"; } - -.fa-tasks::before { - content: "\f0ae"; } - -.fa-jug-detergent::before { - content: "\e519"; } - -.fa-circle-user::before { - content: "\f2bd"; } - -.fa-user-circle::before { - content: "\f2bd"; } - -.fa-user-shield::before { - content: "\f505"; } - -.fa-wind::before { - content: "\f72e"; } - -.fa-car-burst::before { - content: "\f5e1"; } - -.fa-car-crash::before { - content: "\f5e1"; } - -.fa-y::before { - content: "\59"; } - -.fa-person-snowboarding::before { - content: "\f7ce"; } - -.fa-snowboarding::before { - content: "\f7ce"; } - -.fa-truck-fast::before { - content: "\f48b"; } - -.fa-shipping-fast::before { - content: "\f48b"; } - -.fa-fish::before { - content: "\f578"; } - -.fa-user-graduate::before { - content: "\f501"; } - -.fa-circle-half-stroke::before { - content: "\f042"; } - -.fa-adjust::before { - content: "\f042"; } - -.fa-clapperboard::before { - content: "\e131"; } - -.fa-circle-radiation::before { - content: "\f7ba"; } - -.fa-radiation-alt::before { - content: "\f7ba"; } - -.fa-baseball::before { - content: "\f433"; } - -.fa-baseball-ball::before { - content: "\f433"; } - -.fa-jet-fighter-up::before { - content: "\e518"; } - -.fa-diagram-project::before { - content: "\f542"; } - -.fa-project-diagram::before { - content: "\f542"; } - -.fa-copy::before { - content: "\f0c5"; } - -.fa-volume-xmark::before { - content: "\f6a9"; } - -.fa-volume-mute::before { - content: "\f6a9"; } - -.fa-volume-times::before { - content: "\f6a9"; } - -.fa-hand-sparkles::before { - content: "\e05d"; } - -.fa-grip::before { - content: "\f58d"; } - -.fa-grip-horizontal::before { - content: "\f58d"; } - -.fa-share-from-square::before { - content: "\f14d"; } - -.fa-share-square::before { - content: "\f14d"; } - -.fa-child-combatant::before { - content: "\e4e0"; } - -.fa-child-rifle::before { - content: "\e4e0"; } - -.fa-gun::before { - content: "\e19b"; } - -.fa-square-phone::before { - content: "\f098"; } - -.fa-phone-square::before { - content: "\f098"; } - -.fa-plus::before { - content: "\2b"; } - -.fa-add::before { - content: "\2b"; } - -.fa-expand::before { - content: "\f065"; } - -.fa-computer::before { - content: "\e4e5"; } - -.fa-xmark::before { - content: "\f00d"; } - -.fa-close::before { - content: "\f00d"; } - -.fa-multiply::before { - content: "\f00d"; } - -.fa-remove::before { - content: "\f00d"; } - -.fa-times::before { - content: "\f00d"; } - -.fa-arrows-up-down-left-right::before { - content: "\f047"; } - -.fa-arrows::before { - content: "\f047"; } - -.fa-chalkboard-user::before { - content: "\f51c"; } - -.fa-chalkboard-teacher::before { - content: "\f51c"; } - -.fa-peso-sign::before { - content: "\e222"; } - -.fa-building-shield::before { - content: "\e4d8"; } - -.fa-baby::before { - content: "\f77c"; } - -.fa-users-line::before { - content: "\e592"; } - -.fa-quote-left::before { - content: "\f10d"; } - -.fa-quote-left-alt::before { - content: "\f10d"; } - -.fa-tractor::before { - content: "\f722"; } - -.fa-trash-arrow-up::before { - content: "\f829"; } - -.fa-trash-restore::before { - content: "\f829"; } - -.fa-arrow-down-up-lock::before { - content: "\e4b0"; } - -.fa-lines-leaning::before { - content: "\e51e"; } - -.fa-ruler-combined::before { - content: "\f546"; } - -.fa-copyright::before { - content: "\f1f9"; } - -.fa-equals::before { - content: "\3d"; } - -.fa-blender::before { - content: "\f517"; } - -.fa-teeth::before { - content: "\f62e"; } - -.fa-shekel-sign::before { - content: "\f20b"; } - -.fa-ils::before { - content: "\f20b"; } - -.fa-shekel::before { - content: "\f20b"; } - -.fa-sheqel::before { - content: "\f20b"; } - -.fa-sheqel-sign::before { - content: "\f20b"; } - -.fa-map::before { - content: "\f279"; } - -.fa-rocket::before { - content: "\f135"; } - -.fa-photo-film::before { - content: "\f87c"; } - -.fa-photo-video::before { - content: "\f87c"; } - -.fa-folder-minus::before { - content: "\f65d"; } - -.fa-store::before { - content: "\f54e"; } - -.fa-arrow-trend-up::before { - content: "\e098"; } - -.fa-plug-circle-minus::before { - content: "\e55e"; } - -.fa-sign-hanging::before { - content: "\f4d9"; } - -.fa-sign::before { - content: "\f4d9"; } - -.fa-bezier-curve::before { - content: "\f55b"; } - -.fa-bell-slash::before { - content: "\f1f6"; } - -.fa-tablet::before { - content: "\f3fb"; } - -.fa-tablet-android::before { - content: "\f3fb"; } - -.fa-school-flag::before { - content: "\e56e"; } - -.fa-fill::before { - content: "\f575"; } - -.fa-angle-up::before { - content: "\f106"; } - -.fa-drumstick-bite::before { - content: "\f6d7"; } - -.fa-holly-berry::before { - content: "\f7aa"; } - -.fa-chevron-left::before { - content: "\f053"; } - -.fa-bacteria::before { - content: "\e059"; } - -.fa-hand-lizard::before { - content: "\f258"; } - -.fa-notdef::before { - content: "\e1fe"; } - -.fa-disease::before { - content: "\f7fa"; } - -.fa-briefcase-medical::before { - content: "\f469"; } - -.fa-genderless::before { - content: "\f22d"; } - -.fa-chevron-right::before { - content: "\f054"; } - -.fa-retweet::before { - content: "\f079"; } - -.fa-car-rear::before { - content: "\f5de"; } - -.fa-car-alt::before { - content: "\f5de"; } - -.fa-pump-soap::before { - content: "\e06b"; } - -.fa-video-slash::before { - content: "\f4e2"; } - -.fa-battery-quarter::before { - content: "\f243"; } - -.fa-battery-2::before { - content: "\f243"; } - -.fa-radio::before { - content: "\f8d7"; } - -.fa-baby-carriage::before { - content: "\f77d"; } - -.fa-carriage-baby::before { - content: "\f77d"; } - -.fa-traffic-light::before { - content: "\f637"; } - -.fa-thermometer::before { - content: "\f491"; } - -.fa-vr-cardboard::before { - content: "\f729"; } - -.fa-hand-middle-finger::before { - content: "\f806"; } - -.fa-percent::before { - content: "\25"; } - -.fa-percentage::before { - content: "\25"; } - -.fa-truck-moving::before { - content: "\f4df"; } - -.fa-glass-water-droplet::before { - content: "\e4f5"; } - -.fa-display::before { - content: "\e163"; } - -.fa-face-smile::before { - content: "\f118"; } - -.fa-smile::before { - content: "\f118"; } - -.fa-thumbtack::before { - content: "\f08d"; } - -.fa-thumb-tack::before { - content: "\f08d"; } - -.fa-trophy::before { - content: "\f091"; } - -.fa-person-praying::before { - content: "\f683"; } - -.fa-pray::before { - content: "\f683"; } - -.fa-hammer::before { - content: "\f6e3"; } - -.fa-hand-peace::before { - content: "\f25b"; } - -.fa-rotate::before { - content: "\f2f1"; } - -.fa-sync-alt::before { - content: "\f2f1"; } - -.fa-spinner::before { - content: "\f110"; } - -.fa-robot::before { - content: "\f544"; } - -.fa-peace::before { - content: "\f67c"; } - -.fa-gears::before { - content: "\f085"; } - -.fa-cogs::before { - content: "\f085"; } - -.fa-warehouse::before { - content: "\f494"; } - -.fa-arrow-up-right-dots::before { - content: "\e4b7"; } - -.fa-splotch::before { - content: "\f5bc"; } - -.fa-face-grin-hearts::before { - content: "\f584"; } - -.fa-grin-hearts::before { - content: "\f584"; } - -.fa-dice-four::before { - content: "\f524"; } - -.fa-sim-card::before { - content: "\f7c4"; } - -.fa-transgender::before { - content: "\f225"; } - -.fa-transgender-alt::before { - content: "\f225"; } - -.fa-mercury::before { - content: "\f223"; } - -.fa-arrow-turn-down::before { - content: "\f149"; } - -.fa-level-down::before { - content: "\f149"; } - -.fa-person-falling-burst::before { - content: "\e547"; } - -.fa-award::before { - content: "\f559"; } - -.fa-ticket-simple::before { - content: "\f3ff"; } - -.fa-ticket-alt::before { - content: "\f3ff"; } - -.fa-building::before { - content: "\f1ad"; } - -.fa-angles-left::before { - content: "\f100"; } - -.fa-angle-double-left::before { - content: "\f100"; } - -.fa-qrcode::before { - content: "\f029"; } - -.fa-clock-rotate-left::before { - content: "\f1da"; } - -.fa-history::before { - content: "\f1da"; } - -.fa-face-grin-beam-sweat::before { - content: "\f583"; } - -.fa-grin-beam-sweat::before { - content: "\f583"; } - -.fa-file-export::before { - content: "\f56e"; } - -.fa-arrow-right-from-file::before { - content: "\f56e"; } - -.fa-shield::before { - content: "\f132"; } - -.fa-shield-blank::before { - content: "\f132"; } - -.fa-arrow-up-short-wide::before { - content: "\f885"; } - -.fa-sort-amount-up-alt::before { - content: "\f885"; } - -.fa-house-medical::before { - content: "\e3b2"; } - -.fa-golf-ball-tee::before { - content: "\f450"; } - -.fa-golf-ball::before { - content: "\f450"; } - -.fa-circle-chevron-left::before { - content: "\f137"; } - -.fa-chevron-circle-left::before { - content: "\f137"; } - -.fa-house-chimney-window::before { - content: "\e00d"; } - -.fa-pen-nib::before { - content: "\f5ad"; } - -.fa-tent-arrow-turn-left::before { - content: "\e580"; } - -.fa-tents::before { - content: "\e582"; } - -.fa-wand-magic::before { - content: "\f0d0"; } - -.fa-magic::before { - content: "\f0d0"; } - -.fa-dog::before { - content: "\f6d3"; } - -.fa-carrot::before { - content: "\f787"; } - -.fa-moon::before { - content: "\f186"; } - -.fa-wine-glass-empty::before { - content: "\f5ce"; } - -.fa-wine-glass-alt::before { - content: "\f5ce"; } - -.fa-cheese::before { - content: "\f7ef"; } - -.fa-yin-yang::before { - content: "\f6ad"; } - -.fa-music::before { - content: "\f001"; } - -.fa-code-commit::before { - content: "\f386"; } - -.fa-temperature-low::before { - content: "\f76b"; } - -.fa-person-biking::before { - content: "\f84a"; } - -.fa-biking::before { - content: "\f84a"; } - -.fa-broom::before { - content: "\f51a"; } - -.fa-shield-heart::before { - content: "\e574"; } - -.fa-gopuram::before { - content: "\f664"; } - -.fa-earth-oceania::before { - content: "\e47b"; } - -.fa-globe-oceania::before { - content: "\e47b"; } - -.fa-square-xmark::before { - content: "\f2d3"; } - -.fa-times-square::before { - content: "\f2d3"; } - -.fa-xmark-square::before { - content: "\f2d3"; } - -.fa-hashtag::before { - content: "\23"; } - -.fa-up-right-and-down-left-from-center::before { - content: "\f424"; } - -.fa-expand-alt::before { - content: "\f424"; } - -.fa-oil-can::before { - content: "\f613"; } - -.fa-t::before { - content: "\54"; } - -.fa-hippo::before { - content: "\f6ed"; } - -.fa-chart-column::before { - content: "\e0e3"; } - -.fa-infinity::before { - content: "\f534"; } - -.fa-vial-circle-check::before { - content: "\e596"; } - -.fa-person-arrow-down-to-line::before { - content: "\e538"; } - -.fa-voicemail::before { - content: "\f897"; } - -.fa-fan::before { - content: "\f863"; } - -.fa-person-walking-luggage::before { - content: "\e554"; } - -.fa-up-down::before { - content: "\f338"; } - -.fa-arrows-alt-v::before { - content: "\f338"; } - -.fa-cloud-moon-rain::before { - content: "\f73c"; } - -.fa-calendar::before { - content: "\f133"; } - -.fa-trailer::before { - content: "\e041"; } - -.fa-bahai::before { - content: "\f666"; } - -.fa-haykal::before { - content: "\f666"; } - -.fa-sd-card::before { - content: "\f7c2"; } - -.fa-dragon::before { - content: "\f6d5"; } - -.fa-shoe-prints::before { - content: "\f54b"; } - -.fa-circle-plus::before { - content: "\f055"; } - -.fa-plus-circle::before { - content: "\f055"; } - -.fa-face-grin-tongue-wink::before { - content: "\f58b"; } - -.fa-grin-tongue-wink::before { - content: "\f58b"; } - -.fa-hand-holding::before { - content: "\f4bd"; } - -.fa-plug-circle-exclamation::before { - content: "\e55d"; } - -.fa-link-slash::before { - content: "\f127"; } - -.fa-chain-broken::before { - content: "\f127"; } - -.fa-chain-slash::before { - content: "\f127"; } - -.fa-unlink::before { - content: "\f127"; } - -.fa-clone::before { - content: "\f24d"; } - -.fa-person-walking-arrow-loop-left::before { - content: "\e551"; } - -.fa-arrow-up-z-a::before { - content: "\f882"; } - -.fa-sort-alpha-up-alt::before { - content: "\f882"; } - -.fa-fire-flame-curved::before { - content: "\f7e4"; } - -.fa-fire-alt::before { - content: "\f7e4"; } - -.fa-tornado::before { - content: "\f76f"; } - -.fa-file-circle-plus::before { - content: "\e494"; } - -.fa-book-quran::before { - content: "\f687"; } - -.fa-quran::before { - content: "\f687"; } - -.fa-anchor::before { - content: "\f13d"; } - -.fa-border-all::before { - content: "\f84c"; } - -.fa-face-angry::before { - content: "\f556"; } - -.fa-angry::before { - content: "\f556"; } - -.fa-cookie-bite::before { - content: "\f564"; } - -.fa-arrow-trend-down::before { - content: "\e097"; } - -.fa-rss::before { - content: "\f09e"; } - -.fa-feed::before { - content: "\f09e"; } - -.fa-draw-polygon::before { - content: "\f5ee"; } - -.fa-scale-balanced::before { - content: "\f24e"; } - -.fa-balance-scale::before { - content: "\f24e"; } - -.fa-gauge-simple-high::before { - content: "\f62a"; } - -.fa-tachometer::before { - content: "\f62a"; } - -.fa-tachometer-fast::before { - content: "\f62a"; } - -.fa-shower::before { - content: "\f2cc"; } - -.fa-desktop::before { - content: "\f390"; } - -.fa-desktop-alt::before { - content: "\f390"; } - -.fa-m::before { - content: "\4d"; } - -.fa-table-list::before { - content: "\f00b"; } - -.fa-th-list::before { - content: "\f00b"; } - -.fa-comment-sms::before { - content: "\f7cd"; } - -.fa-sms::before { - content: "\f7cd"; } - -.fa-book::before { - content: "\f02d"; } - -.fa-user-plus::before { - content: "\f234"; } - -.fa-check::before { - content: "\f00c"; } - -.fa-battery-three-quarters::before { - content: "\f241"; } - -.fa-battery-4::before { - content: "\f241"; } - -.fa-house-circle-check::before { - content: "\e509"; } - -.fa-angle-left::before { - content: "\f104"; } - -.fa-diagram-successor::before { - content: "\e47a"; } - -.fa-truck-arrow-right::before { - content: "\e58b"; } - -.fa-arrows-split-up-and-left::before { - content: "\e4bc"; } - -.fa-hand-fist::before { - content: "\f6de"; } - -.fa-fist-raised::before { - content: "\f6de"; } - -.fa-cloud-moon::before { - content: "\f6c3"; } - -.fa-briefcase::before { - content: "\f0b1"; } - -.fa-person-falling::before { - content: "\e546"; } - -.fa-image-portrait::before { - content: "\f3e0"; } - -.fa-portrait::before { - content: "\f3e0"; } - -.fa-user-tag::before { - content: "\f507"; } - -.fa-rug::before { - content: "\e569"; } - -.fa-earth-europe::before { - content: "\f7a2"; } - -.fa-globe-europe::before { - content: "\f7a2"; } - -.fa-cart-flatbed-suitcase::before { - content: "\f59d"; } - -.fa-luggage-cart::before { - content: "\f59d"; } - -.fa-rectangle-xmark::before { - content: "\f410"; } - -.fa-rectangle-times::before { - content: "\f410"; } - -.fa-times-rectangle::before { - content: "\f410"; } - -.fa-window-close::before { - content: "\f410"; } - -.fa-baht-sign::before { - content: "\e0ac"; } - -.fa-book-open::before { - content: "\f518"; } - -.fa-book-journal-whills::before { - content: "\f66a"; } - -.fa-journal-whills::before { - content: "\f66a"; } - -.fa-handcuffs::before { - content: "\e4f8"; } - -.fa-triangle-exclamation::before { - content: "\f071"; } - -.fa-exclamation-triangle::before { - content: "\f071"; } - -.fa-warning::before { - content: "\f071"; } - -.fa-database::before { - content: "\f1c0"; } - -.fa-share::before { - content: "\f064"; } - -.fa-arrow-turn-right::before { - content: "\f064"; } - -.fa-mail-forward::before { - content: "\f064"; } - -.fa-bottle-droplet::before { - content: "\e4c4"; } - -.fa-mask-face::before { - content: "\e1d7"; } - -.fa-hill-rockslide::before { - content: "\e508"; } - -.fa-right-left::before { - content: "\f362"; } - -.fa-exchange-alt::before { - content: "\f362"; } - -.fa-paper-plane::before { - content: "\f1d8"; } - -.fa-road-circle-exclamation::before { - content: "\e565"; } - -.fa-dungeon::before { - content: "\f6d9"; } - -.fa-align-right::before { - content: "\f038"; } - -.fa-money-bill-1-wave::before { - content: "\f53b"; } - -.fa-money-bill-wave-alt::before { - content: "\f53b"; } - -.fa-life-ring::before { - content: "\f1cd"; } - -.fa-hands::before { - content: "\f2a7"; } - -.fa-sign-language::before { - content: "\f2a7"; } - -.fa-signing::before { - content: "\f2a7"; } - -.fa-calendar-day::before { - content: "\f783"; } - -.fa-water-ladder::before { - content: "\f5c5"; } - -.fa-ladder-water::before { - content: "\f5c5"; } - -.fa-swimming-pool::before { - content: "\f5c5"; } - -.fa-arrows-up-down::before { - content: "\f07d"; } - -.fa-arrows-v::before { - content: "\f07d"; } - -.fa-face-grimace::before { - content: "\f57f"; } - -.fa-grimace::before { - content: "\f57f"; } - -.fa-wheelchair-move::before { - content: "\e2ce"; } - -.fa-wheelchair-alt::before { - content: "\e2ce"; } - -.fa-turn-down::before { - content: "\f3be"; } - -.fa-level-down-alt::before { - content: "\f3be"; } - -.fa-person-walking-arrow-right::before { - content: "\e552"; } - -.fa-square-envelope::before { - content: "\f199"; } - -.fa-envelope-square::before { - content: "\f199"; } - -.fa-dice::before { - content: "\f522"; } - -.fa-bowling-ball::before { - content: "\f436"; } - -.fa-brain::before { - content: "\f5dc"; } - -.fa-bandage::before { - content: "\f462"; } - -.fa-band-aid::before { - content: "\f462"; } - -.fa-calendar-minus::before { - content: "\f272"; } - -.fa-circle-xmark::before { - content: "\f057"; } - -.fa-times-circle::before { - content: "\f057"; } - -.fa-xmark-circle::before { - content: "\f057"; } - -.fa-gifts::before { - content: "\f79c"; } - -.fa-hotel::before { - content: "\f594"; } - -.fa-earth-asia::before { - content: "\f57e"; } - -.fa-globe-asia::before { - content: "\f57e"; } - -.fa-id-card-clip::before { - content: "\f47f"; } - -.fa-id-card-alt::before { - content: "\f47f"; } - -.fa-magnifying-glass-plus::before { - content: "\f00e"; } - -.fa-search-plus::before { - content: "\f00e"; } - -.fa-thumbs-up::before { - content: "\f164"; } - -.fa-user-clock::before { - content: "\f4fd"; } - -.fa-hand-dots::before { - content: "\f461"; } - -.fa-allergies::before { - content: "\f461"; } - -.fa-file-invoice::before { - content: "\f570"; } - -.fa-window-minimize::before { - content: "\f2d1"; } - -.fa-mug-saucer::before { - content: "\f0f4"; } - -.fa-coffee::before { - content: "\f0f4"; } - -.fa-brush::before { - content: "\f55d"; } - -.fa-mask::before { - content: "\f6fa"; } - -.fa-magnifying-glass-minus::before { - content: "\f010"; } - -.fa-search-minus::before { - content: "\f010"; } - -.fa-ruler-vertical::before { - content: "\f548"; } - -.fa-user-large::before { - content: "\f406"; } - -.fa-user-alt::before { - content: "\f406"; } - -.fa-train-tram::before { - content: "\e5b4"; } - -.fa-user-nurse::before { - content: "\f82f"; } - -.fa-syringe::before { - content: "\f48e"; } - -.fa-cloud-sun::before { - content: "\f6c4"; } - -.fa-stopwatch-20::before { - content: "\e06f"; } - -.fa-square-full::before { - content: "\f45c"; } - -.fa-magnet::before { - content: "\f076"; } - -.fa-jar::before { - content: "\e516"; } - -.fa-note-sticky::before { - content: "\f249"; } - -.fa-sticky-note::before { - content: "\f249"; } - -.fa-bug-slash::before { - content: "\e490"; } - -.fa-arrow-up-from-water-pump::before { - content: "\e4b6"; } - -.fa-bone::before { - content: "\f5d7"; } - -.fa-user-injured::before { - content: "\f728"; } - -.fa-face-sad-tear::before { - content: "\f5b4"; } - -.fa-sad-tear::before { - content: "\f5b4"; } - -.fa-plane::before { - content: "\f072"; } - -.fa-tent-arrows-down::before { - content: "\e581"; } - -.fa-exclamation::before { - content: "\21"; } - -.fa-arrows-spin::before { - content: "\e4bb"; } - -.fa-print::before { - content: "\f02f"; } - -.fa-turkish-lira-sign::before { - content: "\e2bb"; } - -.fa-try::before { - content: "\e2bb"; } - -.fa-turkish-lira::before { - content: "\e2bb"; } - -.fa-dollar-sign::before { - content: "\24"; } - -.fa-dollar::before { - content: "\24"; } - -.fa-usd::before { - content: "\24"; } - -.fa-x::before { - content: "\58"; } - -.fa-magnifying-glass-dollar::before { - content: "\f688"; } - -.fa-search-dollar::before { - content: "\f688"; } - -.fa-users-gear::before { - content: "\f509"; } - -.fa-users-cog::before { - content: "\f509"; } - -.fa-person-military-pointing::before { - content: "\e54a"; } - -.fa-building-columns::before { - content: "\f19c"; } - -.fa-bank::before { - content: "\f19c"; } - -.fa-institution::before { - content: "\f19c"; } - -.fa-museum::before { - content: "\f19c"; } - -.fa-university::before { - content: "\f19c"; } - -.fa-umbrella::before { - content: "\f0e9"; } - -.fa-trowel::before { - content: "\e589"; } - -.fa-d::before { - content: "\44"; } - -.fa-stapler::before { - content: "\e5af"; } - -.fa-masks-theater::before { - content: "\f630"; } - -.fa-theater-masks::before { - content: "\f630"; } - -.fa-kip-sign::before { - content: "\e1c4"; } - -.fa-hand-point-left::before { - content: "\f0a5"; } - -.fa-handshake-simple::before { - content: "\f4c6"; } - -.fa-handshake-alt::before { - content: "\f4c6"; } - -.fa-jet-fighter::before { - content: "\f0fb"; } - -.fa-fighter-jet::before { - content: "\f0fb"; } - -.fa-square-share-nodes::before { - content: "\f1e1"; } - -.fa-share-alt-square::before { - content: "\f1e1"; } - -.fa-barcode::before { - content: "\f02a"; } - -.fa-plus-minus::before { - content: "\e43c"; } - -.fa-video::before { - content: "\f03d"; } - -.fa-video-camera::before { - content: "\f03d"; } - -.fa-graduation-cap::before { - content: "\f19d"; } - -.fa-mortar-board::before { - content: "\f19d"; } - -.fa-hand-holding-medical::before { - content: "\e05c"; } - -.fa-person-circle-check::before { - content: "\e53e"; } - -.fa-turn-up::before { - content: "\f3bf"; } - -.fa-level-up-alt::before { - content: "\f3bf"; } - -.sr-only, -.fa-sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; } - -.sr-only-focusable:not(:focus), -.fa-sr-only-focusable:not(:focus) { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; } -/*! - * Glightbox v3.1.0 - * https://github.com/biati-digital/glightbox - * Released under the MIT license - */ - -.glightbox-container { - width: 100%; - height: 100%; - position: fixed; - top: 0; - left: 0; - z-index: 999999 !important; - overflow: hidden; - -ms-touch-action: none; - touch-action: none; - -webkit-text-size-adjust: 100%; - -moz-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; - text-size-adjust: 100%; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - outline: 0; - overflow: hidden; -} -.glightbox-container.inactive { - display: none; -} -.glightbox-container .gcontainer { - position: relative; - width: 100%; - height: 100%; - z-index: 9999; - overflow: hidden; -} -.glightbox-container .gslider { - -webkit-transition: -webkit-transform 0.4s ease; - transition: -webkit-transform 0.4s ease; - transition: transform 0.4s ease; - transition: transform 0.4s ease, -webkit-transform 0.4s ease; - height: 100%; - left: 0; - top: 0; - width: 100%; - position: relative; - overflow: hidden; - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); -} -.glightbox-container .gslide { - width: 100%; - position: absolute; - opacity: 1; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - opacity: 0; -} -.glightbox-container .gslide.current { - opacity: 1; - z-index: 99999; - position: relative; -} -.glightbox-container .gslide.prev { - opacity: 1; - z-index: 9999; -} -.glightbox-container .gslide-inner-content { - width: 100%; -} -.glightbox-container .ginner-container { - position: relative; - width: 100%; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - max-width: 100%; - margin: auto; - height: 100vh; -} -.glightbox-container .ginner-container.gvideo-container { - width: 100%; -} -.glightbox-container .ginner-container.desc-bottom, -.glightbox-container .ginner-container.desc-top { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; -} -.glightbox-container .ginner-container.desc-left, -.glightbox-container .ginner-container.desc-right { - max-width: 100% !important; -} -.gslide iframe, -.gslide video { - outline: 0 !important; - border: none; - min-height: 165px; - -webkit-overflow-scrolling: touch; - -ms-touch-action: auto; - touch-action: auto; -} -.gslide:not(.current) { - pointer-events: none; -} -.gslide-image { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} -.gslide-image img { - max-height: 100vh; - display: block; - padding: 0; - float: none; - outline: 0; - border: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - max-width: 100vw; - width: auto; - height: auto; - -o-object-fit: cover; - object-fit: cover; - -ms-touch-action: none; - touch-action: none; - margin: auto; - min-width: 200px; -} -.desc-bottom .gslide-image img, -.desc-top .gslide-image img { - width: auto; -} -.desc-left .gslide-image img, -.desc-right .gslide-image img { - width: auto; - max-width: 100%; -} -.gslide-image img.zoomable { - position: relative; -} -.gslide-image img.dragging { - cursor: -webkit-grabbing !important; - cursor: grabbing !important; - -webkit-transition: none; - transition: none; -} -.gslide-video { - position: relative; - max-width: 100vh; - width: 100% !important; -} -.gslide-video .gvideo-wrapper { - width: 100%; - margin: auto; -} -.gslide-video::before { - content: ""; - display: block; - position: absolute; - width: 100%; - height: 100%; - background: rgba(255, 0, 0, 0.34); - display: none; -} -.gslide-video.playing::before { - display: none; -} -.gslide-video.fullscreen { - max-width: 100% !important; - min-width: 100%; - height: 75vh; -} -.gslide-video.fullscreen video { - max-width: 100% !important; - width: 100% !important; -} -.gslide-inline { - background: #fff; - text-align: left; - max-height: calc(100vh - 40px); - overflow: auto; - max-width: 100%; -} -.gslide-inline .ginlined-content { - padding: 20px; - width: 100%; -} -.gslide-inline .dragging { - cursor: -webkit-grabbing !important; - cursor: grabbing !important; - -webkit-transition: none; - transition: none; -} -.ginlined-content { - overflow: auto; - display: block !important; - opacity: 1; -} -.gslide-external { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - width: 100%; - min-width: 100%; - background: #fff; - padding: 0; - overflow: auto; - max-height: 75vh; - height: 100%; -} -.gslide-media { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - width: auto; -} -.zoomed .gslide-media { - -webkit-box-shadow: none !important; - box-shadow: none !important; -} -.desc-bottom .gslide-media, -.desc-top .gslide-media { - margin: 0 auto; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; -} -.gslide-description { - position: relative; - -webkit-box-flex: 1; - -ms-flex: 1 0 100%; - flex: 1 0 100%; -} -.gslide-description.description-left, -.gslide-description.description-right { - max-width: 100%; -} -.gslide-description.description-bottom, -.gslide-description.description-top { - margin: 0 auto; - width: 100%; -} -.gslide-description p { - margin-bottom: 12px; -} -.gslide-description p:last-child { - margin-bottom: 0; -} -.zoomed .gslide-description { - display: none; -} -.glightbox-button-hidden { - display: none; -} -.glightbox-mobile .glightbox-container .gslide-description { - height: auto !important; - width: 100%; - background: 0 0; - position: absolute; - bottom: 0; - padding: 19px 11px; - max-width: 100vw !important; - -webkit-box-ordinal-group: 3 !important; - -ms-flex-order: 2 !important; - order: 2 !important; - max-height: 78vh; - overflow: auto !important; - background: -webkit-gradient( - linear, - left top, - left bottom, - from(rgba(0, 0, 0, 0)), - to(rgba(0, 0, 0, 0.75)) - ); - background: linear-gradient( - to bottom, - rgba(0, 0, 0, 0) 0, - rgba(0, 0, 0, 0.75) 100% - ); - -webkit-transition: opacity 0.3s linear; - transition: opacity 0.3s linear; - padding-bottom: 50px; -} -.glightbox-mobile .glightbox-container .gslide-title { - color: #fff; - font-size: 1em; -} -.glightbox-mobile .glightbox-container .gslide-desc { - color: #a1a1a1; -} -.glightbox-mobile .glightbox-container .gslide-desc a { - color: #fff; - font-weight: 700; -} -.glightbox-mobile .glightbox-container .gslide-desc * { - color: inherit; -} -.glightbox-mobile .glightbox-container .gslide-desc string { - color: #fff; -} -.glightbox-mobile .glightbox-container .gslide-desc .desc-more { - color: #fff; - opacity: 0.4; -} -.gdesc-open .gslide-media { - -webkit-transition: opacity 0.5s ease; - transition: opacity 0.5s ease; - opacity: 0.4; -} -.gdesc-open .gdesc-inner { - padding-bottom: 30px; -} -.gdesc-closed .gslide-media { - -webkit-transition: opacity 0.5s ease; - transition: opacity 0.5s ease; - opacity: 1; -} -.greset { - -webkit-transition: all 0.3s ease; - transition: all 0.3s ease; -} -.gabsolute { - position: absolute; -} -.grelative { - position: relative; -} -.glightbox-desc { - display: none !important; -} -.glightbox-open { - overflow: hidden; -} -.gloader { - height: 25px; - width: 25px; - -webkit-animation: lightboxLoader 0.8s infinite linear; - animation: lightboxLoader 0.8s infinite linear; - border: 2px solid #fff; - border-right-color: transparent; - border-radius: 50%; - position: absolute; - display: block; - z-index: 9999; - left: 0; - right: 0; - margin: 0 auto; - top: 47%; -} -.goverlay { - width: 100%; - height: calc(100vh + 1px); - position: fixed; - top: -1px; - left: 0; - background: #000; - will-change: opacity; -} -.glightbox-mobile .goverlay { - background: #000; -} -.gclose, -.gnext, -.gprev { - z-index: 99999; - cursor: pointer; - width: 26px; - height: 44px; - border: none; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; -} -.gclose svg, -.gnext svg, -.gprev svg { - display: block; - width: 25px; - height: auto; - margin: 0; - padding: 0; -} -.gclose.disabled, -.gnext.disabled, -.gprev.disabled { - opacity: 0.1; -} -.gclose .garrow, -.gnext .garrow, -.gprev .garrow { - stroke: #fff; -} -.gbtn.focused { - outline: 2px solid #0f3d81; -} -iframe.wait-autoplay { - opacity: 0; -} -.glightbox-closing .gclose, -.glightbox-closing .gnext, -.glightbox-closing .gprev { - opacity: 0 !important; -} -.glightbox-clean .gslide-description { - background: #fff; -} -.glightbox-clean .gdesc-inner { - padding: 22px 20px; -} -.glightbox-clean .gslide-title { - font-size: 1em; - font-weight: 400; - font-family: arial; - color: #000; - margin-bottom: 19px; - line-height: 1.4em; -} -.glightbox-clean .gslide-desc { - font-size: 0.86em; - margin-bottom: 0; - font-family: arial; - line-height: 1.4em; -} -.glightbox-clean .gslide-video { - background: #000; -} -.glightbox-clean .gclose, -.glightbox-clean .gnext, -.glightbox-clean .gprev { - background-color: rgba(0, 0, 0, 0.75); - border-radius: 4px; -} -.glightbox-clean .gclose path, -.glightbox-clean .gnext path, -.glightbox-clean .gprev path { - fill: #fff; -} -.glightbox-clean .gprev { - position: absolute; - top: -100%; - left: 30px; - width: 40px; - height: 50px; -} -.glightbox-clean .gnext { - position: absolute; - top: -100%; - right: 30px; - width: 40px; - height: 50px; -} -.glightbox-clean .gclose { - width: 35px; - height: 35px; - top: 15px; - right: 10px; - position: absolute; -} -.glightbox-clean .gclose svg { - width: 18px; - height: auto; -} -.glightbox-clean .gclose:hover { - opacity: 1; -} -.gfadeIn { - -webkit-animation: gfadeIn 0.5s ease; - animation: gfadeIn 0.5s ease; -} -.gfadeOut { - -webkit-animation: gfadeOut 0.5s ease; - animation: gfadeOut 0.5s ease; -} -.gslideOutLeft { - -webkit-animation: gslideOutLeft 0.3s ease; - animation: gslideOutLeft 0.3s ease; -} -.gslideInLeft { - -webkit-animation: gslideInLeft 0.3s ease; - animation: gslideInLeft 0.3s ease; -} -.gslideOutRight { - -webkit-animation: gslideOutRight 0.3s ease; - animation: gslideOutRight 0.3s ease; -} -.gslideInRight { - -webkit-animation: gslideInRight 0.3s ease; - animation: gslideInRight 0.3s ease; -} -.gzoomIn { - -webkit-animation: gzoomIn 0.5s ease; - animation: gzoomIn 0.5s ease; -} -.gzoomOut { - -webkit-animation: gzoomOut 0.5s ease; - animation: gzoomOut 0.5s ease; -} -@-webkit-keyframes lightboxLoader { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} -@keyframes lightboxLoader { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} -@-webkit-keyframes gfadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -@keyframes gfadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -@-webkit-keyframes gfadeOut { - from { - opacity: 1; - } - to { - opacity: 0; - } -} -@keyframes gfadeOut { - from { - opacity: 1; - } - to { - opacity: 0; - } -} -@-webkit-keyframes gslideInLeft { - from { - opacity: 0; - -webkit-transform: translate3d(-60%, 0, 0); - transform: translate3d(-60%, 0, 0); - } - to { - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - opacity: 1; - } -} -@keyframes gslideInLeft { - from { - opacity: 0; - -webkit-transform: translate3d(-60%, 0, 0); - transform: translate3d(-60%, 0, 0); - } - to { - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - opacity: 1; - } -} -@-webkit-keyframes gslideOutLeft { - from { - opacity: 1; - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - to { - -webkit-transform: translate3d(-60%, 0, 0); - transform: translate3d(-60%, 0, 0); - opacity: 0; - visibility: hidden; - } -} -@keyframes gslideOutLeft { - from { - opacity: 1; - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - to { - -webkit-transform: translate3d(-60%, 0, 0); - transform: translate3d(-60%, 0, 0); - opacity: 0; - visibility: hidden; - } -} -@-webkit-keyframes gslideInRight { - from { - opacity: 0; - visibility: visible; - -webkit-transform: translate3d(60%, 0, 0); - transform: translate3d(60%, 0, 0); - } - to { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - opacity: 1; - } -} -@keyframes gslideInRight { - from { - opacity: 0; - visibility: visible; - -webkit-transform: translate3d(60%, 0, 0); - transform: translate3d(60%, 0, 0); - } - to { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - opacity: 1; - } -} -@-webkit-keyframes gslideOutRight { - from { - opacity: 1; - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - to { - -webkit-transform: translate3d(60%, 0, 0); - transform: translate3d(60%, 0, 0); - opacity: 0; - } -} -@keyframes gslideOutRight { - from { - opacity: 1; - visibility: visible; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - to { - -webkit-transform: translate3d(60%, 0, 0); - transform: translate3d(60%, 0, 0); - opacity: 0; - } -} -@-webkit-keyframes gzoomIn { - from { - opacity: 0; - -webkit-transform: scale3d(0.3, 0.3, 0.3); - transform: scale3d(0.3, 0.3, 0.3); - } - to { - opacity: 1; - } -} -@keyframes gzoomIn { - from { - opacity: 0; - -webkit-transform: scale3d(0.3, 0.3, 0.3); - transform: scale3d(0.3, 0.3, 0.3); - } - to { - opacity: 1; - } -} -@-webkit-keyframes gzoomOut { - from { - opacity: 1; - } - 50% { - opacity: 0; - -webkit-transform: scale3d(0.3, 0.3, 0.3); - transform: scale3d(0.3, 0.3, 0.3); - } - to { - opacity: 0; - } -} -@keyframes gzoomOut { - from { - opacity: 1; - } - 50% { - opacity: 0; - -webkit-transform: scale3d(0.3, 0.3, 0.3); - transform: scale3d(0.3, 0.3, 0.3); - } - to { - opacity: 0; - } -} -@media (min-width: 769px) { - .glightbox-container .ginner-container { - width: auto; - height: auto; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - } - .glightbox-container .ginner-container.desc-top .gslide-description { - -webkit-box-ordinal-group: 1; - -ms-flex-order: 0; - order: 0; - } - .glightbox-container .ginner-container.desc-top .gslide-image, - .glightbox-container .ginner-container.desc-top .gslide-image img { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1; - } - .glightbox-container .ginner-container.desc-left .gslide-description { - -webkit-box-ordinal-group: 1; - -ms-flex-order: 0; - order: 0; - } - .glightbox-container .ginner-container.desc-left .gslide-image { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1; - } - .gslide-image img { - max-height: 97vh; - max-width: 100%; - } - .gslide-image img.zoomable { - cursor: -webkit-zoom-in; - cursor: zoom-in; - } - .zoomed .gslide-image img.zoomable { - cursor: -webkit-grab; - cursor: grab; - } - .gslide-inline { - max-height: 95vh; - } - .gslide-external { - max-height: 100vh; - } - .gslide-description.description-left, - .gslide-description.description-right { - max-width: 275px; - } - .glightbox-open { - height: auto; - } - .goverlay { - background: rgba(0, 0, 0, 0.92); - } - .glightbox-clean .gslide-media { - -webkit-box-shadow: 1px 2px 9px 0 rgba(0, 0, 0, 0.65); - box-shadow: 1px 2px 9px 0 rgba(0, 0, 0, 0.65); - } - .glightbox-clean .description-left .gdesc-inner, - .glightbox-clean .description-right .gdesc-inner { - position: absolute; - height: 100%; - overflow-y: auto; - } - .glightbox-clean .gclose, - .glightbox-clean .gnext, - .glightbox-clean .gprev { - background-color: rgba(0, 0, 0, 0.32); - } - .glightbox-clean .gclose:hover, - .glightbox-clean .gnext:hover, - .glightbox-clean .gprev:hover { - background-color: rgba(0, 0, 0, 0.7); - } - .glightbox-clean .gprev { - top: 45%; - } - .glightbox-clean .gnext { - top: 45%; - } -} -@media (min-width: 992px) { - .glightbox-clean .gclose { - opacity: 0.7; - right: 20px; - } -} -@media screen and (max-height: 420px) { - .goverlay { - background: #000; - } -} -[data-aos][data-aos][data-aos-duration="50"], -body[data-aos-duration="50"] [data-aos] { - transition-duration: 50ms; -} -[data-aos][data-aos][data-aos-delay="50"], -body[data-aos-delay="50"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="50"].aos-animate, -body[data-aos-delay="50"] [data-aos].aos-animate { - transition-delay: 50ms; -} -[data-aos][data-aos][data-aos-duration="100"], -body[data-aos-duration="100"] [data-aos] { - transition-duration: 0.1s; -} -[data-aos][data-aos][data-aos-delay="100"], -body[data-aos-delay="100"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="100"].aos-animate, -body[data-aos-delay="100"] [data-aos].aos-animate { - transition-delay: 0.1s; -} -[data-aos][data-aos][data-aos-duration="150"], -body[data-aos-duration="150"] [data-aos] { - transition-duration: 0.15s; -} -[data-aos][data-aos][data-aos-delay="150"], -body[data-aos-delay="150"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="150"].aos-animate, -body[data-aos-delay="150"] [data-aos].aos-animate { - transition-delay: 0.15s; -} -[data-aos][data-aos][data-aos-duration="200"], -body[data-aos-duration="200"] [data-aos] { - transition-duration: 0.2s; -} -[data-aos][data-aos][data-aos-delay="200"], -body[data-aos-delay="200"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="200"].aos-animate, -body[data-aos-delay="200"] [data-aos].aos-animate { - transition-delay: 0.2s; -} -[data-aos][data-aos][data-aos-duration="250"], -body[data-aos-duration="250"] [data-aos] { - transition-duration: 0.25s; -} -[data-aos][data-aos][data-aos-delay="250"], -body[data-aos-delay="250"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="250"].aos-animate, -body[data-aos-delay="250"] [data-aos].aos-animate { - transition-delay: 0.25s; -} -[data-aos][data-aos][data-aos-duration="300"], -body[data-aos-duration="300"] [data-aos] { - transition-duration: 0.3s; -} -[data-aos][data-aos][data-aos-delay="300"], -body[data-aos-delay="300"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="300"].aos-animate, -body[data-aos-delay="300"] [data-aos].aos-animate { - transition-delay: 0.3s; -} -[data-aos][data-aos][data-aos-duration="350"], -body[data-aos-duration="350"] [data-aos] { - transition-duration: 0.35s; -} -[data-aos][data-aos][data-aos-delay="350"], -body[data-aos-delay="350"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="350"].aos-animate, -body[data-aos-delay="350"] [data-aos].aos-animate { - transition-delay: 0.35s; -} -[data-aos][data-aos][data-aos-duration="400"], -body[data-aos-duration="400"] [data-aos] { - transition-duration: 0.4s; -} -[data-aos][data-aos][data-aos-delay="400"], -body[data-aos-delay="400"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="400"].aos-animate, -body[data-aos-delay="400"] [data-aos].aos-animate { - transition-delay: 0.4s; -} -[data-aos][data-aos][data-aos-duration="450"], -body[data-aos-duration="450"] [data-aos] { - transition-duration: 0.45s; -} -[data-aos][data-aos][data-aos-delay="450"], -body[data-aos-delay="450"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="450"].aos-animate, -body[data-aos-delay="450"] [data-aos].aos-animate { - transition-delay: 0.45s; -} -[data-aos][data-aos][data-aos-duration="500"], -body[data-aos-duration="500"] [data-aos] { - transition-duration: 0.5s; -} -[data-aos][data-aos][data-aos-delay="500"], -body[data-aos-delay="500"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="500"].aos-animate, -body[data-aos-delay="500"] [data-aos].aos-animate { - transition-delay: 0.5s; -} -[data-aos][data-aos][data-aos-duration="550"], -body[data-aos-duration="550"] [data-aos] { - transition-duration: 0.55s; -} -[data-aos][data-aos][data-aos-delay="550"], -body[data-aos-delay="550"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="550"].aos-animate, -body[data-aos-delay="550"] [data-aos].aos-animate { - transition-delay: 0.55s; -} -[data-aos][data-aos][data-aos-duration="600"], -body[data-aos-duration="600"] [data-aos] { - transition-duration: 0.6s; -} -[data-aos][data-aos][data-aos-delay="600"], -body[data-aos-delay="600"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="600"].aos-animate, -body[data-aos-delay="600"] [data-aos].aos-animate { - transition-delay: 0.6s; -} -[data-aos][data-aos][data-aos-duration="650"], -body[data-aos-duration="650"] [data-aos] { - transition-duration: 0.65s; -} -[data-aos][data-aos][data-aos-delay="650"], -body[data-aos-delay="650"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="650"].aos-animate, -body[data-aos-delay="650"] [data-aos].aos-animate { - transition-delay: 0.65s; -} -[data-aos][data-aos][data-aos-duration="700"], -body[data-aos-duration="700"] [data-aos] { - transition-duration: 0.7s; -} -[data-aos][data-aos][data-aos-delay="700"], -body[data-aos-delay="700"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="700"].aos-animate, -body[data-aos-delay="700"] [data-aos].aos-animate { - transition-delay: 0.7s; -} -[data-aos][data-aos][data-aos-duration="750"], -body[data-aos-duration="750"] [data-aos] { - transition-duration: 0.75s; -} -[data-aos][data-aos][data-aos-delay="750"], -body[data-aos-delay="750"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="750"].aos-animate, -body[data-aos-delay="750"] [data-aos].aos-animate { - transition-delay: 0.75s; -} -[data-aos][data-aos][data-aos-duration="800"], -body[data-aos-duration="800"] [data-aos] { - transition-duration: 0.8s; -} -[data-aos][data-aos][data-aos-delay="800"], -body[data-aos-delay="800"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="800"].aos-animate, -body[data-aos-delay="800"] [data-aos].aos-animate { - transition-delay: 0.8s; -} -[data-aos][data-aos][data-aos-duration="850"], -body[data-aos-duration="850"] [data-aos] { - transition-duration: 0.85s; -} -[data-aos][data-aos][data-aos-delay="850"], -body[data-aos-delay="850"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="850"].aos-animate, -body[data-aos-delay="850"] [data-aos].aos-animate { - transition-delay: 0.85s; -} -[data-aos][data-aos][data-aos-duration="900"], -body[data-aos-duration="900"] [data-aos] { - transition-duration: 0.9s; -} -[data-aos][data-aos][data-aos-delay="900"], -body[data-aos-delay="900"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="900"].aos-animate, -body[data-aos-delay="900"] [data-aos].aos-animate { - transition-delay: 0.9s; -} -[data-aos][data-aos][data-aos-duration="950"], -body[data-aos-duration="950"] [data-aos] { - transition-duration: 0.95s; -} -[data-aos][data-aos][data-aos-delay="950"], -body[data-aos-delay="950"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="950"].aos-animate, -body[data-aos-delay="950"] [data-aos].aos-animate { - transition-delay: 0.95s; -} -[data-aos][data-aos][data-aos-duration="1000"], -body[data-aos-duration="1000"] [data-aos] { - transition-duration: 1s; -} -[data-aos][data-aos][data-aos-delay="1000"], -body[data-aos-delay="1000"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1000"].aos-animate, -body[data-aos-delay="1000"] [data-aos].aos-animate { - transition-delay: 1s; -} -[data-aos][data-aos][data-aos-duration="1050"], -body[data-aos-duration="1050"] [data-aos] { - transition-duration: 1.05s; -} -[data-aos][data-aos][data-aos-delay="1050"], -body[data-aos-delay="1050"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1050"].aos-animate, -body[data-aos-delay="1050"] [data-aos].aos-animate { - transition-delay: 1.05s; -} -[data-aos][data-aos][data-aos-duration="1100"], -body[data-aos-duration="1100"] [data-aos] { - transition-duration: 1.1s; -} -[data-aos][data-aos][data-aos-delay="1100"], -body[data-aos-delay="1100"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1100"].aos-animate, -body[data-aos-delay="1100"] [data-aos].aos-animate { - transition-delay: 1.1s; -} -[data-aos][data-aos][data-aos-duration="1150"], -body[data-aos-duration="1150"] [data-aos] { - transition-duration: 1.15s; -} -[data-aos][data-aos][data-aos-delay="1150"], -body[data-aos-delay="1150"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1150"].aos-animate, -body[data-aos-delay="1150"] [data-aos].aos-animate { - transition-delay: 1.15s; -} -[data-aos][data-aos][data-aos-duration="1200"], -body[data-aos-duration="1200"] [data-aos] { - transition-duration: 1.2s; -} -[data-aos][data-aos][data-aos-delay="1200"], -body[data-aos-delay="1200"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1200"].aos-animate, -body[data-aos-delay="1200"] [data-aos].aos-animate { - transition-delay: 1.2s; -} -[data-aos][data-aos][data-aos-duration="1250"], -body[data-aos-duration="1250"] [data-aos] { - transition-duration: 1.25s; -} -[data-aos][data-aos][data-aos-delay="1250"], -body[data-aos-delay="1250"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1250"].aos-animate, -body[data-aos-delay="1250"] [data-aos].aos-animate { - transition-delay: 1.25s; -} -[data-aos][data-aos][data-aos-duration="1300"], -body[data-aos-duration="1300"] [data-aos] { - transition-duration: 1.3s; -} -[data-aos][data-aos][data-aos-delay="1300"], -body[data-aos-delay="1300"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1300"].aos-animate, -body[data-aos-delay="1300"] [data-aos].aos-animate { - transition-delay: 1.3s; -} -[data-aos][data-aos][data-aos-duration="1350"], -body[data-aos-duration="1350"] [data-aos] { - transition-duration: 1.35s; -} -[data-aos][data-aos][data-aos-delay="1350"], -body[data-aos-delay="1350"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1350"].aos-animate, -body[data-aos-delay="1350"] [data-aos].aos-animate { - transition-delay: 1.35s; -} -[data-aos][data-aos][data-aos-duration="1400"], -body[data-aos-duration="1400"] [data-aos] { - transition-duration: 1.4s; -} -[data-aos][data-aos][data-aos-delay="1400"], -body[data-aos-delay="1400"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1400"].aos-animate, -body[data-aos-delay="1400"] [data-aos].aos-animate { - transition-delay: 1.4s; -} -[data-aos][data-aos][data-aos-duration="1450"], -body[data-aos-duration="1450"] [data-aos] { - transition-duration: 1.45s; -} -[data-aos][data-aos][data-aos-delay="1450"], -body[data-aos-delay="1450"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1450"].aos-animate, -body[data-aos-delay="1450"] [data-aos].aos-animate { - transition-delay: 1.45s; -} -[data-aos][data-aos][data-aos-duration="1500"], -body[data-aos-duration="1500"] [data-aos] { - transition-duration: 1.5s; -} -[data-aos][data-aos][data-aos-delay="1500"], -body[data-aos-delay="1500"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1500"].aos-animate, -body[data-aos-delay="1500"] [data-aos].aos-animate { - transition-delay: 1.5s; -} -[data-aos][data-aos][data-aos-duration="1550"], -body[data-aos-duration="1550"] [data-aos] { - transition-duration: 1.55s; -} -[data-aos][data-aos][data-aos-delay="1550"], -body[data-aos-delay="1550"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1550"].aos-animate, -body[data-aos-delay="1550"] [data-aos].aos-animate { - transition-delay: 1.55s; -} -[data-aos][data-aos][data-aos-duration="1600"], -body[data-aos-duration="1600"] [data-aos] { - transition-duration: 1.6s; -} -[data-aos][data-aos][data-aos-delay="1600"], -body[data-aos-delay="1600"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1600"].aos-animate, -body[data-aos-delay="1600"] [data-aos].aos-animate { - transition-delay: 1.6s; -} -[data-aos][data-aos][data-aos-duration="1650"], -body[data-aos-duration="1650"] [data-aos] { - transition-duration: 1.65s; -} -[data-aos][data-aos][data-aos-delay="1650"], -body[data-aos-delay="1650"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1650"].aos-animate, -body[data-aos-delay="1650"] [data-aos].aos-animate { - transition-delay: 1.65s; -} -[data-aos][data-aos][data-aos-duration="1700"], -body[data-aos-duration="1700"] [data-aos] { - transition-duration: 1.7s; -} -[data-aos][data-aos][data-aos-delay="1700"], -body[data-aos-delay="1700"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1700"].aos-animate, -body[data-aos-delay="1700"] [data-aos].aos-animate { - transition-delay: 1.7s; -} -[data-aos][data-aos][data-aos-duration="1750"], -body[data-aos-duration="1750"] [data-aos] { - transition-duration: 1.75s; -} -[data-aos][data-aos][data-aos-delay="1750"], -body[data-aos-delay="1750"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1750"].aos-animate, -body[data-aos-delay="1750"] [data-aos].aos-animate { - transition-delay: 1.75s; -} -[data-aos][data-aos][data-aos-duration="1800"], -body[data-aos-duration="1800"] [data-aos] { - transition-duration: 1.8s; -} -[data-aos][data-aos][data-aos-delay="1800"], -body[data-aos-delay="1800"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1800"].aos-animate, -body[data-aos-delay="1800"] [data-aos].aos-animate { - transition-delay: 1.8s; -} -[data-aos][data-aos][data-aos-duration="1850"], -body[data-aos-duration="1850"] [data-aos] { - transition-duration: 1.85s; -} -[data-aos][data-aos][data-aos-delay="1850"], -body[data-aos-delay="1850"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1850"].aos-animate, -body[data-aos-delay="1850"] [data-aos].aos-animate { - transition-delay: 1.85s; -} -[data-aos][data-aos][data-aos-duration="1900"], -body[data-aos-duration="1900"] [data-aos] { - transition-duration: 1.9s; -} -[data-aos][data-aos][data-aos-delay="1900"], -body[data-aos-delay="1900"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1900"].aos-animate, -body[data-aos-delay="1900"] [data-aos].aos-animate { - transition-delay: 1.9s; -} -[data-aos][data-aos][data-aos-duration="1950"], -body[data-aos-duration="1950"] [data-aos] { - transition-duration: 1.95s; -} -[data-aos][data-aos][data-aos-delay="1950"], -body[data-aos-delay="1950"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="1950"].aos-animate, -body[data-aos-delay="1950"] [data-aos].aos-animate { - transition-delay: 1.95s; -} -[data-aos][data-aos][data-aos-duration="2000"], -body[data-aos-duration="2000"] [data-aos] { - transition-duration: 2s; -} -[data-aos][data-aos][data-aos-delay="2000"], -body[data-aos-delay="2000"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2000"].aos-animate, -body[data-aos-delay="2000"] [data-aos].aos-animate { - transition-delay: 2s; -} -[data-aos][data-aos][data-aos-duration="2050"], -body[data-aos-duration="2050"] [data-aos] { - transition-duration: 2.05s; -} -[data-aos][data-aos][data-aos-delay="2050"], -body[data-aos-delay="2050"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2050"].aos-animate, -body[data-aos-delay="2050"] [data-aos].aos-animate { - transition-delay: 2.05s; -} -[data-aos][data-aos][data-aos-duration="2100"], -body[data-aos-duration="2100"] [data-aos] { - transition-duration: 2.1s; -} -[data-aos][data-aos][data-aos-delay="2100"], -body[data-aos-delay="2100"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2100"].aos-animate, -body[data-aos-delay="2100"] [data-aos].aos-animate { - transition-delay: 2.1s; -} -[data-aos][data-aos][data-aos-duration="2150"], -body[data-aos-duration="2150"] [data-aos] { - transition-duration: 2.15s; -} -[data-aos][data-aos][data-aos-delay="2150"], -body[data-aos-delay="2150"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2150"].aos-animate, -body[data-aos-delay="2150"] [data-aos].aos-animate { - transition-delay: 2.15s; -} -[data-aos][data-aos][data-aos-duration="2200"], -body[data-aos-duration="2200"] [data-aos] { - transition-duration: 2.2s; -} -[data-aos][data-aos][data-aos-delay="2200"], -body[data-aos-delay="2200"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2200"].aos-animate, -body[data-aos-delay="2200"] [data-aos].aos-animate { - transition-delay: 2.2s; -} -[data-aos][data-aos][data-aos-duration="2250"], -body[data-aos-duration="2250"] [data-aos] { - transition-duration: 2.25s; -} -[data-aos][data-aos][data-aos-delay="2250"], -body[data-aos-delay="2250"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2250"].aos-animate, -body[data-aos-delay="2250"] [data-aos].aos-animate { - transition-delay: 2.25s; -} -[data-aos][data-aos][data-aos-duration="2300"], -body[data-aos-duration="2300"] [data-aos] { - transition-duration: 2.3s; -} -[data-aos][data-aos][data-aos-delay="2300"], -body[data-aos-delay="2300"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2300"].aos-animate, -body[data-aos-delay="2300"] [data-aos].aos-animate { - transition-delay: 2.3s; -} -[data-aos][data-aos][data-aos-duration="2350"], -body[data-aos-duration="2350"] [data-aos] { - transition-duration: 2.35s; -} -[data-aos][data-aos][data-aos-delay="2350"], -body[data-aos-delay="2350"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2350"].aos-animate, -body[data-aos-delay="2350"] [data-aos].aos-animate { - transition-delay: 2.35s; -} -[data-aos][data-aos][data-aos-duration="2400"], -body[data-aos-duration="2400"] [data-aos] { - transition-duration: 2.4s; -} -[data-aos][data-aos][data-aos-delay="2400"], -body[data-aos-delay="2400"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2400"].aos-animate, -body[data-aos-delay="2400"] [data-aos].aos-animate { - transition-delay: 2.4s; -} -[data-aos][data-aos][data-aos-duration="2450"], -body[data-aos-duration="2450"] [data-aos] { - transition-duration: 2.45s; -} -[data-aos][data-aos][data-aos-delay="2450"], -body[data-aos-delay="2450"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2450"].aos-animate, -body[data-aos-delay="2450"] [data-aos].aos-animate { - transition-delay: 2.45s; -} -[data-aos][data-aos][data-aos-duration="2500"], -body[data-aos-duration="2500"] [data-aos] { - transition-duration: 2.5s; -} -[data-aos][data-aos][data-aos-delay="2500"], -body[data-aos-delay="2500"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2500"].aos-animate, -body[data-aos-delay="2500"] [data-aos].aos-animate { - transition-delay: 2.5s; -} -[data-aos][data-aos][data-aos-duration="2550"], -body[data-aos-duration="2550"] [data-aos] { - transition-duration: 2.55s; -} -[data-aos][data-aos][data-aos-delay="2550"], -body[data-aos-delay="2550"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2550"].aos-animate, -body[data-aos-delay="2550"] [data-aos].aos-animate { - transition-delay: 2.55s; -} -[data-aos][data-aos][data-aos-duration="2600"], -body[data-aos-duration="2600"] [data-aos] { - transition-duration: 2.6s; -} -[data-aos][data-aos][data-aos-delay="2600"], -body[data-aos-delay="2600"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2600"].aos-animate, -body[data-aos-delay="2600"] [data-aos].aos-animate { - transition-delay: 2.6s; -} -[data-aos][data-aos][data-aos-duration="2650"], -body[data-aos-duration="2650"] [data-aos] { - transition-duration: 2.65s; -} -[data-aos][data-aos][data-aos-delay="2650"], -body[data-aos-delay="2650"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2650"].aos-animate, -body[data-aos-delay="2650"] [data-aos].aos-animate { - transition-delay: 2.65s; -} -[data-aos][data-aos][data-aos-duration="2700"], -body[data-aos-duration="2700"] [data-aos] { - transition-duration: 2.7s; -} -[data-aos][data-aos][data-aos-delay="2700"], -body[data-aos-delay="2700"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2700"].aos-animate, -body[data-aos-delay="2700"] [data-aos].aos-animate { - transition-delay: 2.7s; -} -[data-aos][data-aos][data-aos-duration="2750"], -body[data-aos-duration="2750"] [data-aos] { - transition-duration: 2.75s; -} -[data-aos][data-aos][data-aos-delay="2750"], -body[data-aos-delay="2750"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2750"].aos-animate, -body[data-aos-delay="2750"] [data-aos].aos-animate { - transition-delay: 2.75s; -} -[data-aos][data-aos][data-aos-duration="2800"], -body[data-aos-duration="2800"] [data-aos] { - transition-duration: 2.8s; -} -[data-aos][data-aos][data-aos-delay="2800"], -body[data-aos-delay="2800"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2800"].aos-animate, -body[data-aos-delay="2800"] [data-aos].aos-animate { - transition-delay: 2.8s; -} -[data-aos][data-aos][data-aos-duration="2850"], -body[data-aos-duration="2850"] [data-aos] { - transition-duration: 2.85s; -} -[data-aos][data-aos][data-aos-delay="2850"], -body[data-aos-delay="2850"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2850"].aos-animate, -body[data-aos-delay="2850"] [data-aos].aos-animate { - transition-delay: 2.85s; -} -[data-aos][data-aos][data-aos-duration="2900"], -body[data-aos-duration="2900"] [data-aos] { - transition-duration: 2.9s; -} -[data-aos][data-aos][data-aos-delay="2900"], -body[data-aos-delay="2900"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2900"].aos-animate, -body[data-aos-delay="2900"] [data-aos].aos-animate { - transition-delay: 2.9s; -} -[data-aos][data-aos][data-aos-duration="2950"], -body[data-aos-duration="2950"] [data-aos] { - transition-duration: 2.95s; -} -[data-aos][data-aos][data-aos-delay="2950"], -body[data-aos-delay="2950"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="2950"].aos-animate, -body[data-aos-delay="2950"] [data-aos].aos-animate { - transition-delay: 2.95s; -} -[data-aos][data-aos][data-aos-duration="3000"], -body[data-aos-duration="3000"] [data-aos] { - transition-duration: 3s; -} -[data-aos][data-aos][data-aos-delay="3000"], -body[data-aos-delay="3000"] [data-aos] { - transition-delay: 0; -} -[data-aos][data-aos][data-aos-delay="3000"].aos-animate, -body[data-aos-delay="3000"] [data-aos].aos-animate { - transition-delay: 3s; -} -[data-aos][data-aos][data-aos-easing="linear"], -body[data-aos-easing="linear"] [data-aos] { - transition-timing-function: cubic-bezier(0.25, 0.25, 0.75, 0.75); -} -[data-aos][data-aos][data-aos-easing="ease"], -body[data-aos-easing="ease"] [data-aos] { - transition-timing-function: ease; -} -[data-aos][data-aos][data-aos-easing="ease-in"], -body[data-aos-easing="ease-in"] [data-aos] { - transition-timing-function: ease-in; -} -[data-aos][data-aos][data-aos-easing="ease-out"], -body[data-aos-easing="ease-out"] [data-aos] { - transition-timing-function: ease-out; -} -[data-aos][data-aos][data-aos-easing="ease-in-out"], -body[data-aos-easing="ease-in-out"] [data-aos] { - transition-timing-function: ease-in-out; -} -[data-aos][data-aos][data-aos-easing="ease-in-back"], -body[data-aos-easing="ease-in-back"] [data-aos] { - transition-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045); -} -[data-aos][data-aos][data-aos-easing="ease-out-back"], -body[data-aos-easing="ease-out-back"] [data-aos] { - transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275); -} -[data-aos][data-aos][data-aos-easing="ease-in-out-back"], -body[data-aos-easing="ease-in-out-back"] [data-aos] { - transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); -} -[data-aos][data-aos][data-aos-easing="ease-in-sine"], -body[data-aos-easing="ease-in-sine"] [data-aos] { - transition-timing-function: cubic-bezier(0.47, 0, 0.745, 0.715); -} -[data-aos][data-aos][data-aos-easing="ease-out-sine"], -body[data-aos-easing="ease-out-sine"] [data-aos] { - transition-timing-function: cubic-bezier(0.39, 0.575, 0.565, 1); -} -[data-aos][data-aos][data-aos-easing="ease-in-out-sine"], -body[data-aos-easing="ease-in-out-sine"] [data-aos] { - transition-timing-function: cubic-bezier(0.445, 0.05, 0.55, 0.95); -} -[data-aos][data-aos][data-aos-easing="ease-in-quad"], -body[data-aos-easing="ease-in-quad"] [data-aos] { - transition-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); -} -[data-aos][data-aos][data-aos-easing="ease-out-quad"], -body[data-aos-easing="ease-out-quad"] [data-aos] { - transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); -} -[data-aos][data-aos][data-aos-easing="ease-in-out-quad"], -body[data-aos-easing="ease-in-out-quad"] [data-aos] { - transition-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); -} -[data-aos][data-aos][data-aos-easing="ease-in-cubic"], -body[data-aos-easing="ease-in-cubic"] [data-aos] { - transition-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); -} -[data-aos][data-aos][data-aos-easing="ease-out-cubic"], -body[data-aos-easing="ease-out-cubic"] [data-aos] { - transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); -} -[data-aos][data-aos][data-aos-easing="ease-in-out-cubic"], -body[data-aos-easing="ease-in-out-cubic"] [data-aos] { - transition-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); -} -[data-aos][data-aos][data-aos-easing="ease-in-quart"], -body[data-aos-easing="ease-in-quart"] [data-aos] { - transition-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); -} -[data-aos][data-aos][data-aos-easing="ease-out-quart"], -body[data-aos-easing="ease-out-quart"] [data-aos] { - transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); -} -[data-aos][data-aos][data-aos-easing="ease-in-out-quart"], -body[data-aos-easing="ease-in-out-quart"] [data-aos] { - transition-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); -} -[data-aos^="fade"][data-aos^="fade"] { - opacity: 0; - transition-property: opacity, transform; -} -[data-aos^="fade"][data-aos^="fade"].aos-animate { - opacity: 1; - transform: translateZ(0); -} -[data-aos="fade-up"] { - transform: translate3d(0, 20px, 0); -} -[data-aos="fade-down"] { - transform: translate3d(0, -20px, 0); -} -[data-aos="fade-right"] { - transform: translate3d(-20px, 0, 0); -} -[data-aos="fade-left"] { - transform: translate3d(20px, 0, 0); -} -[data-aos="fade-up-right"] { - transform: translate3d(-20px, 20px, 0); -} -[data-aos="fade-up-left"] { - transform: translate3d(20px, 20px, 0); -} -[data-aos="fade-down-right"] { - transform: translate3d(-20px, -20px, 0); -} -[data-aos="fade-down-left"] { - transform: translate3d(20px, -20px, 0); -} -[data-aos^="slide"][data-aos^="slide"] { - transition-property: transform; -} -[data-aos^="slide"][data-aos^="slide"].aos-animate { - transform: translateZ(0); -} -[data-aos="slide-up"] { - transform: translate3d(0, 100%, 0); -} -[data-aos="slide-down"] { - transform: translate3d(0, -100%, 0); -} -[data-aos="slide-right"] { - transform: translate3d(-100%, 0, 0); -} -[data-aos="slide-left"] { - transform: translate3d(100%, 0, 0); -} -@charset "UTF-8"; -/*! - * Bootstrap v5.3.2 (https://getbootstrap.com/) - * Copyright 2011-2023 The Bootstrap Authors - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */ -:root, -[data-bs-theme="light"] { - --bs-blue: #0d6efd; - --bs-indigo: #6610f2; - --bs-purple: #6f42c1; - --bs-pink: #d63384; - --bs-red: #dc3545; - --bs-orange: #fd7e14; - --bs-yellow: #ffc107; - --bs-green: #198754; - --bs-teal: #20c997; - --bs-cyan: #0dcaf0; - --bs-black: #191f27; - --bs-white: #fff; - --bs-gray: #6c757d; - --bs-gray-dark: #343a40; - --bs-gray-100: #f8f9fa; - --bs-gray-200: #e9ecef; - --bs-gray-300: #dee2e6; - --bs-gray-400: #ced4da; - --bs-gray-500: #adb5bd; - --bs-gray-600: #6c757d; - --bs-gray-700: #495057; - --bs-gray-800: #343a40; - --bs-gray-900: #212529; - --bs-primary: #0d6efd; - --bs-secondary: #6c757d; - --bs-success: #198754; - --bs-info: #0dcaf0; - --bs-warning: #ffc107; - --bs-danger: #dc3545; - --bs-light: #eee; - --bs-dark: #222; - --bs-primary-rgb: 13, 110, 253; - --bs-secondary-rgb: 108, 117, 125; - --bs-success-rgb: 25, 135, 84; - --bs-info-rgb: 13, 202, 240; - --bs-warning-rgb: 255, 193, 7; - --bs-danger-rgb: 220, 53, 69; - --bs-light-rgb: 238, 238, 238; - --bs-dark-rgb: 34, 34, 34; - --bs-primary-text-emphasis: #052c65; - --bs-secondary-text-emphasis: #2b2f32; - --bs-success-text-emphasis: #0a3622; - --bs-info-text-emphasis: #055160; - --bs-warning-text-emphasis: #664d03; - --bs-danger-text-emphasis: #58151c; - --bs-light-text-emphasis: #495057; - --bs-dark-text-emphasis: #495057; - --bs-primary-bg-subtle: #cfe2ff; - --bs-secondary-bg-subtle: #e2e3e5; - --bs-success-bg-subtle: #d1e7dd; - --bs-info-bg-subtle: #cff4fc; - --bs-warning-bg-subtle: #fff3cd; - --bs-danger-bg-subtle: #f8d7da; - --bs-light-bg-subtle: #fcfcfd; - --bs-dark-bg-subtle: #ced4da; - --bs-primary-border-subtle: #9ec5fe; - --bs-secondary-border-subtle: #c4c8cb; - --bs-success-border-subtle: #a3cfbb; - --bs-info-border-subtle: #9eeaf9; - --bs-warning-border-subtle: #ffe69c; - --bs-danger-border-subtle: #f1aeb5; - --bs-light-border-subtle: #e9ecef; - --bs-dark-border-subtle: #adb5bd; - --bs-white-rgb: 255, 255, 255; - --bs-black-rgb: 25, 31, 39; - --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); - --bs-body-font-family: var(--bs-font-sans-serif); - --bs-body-font-size: 1rem; - --bs-body-font-weight: 400; - --bs-body-line-height: 1.5; - --bs-body-color: #212529; - --bs-body-color-rgb: 33, 37, 41; - --bs-body-bg: #0e1015; - --bs-body-bg-rgb: 14, 16, 21; - --bs-emphasis-color: #191f27; - --bs-emphasis-color-rgb: 25, 31, 39; - --bs-secondary-color: rgba(33, 37, 41, 0.75); - --bs-secondary-color-rgb: 33, 37, 41; - --bs-secondary-bg: #e9ecef; - --bs-secondary-bg-rgb: 233, 236, 239; - --bs-tertiary-color: rgba(33, 37, 41, 0.5); - --bs-tertiary-color-rgb: 33, 37, 41; - --bs-tertiary-bg: #f8f9fa; - --bs-tertiary-bg-rgb: 248, 249, 250; - --bs-heading-color: inherit; - --bs-link-color: #0d6efd; - --bs-link-color-rgb: 13, 110, 253; - --bs-link-decoration: underline; - --bs-link-hover-color: #0a58ca; - --bs-link-hover-color-rgb: 10, 88, 202; - --bs-code-color: #d63384; - --bs-highlight-color: #212529; - --bs-highlight-bg: #fff3cd; - --bs-border-width: 1px; - --bs-border-style: solid; - --bs-border-color: rgba(24, 176, 162, 0.15); - --bs-border-color-translucent: rgba(25, 31, 39, 0.175); - --bs-border-radius: 0.375rem; - --bs-border-radius-sm: 0.25rem; - --bs-border-radius-lg: 0.5rem; - --bs-border-radius-xl: 1rem; - --bs-border-radius-xxl: 2rem; - --bs-border-radius-2xl: var(--bs-border-radius-xxl); - --bs-border-radius-pill: 50rem; - --bs-box-shadow: 0 0.5rem 1rem rgba(25, 31, 39, 0.15); - --bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(25, 31, 39, 0.075); - --bs-box-shadow-lg: 0 1rem 3rem rgba(25, 31, 39, 0.175); - --bs-box-shadow-inset: inset 0 1px 2px rgba(25, 31, 39, 0.075); - --bs-focus-ring-width: 0.25rem; - --bs-focus-ring-opacity: 0.25; - --bs-focus-ring-color: rgba(13, 110, 253, 0.25); - --bs-form-valid-color: #198754; - --bs-form-valid-border-color: #198754; - --bs-form-invalid-color: #dc3545; - --bs-form-invalid-border-color: #dc3545; } - -[data-bs-theme="dark"] { - color-scheme: dark; - --bs-body-color: #dee2e6; - --bs-body-color-rgb: 222, 226, 230; - --bs-body-bg: #212529; - --bs-body-bg-rgb: 33, 37, 41; - --bs-emphasis-color: #fff; - --bs-emphasis-color-rgb: 255, 255, 255; - --bs-secondary-color: rgba(222, 226, 230, 0.75); - --bs-secondary-color-rgb: 222, 226, 230; - --bs-secondary-bg: #343a40; - --bs-secondary-bg-rgb: 52, 58, 64; - --bs-tertiary-color: rgba(222, 226, 230, 0.5); - --bs-tertiary-color-rgb: 222, 226, 230; - --bs-tertiary-bg: #2b3035; - --bs-tertiary-bg-rgb: 43, 48, 53; - --bs-primary-text-emphasis: #6ea8fe; - --bs-secondary-text-emphasis: #a7acb1; - --bs-success-text-emphasis: #75b798; - --bs-info-text-emphasis: #6edff6; - --bs-warning-text-emphasis: #ffda6a; - --bs-danger-text-emphasis: #ea868f; - --bs-light-text-emphasis: #f8f9fa; - --bs-dark-text-emphasis: #dee2e6; - --bs-primary-bg-subtle: #031633; - --bs-secondary-bg-subtle: #161719; - --bs-success-bg-subtle: #051b11; - --bs-info-bg-subtle: #032830; - --bs-warning-bg-subtle: #332701; - --bs-danger-bg-subtle: #2c0b0e; - --bs-light-bg-subtle: #343a40; - --bs-dark-bg-subtle: #272d34; - --bs-primary-border-subtle: #084298; - --bs-secondary-border-subtle: #41464b; - --bs-success-border-subtle: #0f5132; - --bs-info-border-subtle: #087990; - --bs-warning-border-subtle: #997404; - --bs-danger-border-subtle: #842029; - --bs-light-border-subtle: #495057; - --bs-dark-border-subtle: #343a40; - --bs-heading-color: inherit; - --bs-link-color: #6ea8fe; - --bs-link-hover-color: #8bb9fe; - --bs-link-color-rgb: 110, 168, 254; - --bs-link-hover-color-rgb: 139, 185, 254; - --bs-code-color: #e685b5; - --bs-highlight-color: #dee2e6; - --bs-highlight-bg: #664d03; - --bs-border-color: #495057; - --bs-border-color-translucent: rgba(255, 255, 255, 0.15); - --bs-form-valid-color: #75b798; - --bs-form-valid-border-color: #75b798; - --bs-form-invalid-color: #ea868f; - --bs-form-invalid-border-color: #ea868f; } - -*, -*::before, -*::after { - box-sizing: border-box; } - -@media (prefers-reduced-motion: no-preference) { - :root { - scroll-behavior: smooth; } } - -body { - margin: 0; - font-family: var(--bs-body-font-family); - font-size: var(--bs-body-font-size); - font-weight: var(--bs-body-font-weight); - line-height: var(--bs-body-line-height); - color: var(--bs-body-color); - text-align: var(--bs-body-text-align); - background-color: var(--bs-body-bg); - -webkit-text-size-adjust: 100%; - -webkit-tap-highlight-color: rgba(25, 31, 39, 0); } - -hr { - margin: 1rem 0; - color: inherit; - border: 0; - border-top: var(--bs-border-width) solid; - opacity: 0.25; } - -h6, .h6, h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 { - margin-top: 0; - margin-bottom: 0.5rem; - font-weight: 500; - line-height: 1.2; - color: var(--bs-heading-color); } - -h1, .h1 { - font-size: calc(1.375rem + 1.5vw); } - @media (min-width: 1200px) { - h1, .h1 { - font-size: 2.5rem; } } -h2, .h2 { - font-size: calc(1.325rem + 0.9vw); } - @media (min-width: 1200px) { - h2, .h2 { - font-size: 2rem; } } -h3, .h3 { - font-size: calc(1.3rem + 0.6vw); } - @media (min-width: 1200px) { - h3, .h3 { - font-size: 1.75rem; } } -h4, .h4 { - font-size: calc(1.275rem + 0.3vw); } - @media (min-width: 1200px) { - h4, .h4 { - font-size: 1.5rem; } } -h5, .h5 { - font-size: 1.25rem; } - -h6, .h6 { - font-size: 1rem; } - -p { - margin-top: 0; - margin-bottom: 1rem; } - -abbr[title] { - text-decoration: underline dotted; - cursor: help; - text-decoration-skip-ink: none; } - -address { - margin-bottom: 1rem; - font-style: normal; - line-height: inherit; } - -ol, -ul { - padding-left: 2rem; } - -ol, -ul, -dl { - margin-top: 0; - margin-bottom: 1rem; } - -ol ol, -ul ul, -ol ul, -ul ol { - margin-bottom: 0; } - -dt { - font-weight: 700; } - -dd { - margin-bottom: .5rem; - margin-left: 0; } - -blockquote { - margin: 0 0 1rem; } - -b, -strong { - font-weight: bolder; } - -small, .small { - font-size: 0.875em; } - -mark, .mark { - padding: 0.1875em; - color: var(--bs-highlight-color); - background-color: var(--bs-highlight-bg); } - -sub, -sup { - position: relative; - font-size: 0.75em; - line-height: 0; - vertical-align: baseline; } - -sub { - bottom: -.25em; } - -sup { - top: -.5em; } - -a { - color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1)); - text-decoration: underline; } - a:hover { - --bs-link-color-rgb: var(--bs-link-hover-color-rgb); } - -a:not([href]):not([class]), a:not([href]):not([class]):hover { - color: inherit; - text-decoration: none; } - -pre, -code, -kbd, -samp { - font-family: var(--bs-font-monospace); - font-size: 1em; } - -pre { - display: block; - margin-top: 0; - margin-bottom: 1rem; - overflow: auto; - font-size: 0.875em; } - pre code { - font-size: inherit; - color: inherit; - word-break: normal; } - -code { - font-size: 0.875em; - color: var(--bs-code-color); - word-wrap: break-word; } - a > code { - color: inherit; } - -kbd { - padding: 0.1875rem 0.375rem; - font-size: 0.875em; - color: var(--bs-body-bg); - background-color: var(--bs-body-color); - border-radius: 0.25rem; } - kbd kbd { - padding: 0; - font-size: 1em; } - -figure { - margin: 0 0 1rem; } - -img, -svg { - vertical-align: middle; } - -table { - caption-side: bottom; - border-collapse: collapse; } - -caption { - padding-top: 0.5rem; - padding-bottom: 0.5rem; - color: var(--bs-secondary-color); - text-align: left; } - -th { - text-align: inherit; - text-align: -webkit-match-parent; } - -thead, -tbody, -tfoot, -tr, -td, -th { - border-color: inherit; - border-style: solid; - border-width: 0; } - -label { - display: inline-block; } - -button { - border-radius: 0; } - -button:focus:not(:focus-visible) { - outline: 0; } - -input, -button, -select, -optgroup, -textarea { - margin: 0; - font-family: inherit; - font-size: inherit; - line-height: inherit; } - -button, -select { - text-transform: none; } - -[role="button"] { - cursor: pointer; } - -select { - word-wrap: normal; } - select:disabled { - opacity: 1; } - -[list]:not([type="date"]):not([type="datetime-local"]):not([type="month"]):not([type="week"]):not([type="time"])::-webkit-calendar-picker-indicator { - display: none !important; } - -button, -[type="button"], -[type="reset"], -[type="submit"] { - -webkit-appearance: button; } - button:not(:disabled), - [type="button"]:not(:disabled), - [type="reset"]:not(:disabled), - [type="submit"]:not(:disabled) { - cursor: pointer; } - -::-moz-focus-inner { - padding: 0; - border-style: none; } - -textarea { - resize: vertical; } - -fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0; } - -legend { - float: left; - width: 100%; - padding: 0; - margin-bottom: 0.5rem; - font-size: calc(1.275rem + 0.3vw); - line-height: inherit; } - @media (min-width: 1200px) { - legend { - font-size: 1.5rem; } } - legend + * { - clear: left; } - -::-webkit-datetime-edit-fields-wrapper, -::-webkit-datetime-edit-text, -::-webkit-datetime-edit-minute, -::-webkit-datetime-edit-hour-field, -::-webkit-datetime-edit-day-field, -::-webkit-datetime-edit-month-field, -::-webkit-datetime-edit-year-field { - padding: 0; } - -::-webkit-inner-spin-button { - height: auto; } - -[type="search"] { - -webkit-appearance: textfield; - outline-offset: -2px; } - -/* rtl:raw: -[type="tel"], -[type="url"], -[type="email"], -[type="number"] { - direction: ltr; -} -*/ -::-webkit-search-decoration { - -webkit-appearance: none; } - -::-webkit-color-swatch-wrapper { - padding: 0; } - -::file-selector-button { - font: inherit; - -webkit-appearance: button; } - -output { - display: inline-block; } - -iframe { - border: 0; } - -summary { - display: list-item; - cursor: pointer; } - -progress { - vertical-align: baseline; } - -[hidden] { - display: none !important; } - -.lead { - font-size: 1.25rem; - font-weight: 300; } - -.display-1 { - font-size: calc(1.625rem + 4.5vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-1 { - font-size: 5rem; } } -.display-2 { - font-size: calc(1.575rem + 3.9vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-2 { - font-size: 4.5rem; } } -.display-3 { - font-size: calc(1.525rem + 3.3vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-3 { - font-size: 4rem; } } -.display-4 { - font-size: calc(1.475rem + 2.7vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-4 { - font-size: 3.5rem; } } -.display-5 { - font-size: calc(1.425rem + 2.1vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-5 { - font-size: 3rem; } } -.display-6 { - font-size: calc(1.375rem + 1.5vw); - font-weight: 300; - line-height: 1.2; } - @media (min-width: 1200px) { - .display-6 { - font-size: 2.5rem; } } -.list-unstyled { - padding-left: 0; - list-style: none; } - -.list-inline { - padding-left: 0; - list-style: none; } - -.list-inline-item { - display: inline-block; } - .list-inline-item:not(:last-child) { - margin-right: 0.5rem; } - -.initialism { - font-size: 0.875em; - text-transform: uppercase; } - -.blockquote { - margin-bottom: 1rem; - font-size: 1.25rem; } - .blockquote > :last-child { - margin-bottom: 0; } - -.blockquote-footer { - margin-top: -1rem; - margin-bottom: 1rem; - font-size: 0.875em; - color: #6c757d; } - .blockquote-footer::before { - content: "\2014\00A0"; } - -.img-fluid { - max-width: 100%; - height: auto; } - -.img-thumbnail { - padding: 0.25rem; - background-color: var(--bs-body-bg); - border: var(--bs-border-width) solid var(--bs-border-color); - border-radius: var(--bs-border-radius); - max-width: 100%; - height: auto; } - -.figure { - display: inline-block; } - -.figure-img { - margin-bottom: 0.5rem; - line-height: 1; } - -.figure-caption { - font-size: 0.875em; - color: var(--bs-secondary-color); } - -.container, -.container-fluid, -.container-xxl, -.container-xl, -.container-lg, -.container-md, -.container-sm { - --bs-gutter-x: 1.5rem; - --bs-gutter-y: 0; - width: 100%; - padding-right: calc(var(--bs-gutter-x) * .5); - padding-left: calc(var(--bs-gutter-x) * .5); - margin-right: auto; - margin-left: auto; } - -@media (min-width: 576px) { - .container-sm, .container { - max-width: 540px; } } - -@media (min-width: 768px) { - .container-md, .container-sm, .container { - max-width: 720px; } } - -@media (min-width: 992px) { - .container-lg, .container-md, .container-sm, .container { - max-width: 960px; } } - -@media (min-width: 1200px) { - .container-xl, .container-lg, .container-md, .container-sm, .container { - max-width: 1140px; } } - -@media (min-width: 1400px) { - .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container { - max-width: 1320px; } } - -:root { - --bs-breakpoint-xs: 0; - --bs-breakpoint-sm: 576px; - --bs-breakpoint-md: 768px; - --bs-breakpoint-lg: 992px; - --bs-breakpoint-xl: 1200px; - --bs-breakpoint-xxl: 1400px; } - -.row { - --bs-gutter-x: 1.5rem; - --bs-gutter-y: 0; - display: flex; - flex-wrap: wrap; - margin-top: calc(-1 * var(--bs-gutter-y)); - margin-right: calc(-.5 * var(--bs-gutter-x)); - margin-left: calc(-.5 * var(--bs-gutter-x)); } - .row > * { - flex-shrink: 0; - width: 100%; - max-width: 100%; - padding-right: calc(var(--bs-gutter-x) * .5); - padding-left: calc(var(--bs-gutter-x) * .5); - margin-top: var(--bs-gutter-y); } - -.col { - flex: 1 0 0%; } - -.row-cols-auto > * { - flex: 0 0 auto; - width: auto; } - -.row-cols-1 > * { - flex: 0 0 auto; - width: 100%; } - -.row-cols-2 > * { - flex: 0 0 auto; - width: 50%; } - -.row-cols-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - -.row-cols-4 > * { - flex: 0 0 auto; - width: 25%; } - -.row-cols-5 > * { - flex: 0 0 auto; - width: 20%; } - -.row-cols-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - -.col-auto { - flex: 0 0 auto; - width: auto; } - -.col-1 { - flex: 0 0 auto; - width: 8.33333333%; } - -.col-2 { - flex: 0 0 auto; - width: 16.66666667%; } - -.col-3 { - flex: 0 0 auto; - width: 25%; } - -.col-4 { - flex: 0 0 auto; - width: 33.33333333%; } - -.col-5 { - flex: 0 0 auto; - width: 41.66666667%; } - -.col-6 { - flex: 0 0 auto; - width: 50%; } - -.col-7 { - flex: 0 0 auto; - width: 58.33333333%; } - -.col-8 { - flex: 0 0 auto; - width: 66.66666667%; } - -.col-9 { - flex: 0 0 auto; - width: 75%; } - -.col-10 { - flex: 0 0 auto; - width: 83.33333333%; } - -.col-11 { - flex: 0 0 auto; - width: 91.66666667%; } - -.col-12 { - flex: 0 0 auto; - width: 100%; } - -.offset-1 { - margin-left: 8.33333333%; } - -.offset-2 { - margin-left: 16.66666667%; } - -.offset-3 { - margin-left: 25%; } - -.offset-4 { - margin-left: 33.33333333%; } - -.offset-5 { - margin-left: 41.66666667%; } - -.offset-6 { - margin-left: 50%; } - -.offset-7 { - margin-left: 58.33333333%; } - -.offset-8 { - margin-left: 66.66666667%; } - -.offset-9 { - margin-left: 75%; } - -.offset-10 { - margin-left: 83.33333333%; } - -.offset-11 { - margin-left: 91.66666667%; } - -.g-0, -.gx-0 { - --bs-gutter-x: 0; } - -.g-0, -.gy-0 { - --bs-gutter-y: 0; } - -.g-1, -.gx-1 { - --bs-gutter-x: 0.25rem; } - -.g-1, -.gy-1 { - --bs-gutter-y: 0.25rem; } - -.g-2, -.gx-2 { - --bs-gutter-x: 0.5rem; } - -.g-2, -.gy-2 { - --bs-gutter-y: 0.5rem; } - -.g-3, -.gx-3 { - --bs-gutter-x: 1rem; } - -.g-3, -.gy-3 { - --bs-gutter-y: 1rem; } - -.g-4, -.gx-4 { - --bs-gutter-x: 1.5rem; } - -.g-4, -.gy-4 { - --bs-gutter-y: 1.5rem; } - -.g-5, -.gx-5 { - --bs-gutter-x: 3rem; } - -.g-5, -.gy-5 { - --bs-gutter-y: 3rem; } - -@media (min-width: 576px) { - .col-sm { - flex: 1 0 0%; } - .row-cols-sm-auto > * { - flex: 0 0 auto; - width: auto; } - .row-cols-sm-1 > * { - flex: 0 0 auto; - width: 100%; } - .row-cols-sm-2 > * { - flex: 0 0 auto; - width: 50%; } - .row-cols-sm-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - .row-cols-sm-4 > * { - flex: 0 0 auto; - width: 25%; } - .row-cols-sm-5 > * { - flex: 0 0 auto; - width: 20%; } - .row-cols-sm-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - .col-sm-auto { - flex: 0 0 auto; - width: auto; } - .col-sm-1 { - flex: 0 0 auto; - width: 8.33333333%; } - .col-sm-2 { - flex: 0 0 auto; - width: 16.66666667%; } - .col-sm-3 { - flex: 0 0 auto; - width: 25%; } - .col-sm-4 { - flex: 0 0 auto; - width: 33.33333333%; } - .col-sm-5 { - flex: 0 0 auto; - width: 41.66666667%; } - .col-sm-6 { - flex: 0 0 auto; - width: 50%; } - .col-sm-7 { - flex: 0 0 auto; - width: 58.33333333%; } - .col-sm-8 { - flex: 0 0 auto; - width: 66.66666667%; } - .col-sm-9 { - flex: 0 0 auto; - width: 75%; } - .col-sm-10 { - flex: 0 0 auto; - width: 83.33333333%; } - .col-sm-11 { - flex: 0 0 auto; - width: 91.66666667%; } - .col-sm-12 { - flex: 0 0 auto; - width: 100%; } - .offset-sm-0 { - margin-left: 0; } - .offset-sm-1 { - margin-left: 8.33333333%; } - .offset-sm-2 { - margin-left: 16.66666667%; } - .offset-sm-3 { - margin-left: 25%; } - .offset-sm-4 { - margin-left: 33.33333333%; } - .offset-sm-5 { - margin-left: 41.66666667%; } - .offset-sm-6 { - margin-left: 50%; } - .offset-sm-7 { - margin-left: 58.33333333%; } - .offset-sm-8 { - margin-left: 66.66666667%; } - .offset-sm-9 { - margin-left: 75%; } - .offset-sm-10 { - margin-left: 83.33333333%; } - .offset-sm-11 { - margin-left: 91.66666667%; } - .g-sm-0, - .gx-sm-0 { - --bs-gutter-x: 0; } - .g-sm-0, - .gy-sm-0 { - --bs-gutter-y: 0; } - .g-sm-1, - .gx-sm-1 { - --bs-gutter-x: 0.25rem; } - .g-sm-1, - .gy-sm-1 { - --bs-gutter-y: 0.25rem; } - .g-sm-2, - .gx-sm-2 { - --bs-gutter-x: 0.5rem; } - .g-sm-2, - .gy-sm-2 { - --bs-gutter-y: 0.5rem; } - .g-sm-3, - .gx-sm-3 { - --bs-gutter-x: 1rem; } - .g-sm-3, - .gy-sm-3 { - --bs-gutter-y: 1rem; } - .g-sm-4, - .gx-sm-4 { - --bs-gutter-x: 1.5rem; } - .g-sm-4, - .gy-sm-4 { - --bs-gutter-y: 1.5rem; } - .g-sm-5, - .gx-sm-5 { - --bs-gutter-x: 3rem; } - .g-sm-5, - .gy-sm-5 { - --bs-gutter-y: 3rem; } } - -@media (min-width: 768px) { - .col-md { - flex: 1 0 0%; } - .row-cols-md-auto > * { - flex: 0 0 auto; - width: auto; } - .row-cols-md-1 > * { - flex: 0 0 auto; - width: 100%; } - .row-cols-md-2 > * { - flex: 0 0 auto; - width: 50%; } - .row-cols-md-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - .row-cols-md-4 > * { - flex: 0 0 auto; - width: 25%; } - .row-cols-md-5 > * { - flex: 0 0 auto; - width: 20%; } - .row-cols-md-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - .col-md-auto { - flex: 0 0 auto; - width: auto; } - .col-md-1 { - flex: 0 0 auto; - width: 8.33333333%; } - .col-md-2 { - flex: 0 0 auto; - width: 16.66666667%; } - .col-md-3 { - flex: 0 0 auto; - width: 25%; } - .col-md-4 { - flex: 0 0 auto; - width: 33.33333333%; } - .col-md-5 { - flex: 0 0 auto; - width: 41.66666667%; } - .col-md-6 { - flex: 0 0 auto; - width: 50%; } - .col-md-7 { - flex: 0 0 auto; - width: 58.33333333%; } - .col-md-8 { - flex: 0 0 auto; - width: 66.66666667%; } - .col-md-9 { - flex: 0 0 auto; - width: 75%; } - .col-md-10 { - flex: 0 0 auto; - width: 83.33333333%; } - .col-md-11 { - flex: 0 0 auto; - width: 91.66666667%; } - .col-md-12 { - flex: 0 0 auto; - width: 100%; } - .offset-md-0 { - margin-left: 0; } - .offset-md-1 { - margin-left: 8.33333333%; } - .offset-md-2 { - margin-left: 16.66666667%; } - .offset-md-3 { - margin-left: 25%; } - .offset-md-4 { - margin-left: 33.33333333%; } - .offset-md-5 { - margin-left: 41.66666667%; } - .offset-md-6 { - margin-left: 50%; } - .offset-md-7 { - margin-left: 58.33333333%; } - .offset-md-8 { - margin-left: 66.66666667%; } - .offset-md-9 { - margin-left: 75%; } - .offset-md-10 { - margin-left: 83.33333333%; } - .offset-md-11 { - margin-left: 91.66666667%; } - .g-md-0, - .gx-md-0 { - --bs-gutter-x: 0; } - .g-md-0, - .gy-md-0 { - --bs-gutter-y: 0; } - .g-md-1, - .gx-md-1 { - --bs-gutter-x: 0.25rem; } - .g-md-1, - .gy-md-1 { - --bs-gutter-y: 0.25rem; } - .g-md-2, - .gx-md-2 { - --bs-gutter-x: 0.5rem; } - .g-md-2, - .gy-md-2 { - --bs-gutter-y: 0.5rem; } - .g-md-3, - .gx-md-3 { - --bs-gutter-x: 1rem; } - .g-md-3, - .gy-md-3 { - --bs-gutter-y: 1rem; } - .g-md-4, - .gx-md-4 { - --bs-gutter-x: 1.5rem; } - .g-md-4, - .gy-md-4 { - --bs-gutter-y: 1.5rem; } - .g-md-5, - .gx-md-5 { - --bs-gutter-x: 3rem; } - .g-md-5, - .gy-md-5 { - --bs-gutter-y: 3rem; } } - -@media (min-width: 992px) { - .col-lg { - flex: 1 0 0%; } - .row-cols-lg-auto > * { - flex: 0 0 auto; - width: auto; } - .row-cols-lg-1 > * { - flex: 0 0 auto; - width: 100%; } - .row-cols-lg-2 > * { - flex: 0 0 auto; - width: 50%; } - .row-cols-lg-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - .row-cols-lg-4 > * { - flex: 0 0 auto; - width: 25%; } - .row-cols-lg-5 > * { - flex: 0 0 auto; - width: 20%; } - .row-cols-lg-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - .col-lg-auto { - flex: 0 0 auto; - width: auto; } - .col-lg-1 { - flex: 0 0 auto; - width: 8.33333333%; } - .col-lg-2 { - flex: 0 0 auto; - width: 16.66666667%; } - .col-lg-3 { - flex: 0 0 auto; - width: 25%; } - .col-lg-4 { - flex: 0 0 auto; - width: 33.33333333%; } - .col-lg-5 { - flex: 0 0 auto; - width: 41.66666667%; } - .col-lg-6 { - flex: 0 0 auto; - width: 50%; } - .col-lg-7 { - flex: 0 0 auto; - width: 58.33333333%; } - .col-lg-8 { - flex: 0 0 auto; - width: 66.66666667%; } - .col-lg-9 { - flex: 0 0 auto; - width: 75%; } - .col-lg-10 { - flex: 0 0 auto; - width: 83.33333333%; } - .col-lg-11 { - flex: 0 0 auto; - width: 91.66666667%; } - .col-lg-12 { - flex: 0 0 auto; - width: 100%; } - .offset-lg-0 { - margin-left: 0; } - .offset-lg-1 { - margin-left: 8.33333333%; } - .offset-lg-2 { - margin-left: 16.66666667%; } - .offset-lg-3 { - margin-left: 25%; } - .offset-lg-4 { - margin-left: 33.33333333%; } - .offset-lg-5 { - margin-left: 41.66666667%; } - .offset-lg-6 { - margin-left: 50%; } - .offset-lg-7 { - margin-left: 58.33333333%; } - .offset-lg-8 { - margin-left: 66.66666667%; } - .offset-lg-9 { - margin-left: 75%; } - .offset-lg-10 { - margin-left: 83.33333333%; } - .offset-lg-11 { - margin-left: 91.66666667%; } - .g-lg-0, - .gx-lg-0 { - --bs-gutter-x: 0; } - .g-lg-0, - .gy-lg-0 { - --bs-gutter-y: 0; } - .g-lg-1, - .gx-lg-1 { - --bs-gutter-x: 0.25rem; } - .g-lg-1, - .gy-lg-1 { - --bs-gutter-y: 0.25rem; } - .g-lg-2, - .gx-lg-2 { - --bs-gutter-x: 0.5rem; } - .g-lg-2, - .gy-lg-2 { - --bs-gutter-y: 0.5rem; } - .g-lg-3, - .gx-lg-3 { - --bs-gutter-x: 1rem; } - .g-lg-3, - .gy-lg-3 { - --bs-gutter-y: 1rem; } - .g-lg-4, - .gx-lg-4 { - --bs-gutter-x: 1.5rem; } - .g-lg-4, - .gy-lg-4 { - --bs-gutter-y: 1.5rem; } - .g-lg-5, - .gx-lg-5 { - --bs-gutter-x: 3rem; } - .g-lg-5, - .gy-lg-5 { - --bs-gutter-y: 3rem; } } - -@media (min-width: 1200px) { - .col-xl { - flex: 1 0 0%; } - .row-cols-xl-auto > * { - flex: 0 0 auto; - width: auto; } - .row-cols-xl-1 > * { - flex: 0 0 auto; - width: 100%; } - .row-cols-xl-2 > * { - flex: 0 0 auto; - width: 50%; } - .row-cols-xl-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - .row-cols-xl-4 > * { - flex: 0 0 auto; - width: 25%; } - .row-cols-xl-5 > * { - flex: 0 0 auto; - width: 20%; } - .row-cols-xl-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - .col-xl-auto { - flex: 0 0 auto; - width: auto; } - .col-xl-1 { - flex: 0 0 auto; - width: 8.33333333%; } - .col-xl-2 { - flex: 0 0 auto; - width: 16.66666667%; } - .col-xl-3 { - flex: 0 0 auto; - width: 25%; } - .col-xl-4 { - flex: 0 0 auto; - width: 33.33333333%; } - .col-xl-5 { - flex: 0 0 auto; - width: 41.66666667%; } - .col-xl-6 { - flex: 0 0 auto; - width: 50%; } - .col-xl-7 { - flex: 0 0 auto; - width: 58.33333333%; } - .col-xl-8 { - flex: 0 0 auto; - width: 66.66666667%; } - .col-xl-9 { - flex: 0 0 auto; - width: 75%; } - .col-xl-10 { - flex: 0 0 auto; - width: 83.33333333%; } - .col-xl-11 { - flex: 0 0 auto; - width: 91.66666667%; } - .col-xl-12 { - flex: 0 0 auto; - width: 100%; } - .offset-xl-0 { - margin-left: 0; } - .offset-xl-1 { - margin-left: 8.33333333%; } - .offset-xl-2 { - margin-left: 16.66666667%; } - .offset-xl-3 { - margin-left: 25%; } - .offset-xl-4 { - margin-left: 33.33333333%; } - .offset-xl-5 { - margin-left: 41.66666667%; } - .offset-xl-6 { - margin-left: 50%; } - .offset-xl-7 { - margin-left: 58.33333333%; } - .offset-xl-8 { - margin-left: 66.66666667%; } - .offset-xl-9 { - margin-left: 75%; } - .offset-xl-10 { - margin-left: 83.33333333%; } - .offset-xl-11 { - margin-left: 91.66666667%; } - .g-xl-0, - .gx-xl-0 { - --bs-gutter-x: 0; } - .g-xl-0, - .gy-xl-0 { - --bs-gutter-y: 0; } - .g-xl-1, - .gx-xl-1 { - --bs-gutter-x: 0.25rem; } - .g-xl-1, - .gy-xl-1 { - --bs-gutter-y: 0.25rem; } - .g-xl-2, - .gx-xl-2 { - --bs-gutter-x: 0.5rem; } - .g-xl-2, - .gy-xl-2 { - --bs-gutter-y: 0.5rem; } - .g-xl-3, - .gx-xl-3 { - --bs-gutter-x: 1rem; } - .g-xl-3, - .gy-xl-3 { - --bs-gutter-y: 1rem; } - .g-xl-4, - .gx-xl-4 { - --bs-gutter-x: 1.5rem; } - .g-xl-4, - .gy-xl-4 { - --bs-gutter-y: 1.5rem; } - .g-xl-5, - .gx-xl-5 { - --bs-gutter-x: 3rem; } - .g-xl-5, - .gy-xl-5 { - --bs-gutter-y: 3rem; } } - -@media (min-width: 1400px) { - .col-xxl { - flex: 1 0 0%; } - .row-cols-xxl-auto > * { - flex: 0 0 auto; - width: auto; } - .row-cols-xxl-1 > * { - flex: 0 0 auto; - width: 100%; } - .row-cols-xxl-2 > * { - flex: 0 0 auto; - width: 50%; } - .row-cols-xxl-3 > * { - flex: 0 0 auto; - width: 33.33333333%; } - .row-cols-xxl-4 > * { - flex: 0 0 auto; - width: 25%; } - .row-cols-xxl-5 > * { - flex: 0 0 auto; - width: 20%; } - .row-cols-xxl-6 > * { - flex: 0 0 auto; - width: 16.66666667%; } - .col-xxl-auto { - flex: 0 0 auto; - width: auto; } - .col-xxl-1 { - flex: 0 0 auto; - width: 8.33333333%; } - .col-xxl-2 { - flex: 0 0 auto; - width: 16.66666667%; } - .col-xxl-3 { - flex: 0 0 auto; - width: 25%; } - .col-xxl-4 { - flex: 0 0 auto; - width: 33.33333333%; } - .col-xxl-5 { - flex: 0 0 auto; - width: 41.66666667%; } - .col-xxl-6 { - flex: 0 0 auto; - width: 50%; } - .col-xxl-7 { - flex: 0 0 auto; - width: 58.33333333%; } - .col-xxl-8 { - flex: 0 0 auto; - width: 66.66666667%; } - .col-xxl-9 { - flex: 0 0 auto; - width: 75%; } - .col-xxl-10 { - flex: 0 0 auto; - width: 83.33333333%; } - .col-xxl-11 { - flex: 0 0 auto; - width: 91.66666667%; } - .col-xxl-12 { - flex: 0 0 auto; - width: 100%; } - .offset-xxl-0 { - margin-left: 0; } - .offset-xxl-1 { - margin-left: 8.33333333%; } - .offset-xxl-2 { - margin-left: 16.66666667%; } - .offset-xxl-3 { - margin-left: 25%; } - .offset-xxl-4 { - margin-left: 33.33333333%; } - .offset-xxl-5 { - margin-left: 41.66666667%; } - .offset-xxl-6 { - margin-left: 50%; } - .offset-xxl-7 { - margin-left: 58.33333333%; } - .offset-xxl-8 { - margin-left: 66.66666667%; } - .offset-xxl-9 { - margin-left: 75%; } - .offset-xxl-10 { - margin-left: 83.33333333%; } - .offset-xxl-11 { - margin-left: 91.66666667%; } - .g-xxl-0, - .gx-xxl-0 { - --bs-gutter-x: 0; } - .g-xxl-0, - .gy-xxl-0 { - --bs-gutter-y: 0; } - .g-xxl-1, - .gx-xxl-1 { - --bs-gutter-x: 0.25rem; } - .g-xxl-1, - .gy-xxl-1 { - --bs-gutter-y: 0.25rem; } - .g-xxl-2, - .gx-xxl-2 { - --bs-gutter-x: 0.5rem; } - .g-xxl-2, - .gy-xxl-2 { - --bs-gutter-y: 0.5rem; } - .g-xxl-3, - .gx-xxl-3 { - --bs-gutter-x: 1rem; } - .g-xxl-3, - .gy-xxl-3 { - --bs-gutter-y: 1rem; } - .g-xxl-4, - .gx-xxl-4 { - --bs-gutter-x: 1.5rem; } - .g-xxl-4, - .gy-xxl-4 { - --bs-gutter-y: 1.5rem; } - .g-xxl-5, - .gx-xxl-5 { - --bs-gutter-x: 3rem; } - .g-xxl-5, - .gy-xxl-5 { - --bs-gutter-y: 3rem; } } - -.table { - --bs-table-color-type: initial; - --bs-table-bg-type: initial; - --bs-table-color-state: initial; - --bs-table-bg-state: initial; - --bs-table-color: var(--bs-emphasis-color); - --bs-table-bg: var(--bs-body-bg); - --bs-table-border-color: var(--bs-border-color); - --bs-table-accent-bg: transparent; - --bs-table-striped-color: var(--bs-emphasis-color); - --bs-table-striped-bg: rgba(var(--bs-emphasis-color-rgb), 0.05); - --bs-table-active-color: var(--bs-emphasis-color); - --bs-table-active-bg: rgba(var(--bs-emphasis-color-rgb), 0.1); - --bs-table-hover-color: var(--bs-emphasis-color); - --bs-table-hover-bg: rgba(var(--bs-emphasis-color-rgb), 0.075); - width: 100%; - margin-bottom: 1rem; - vertical-align: top; - border-color: var(--bs-table-border-color); } - .table > :not(caption) > * > * { - padding: 0.5rem 0.5rem; - color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color))); - background-color: var(--bs-table-bg); - border-bottom-width: var(--bs-border-width); - box-shadow: inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg))); } - .table > tbody { - vertical-align: inherit; } - .table > thead { - vertical-align: bottom; } - -.table-group-divider { - border-top: calc(var(--bs-border-width) * 2) solid currentcolor; } - -.caption-top { - caption-side: top; } - -.table-sm > :not(caption) > * > * { - padding: 0.25rem 0.25rem; } - -.table-bordered > :not(caption) > * { - border-width: var(--bs-border-width) 0; } - .table-bordered > :not(caption) > * > * { - border-width: 0 var(--bs-border-width); } - -.table-borderless > :not(caption) > * > * { - border-bottom-width: 0; } - -.table-borderless > :not(:first-child) { - border-top-width: 0; } - -.table-striped > tbody > tr:nth-of-type(odd) > * { - --bs-table-color-type: var(--bs-table-striped-color); - --bs-table-bg-type: var(--bs-table-striped-bg); } - -.table-striped-columns > :not(caption) > tr > :nth-child(even) { - --bs-table-color-type: var(--bs-table-striped-color); - --bs-table-bg-type: var(--bs-table-striped-bg); } - -.table-active { - --bs-table-color-state: var(--bs-table-active-color); - --bs-table-bg-state: var(--bs-table-active-bg); } - -.table-hover > tbody > tr:hover > * { - --bs-table-color-state: var(--bs-table-hover-color); - --bs-table-bg-state: var(--bs-table-hover-bg); } - -.table-primary { - --bs-table-color: #191f27; - --bs-table-bg: #cfe2ff; - --bs-table-border-color: #abbbd4; - --bs-table-striped-bg: #c6d8f4; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #bdcfe9; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #c1d3ef; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-secondary { - --bs-table-color: #191f27; - --bs-table-bg: #e2e3e5; - --bs-table-border-color: #babcbf; - --bs-table-striped-bg: #d8d9dc; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #cecfd2; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #d3d4d7; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-success { - --bs-table-color: #191f27; - --bs-table-bg: #d1e7dd; - --bs-table-border-color: #acbfb9; - --bs-table-striped-bg: #c8ddd4; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #bfd3cb; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #c3d8cf; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-info { - --bs-table-color: #191f27; - --bs-table-bg: #cff4fc; - --bs-table-border-color: #abc9d1; - --bs-table-striped-bg: #c6e9f1; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #bddfe7; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #c1e4ec; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-warning { - --bs-table-color: #191f27; - --bs-table-bg: #fff3cd; - --bs-table-border-color: #d1c9ac; - --bs-table-striped-bg: #f4e8c5; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #e8debc; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #eee3c1; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-danger { - --bs-table-color: #191f27; - --bs-table-bg: #f8d7da; - --bs-table-border-color: #cbb2b6; - --bs-table-striped-bg: #edced1; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #e2c5c8; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #e7c9cd; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-light { - --bs-table-color: #191f27; - --bs-table-bg: #eee; - --bs-table-border-color: #c3c5c6; - --bs-table-striped-bg: #e3e4e4; - --bs-table-striped-color: #191f27; - --bs-table-active-bg: #d9d9da; - --bs-table-active-color: #191f27; - --bs-table-hover-bg: #dededf; - --bs-table-hover-color: #191f27; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-dark { - --bs-table-color: #fff; - --bs-table-bg: #222; - --bs-table-border-color: #4e4e4e; - --bs-table-striped-bg: #2d2d2d; - --bs-table-striped-color: #fff; - --bs-table-active-bg: #383838; - --bs-table-active-color: #fff; - --bs-table-hover-bg: #333333; - --bs-table-hover-color: #fff; - color: var(--bs-table-color); - border-color: var(--bs-table-border-color); } - -.table-responsive { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } - -@media (max-width: 575.98px) { - .table-responsive-sm { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } } - -@media (max-width: 767.98px) { - .table-responsive-md { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } } - -@media (max-width: 991.98px) { - .table-responsive-lg { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } } - -@media (max-width: 1199.98px) { - .table-responsive-xl { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } } - -@media (max-width: 1399.98px) { - .table-responsive-xxl { - overflow-x: auto; - -webkit-overflow-scrolling: touch; } } - -.form-label { - margin-bottom: 0.5rem; } - -.col-form-label { - padding-top: calc(0.375rem + var(--bs-border-width)); - padding-bottom: calc(0.375rem + var(--bs-border-width)); - margin-bottom: 0; - font-size: inherit; - line-height: 1.5; } - -.col-form-label-lg { - padding-top: calc(0.5rem + var(--bs-border-width)); - padding-bottom: calc(0.5rem + var(--bs-border-width)); - font-size: 1.25rem; } - -.col-form-label-sm { - padding-top: calc(0.25rem + var(--bs-border-width)); - padding-bottom: calc(0.25rem + var(--bs-border-width)); - font-size: 0.875rem; } - -.form-text { - margin-top: 0.25rem; - font-size: 0.875em; - color: var(--bs-secondary-color); } - -.form-control { - display: block; - width: 100%; - padding: 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: var(--bs-body-color); - appearance: none; - background-color: var(--bs-body-bg); - background-clip: padding-box; - border: var(--bs-border-width) solid var(--bs-border-color); - border-radius: var(--bs-border-radius); - transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-control { - transition: none; } } - .form-control[type="file"] { - overflow: hidden; } - .form-control[type="file"]:not(:disabled):not([readonly]) { - cursor: pointer; } - .form-control:focus { - color: var(--bs-body-color); - background-color: var(--bs-body-bg); - border-color: #86b7fe; - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .form-control::-webkit-date-and-time-value { - min-width: 85px; - height: 1.5em; - margin: 0; } - .form-control::-webkit-datetime-edit { - display: block; - padding: 0; } - .form-control::placeholder { - color: var(--bs-secondary-color); - opacity: 1; } - .form-control:disabled { - background-color: var(--bs-secondary-bg); - opacity: 1; } - .form-control::file-selector-button { - padding: 0.375rem 0.75rem; - margin: -0.375rem -0.75rem; - margin-inline-end: 0.75rem; - color: var(--bs-body-color); - background-color: var(--bs-tertiary-bg); - pointer-events: none; - border-color: inherit; - border-style: solid; - border-width: 0; - border-inline-end-width: var(--bs-border-width); - border-radius: 0; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-control::file-selector-button { - transition: none; } } - .form-control:hover:not(:disabled):not([readonly])::file-selector-button { - background-color: var(--bs-secondary-bg); } - -.form-control-plaintext { - display: block; - width: 100%; - padding: 0.375rem 0; - margin-bottom: 0; - line-height: 1.5; - color: var(--bs-body-color); - background-color: transparent; - border: solid transparent; - border-width: var(--bs-border-width) 0; } - .form-control-plaintext:focus { - outline: 0; } - .form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { - padding-right: 0; - padding-left: 0; } - -.form-control-sm { - min-height: calc(1.5em + 0.5rem + calc(var(--bs-border-width) * 2)); - padding: 0.25rem 0.5rem; - font-size: 0.875rem; - border-radius: var(--bs-border-radius-sm); } - .form-control-sm::file-selector-button { - padding: 0.25rem 0.5rem; - margin: -0.25rem -0.5rem; - margin-inline-end: 0.5rem; } - -.form-control-lg { - min-height: calc(1.5em + 1rem + calc(var(--bs-border-width) * 2)); - padding: 0.5rem 1rem; - font-size: 1.25rem; - border-radius: var(--bs-border-radius-lg); } - .form-control-lg::file-selector-button { - padding: 0.5rem 1rem; - margin: -0.5rem -1rem; - margin-inline-end: 1rem; } - -textarea.form-control { - min-height: calc(1.5em + 0.75rem + calc(var(--bs-border-width) * 2)); } - -textarea.form-control-sm { - min-height: calc(1.5em + 0.5rem + calc(var(--bs-border-width) * 2)); } - -textarea.form-control-lg { - min-height: calc(1.5em + 1rem + calc(var(--bs-border-width) * 2)); } - -.form-control-color { - width: 3rem; - height: calc(1.5em + 0.75rem + calc(var(--bs-border-width) * 2)); - padding: 0.375rem; } - .form-control-color:not(:disabled):not([readonly]) { - cursor: pointer; } - .form-control-color::-moz-color-swatch { - border: 0 !important; - border-radius: var(--bs-border-radius); } - .form-control-color::-webkit-color-swatch { - border: 0 !important; - border-radius: var(--bs-border-radius); } - .form-control-color.form-control-sm { - height: calc(1.5em + 0.5rem + calc(var(--bs-border-width) * 2)); } - .form-control-color.form-control-lg { - height: calc(1.5em + 1rem + calc(var(--bs-border-width) * 2)); } - -.form-select { - --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); - display: block; - width: 100%; - padding: 0.375rem 2.25rem 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: var(--bs-body-color); - appearance: none; - background-color: var(--bs-body-bg); - background-image: var(--bs-form-select-bg-img), var(--bs-form-select-bg-icon, none); - background-repeat: no-repeat; - background-position: right 0.75rem center; - background-size: 16px 12px; - border: var(--bs-border-width) solid var(--bs-border-color); - border-radius: var(--bs-border-radius); - transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-select { - transition: none; } } - .form-select:focus { - border-color: #86b7fe; - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .form-select[multiple], .form-select[size]:not([size="1"]) { - padding-right: 0.75rem; - background-image: none; } - .form-select:disabled { - background-color: var(--bs-secondary-bg); } - .form-select:-moz-focusring { - color: transparent; - text-shadow: 0 0 0 var(--bs-body-color); } - -.form-select-sm { - padding-top: 0.25rem; - padding-bottom: 0.25rem; - padding-left: 0.5rem; - font-size: 0.875rem; - border-radius: var(--bs-border-radius-sm); } - -.form-select-lg { - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-left: 1rem; - font-size: 1.25rem; - border-radius: var(--bs-border-radius-lg); } - -[data-bs-theme="dark"] .form-select { - --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); } - -.form-check { - display: block; - min-height: 1.5rem; - padding-left: 1.5em; - margin-bottom: 0.125rem; } - .form-check .form-check-input { - float: left; - margin-left: -1.5em; } - -.form-check-reverse { - padding-right: 1.5em; - padding-left: 0; - text-align: right; } - .form-check-reverse .form-check-input { - float: right; - margin-right: -1.5em; - margin-left: 0; } - -.form-check-input { - --bs-form-check-bg: var(--bs-body-bg); - flex-shrink: 0; - width: 1em; - height: 1em; - margin-top: 0.25em; - vertical-align: top; - appearance: none; - background-color: var(--bs-form-check-bg); - background-image: var(--bs-form-check-bg-image); - background-repeat: no-repeat; - background-position: center; - background-size: contain; - border: var(--bs-border-width) solid var(--bs-border-color); - print-color-adjust: exact; } - .form-check-input[type="checkbox"] { - border-radius: 0.25em; } - .form-check-input[type="radio"] { - border-radius: 50%; } - .form-check-input:active { - filter: brightness(90%); } - .form-check-input:focus { - border-color: #86b7fe; - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .form-check-input:checked { - background-color: #0d6efd; - border-color: #0d6efd; } - .form-check-input:checked[type="checkbox"] { - --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e"); } - .form-check-input:checked[type="radio"] { - --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"); } - .form-check-input[type="checkbox"]:indeterminate { - background-color: #0d6efd; - border-color: #0d6efd; - --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"); } - .form-check-input:disabled { - pointer-events: none; - filter: none; - opacity: 0.5; } - .form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { - cursor: default; - opacity: 0.5; } - -.form-switch { - padding-left: 2.5em; } - .form-switch .form-check-input { - --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%2825, 31, 39, 0.25%29'/%3e%3c/svg%3e"); - width: 2em; - margin-left: -2.5em; - background-image: var(--bs-form-switch-bg); - background-position: left center; - border-radius: 2em; - transition: background-position 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-switch .form-check-input { - transition: none; } } - .form-switch .form-check-input:focus { - --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e"); } - .form-switch .form-check-input:checked { - background-position: right center; - --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); } - .form-switch.form-check-reverse { - padding-right: 2.5em; - padding-left: 0; } - .form-switch.form-check-reverse .form-check-input { - margin-right: -2.5em; - margin-left: 0; } - -.form-check-inline { - display: inline-block; - margin-right: 1rem; } - -.btn-check { - position: absolute; - clip: rect(0, 0, 0, 0); - pointer-events: none; } - .btn-check[disabled] + .btn, .btn-check:disabled + .btn { - pointer-events: none; - filter: none; - opacity: 0.65; } - -[data-bs-theme="dark"] .form-switch .form-check-input:not(:checked):not(:focus) { - --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e"); } - -.form-range { - width: 100%; - height: 1.5rem; - padding: 0; - appearance: none; - background-color: transparent; } - .form-range:focus { - outline: 0; } - .form-range:focus::-webkit-slider-thumb { - box-shadow: 0 0 0 1px #0e1015, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .form-range:focus::-moz-range-thumb { - box-shadow: 0 0 0 1px #0e1015, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .form-range::-moz-focus-outer { - border: 0; } - .form-range::-webkit-slider-thumb { - width: 1rem; - height: 1rem; - margin-top: -0.25rem; - appearance: none; - background-color: #0d6efd; - border: 0; - border-radius: 1rem; - transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-range::-webkit-slider-thumb { - transition: none; } } - .form-range::-webkit-slider-thumb:active { - background-color: #b6d4fe; } - .form-range::-webkit-slider-runnable-track { - width: 100%; - height: 0.5rem; - color: transparent; - cursor: pointer; - background-color: var(--bs-secondary-bg); - border-color: transparent; - border-radius: 1rem; } - .form-range::-moz-range-thumb { - width: 1rem; - height: 1rem; - appearance: none; - background-color: #0d6efd; - border: 0; - border-radius: 1rem; - transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-range::-moz-range-thumb { - transition: none; } } - .form-range::-moz-range-thumb:active { - background-color: #b6d4fe; } - .form-range::-moz-range-track { - width: 100%; - height: 0.5rem; - color: transparent; - cursor: pointer; - background-color: var(--bs-secondary-bg); - border-color: transparent; - border-radius: 1rem; } - .form-range:disabled { - pointer-events: none; } - .form-range:disabled::-webkit-slider-thumb { - background-color: var(--bs-secondary-color); } - .form-range:disabled::-moz-range-thumb { - background-color: var(--bs-secondary-color); } - -.form-floating { - position: relative; } - .form-floating > .form-control, - .form-floating > .form-control-plaintext, - .form-floating > .form-select { - height: calc(3.5rem + calc(var(--bs-border-width) * 2)); - min-height: calc(3.5rem + calc(var(--bs-border-width) * 2)); - line-height: 1.25; } - .form-floating > label { - position: absolute; - top: 0; - left: 0; - z-index: 2; - height: 100%; - padding: 1rem 0.75rem; - overflow: hidden; - text-align: start; - text-overflow: ellipsis; - white-space: nowrap; - pointer-events: none; - border: var(--bs-border-width) solid transparent; - transform-origin: 0 0; - transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .form-floating > label { - transition: none; } } - .form-floating > .form-control, - .form-floating > .form-control-plaintext { - padding: 1rem 0.75rem; } - .form-floating > .form-control::placeholder, - .form-floating > .form-control-plaintext::placeholder { - color: transparent; } - .form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown), - .form-floating > .form-control-plaintext:focus, - .form-floating > .form-control-plaintext:not(:placeholder-shown) { - padding-top: 1.625rem; - padding-bottom: 0.625rem; } - .form-floating > .form-control:-webkit-autofill, - .form-floating > .form-control-plaintext:-webkit-autofill { - padding-top: 1.625rem; - padding-bottom: 0.625rem; } - .form-floating > .form-select { - padding-top: 1.625rem; - padding-bottom: 0.625rem; } - .form-floating > .form-control:focus ~ label, - .form-floating > .form-control:not(:placeholder-shown) ~ label, - .form-floating > .form-control-plaintext ~ label, - .form-floating > .form-select ~ label { - color: rgba(var(--bs-body-color-rgb), 0.65); - transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); } - .form-floating > .form-control:focus ~ label::after, - .form-floating > .form-control:not(:placeholder-shown) ~ label::after, - .form-floating > .form-control-plaintext ~ label::after, - .form-floating > .form-select ~ label::after { - position: absolute; - inset: 1rem 0.375rem; - z-index: -1; - height: 1.5em; - content: ""; - background-color: var(--bs-body-bg); - border-radius: var(--bs-border-radius); } - .form-floating > .form-control:-webkit-autofill ~ label { - color: rgba(var(--bs-body-color-rgb), 0.65); - transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); } - .form-floating > .form-control-plaintext ~ label { - border-width: var(--bs-border-width) 0; } - .form-floating > :disabled ~ label, - .form-floating > .form-control:disabled ~ label { - color: #6c757d; } - .form-floating > :disabled ~ label::after, - .form-floating > .form-control:disabled ~ label::after { - background-color: var(--bs-secondary-bg); } - -.input-group { - position: relative; - display: flex; - flex-wrap: wrap; - align-items: stretch; - width: 100%; } - .input-group > .form-control, - .input-group > .form-select, - .input-group > .form-floating { - position: relative; - flex: 1 1 auto; - width: 1%; - min-width: 0; } - .input-group > .form-control:focus, - .input-group > .form-select:focus, - .input-group > .form-floating:focus-within { - z-index: 5; } - .input-group .btn { - position: relative; - z-index: 2; } - .input-group .btn:focus { - z-index: 5; } - -.input-group-text { - display: flex; - align-items: center; - padding: 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: var(--bs-body-color); - text-align: center; - white-space: nowrap; - background-color: var(--bs-tertiary-bg); - border: var(--bs-border-width) solid var(--bs-border-color); - border-radius: var(--bs-border-radius); } - -.input-group-lg > .form-control, -.input-group-lg > .form-select, -.input-group-lg > .input-group-text, -.input-group-lg > .btn { - padding: 0.5rem 1rem; - font-size: 1.25rem; - border-radius: var(--bs-border-radius-lg); } - -.input-group-sm > .form-control, -.input-group-sm > .form-select, -.input-group-sm > .input-group-text, -.input-group-sm > .btn { - padding: 0.25rem 0.5rem; - font-size: 0.875rem; - border-radius: var(--bs-border-radius-sm); } - -.input-group-lg > .form-select, -.input-group-sm > .form-select { - padding-right: 3rem; } - -.input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), -.input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n + 3), -.input-group:not(.has-validation) > .form-floating:not(:last-child) > .form-control, -.input-group:not(.has-validation) > .form-floating:not(:last-child) > .form-select { - border-top-right-radius: 0; - border-bottom-right-radius: 0; } - -.input-group.has-validation > :nth-last-child(n + 3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), -.input-group.has-validation > .dropdown-toggle:nth-last-child(n + 4), -.input-group.has-validation > .form-floating:nth-last-child(n + 3) > .form-control, -.input-group.has-validation > .form-floating:nth-last-child(n + 3) > .form-select { - border-top-right-radius: 0; - border-bottom-right-radius: 0; } - -.input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { - margin-left: calc(var(--bs-border-width) * -1); - border-top-left-radius: 0; - border-bottom-left-radius: 0; } - -.input-group > .form-floating:not(:first-child) > .form-control, -.input-group > .form-floating:not(:first-child) > .form-select { - border-top-left-radius: 0; - border-bottom-left-radius: 0; } - -.valid-feedback { - display: none; - width: 100%; - margin-top: 0.25rem; - font-size: 0.875em; - color: var(--bs-form-valid-color); } - -.valid-tooltip { - position: absolute; - top: 100%; - z-index: 5; - display: none; - max-width: 100%; - padding: 0.25rem 0.5rem; - margin-top: .1rem; - font-size: 0.875rem; - color: #fff; - background-color: var(--bs-success); - border-radius: var(--bs-border-radius); } - -.was-validated :valid ~ .valid-feedback, -.was-validated :valid ~ .valid-tooltip, -.is-valid ~ .valid-feedback, -.is-valid ~ .valid-tooltip { - display: block; } - -.was-validated .form-control:valid, .form-control.is-valid { - border-color: var(--bs-form-valid-border-color); - padding-right: calc(1.5em + 0.75rem); - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); - background-repeat: no-repeat; - background-position: right calc(0.375em + 0.1875rem) center; - background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } - .was-validated .form-control:valid:focus, .form-control.is-valid:focus { - border-color: var(--bs-form-valid-border-color); - box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); } - -.was-validated textarea.form-control:valid, textarea.form-control.is-valid { - padding-right: calc(1.5em + 0.75rem); - background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } - -.was-validated .form-select:valid, .form-select.is-valid { - border-color: var(--bs-form-valid-border-color); } - .was-validated .form-select:valid:not([multiple]):not([size]), .was-validated .form-select:valid:not([multiple])[size="1"], .form-select.is-valid:not([multiple]):not([size]), .form-select.is-valid:not([multiple])[size="1"] { - --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); - padding-right: 4.125rem; - background-position: right 0.75rem center, center right 2.25rem; - background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } - .was-validated .form-select:valid:focus, .form-select.is-valid:focus { - border-color: var(--bs-form-valid-border-color); - box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); } - -.was-validated .form-control-color:valid, .form-control-color.is-valid { - width: calc(3rem + calc(1.5em + 0.75rem)); } - -.was-validated .form-check-input:valid, .form-check-input.is-valid { - border-color: var(--bs-form-valid-border-color); } - .was-validated .form-check-input:valid:checked, .form-check-input.is-valid:checked { - background-color: var(--bs-form-valid-color); } - .was-validated .form-check-input:valid:focus, .form-check-input.is-valid:focus { - box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); } - .was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { - color: var(--bs-form-valid-color); } - -.form-check-inline .form-check-input ~ .valid-feedback { - margin-left: .5em; } - -.was-validated .input-group > .form-control:not(:focus):valid, .input-group > .form-control:not(:focus).is-valid, .was-validated .input-group > .form-select:not(:focus):valid, -.input-group > .form-select:not(:focus).is-valid, .was-validated .input-group > .form-floating:not(:focus-within):valid, -.input-group > .form-floating:not(:focus-within).is-valid { - z-index: 3; } - -.invalid-feedback { - display: none; - width: 100%; - margin-top: 0.25rem; - font-size: 0.875em; - color: var(--bs-form-invalid-color); } - -.invalid-tooltip { - position: absolute; - top: 100%; - z-index: 5; - display: none; - max-width: 100%; - padding: 0.25rem 0.5rem; - margin-top: .1rem; - font-size: 0.875rem; - color: #fff; - background-color: var(--bs-danger); - border-radius: var(--bs-border-radius); } - -.was-validated :invalid ~ .invalid-feedback, -.was-validated :invalid ~ .invalid-tooltip, -.is-invalid ~ .invalid-feedback, -.is-invalid ~ .invalid-tooltip { - display: block; } - -.was-validated .form-control:invalid, .form-control.is-invalid { - border-color: var(--bs-form-invalid-border-color); - padding-right: calc(1.5em + 0.75rem); - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); - background-repeat: no-repeat; - background-position: right calc(0.375em + 0.1875rem) center; - background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } - .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { - border-color: var(--bs-form-invalid-border-color); - box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); } - -.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { - padding-right: calc(1.5em + 0.75rem); - background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } - -.was-validated .form-select:invalid, .form-select.is-invalid { - border-color: var(--bs-form-invalid-border-color); } - .was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { - --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); - padding-right: 4.125rem; - background-position: right 0.75rem center, center right 2.25rem; - background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } - .was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { - border-color: var(--bs-form-invalid-border-color); - box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); } - -.was-validated .form-control-color:invalid, .form-control-color.is-invalid { - width: calc(3rem + calc(1.5em + 0.75rem)); } - -.was-validated .form-check-input:invalid, .form-check-input.is-invalid { - border-color: var(--bs-form-invalid-border-color); } - .was-validated .form-check-input:invalid:checked, .form-check-input.is-invalid:checked { - background-color: var(--bs-form-invalid-color); } - .was-validated .form-check-input:invalid:focus, .form-check-input.is-invalid:focus { - box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); } - .was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { - color: var(--bs-form-invalid-color); } - -.form-check-inline .form-check-input ~ .invalid-feedback { - margin-left: .5em; } - -.was-validated .input-group > .form-control:not(:focus):invalid, .input-group > .form-control:not(:focus).is-invalid, .was-validated .input-group > .form-select:not(:focus):invalid, -.input-group > .form-select:not(:focus).is-invalid, .was-validated .input-group > .form-floating:not(:focus-within):invalid, -.input-group > .form-floating:not(:focus-within).is-invalid { - z-index: 4; } - -.btn { - --bs-btn-padding-x: 0.75rem; - --bs-btn-padding-y: 0.375rem; - --bs-btn-font-family: ; - --bs-btn-font-size: 1rem; - --bs-btn-font-weight: 400; - --bs-btn-line-height: 1.5; - --bs-btn-color: var(--bs-body-color); - --bs-btn-bg: transparent; - --bs-btn-border-width: var(--bs-border-width); - --bs-btn-border-color: transparent; - --bs-btn-border-radius: var(--bs-border-radius); - --bs-btn-hover-border-color: transparent; - --bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(25, 31, 39, 0.075); - --bs-btn-disabled-opacity: 0.65; - --bs-btn-focus-box-shadow: 0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5); - display: inline-block; - padding: var(--bs-btn-padding-y) var(--bs-btn-padding-x); - font-family: var(--bs-btn-font-family); - font-size: var(--bs-btn-font-size); - font-weight: var(--bs-btn-font-weight); - line-height: var(--bs-btn-line-height); - color: var(--bs-btn-color); - text-align: center; - text-decoration: none; - vertical-align: middle; - cursor: pointer; - user-select: none; - border: var(--bs-btn-border-width) solid var(--bs-btn-border-color); - border-radius: var(--bs-btn-border-radius); - background-color: var(--bs-btn-bg); - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .btn { - transition: none; } } - .btn:hover { - color: var(--bs-btn-hover-color); - background-color: var(--bs-btn-hover-bg); - border-color: var(--bs-btn-hover-border-color); } - .btn-check + .btn:hover { - color: var(--bs-btn-color); - background-color: var(--bs-btn-bg); - border-color: var(--bs-btn-border-color); } - .btn:focus-visible { - color: var(--bs-btn-hover-color); - background-color: var(--bs-btn-hover-bg); - border-color: var(--bs-btn-hover-border-color); - outline: 0; - box-shadow: var(--bs-btn-focus-box-shadow); } - .btn-check:focus-visible + .btn { - border-color: var(--bs-btn-hover-border-color); - outline: 0; - box-shadow: var(--bs-btn-focus-box-shadow); } - .btn-check:checked + .btn, :not(.btn-check) + .btn:active, .btn:first-child:active, .btn.active, .btn.show { - color: var(--bs-btn-active-color); - background-color: var(--bs-btn-active-bg); - border-color: var(--bs-btn-active-border-color); } - .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { - box-shadow: var(--bs-btn-focus-box-shadow); } - .btn:disabled, .btn.disabled, fieldset:disabled .btn { - color: var(--bs-btn-disabled-color); - pointer-events: none; - background-color: var(--bs-btn-disabled-bg); - border-color: var(--bs-btn-disabled-border-color); - opacity: var(--bs-btn-disabled-opacity); } - -.btn-primary { - --bs-btn-color: #fff; - --bs-btn-bg: #0d6efd; - --bs-btn-border-color: #0d6efd; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #0b5ed7; - --bs-btn-hover-border-color: #0a58ca; - --bs-btn-focus-shadow-rgb: 49, 132, 253; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #0a58ca; - --bs-btn-active-border-color: #0a53be; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #fff; - --bs-btn-disabled-bg: #0d6efd; - --bs-btn-disabled-border-color: #0d6efd; } - -.btn-secondary { - --bs-btn-color: #fff; - --bs-btn-bg: #6c757d; - --bs-btn-border-color: #6c757d; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #5c636a; - --bs-btn-hover-border-color: #565e64; - --bs-btn-focus-shadow-rgb: 130, 138, 145; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #565e64; - --bs-btn-active-border-color: #51585e; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #fff; - --bs-btn-disabled-bg: #6c757d; - --bs-btn-disabled-border-color: #6c757d; } - -.btn-success { - --bs-btn-color: #fff; - --bs-btn-bg: #198754; - --bs-btn-border-color: #198754; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #157347; - --bs-btn-hover-border-color: #146c43; - --bs-btn-focus-shadow-rgb: 60, 153, 110; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #146c43; - --bs-btn-active-border-color: #13653f; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #fff; - --bs-btn-disabled-bg: #198754; - --bs-btn-disabled-border-color: #198754; } - -.btn-info { - --bs-btn-color: #191f27; - --bs-btn-bg: #0dcaf0; - --bs-btn-border-color: #0dcaf0; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #31d2f2; - --bs-btn-hover-border-color: #25cff2; - --bs-btn-focus-shadow-rgb: 15, 176, 210; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #3dd5f3; - --bs-btn-active-border-color: #25cff2; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #191f27; - --bs-btn-disabled-bg: #0dcaf0; - --bs-btn-disabled-border-color: #0dcaf0; } - -.btn-warning { - --bs-btn-color: #191f27; - --bs-btn-bg: #ffc107; - --bs-btn-border-color: #ffc107; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #ffca2c; - --bs-btn-hover-border-color: #ffc720; - --bs-btn-focus-shadow-rgb: 221, 169, 12; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #ffcd39; - --bs-btn-active-border-color: #ffc720; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #191f27; - --bs-btn-disabled-bg: #ffc107; - --bs-btn-disabled-border-color: #ffc107; } - -.btn-danger { - --bs-btn-color: #fff; - --bs-btn-bg: #dc3545; - --bs-btn-border-color: #dc3545; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #bb2d3b; - --bs-btn-hover-border-color: #b02a37; - --bs-btn-focus-shadow-rgb: 225, 83, 97; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #b02a37; - --bs-btn-active-border-color: #a52834; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #fff; - --bs-btn-disabled-bg: #dc3545; - --bs-btn-disabled-border-color: #dc3545; } - -.btn-light { - --bs-btn-color: #191f27; - --bs-btn-bg: #eee; - --bs-btn-border-color: #eee; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #cacaca; - --bs-btn-hover-border-color: #bebebe; - --bs-btn-focus-shadow-rgb: 206, 207, 208; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #bebebe; - --bs-btn-active-border-color: #b3b3b3; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #191f27; - --bs-btn-disabled-bg: #eee; - --bs-btn-disabled-border-color: #eee; } - -.btn-dark { - --bs-btn-color: #fff; - --bs-btn-bg: #222; - --bs-btn-border-color: #222; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #434343; - --bs-btn-hover-border-color: #383838; - --bs-btn-focus-shadow-rgb: 67, 67, 67; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #4e4e4e; - --bs-btn-active-border-color: #383838; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #fff; - --bs-btn-disabled-bg: #222; - --bs-btn-disabled-border-color: #222; } - -.btn-outline-primary { - --bs-btn-color: #0d6efd; - --bs-btn-border-color: #0d6efd; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #0d6efd; - --bs-btn-hover-border-color: #0d6efd; - --bs-btn-focus-shadow-rgb: 13, 110, 253; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #0d6efd; - --bs-btn-active-border-color: #0d6efd; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #0d6efd; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #0d6efd; - --bs-gradient: none; } - -.btn-outline-secondary { - --bs-btn-color: #6c757d; - --bs-btn-border-color: #6c757d; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #6c757d; - --bs-btn-hover-border-color: #6c757d; - --bs-btn-focus-shadow-rgb: 108, 117, 125; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #6c757d; - --bs-btn-active-border-color: #6c757d; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #6c757d; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #6c757d; - --bs-gradient: none; } - -.btn-outline-success { - --bs-btn-color: #198754; - --bs-btn-border-color: #198754; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #198754; - --bs-btn-hover-border-color: #198754; - --bs-btn-focus-shadow-rgb: 25, 135, 84; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #198754; - --bs-btn-active-border-color: #198754; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #198754; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #198754; - --bs-gradient: none; } - -.btn-outline-info { - --bs-btn-color: #0dcaf0; - --bs-btn-border-color: #0dcaf0; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #0dcaf0; - --bs-btn-hover-border-color: #0dcaf0; - --bs-btn-focus-shadow-rgb: 13, 202, 240; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #0dcaf0; - --bs-btn-active-border-color: #0dcaf0; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #0dcaf0; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #0dcaf0; - --bs-gradient: none; } - -.btn-outline-warning { - --bs-btn-color: #ffc107; - --bs-btn-border-color: #ffc107; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #ffc107; - --bs-btn-hover-border-color: #ffc107; - --bs-btn-focus-shadow-rgb: 255, 193, 7; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #ffc107; - --bs-btn-active-border-color: #ffc107; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #ffc107; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #ffc107; - --bs-gradient: none; } - -.btn-outline-danger { - --bs-btn-color: #dc3545; - --bs-btn-border-color: #dc3545; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #dc3545; - --bs-btn-hover-border-color: #dc3545; - --bs-btn-focus-shadow-rgb: 220, 53, 69; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #dc3545; - --bs-btn-active-border-color: #dc3545; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #dc3545; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #dc3545; - --bs-gradient: none; } - -.btn-outline-light { - --bs-btn-color: #eee; - --bs-btn-border-color: #eee; - --bs-btn-hover-color: #191f27; - --bs-btn-hover-bg: #eee; - --bs-btn-hover-border-color: #eee; - --bs-btn-focus-shadow-rgb: 238, 238, 238; - --bs-btn-active-color: #191f27; - --bs-btn-active-bg: #eee; - --bs-btn-active-border-color: #eee; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #eee; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #eee; - --bs-gradient: none; } - -.btn-outline-dark { - --bs-btn-color: #222; - --bs-btn-border-color: #222; - --bs-btn-hover-color: #fff; - --bs-btn-hover-bg: #222; - --bs-btn-hover-border-color: #222; - --bs-btn-focus-shadow-rgb: 34, 34, 34; - --bs-btn-active-color: #fff; - --bs-btn-active-bg: #222; - --bs-btn-active-border-color: #222; - --bs-btn-active-shadow: inset 0 3px 5px rgba(25, 31, 39, 0.125); - --bs-btn-disabled-color: #222; - --bs-btn-disabled-bg: transparent; - --bs-btn-disabled-border-color: #222; - --bs-gradient: none; } - -.btn-link { - --bs-btn-font-weight: 400; - --bs-btn-color: var(--bs-link-color); - --bs-btn-bg: transparent; - --bs-btn-border-color: transparent; - --bs-btn-hover-color: var(--bs-link-hover-color); - --bs-btn-hover-border-color: transparent; - --bs-btn-active-color: var(--bs-link-hover-color); - --bs-btn-active-border-color: transparent; - --bs-btn-disabled-color: #6c757d; - --bs-btn-disabled-border-color: transparent; - --bs-btn-box-shadow: 0 0 0 #000; - --bs-btn-focus-shadow-rgb: 49, 132, 253; - text-decoration: underline; } - .btn-link:focus-visible { - color: var(--bs-btn-color); } - .btn-link:hover { - color: var(--bs-btn-hover-color); } - -.btn-lg { - --bs-btn-padding-y: 0.5rem; - --bs-btn-padding-x: 1rem; - --bs-btn-font-size: 1.25rem; - --bs-btn-border-radius: var(--bs-border-radius-lg); } - -.btn-sm { - --bs-btn-padding-y: 0.25rem; - --bs-btn-padding-x: 0.5rem; - --bs-btn-font-size: 0.875rem; - --bs-btn-border-radius: var(--bs-border-radius-sm); } - -.fade { - transition: opacity 0.15s linear; } - @media (prefers-reduced-motion: reduce) { - .fade { - transition: none; } } - .fade:not(.show) { - opacity: 0; } - -.collapse:not(.show) { - display: none; } - -.collapsing { - height: 0; - overflow: hidden; - transition: height 0.35s ease; } - @media (prefers-reduced-motion: reduce) { - .collapsing { - transition: none; } } - .collapsing.collapse-horizontal { - width: 0; - height: auto; - transition: width 0.35s ease; } - @media (prefers-reduced-motion: reduce) { - .collapsing.collapse-horizontal { - transition: none; } } -.dropup, -.dropend, -.dropdown, -.dropstart, -.dropup-center, -.dropdown-center { - position: relative; } - -.dropdown-toggle { - white-space: nowrap; } - .dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0.3em solid; - border-right: 0.3em solid transparent; - border-bottom: 0; - border-left: 0.3em solid transparent; } - .dropdown-toggle:empty::after { - margin-left: 0; } - -.dropdown-menu { - --bs-dropdown-zindex: 1000; - --bs-dropdown-min-width: 10rem; - --bs-dropdown-padding-x: 0; - --bs-dropdown-padding-y: 0.5rem; - --bs-dropdown-spacer: 0.125rem; - --bs-dropdown-font-size: 1rem; - --bs-dropdown-color: var(--bs-body-color); - --bs-dropdown-bg: var(--bs-body-bg); - --bs-dropdown-border-color: var(--bs-border-color-translucent); - --bs-dropdown-border-radius: var(--bs-border-radius); - --bs-dropdown-border-width: var(--bs-border-width); - --bs-dropdown-inner-border-radius: calc(var(--bs-border-radius) - var(--bs-border-width)); - --bs-dropdown-divider-bg: var(--bs-border-color-translucent); - --bs-dropdown-divider-margin-y: 0.5rem; - --bs-dropdown-box-shadow: var(--bs-box-shadow); - --bs-dropdown-link-color: var(--bs-body-color); - --bs-dropdown-link-hover-color: var(--bs-body-color); - --bs-dropdown-link-hover-bg: var(--bs-tertiary-bg); - --bs-dropdown-link-active-color: #fff; - --bs-dropdown-link-active-bg: #0d6efd; - --bs-dropdown-link-disabled-color: var(--bs-tertiary-color); - --bs-dropdown-item-padding-x: 1rem; - --bs-dropdown-item-padding-y: 0.25rem; - --bs-dropdown-header-color: #6c757d; - --bs-dropdown-header-padding-x: 1rem; - --bs-dropdown-header-padding-y: 0.5rem; - position: absolute; - z-index: var(--bs-dropdown-zindex); - display: none; - min-width: var(--bs-dropdown-min-width); - padding: var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x); - margin: 0; - font-size: var(--bs-dropdown-font-size); - color: var(--bs-dropdown-color); - text-align: left; - list-style: none; - background-color: var(--bs-dropdown-bg); - background-clip: padding-box; - border: var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color); - border-radius: var(--bs-dropdown-border-radius); } - .dropdown-menu[data-bs-popper] { - top: 100%; - left: 0; - margin-top: var(--bs-dropdown-spacer); } - -.dropdown-menu-start { - --bs-position: start; } - .dropdown-menu-start[data-bs-popper] { - right: auto; - left: 0; } - -.dropdown-menu-end { - --bs-position: end; } - .dropdown-menu-end[data-bs-popper] { - right: 0; - left: auto; } - -@media (min-width: 576px) { - .dropdown-menu-sm-start { - --bs-position: start; } - .dropdown-menu-sm-start[data-bs-popper] { - right: auto; - left: 0; } - .dropdown-menu-sm-end { - --bs-position: end; } - .dropdown-menu-sm-end[data-bs-popper] { - right: 0; - left: auto; } } - -@media (min-width: 768px) { - .dropdown-menu-md-start { - --bs-position: start; } - .dropdown-menu-md-start[data-bs-popper] { - right: auto; - left: 0; } - .dropdown-menu-md-end { - --bs-position: end; } - .dropdown-menu-md-end[data-bs-popper] { - right: 0; - left: auto; } } - -@media (min-width: 992px) { - .dropdown-menu-lg-start { - --bs-position: start; } - .dropdown-menu-lg-start[data-bs-popper] { - right: auto; - left: 0; } - .dropdown-menu-lg-end { - --bs-position: end; } - .dropdown-menu-lg-end[data-bs-popper] { - right: 0; - left: auto; } } - -@media (min-width: 1200px) { - .dropdown-menu-xl-start { - --bs-position: start; } - .dropdown-menu-xl-start[data-bs-popper] { - right: auto; - left: 0; } - .dropdown-menu-xl-end { - --bs-position: end; } - .dropdown-menu-xl-end[data-bs-popper] { - right: 0; - left: auto; } } - -@media (min-width: 1400px) { - .dropdown-menu-xxl-start { - --bs-position: start; } - .dropdown-menu-xxl-start[data-bs-popper] { - right: auto; - left: 0; } - .dropdown-menu-xxl-end { - --bs-position: end; } - .dropdown-menu-xxl-end[data-bs-popper] { - right: 0; - left: auto; } } - -.dropup .dropdown-menu[data-bs-popper] { - top: auto; - bottom: 100%; - margin-top: 0; - margin-bottom: var(--bs-dropdown-spacer); } - -.dropup .dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0; - border-right: 0.3em solid transparent; - border-bottom: 0.3em solid; - border-left: 0.3em solid transparent; } - -.dropup .dropdown-toggle:empty::after { - margin-left: 0; } - -.dropend .dropdown-menu[data-bs-popper] { - top: 0; - right: auto; - left: 100%; - margin-top: 0; - margin-left: var(--bs-dropdown-spacer); } - -.dropend .dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0.3em solid transparent; - border-right: 0; - border-bottom: 0.3em solid transparent; - border-left: 0.3em solid; } - -.dropend .dropdown-toggle:empty::after { - margin-left: 0; } - -.dropend .dropdown-toggle::after { - vertical-align: 0; } - -.dropstart .dropdown-menu[data-bs-popper] { - top: 0; - right: 100%; - left: auto; - margin-top: 0; - margin-right: var(--bs-dropdown-spacer); } - -.dropstart .dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; } - -.dropstart .dropdown-toggle::after { - display: none; } - -.dropstart .dropdown-toggle::before { - display: inline-block; - margin-right: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0.3em solid transparent; - border-right: 0.3em solid; - border-bottom: 0.3em solid transparent; } - -.dropstart .dropdown-toggle:empty::after { - margin-left: 0; } - -.dropstart .dropdown-toggle::before { - vertical-align: 0; } - -.dropdown-divider { - height: 0; - margin: var(--bs-dropdown-divider-margin-y) 0; - overflow: hidden; - border-top: 1px solid var(--bs-dropdown-divider-bg); - opacity: 1; } - -.dropdown-item { - display: block; - width: 100%; - padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); - clear: both; - font-weight: 400; - color: var(--bs-dropdown-link-color); - text-align: inherit; - text-decoration: none; - white-space: nowrap; - background-color: transparent; - border: 0; - border-radius: var(--bs-dropdown-item-border-radius, 0); } - .dropdown-item:hover, .dropdown-item:focus { - color: var(--bs-dropdown-link-hover-color); - background-color: var(--bs-dropdown-link-hover-bg); } - .dropdown-item.active, .dropdown-item:active { - color: var(--bs-dropdown-link-active-color); - text-decoration: none; - background-color: var(--bs-dropdown-link-active-bg); } - .dropdown-item.disabled, .dropdown-item:disabled { - color: var(--bs-dropdown-link-disabled-color); - pointer-events: none; - background-color: transparent; } - -.dropdown-menu.show { - display: block; } - -.dropdown-header { - display: block; - padding: var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x); - margin-bottom: 0; - font-size: 0.875rem; - color: var(--bs-dropdown-header-color); - white-space: nowrap; } - -.dropdown-item-text { - display: block; - padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); - color: var(--bs-dropdown-link-color); } - -.dropdown-menu-dark { - --bs-dropdown-color: #dee2e6; - --bs-dropdown-bg: #343a40; - --bs-dropdown-border-color: var(--bs-border-color-translucent); - --bs-dropdown-box-shadow: ; - --bs-dropdown-link-color: #dee2e6; - --bs-dropdown-link-hover-color: #fff; - --bs-dropdown-divider-bg: var(--bs-border-color-translucent); - --bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.15); - --bs-dropdown-link-active-color: #fff; - --bs-dropdown-link-active-bg: #0d6efd; - --bs-dropdown-link-disabled-color: #adb5bd; - --bs-dropdown-header-color: #adb5bd; } - -.nav { - --bs-nav-link-padding-x: 1rem; - --bs-nav-link-padding-y: 0.5rem; - --bs-nav-link-font-weight: ; - --bs-nav-link-color: var(--bs-link-color); - --bs-nav-link-hover-color: var(--bs-link-hover-color); - --bs-nav-link-disabled-color: var(--bs-secondary-color); - display: flex; - flex-wrap: wrap; - padding-left: 0; - margin-bottom: 0; - list-style: none; } - -.nav-link { - display: block; - padding: var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x); - font-size: var(--bs-nav-link-font-size); - font-weight: var(--bs-nav-link-font-weight); - color: var(--bs-nav-link-color); - text-decoration: none; - background: none; - border: 0; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .nav-link { - transition: none; } } - .nav-link:hover, .nav-link:focus { - color: var(--bs-nav-link-hover-color); } - .nav-link:focus-visible { - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } - .nav-link.disabled, .nav-link:disabled { - color: var(--bs-nav-link-disabled-color); - pointer-events: none; - cursor: default; } - -.nav-tabs { - --bs-nav-tabs-border-width: var(--bs-border-width); - --bs-nav-tabs-border-color: var(--bs-border-color); - --bs-nav-tabs-border-radius: var(--bs-border-radius); - --bs-nav-tabs-link-hover-border-color: var(--bs-secondary-bg) var(--bs-secondary-bg) var(--bs-border-color); - --bs-nav-tabs-link-active-color: var(--bs-emphasis-color); - --bs-nav-tabs-link-active-bg: var(--bs-body-bg); - --bs-nav-tabs-link-active-border-color: var(--bs-border-color) var(--bs-border-color) var(--bs-body-bg); - border-bottom: var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color); } - .nav-tabs .nav-link { - margin-bottom: calc(-1 * var(--bs-nav-tabs-border-width)); - border: var(--bs-nav-tabs-border-width) solid transparent; - border-top-left-radius: var(--bs-nav-tabs-border-radius); - border-top-right-radius: var(--bs-nav-tabs-border-radius); } - .nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { - isolation: isolate; - border-color: var(--bs-nav-tabs-link-hover-border-color); } - .nav-tabs .nav-link.active, - .nav-tabs .nav-item.show .nav-link { - color: var(--bs-nav-tabs-link-active-color); - background-color: var(--bs-nav-tabs-link-active-bg); - border-color: var(--bs-nav-tabs-link-active-border-color); } - .nav-tabs .dropdown-menu { - margin-top: calc(-1 * var(--bs-nav-tabs-border-width)); - border-top-left-radius: 0; - border-top-right-radius: 0; } - -.nav-pills { - --bs-nav-pills-border-radius: var(--bs-border-radius); - --bs-nav-pills-link-active-color: #fff; - --bs-nav-pills-link-active-bg: #0d6efd; } - .nav-pills .nav-link { - border-radius: var(--bs-nav-pills-border-radius); } - .nav-pills .nav-link.active, - .nav-pills .show > .nav-link { - color: var(--bs-nav-pills-link-active-color); - background-color: var(--bs-nav-pills-link-active-bg); } - -.nav-underline { - --bs-nav-underline-gap: 1rem; - --bs-nav-underline-border-width: 0.125rem; - --bs-nav-underline-link-active-color: var(--bs-emphasis-color); - gap: var(--bs-nav-underline-gap); } - .nav-underline .nav-link { - padding-right: 0; - padding-left: 0; - border-bottom: var(--bs-nav-underline-border-width) solid transparent; } - .nav-underline .nav-link:hover, .nav-underline .nav-link:focus { - border-bottom-color: currentcolor; } - .nav-underline .nav-link.active, - .nav-underline .show > .nav-link { - font-weight: 700; - color: var(--bs-nav-underline-link-active-color); - border-bottom-color: currentcolor; } - -.nav-fill > .nav-link, -.nav-fill .nav-item { - flex: 1 1 auto; - text-align: center; } - -.nav-justified > .nav-link, -.nav-justified .nav-item { - flex-basis: 0; - flex-grow: 1; - text-align: center; } - -.nav-fill .nav-item .nav-link, -.nav-justified .nav-item .nav-link { - width: 100%; } - -.tab-content > .tab-pane { - display: none; } - -.tab-content > .active { - display: block; } - -.navbar { - --bs-navbar-padding-x: 0; - --bs-navbar-padding-y: 0.5rem; - --bs-navbar-color: rgba(var(--bs-emphasis-color-rgb), 0.65); - --bs-navbar-hover-color: rgba(var(--bs-emphasis-color-rgb), 0.8); - --bs-navbar-disabled-color: rgba(var(--bs-emphasis-color-rgb), 0.3); - --bs-navbar-active-color: rgba(var(--bs-emphasis-color-rgb), 1); - --bs-navbar-brand-padding-y: 0.3125rem; - --bs-navbar-brand-margin-end: 1rem; - --bs-navbar-brand-font-size: 1.25rem; - --bs-navbar-brand-color: rgba(var(--bs-emphasis-color-rgb), 1); - --bs-navbar-brand-hover-color: rgba(var(--bs-emphasis-color-rgb), 1); - --bs-navbar-nav-link-padding-x: 0.5rem; - --bs-navbar-toggler-padding-y: 0.25rem; - --bs-navbar-toggler-padding-x: 0.75rem; - --bs-navbar-toggler-font-size: 1.25rem; - --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2833, 37, 41, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); - --bs-navbar-toggler-border-color: rgba(var(--bs-emphasis-color-rgb), 0.15); - --bs-navbar-toggler-border-radius: var(--bs-border-radius); - --bs-navbar-toggler-focus-width: 0.25rem; - --bs-navbar-toggler-transition: box-shadow 0.15s ease-in-out; - position: relative; - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: space-between; - padding: var(--bs-navbar-padding-y) var(--bs-navbar-padding-x); } - .navbar > .container, - .navbar > .container-fluid, - .navbar > .container-sm, - .navbar > .container-md, - .navbar > .container-lg, - .navbar > .container-xl, - .navbar > .container-xxl { - display: flex; - flex-wrap: inherit; - align-items: center; - justify-content: space-between; } - -.navbar-brand { - padding-top: var(--bs-navbar-brand-padding-y); - padding-bottom: var(--bs-navbar-brand-padding-y); - margin-right: var(--bs-navbar-brand-margin-end); - font-size: var(--bs-navbar-brand-font-size); - color: var(--bs-navbar-brand-color); - text-decoration: none; - white-space: nowrap; } - .navbar-brand:hover, .navbar-brand:focus { - color: var(--bs-navbar-brand-hover-color); } - -.navbar-nav { - --bs-nav-link-padding-x: 0; - --bs-nav-link-padding-y: 0.5rem; - --bs-nav-link-font-weight: ; - --bs-nav-link-color: var(--bs-navbar-color); - --bs-nav-link-hover-color: var(--bs-navbar-hover-color); - --bs-nav-link-disabled-color: var(--bs-navbar-disabled-color); - display: flex; - flex-direction: column; - padding-left: 0; - margin-bottom: 0; - list-style: none; } - .navbar-nav .nav-link.active, .navbar-nav .nav-link.show { - color: var(--bs-navbar-active-color); } - .navbar-nav .dropdown-menu { - position: static; } - -.navbar-text { - padding-top: 0.5rem; - padding-bottom: 0.5rem; - color: var(--bs-navbar-color); } - .navbar-text a, - .navbar-text a:hover, - .navbar-text a:focus { - color: var(--bs-navbar-active-color); } - -.navbar-collapse { - flex-basis: 100%; - flex-grow: 1; - align-items: center; } - -.navbar-toggler { - padding: var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x); - font-size: var(--bs-navbar-toggler-font-size); - line-height: 1; - color: var(--bs-navbar-color); - background-color: transparent; - border: var(--bs-border-width) solid var(--bs-navbar-toggler-border-color); - border-radius: var(--bs-navbar-toggler-border-radius); - transition: var(--bs-navbar-toggler-transition); } - @media (prefers-reduced-motion: reduce) { - .navbar-toggler { - transition: none; } } - .navbar-toggler:hover { - text-decoration: none; } - .navbar-toggler:focus { - text-decoration: none; - outline: 0; - box-shadow: 0 0 0 var(--bs-navbar-toggler-focus-width); } - -.navbar-toggler-icon { - display: inline-block; - width: 1.5em; - height: 1.5em; - vertical-align: middle; - background-image: var(--bs-navbar-toggler-icon-bg); - background-repeat: no-repeat; - background-position: center; - background-size: 100%; } - -.navbar-nav-scroll { - max-height: var(--bs-scroll-height, 75vh); - overflow-y: auto; } - -@media (min-width: 576px) { - .navbar-expand-sm { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand-sm .navbar-nav { - flex-direction: row; } - .navbar-expand-sm .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand-sm .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand-sm .navbar-nav-scroll { - overflow: visible; } - .navbar-expand-sm .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand-sm .navbar-toggler { - display: none; } - .navbar-expand-sm .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand-sm .offcanvas .offcanvas-header { - display: none; } - .navbar-expand-sm .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } } - -@media (min-width: 768px) { - .navbar-expand-md { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand-md .navbar-nav { - flex-direction: row; } - .navbar-expand-md .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand-md .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand-md .navbar-nav-scroll { - overflow: visible; } - .navbar-expand-md .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand-md .navbar-toggler { - display: none; } - .navbar-expand-md .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand-md .offcanvas .offcanvas-header { - display: none; } - .navbar-expand-md .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } } - -@media (min-width: 992px) { - .navbar-expand-lg { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand-lg .navbar-nav { - flex-direction: row; } - .navbar-expand-lg .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand-lg .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand-lg .navbar-nav-scroll { - overflow: visible; } - .navbar-expand-lg .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand-lg .navbar-toggler { - display: none; } - .navbar-expand-lg .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand-lg .offcanvas .offcanvas-header { - display: none; } - .navbar-expand-lg .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } } - -@media (min-width: 1200px) { - .navbar-expand-xl { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand-xl .navbar-nav { - flex-direction: row; } - .navbar-expand-xl .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand-xl .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand-xl .navbar-nav-scroll { - overflow: visible; } - .navbar-expand-xl .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand-xl .navbar-toggler { - display: none; } - .navbar-expand-xl .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand-xl .offcanvas .offcanvas-header { - display: none; } - .navbar-expand-xl .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } } - -@media (min-width: 1400px) { - .navbar-expand-xxl { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand-xxl .navbar-nav { - flex-direction: row; } - .navbar-expand-xxl .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand-xxl .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand-xxl .navbar-nav-scroll { - overflow: visible; } - .navbar-expand-xxl .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand-xxl .navbar-toggler { - display: none; } - .navbar-expand-xxl .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand-xxl .offcanvas .offcanvas-header { - display: none; } - .navbar-expand-xxl .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } } - -.navbar-expand { - flex-wrap: nowrap; - justify-content: flex-start; } - .navbar-expand .navbar-nav { - flex-direction: row; } - .navbar-expand .navbar-nav .dropdown-menu { - position: absolute; } - .navbar-expand .navbar-nav .nav-link { - padding-right: var(--bs-navbar-nav-link-padding-x); - padding-left: var(--bs-navbar-nav-link-padding-x); } - .navbar-expand .navbar-nav-scroll { - overflow: visible; } - .navbar-expand .navbar-collapse { - display: flex !important; - flex-basis: auto; } - .navbar-expand .navbar-toggler { - display: none; } - .navbar-expand .offcanvas { - position: static; - z-index: auto; - flex-grow: 1; - width: auto !important; - height: auto !important; - visibility: visible !important; - background-color: transparent !important; - border: 0 !important; - transform: none !important; - transition: none; } - .navbar-expand .offcanvas .offcanvas-header { - display: none; } - .navbar-expand .offcanvas .offcanvas-body { - display: flex; - flex-grow: 0; - padding: 0; - overflow-y: visible; } - -.navbar-dark, -.navbar[data-bs-theme="dark"] { - --bs-navbar-color: rgba(255, 255, 255, 0.55); - --bs-navbar-hover-color: rgba(255, 255, 255, 0.75); - --bs-navbar-disabled-color: rgba(255, 255, 255, 0.25); - --bs-navbar-active-color: #fff; - --bs-navbar-brand-color: #fff; - --bs-navbar-brand-hover-color: #fff; - --bs-navbar-toggler-border-color: rgba(255, 255, 255, 0.1); - --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); } - -[data-bs-theme="dark"] .navbar-toggler-icon { - --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); } - -.card { - --bs-card-spacer-y: 1rem; - --bs-card-spacer-x: 1rem; - --bs-card-title-spacer-y: 0.5rem; - --bs-card-title-color: ; - --bs-card-subtitle-color: ; - --bs-card-border-width: var(--bs-border-width); - --bs-card-border-color: var(--bs-border-color-translucent); - --bs-card-border-radius: var(--bs-border-radius); - --bs-card-box-shadow: ; - --bs-card-inner-border-radius: calc(var(--bs-border-radius) - (var(--bs-border-width))); - --bs-card-cap-padding-y: 0.5rem; - --bs-card-cap-padding-x: 1rem; - --bs-card-cap-bg: rgba(var(--bs-body-color-rgb), 0.03); - --bs-card-cap-color: ; - --bs-card-height: ; - --bs-card-color: ; - --bs-card-bg: var(--bs-body-bg); - --bs-card-img-overlay-padding: 1rem; - --bs-card-group-margin: 0.75rem; - position: relative; - display: flex; - flex-direction: column; - min-width: 0; - height: var(--bs-card-height); - color: var(--bs-body-color); - word-wrap: break-word; - background-color: var(--bs-card-bg); - background-clip: border-box; - border: var(--bs-card-border-width) solid var(--bs-card-border-color); - border-radius: var(--bs-card-border-radius); } - .card > hr { - margin-right: 0; - margin-left: 0; } - .card > .list-group { - border-top: inherit; - border-bottom: inherit; } - .card > .list-group:first-child { - border-top-width: 0; - border-top-left-radius: var(--bs-card-inner-border-radius); - border-top-right-radius: var(--bs-card-inner-border-radius); } - .card > .list-group:last-child { - border-bottom-width: 0; - border-bottom-right-radius: var(--bs-card-inner-border-radius); - border-bottom-left-radius: var(--bs-card-inner-border-radius); } - .card > .card-header + .list-group, - .card > .list-group + .card-footer { - border-top: 0; } - -.card-body { - flex: 1 1 auto; - padding: var(--bs-card-spacer-y) var(--bs-card-spacer-x); - color: var(--bs-card-color); } - -.card-title { - margin-bottom: var(--bs-card-title-spacer-y); - color: var(--bs-card-title-color); } - -.card-subtitle { - margin-top: calc(-.5 * var(--bs-card-title-spacer-y)); - margin-bottom: 0; - color: var(--bs-card-subtitle-color); } - -.card-text:last-child { - margin-bottom: 0; } - -.card-link + .card-link { - margin-left: var(--bs-card-spacer-x); } - -.card-header { - padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); - margin-bottom: 0; - color: var(--bs-card-cap-color); - background-color: var(--bs-card-cap-bg); - border-bottom: var(--bs-card-border-width) solid var(--bs-card-border-color); } - .card-header:first-child { - border-radius: var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0; } - -.card-footer { - padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); - color: var(--bs-card-cap-color); - background-color: var(--bs-card-cap-bg); - border-top: var(--bs-card-border-width) solid var(--bs-card-border-color); } - .card-footer:last-child { - border-radius: 0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius); } - -.card-header-tabs { - margin-right: calc(-.5 * var(--bs-card-cap-padding-x)); - margin-bottom: calc(-1 * var(--bs-card-cap-padding-y)); - margin-left: calc(-.5 * var(--bs-card-cap-padding-x)); - border-bottom: 0; } - .card-header-tabs .nav-link.active { - background-color: var(--bs-card-bg); - border-bottom-color: var(--bs-card-bg); } - -.card-header-pills { - margin-right: calc(-.5 * var(--bs-card-cap-padding-x)); - margin-left: calc(-.5 * var(--bs-card-cap-padding-x)); } - -.card-img-overlay { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - padding: var(--bs-card-img-overlay-padding); - border-radius: var(--bs-card-inner-border-radius); } - -.card-img, -.card-img-top, -.card-img-bottom { - width: 100%; } - -.card-img, -.card-img-top { - border-top-left-radius: var(--bs-card-inner-border-radius); - border-top-right-radius: var(--bs-card-inner-border-radius); } - -.card-img, -.card-img-bottom { - border-bottom-right-radius: var(--bs-card-inner-border-radius); - border-bottom-left-radius: var(--bs-card-inner-border-radius); } - -.card-group > .card { - margin-bottom: var(--bs-card-group-margin); } - -@media (min-width: 576px) { - .card-group { - display: flex; - flex-flow: row wrap; } - .card-group > .card { - flex: 1 0 0%; - margin-bottom: 0; } - .card-group > .card + .card { - margin-left: 0; - border-left: 0; } - .card-group > .card:not(:last-child) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; } - .card-group > .card:not(:last-child) .card-img-top, - .card-group > .card:not(:last-child) .card-header { - border-top-right-radius: 0; } - .card-group > .card:not(:last-child) .card-img-bottom, - .card-group > .card:not(:last-child) .card-footer { - border-bottom-right-radius: 0; } - .card-group > .card:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; } - .card-group > .card:not(:first-child) .card-img-top, - .card-group > .card:not(:first-child) .card-header { - border-top-left-radius: 0; } - .card-group > .card:not(:first-child) .card-img-bottom, - .card-group > .card:not(:first-child) .card-footer { - border-bottom-left-radius: 0; } } - -.accordion { - --bs-accordion-color: var(--bs-body-color); - --bs-accordion-bg: var(--bs-body-bg); - --bs-accordion-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease; - --bs-accordion-border-color: var(--bs-border-color); - --bs-accordion-border-width: var(--bs-border-width); - --bs-accordion-border-radius: var(--bs-border-radius); - --bs-accordion-inner-border-radius: calc(var(--bs-border-radius) - (var(--bs-border-width))); - --bs-accordion-btn-padding-x: 1.25rem; - --bs-accordion-btn-padding-y: 1rem; - --bs-accordion-btn-color: var(--bs-body-color); - --bs-accordion-btn-bg: var(--bs-accordion-bg); - --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); - --bs-accordion-btn-icon-width: 1.25rem; - --bs-accordion-btn-icon-transform: rotate(-180deg); - --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; - --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23052c65'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); - --bs-accordion-btn-focus-border-color: #86b7fe; - --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); - --bs-accordion-body-padding-x: 1.25rem; - --bs-accordion-body-padding-y: 1rem; - --bs-accordion-active-color: var(--bs-primary-text-emphasis); - --bs-accordion-active-bg: var(--bs-primary-bg-subtle); } - -.accordion-button { - position: relative; - display: flex; - align-items: center; - width: 100%; - padding: var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x); - font-size: 1rem; - color: var(--bs-accordion-btn-color); - text-align: left; - background-color: var(--bs-accordion-btn-bg); - border: 0; - border-radius: 0; - overflow-anchor: none; - transition: var(--bs-accordion-transition); } - @media (prefers-reduced-motion: reduce) { - .accordion-button { - transition: none; } } - .accordion-button:not(.collapsed) { - color: var(--bs-accordion-active-color); - background-color: var(--bs-accordion-active-bg); - box-shadow: inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color); } - .accordion-button:not(.collapsed)::after { - background-image: var(--bs-accordion-btn-active-icon); - transform: var(--bs-accordion-btn-icon-transform); } - .accordion-button::after { - flex-shrink: 0; - width: var(--bs-accordion-btn-icon-width); - height: var(--bs-accordion-btn-icon-width); - margin-left: auto; - content: ""; - background-image: var(--bs-accordion-btn-icon); - background-repeat: no-repeat; - background-size: var(--bs-accordion-btn-icon-width); - transition: var(--bs-accordion-btn-icon-transition); } - @media (prefers-reduced-motion: reduce) { - .accordion-button::after { - transition: none; } } - .accordion-button:hover { - z-index: 2; } - .accordion-button:focus { - z-index: 3; - border-color: var(--bs-accordion-btn-focus-border-color); - outline: 0; - box-shadow: var(--bs-accordion-btn-focus-box-shadow); } - -.accordion-header { - margin-bottom: 0; } - -.accordion-item { - color: var(--bs-accordion-color); - background-color: var(--bs-accordion-bg); - border: var(--bs-accordion-border-width) solid var(--bs-accordion-border-color); } - .accordion-item:first-of-type { - border-top-left-radius: var(--bs-accordion-border-radius); - border-top-right-radius: var(--bs-accordion-border-radius); } - .accordion-item:first-of-type .accordion-button { - border-top-left-radius: var(--bs-accordion-inner-border-radius); - border-top-right-radius: var(--bs-accordion-inner-border-radius); } - .accordion-item:not(:first-of-type) { - border-top: 0; } - .accordion-item:last-of-type { - border-bottom-right-radius: var(--bs-accordion-border-radius); - border-bottom-left-radius: var(--bs-accordion-border-radius); } - .accordion-item:last-of-type .accordion-button.collapsed { - border-bottom-right-radius: var(--bs-accordion-inner-border-radius); - border-bottom-left-radius: var(--bs-accordion-inner-border-radius); } - .accordion-item:last-of-type .accordion-collapse { - border-bottom-right-radius: var(--bs-accordion-border-radius); - border-bottom-left-radius: var(--bs-accordion-border-radius); } - -.accordion-body { - padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); } - -.accordion-flush .accordion-collapse { - border-width: 0; } - -.accordion-flush .accordion-item { - border-right: 0; - border-left: 0; - border-radius: 0; } - .accordion-flush .accordion-item:first-child { - border-top: 0; } - .accordion-flush .accordion-item:last-child { - border-bottom: 0; } - .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed { - border-radius: 0; } - -[data-bs-theme="dark"] .accordion-button::after { - --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); - --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); } - -.breadcrumb { - --bs-breadcrumb-padding-x: 0; - --bs-breadcrumb-padding-y: 0; - --bs-breadcrumb-margin-bottom: 1rem; - --bs-breadcrumb-bg: ; - --bs-breadcrumb-border-radius: ; - --bs-breadcrumb-divider-color: var(--bs-secondary-color); - --bs-breadcrumb-item-padding-x: 0.5rem; - --bs-breadcrumb-item-active-color: var(--bs-secondary-color); - display: flex; - flex-wrap: wrap; - padding: var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x); - margin-bottom: var(--bs-breadcrumb-margin-bottom); - font-size: var(--bs-breadcrumb-font-size); - list-style: none; - background-color: var(--bs-breadcrumb-bg); - border-radius: var(--bs-breadcrumb-border-radius); } - -.breadcrumb-item + .breadcrumb-item { - padding-left: var(--bs-breadcrumb-item-padding-x); } - .breadcrumb-item + .breadcrumb-item::before { - float: left; - padding-right: var(--bs-breadcrumb-item-padding-x); - color: var(--bs-breadcrumb-divider-color); - content: var(--bs-breadcrumb-divider, "/") /* rtl: var(--bs-breadcrumb-divider, "/") */; } - -.breadcrumb-item.active { - color: var(--bs-breadcrumb-item-active-color); } - -.pagination { - --bs-pagination-padding-x: 0.75rem; - --bs-pagination-padding-y: 0.375rem; - --bs-pagination-font-size: 1rem; - --bs-pagination-color: var(--bs-link-color); - --bs-pagination-bg: var(--bs-body-bg); - --bs-pagination-border-width: var(--bs-border-width); - --bs-pagination-border-color: var(--bs-border-color); - --bs-pagination-border-radius: var(--bs-border-radius); - --bs-pagination-hover-color: var(--bs-link-hover-color); - --bs-pagination-hover-bg: var(--bs-tertiary-bg); - --bs-pagination-hover-border-color: var(--bs-border-color); - --bs-pagination-focus-color: var(--bs-link-hover-color); - --bs-pagination-focus-bg: var(--bs-secondary-bg); - --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); - --bs-pagination-active-color: #fff; - --bs-pagination-active-bg: #0d6efd; - --bs-pagination-active-border-color: #0d6efd; - --bs-pagination-disabled-color: var(--bs-secondary-color); - --bs-pagination-disabled-bg: var(--bs-secondary-bg); - --bs-pagination-disabled-border-color: var(--bs-border-color); - display: flex; - padding-left: 0; - list-style: none; } - -.page-link { - position: relative; - display: block; - padding: var(--bs-pagination-padding-y) var(--bs-pagination-padding-x); - font-size: var(--bs-pagination-font-size); - color: var(--bs-pagination-color); - text-decoration: none; - background-color: var(--bs-pagination-bg); - border: var(--bs-pagination-border-width) solid var(--bs-pagination-border-color); - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } - @media (prefers-reduced-motion: reduce) { - .page-link { - transition: none; } } - .page-link:hover { - z-index: 2; - color: var(--bs-pagination-hover-color); - background-color: var(--bs-pagination-hover-bg); - border-color: var(--bs-pagination-hover-border-color); } - .page-link:focus { - z-index: 3; - color: var(--bs-pagination-focus-color); - background-color: var(--bs-pagination-focus-bg); - outline: 0; - box-shadow: var(--bs-pagination-focus-box-shadow); } - .page-link.active, .active > .page-link { - z-index: 3; - color: var(--bs-pagination-active-color); - background-color: var(--bs-pagination-active-bg); - border-color: var(--bs-pagination-active-border-color); } - .page-link.disabled, .disabled > .page-link { - color: var(--bs-pagination-disabled-color); - pointer-events: none; - background-color: var(--bs-pagination-disabled-bg); - border-color: var(--bs-pagination-disabled-border-color); } - -.page-item:not(:first-child) .page-link { - margin-left: calc(var(--bs-border-width) * -1); } - -.page-item:first-child .page-link { - border-top-left-radius: var(--bs-pagination-border-radius); - border-bottom-left-radius: var(--bs-pagination-border-radius); } - -.page-item:last-child .page-link { - border-top-right-radius: var(--bs-pagination-border-radius); - border-bottom-right-radius: var(--bs-pagination-border-radius); } - -.pagination-lg { - --bs-pagination-padding-x: 1.5rem; - --bs-pagination-padding-y: 0.75rem; - --bs-pagination-font-size: 1.25rem; - --bs-pagination-border-radius: var(--bs-border-radius-lg); } - -.pagination-sm { - --bs-pagination-padding-x: 0.5rem; - --bs-pagination-padding-y: 0.25rem; - --bs-pagination-font-size: 0.875rem; - --bs-pagination-border-radius: var(--bs-border-radius-sm); } - -.btn-close { - --bs-btn-close-color: #191f27; - --bs-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23191f27'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e"); - --bs-btn-close-opacity: 0.5; - --bs-btn-close-hover-opacity: 0.75; - --bs-btn-close-focus-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); - --bs-btn-close-focus-opacity: 1; - --bs-btn-close-disabled-opacity: 0.25; - --bs-btn-close-white-filter: invert(1) grayscale(100%) brightness(200%); - box-sizing: content-box; - width: 1em; - height: 1em; - padding: 0.25em 0.25em; - color: var(--bs-btn-close-color); - background: transparent var(--bs-btn-close-bg) center/1em auto no-repeat; - border: 0; - border-radius: 0.375rem; - opacity: var(--bs-btn-close-opacity); } - .btn-close:hover { - color: var(--bs-btn-close-color); - text-decoration: none; - opacity: var(--bs-btn-close-hover-opacity); } - .btn-close:focus { - outline: 0; - box-shadow: var(--bs-btn-close-focus-shadow); - opacity: var(--bs-btn-close-focus-opacity); } - .btn-close:disabled, .btn-close.disabled { - pointer-events: none; - user-select: none; - opacity: var(--bs-btn-close-disabled-opacity); } - -.btn-close-white { - filter: var(--bs-btn-close-white-filter); } - -[data-bs-theme="dark"] .btn-close { - filter: var(--bs-btn-close-white-filter); } - -.modal { - --bs-modal-zindex: 1055; - --bs-modal-width: 500px; - --bs-modal-padding: 1rem; - --bs-modal-margin: 0.5rem; - --bs-modal-color: ; - --bs-modal-bg: var(--bs-body-bg); - --bs-modal-border-color: var(--bs-border-color-translucent); - --bs-modal-border-width: var(--bs-border-width); - --bs-modal-border-radius: var(--bs-border-radius-lg); - --bs-modal-box-shadow: var(--bs-box-shadow-sm); - --bs-modal-inner-border-radius: calc(var(--bs-border-radius-lg) - (var(--bs-border-width))); - --bs-modal-header-padding-x: 1rem; - --bs-modal-header-padding-y: 1rem; - --bs-modal-header-padding: 1rem 1rem; - --bs-modal-header-border-color: var(--bs-border-color); - --bs-modal-header-border-width: var(--bs-border-width); - --bs-modal-title-line-height: 1.5; - --bs-modal-footer-gap: 0.5rem; - --bs-modal-footer-bg: ; - --bs-modal-footer-border-color: var(--bs-border-color); - --bs-modal-footer-border-width: var(--bs-border-width); - position: fixed; - top: 0; - left: 0; - z-index: var(--bs-modal-zindex); - display: none; - width: 100%; - height: 100%; - overflow-x: hidden; - overflow-y: auto; - outline: 0; } - -.modal-dialog { - position: relative; - width: auto; - margin: var(--bs-modal-margin); - pointer-events: none; } - .modal.fade .modal-dialog { - transition: transform 0.3s ease-out; - transform: translate(0, -50px); } - @media (prefers-reduced-motion: reduce) { - .modal.fade .modal-dialog { - transition: none; } } - .modal.show .modal-dialog { - transform: none; } - .modal.modal-static .modal-dialog { - transform: scale(1.02); } - -.modal-dialog-scrollable { - height: calc(100% - var(--bs-modal-margin) * 2); } - .modal-dialog-scrollable .modal-content { - max-height: 100%; - overflow: hidden; } - .modal-dialog-scrollable .modal-body { - overflow-y: auto; } - -.modal-dialog-centered { - display: flex; - align-items: center; - min-height: calc(100% - var(--bs-modal-margin) * 2); } - -.modal-content { - position: relative; - display: flex; - flex-direction: column; - width: 100%; - color: var(--bs-modal-color); - pointer-events: auto; - background-color: var(--bs-modal-bg); - background-clip: padding-box; - border: var(--bs-modal-border-width) solid var(--bs-modal-border-color); - border-radius: var(--bs-modal-border-radius); - outline: 0; } - -.modal-backdrop { - --bs-backdrop-zindex: 1050; - --bs-backdrop-bg: #191f27; - --bs-backdrop-opacity: 0.5; - position: fixed; - top: 0; - left: 0; - z-index: var(--bs-backdrop-zindex); - width: 100vw; - height: 100vh; - background-color: var(--bs-backdrop-bg); } - .modal-backdrop.fade { - opacity: 0; } - .modal-backdrop.show { - opacity: var(--bs-backdrop-opacity); } - -.modal-header { - display: flex; - flex-shrink: 0; - align-items: center; - justify-content: space-between; - padding: var(--bs-modal-header-padding); - border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); - border-top-left-radius: var(--bs-modal-inner-border-radius); - border-top-right-radius: var(--bs-modal-inner-border-radius); } - .modal-header .btn-close { - padding: calc(var(--bs-modal-header-padding-y) * .5) calc(var(--bs-modal-header-padding-x) * .5); - margin: calc(-.5 * var(--bs-modal-header-padding-y)) calc(-.5 * var(--bs-modal-header-padding-x)) calc(-.5 * var(--bs-modal-header-padding-y)) auto; } - -.modal-title { - margin-bottom: 0; - line-height: var(--bs-modal-title-line-height); } - -.modal-body { - position: relative; - flex: 1 1 auto; - padding: var(--bs-modal-padding); } - -.modal-footer { - display: flex; - flex-shrink: 0; - flex-wrap: wrap; - align-items: center; - justify-content: flex-end; - padding: calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * .5); - background-color: var(--bs-modal-footer-bg); - border-top: var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color); - border-bottom-right-radius: var(--bs-modal-inner-border-radius); - border-bottom-left-radius: var(--bs-modal-inner-border-radius); } - .modal-footer > * { - margin: calc(var(--bs-modal-footer-gap) * .5); } - -@media (min-width: 576px) { - .modal { - --bs-modal-margin: 1.75rem; - --bs-modal-box-shadow: var(--bs-box-shadow); } - .modal-dialog { - max-width: var(--bs-modal-width); - margin-right: auto; - margin-left: auto; } - .modal-sm { - --bs-modal-width: 300px; } } - -@media (min-width: 992px) { - .modal-lg, - .modal-xl { - --bs-modal-width: 800px; } } - -@media (min-width: 1200px) { - .modal-xl { - --bs-modal-width: 1140px; } } - -.modal-fullscreen { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen .modal-header, - .modal-fullscreen .modal-footer { - border-radius: 0; } - .modal-fullscreen .modal-body { - overflow-y: auto; } - -@media (max-width: 575.98px) { - .modal-fullscreen-sm-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen-sm-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen-sm-down .modal-header, - .modal-fullscreen-sm-down .modal-footer { - border-radius: 0; } - .modal-fullscreen-sm-down .modal-body { - overflow-y: auto; } } - -@media (max-width: 767.98px) { - .modal-fullscreen-md-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen-md-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen-md-down .modal-header, - .modal-fullscreen-md-down .modal-footer { - border-radius: 0; } - .modal-fullscreen-md-down .modal-body { - overflow-y: auto; } } - -@media (max-width: 991.98px) { - .modal-fullscreen-lg-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen-lg-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen-lg-down .modal-header, - .modal-fullscreen-lg-down .modal-footer { - border-radius: 0; } - .modal-fullscreen-lg-down .modal-body { - overflow-y: auto; } } - -@media (max-width: 1199.98px) { - .modal-fullscreen-xl-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen-xl-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen-xl-down .modal-header, - .modal-fullscreen-xl-down .modal-footer { - border-radius: 0; } - .modal-fullscreen-xl-down .modal-body { - overflow-y: auto; } } - -@media (max-width: 1399.98px) { - .modal-fullscreen-xxl-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; } - .modal-fullscreen-xxl-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; } - .modal-fullscreen-xxl-down .modal-header, - .modal-fullscreen-xxl-down .modal-footer { - border-radius: 0; } - .modal-fullscreen-xxl-down .modal-body { - overflow-y: auto; } } - -.clearfix::after { - display: block; - clear: both; - content: ""; } - -.text-bg-primary { - color: #fff !important; - background-color: RGBA(var(--bs-primary-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-secondary { - color: #fff !important; - background-color: RGBA(var(--bs-secondary-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-success { - color: #fff !important; - background-color: RGBA(var(--bs-success-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-info { - color: #191f27 !important; - background-color: RGBA(var(--bs-info-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-warning { - color: #191f27 !important; - background-color: RGBA(var(--bs-warning-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-danger { - color: #fff !important; - background-color: RGBA(var(--bs-danger-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-light { - color: #191f27 !important; - background-color: RGBA(var(--bs-light-rgb), var(--bs-bg-opacity, 1)) !important; } - -.text-bg-dark { - color: #fff !important; - background-color: RGBA(var(--bs-dark-rgb), var(--bs-bg-opacity, 1)) !important; } - -.link-primary { - color: RGBA(var(--bs-primary-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-primary-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-primary:hover, .link-primary:focus { - color: RGBA(10, 88, 202, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(10, 88, 202, var(--bs-link-underline-opacity, 1)) !important; } - -.link-secondary { - color: RGBA(var(--bs-secondary-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-secondary-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-secondary:hover, .link-secondary:focus { - color: RGBA(86, 94, 100, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(86, 94, 100, var(--bs-link-underline-opacity, 1)) !important; } - -.link-success { - color: RGBA(var(--bs-success-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-success-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-success:hover, .link-success:focus { - color: RGBA(20, 108, 67, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(20, 108, 67, var(--bs-link-underline-opacity, 1)) !important; } - -.link-info { - color: RGBA(var(--bs-info-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-info-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-info:hover, .link-info:focus { - color: RGBA(61, 213, 243, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(61, 213, 243, var(--bs-link-underline-opacity, 1)) !important; } - -.link-warning { - color: RGBA(var(--bs-warning-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-warning-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-warning:hover, .link-warning:focus { - color: RGBA(255, 205, 57, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(255, 205, 57, var(--bs-link-underline-opacity, 1)) !important; } - -.link-danger { - color: RGBA(var(--bs-danger-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-danger:hover, .link-danger:focus { - color: RGBA(176, 42, 55, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(176, 42, 55, var(--bs-link-underline-opacity, 1)) !important; } - -.link-light { - color: RGBA(var(--bs-light-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-light:hover, .link-light:focus { - color: RGBA(241, 241, 241, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(241, 241, 241, var(--bs-link-underline-opacity, 1)) !important; } - -.link-dark { - color: RGBA(var(--bs-dark-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-dark-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-dark:hover, .link-dark:focus { - color: RGBA(27, 27, 27, var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(27, 27, 27, var(--bs-link-underline-opacity, 1)) !important; } - -.link-body-emphasis { - color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 1)) !important; - text-decoration-color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 1)) !important; } - .link-body-emphasis:hover, .link-body-emphasis:focus { - color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 0.75)) !important; - text-decoration-color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 0.75)) !important; } - -.focus-ring:focus { - outline: 0; - box-shadow: var(--bs-focus-ring-x, 0) var(--bs-focus-ring-y, 0) var(--bs-focus-ring-blur, 0) var(--bs-focus-ring-width) var(--bs-focus-ring-color); } - -.icon-link { - display: inline-flex; - gap: 0.375rem; - align-items: center; - text-decoration-color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 0.5)); - text-underline-offset: 0.25em; - backface-visibility: hidden; } - .icon-link > .bi { - flex-shrink: 0; - width: 1em; - height: 1em; - fill: currentcolor; - transition: 0.2s ease-in-out transform; } - @media (prefers-reduced-motion: reduce) { - .icon-link > .bi { - transition: none; } } -.icon-link-hover:hover > .bi, .icon-link-hover:focus-visible > .bi { - transform: var(--bs-icon-link-transform, translate3d(0.25em, 0, 0)); } - -.ratio { - position: relative; - width: 100%; } - .ratio::before { - display: block; - padding-top: var(--bs-aspect-ratio); - content: ""; } - .ratio > * { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; } - -.ratio-1x1 { - --bs-aspect-ratio: 100%; } - -.ratio-4x3 { - --bs-aspect-ratio: calc(3 / 4 * 100%); } - -.ratio-16x9 { - --bs-aspect-ratio: calc(9 / 16 * 100%); } - -.ratio-21x9 { - --bs-aspect-ratio: calc(9 / 21 * 100%); } - -.fixed-top { - position: fixed; - top: 0; - right: 0; - left: 0; - z-index: 1030; } - -.fixed-bottom { - position: fixed; - right: 0; - bottom: 0; - left: 0; - z-index: 1030; } - -.sticky-top { - position: sticky; - top: 0; - z-index: 1020; } - -.sticky-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } - -@media (min-width: 576px) { - .sticky-sm-top { - position: sticky; - top: 0; - z-index: 1020; } - .sticky-sm-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } } - -@media (min-width: 768px) { - .sticky-md-top { - position: sticky; - top: 0; - z-index: 1020; } - .sticky-md-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } } - -@media (min-width: 992px) { - .sticky-lg-top { - position: sticky; - top: 0; - z-index: 1020; } - .sticky-lg-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } } - -@media (min-width: 1200px) { - .sticky-xl-top { - position: sticky; - top: 0; - z-index: 1020; } - .sticky-xl-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } } - -@media (min-width: 1400px) { - .sticky-xxl-top { - position: sticky; - top: 0; - z-index: 1020; } - .sticky-xxl-bottom { - position: sticky; - bottom: 0; - z-index: 1020; } } - -.hstack { - display: flex; - flex-direction: row; - align-items: center; - align-self: stretch; } - -.vstack { - display: flex; - flex: 1 1 auto; - flex-direction: column; - align-self: stretch; } - -.visually-hidden, -.visually-hidden-focusable:not(:focus):not(:focus-within) { - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; } - .visually-hidden:not(caption), - .visually-hidden-focusable:not(:focus):not(:focus-within):not(caption) { - position: absolute !important; } - -.stretched-link::after { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1; - content: ""; } - -.text-truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; } - -.vr { - display: inline-block; - align-self: stretch; - width: var(--bs-border-width); - min-height: 1em; - background-color: currentcolor; - opacity: 0.25; } - -.align-baseline { - vertical-align: baseline !important; } - -.align-top { - vertical-align: top !important; } - -.align-middle { - vertical-align: middle !important; } - -.align-bottom { - vertical-align: bottom !important; } - -.align-text-bottom { - vertical-align: text-bottom !important; } - -.align-text-top { - vertical-align: text-top !important; } - -.float-start { - float: left !important; } - -.float-end { - float: right !important; } - -.float-none { - float: none !important; } - -.object-fit-contain { - object-fit: contain !important; } - -.object-fit-cover { - object-fit: cover !important; } - -.object-fit-fill { - object-fit: fill !important; } - -.object-fit-scale { - object-fit: scale-down !important; } - -.object-fit-none { - object-fit: none !important; } - -.opacity-0 { - opacity: 0 !important; } - -.opacity-25 { - opacity: 0.25 !important; } - -.opacity-50 { - opacity: 0.5 !important; } - -.opacity-75 { - opacity: 0.75 !important; } - -.opacity-100 { - opacity: 1 !important; } - -.overflow-auto { - overflow: auto !important; } - -.overflow-hidden { - overflow: hidden !important; } - -.overflow-visible { - overflow: visible !important; } - -.overflow-scroll { - overflow: scroll !important; } - -.overflow-x-auto { - overflow-x: auto !important; } - -.overflow-x-hidden { - overflow-x: hidden !important; } - -.overflow-x-visible { - overflow-x: visible !important; } - -.overflow-x-scroll { - overflow-x: scroll !important; } - -.overflow-y-auto { - overflow-y: auto !important; } - -.overflow-y-hidden { - overflow-y: hidden !important; } - -.overflow-y-visible { - overflow-y: visible !important; } - -.overflow-y-scroll { - overflow-y: scroll !important; } - -.d-inline { - display: inline !important; } - -.d-inline-block { - display: inline-block !important; } - -.d-block { - display: block !important; } - -.d-grid { - display: grid !important; } - -.d-inline-grid { - display: inline-grid !important; } - -.d-table { - display: table !important; } - -.d-table-row { - display: table-row !important; } - -.d-table-cell { - display: table-cell !important; } - -.d-flex { - display: flex !important; } - -.d-inline-flex { - display: inline-flex !important; } - -.d-none { - display: none !important; } - -.shadow { - box-shadow: var(--bs-box-shadow) !important; } - -.shadow-sm { - box-shadow: var(--bs-box-shadow-sm) !important; } - -.shadow-lg { - box-shadow: var(--bs-box-shadow-lg) !important; } - -.shadow-none { - box-shadow: none !important; } - -.focus-ring-primary { - --bs-focus-ring-color: rgba(var(--bs-primary-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-secondary { - --bs-focus-ring-color: rgba(var(--bs-secondary-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-success { - --bs-focus-ring-color: rgba(var(--bs-success-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-info { - --bs-focus-ring-color: rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-warning { - --bs-focus-ring-color: rgba(var(--bs-warning-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-danger { - --bs-focus-ring-color: rgba(var(--bs-danger-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-light { - --bs-focus-ring-color: rgba(var(--bs-light-rgb), var(--bs-focus-ring-opacity)); } - -.focus-ring-dark { - --bs-focus-ring-color: rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity)); } - -.position-static { - position: static !important; } - -.position-relative { - position: relative !important; } - -.position-absolute { - position: absolute !important; } - -.position-fixed { - position: fixed !important; } - -.position-sticky { - position: sticky !important; } - -.top-0 { - top: 0 !important; } - -.top-50 { - top: 50% !important; } - -.top-100 { - top: 100% !important; } - -.bottom-0 { - bottom: 0 !important; } - -.bottom-50 { - bottom: 50% !important; } - -.bottom-100 { - bottom: 100% !important; } - -.start-0 { - left: 0 !important; } - -.start-50 { - left: 50% !important; } - -.start-100 { - left: 100% !important; } - -.end-0 { - right: 0 !important; } - -.end-50 { - right: 50% !important; } - -.end-100 { - right: 100% !important; } - -.translate-middle { - transform: translate(-50%, -50%) !important; } - -.translate-middle-x { - transform: translateX(-50%) !important; } - -.translate-middle-y { - transform: translateY(-50%) !important; } - -.border { - border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } - -.border-0 { - border: 0 !important; } - -.border-top { - border-top: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } - -.border-top-0 { - border-top: 0 !important; } - -.border-end { - border-right: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } - -.border-end-0 { - border-right: 0 !important; } - -.border-bottom { - border-bottom: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } - -.border-bottom-0 { - border-bottom: 0 !important; } - -.border-start { - border-left: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } - -.border-start-0 { - border-left: 0 !important; } - -.border-primary { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-primary-rgb), var(--bs-border-opacity)) !important; } - -.border-secondary { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-secondary-rgb), var(--bs-border-opacity)) !important; } - -.border-success { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-success-rgb), var(--bs-border-opacity)) !important; } - -.border-info { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-info-rgb), var(--bs-border-opacity)) !important; } - -.border-warning { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-warning-rgb), var(--bs-border-opacity)) !important; } - -.border-danger { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-danger-rgb), var(--bs-border-opacity)) !important; } - -.border-light { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important; } - -.border-dark { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-dark-rgb), var(--bs-border-opacity)) !important; } - -.border-black { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-black-rgb), var(--bs-border-opacity)) !important; } - -.border-white { - --bs-border-opacity: 1; - border-color: rgba(var(--bs-white-rgb), var(--bs-border-opacity)) !important; } - -.border-primary-subtle { - border-color: var(--bs-primary-border-subtle) !important; } - -.border-secondary-subtle { - border-color: var(--bs-secondary-border-subtle) !important; } - -.border-success-subtle { - border-color: var(--bs-success-border-subtle) !important; } - -.border-info-subtle { - border-color: var(--bs-info-border-subtle) !important; } - -.border-warning-subtle { - border-color: var(--bs-warning-border-subtle) !important; } - -.border-danger-subtle { - border-color: var(--bs-danger-border-subtle) !important; } - -.border-light-subtle { - border-color: var(--bs-light-border-subtle) !important; } - -.border-dark-subtle { - border-color: var(--bs-dark-border-subtle) !important; } - -.border-1 { - border-width: 1px !important; } - -.border-2 { - border-width: 2px !important; } - -.border-3 { - border-width: 3px !important; } - -.border-4 { - border-width: 4px !important; } - -.border-5 { - border-width: 5px !important; } - -.border-opacity-10 { - --bs-border-opacity: 0.1; } - -.border-opacity-25 { - --bs-border-opacity: 0.25; } - -.border-opacity-50 { - --bs-border-opacity: 0.5; } - -.border-opacity-75 { - --bs-border-opacity: 0.75; } - -.border-opacity-100 { - --bs-border-opacity: 1; } - -.w-25 { - width: 25% !important; } - -.w-50 { - width: 50% !important; } - -.w-75 { - width: 75% !important; } - -.w-100 { - width: 100% !important; } - -.w-auto { - width: auto !important; } - -.mw-100 { - max-width: 100% !important; } - -.vw-100 { - width: 100vw !important; } - -.min-vw-100 { - min-width: 100vw !important; } - -.h-25 { - height: 25% !important; } - -.h-50 { - height: 50% !important; } - -.h-75 { - height: 75% !important; } - -.h-100 { - height: 100% !important; } - -.h-auto { - height: auto !important; } - -.mh-100 { - max-height: 100% !important; } - -.vh-100 { - height: 100vh !important; } - -.min-vh-100 { - min-height: 100vh !important; } - -.flex-fill { - flex: 1 1 auto !important; } - -.flex-row { - flex-direction: row !important; } - -.flex-column { - flex-direction: column !important; } - -.flex-row-reverse { - flex-direction: row-reverse !important; } - -.flex-column-reverse { - flex-direction: column-reverse !important; } - -.flex-grow-0 { - flex-grow: 0 !important; } - -.flex-grow-1 { - flex-grow: 1 !important; } - -.flex-shrink-0 { - flex-shrink: 0 !important; } - -.flex-shrink-1 { - flex-shrink: 1 !important; } - -.flex-wrap { - flex-wrap: wrap !important; } - -.flex-nowrap { - flex-wrap: nowrap !important; } - -.flex-wrap-reverse { - flex-wrap: wrap-reverse !important; } - -.justify-content-start { - justify-content: flex-start !important; } - -.justify-content-end { - justify-content: flex-end !important; } - -.justify-content-center { - justify-content: center !important; } - -.justify-content-between { - justify-content: space-between !important; } - -.justify-content-around { - justify-content: space-around !important; } - -.justify-content-evenly { - justify-content: space-evenly !important; } - -.align-items-start { - align-items: flex-start !important; } - -.align-items-end { - align-items: flex-end !important; } - -.align-items-center { - align-items: center !important; } - -.align-items-baseline { - align-items: baseline !important; } - -.align-items-stretch { - align-items: stretch !important; } - -.align-content-start { - align-content: flex-start !important; } - -.align-content-end { - align-content: flex-end !important; } - -.align-content-center { - align-content: center !important; } - -.align-content-between { - align-content: space-between !important; } - -.align-content-around { - align-content: space-around !important; } - -.align-content-stretch { - align-content: stretch !important; } - -.align-self-auto { - align-self: auto !important; } - -.align-self-start { - align-self: flex-start !important; } - -.align-self-end { - align-self: flex-end !important; } - -.align-self-center { - align-self: center !important; } - -.align-self-baseline { - align-self: baseline !important; } - -.align-self-stretch { - align-self: stretch !important; } - -.order-first { - order: -1 !important; } - -.order-0 { - order: 0 !important; } - -.order-1 { - order: 1 !important; } - -.order-2 { - order: 2 !important; } - -.order-3 { - order: 3 !important; } - -.order-4 { - order: 4 !important; } - -.order-5 { - order: 5 !important; } - -.order-last { - order: 6 !important; } - -.m-0 { - margin: 0 !important; } - -.m-1 { - margin: 0.25rem !important; } - -.m-2 { - margin: 0.5rem !important; } - -.m-3 { - margin: 1rem !important; } - -.m-4 { - margin: 1.5rem !important; } - -.m-5 { - margin: 3rem !important; } - -.m-auto { - margin: auto !important; } - -.mx-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - -.mx-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - -.mx-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - -.mx-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - -.mx-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - -.mx-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - -.mx-auto { - margin-right: auto !important; - margin-left: auto !important; } - -.my-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; } - -.my-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; } - -.my-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; } - -.my-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; } - -.my-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - -.my-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; } - -.my-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - -.mt-0 { - margin-top: 0 !important; } - -.mt-1 { - margin-top: 0.25rem !important; } - -.mt-2 { - margin-top: 0.5rem !important; } - -.mt-3 { - margin-top: 1rem !important; } - -.mt-4 { - margin-top: 1.5rem !important; } - -.mt-5 { - margin-top: 3rem !important; } - -.mt-auto { - margin-top: auto !important; } - -.me-0 { - margin-right: 0 !important; } - -.me-1 { - margin-right: 0.25rem !important; } - -.me-2 { - margin-right: 0.5rem !important; } - -.me-3 { - margin-right: 1rem !important; } - -.me-4 { - margin-right: 1.5rem !important; } - -.me-5 { - margin-right: 3rem !important; } - -.me-auto { - margin-right: auto !important; } - -.mb-0 { - margin-bottom: 0 !important; } - -.mb-1 { - margin-bottom: 0.25rem !important; } - -.mb-2 { - margin-bottom: 0.5rem !important; } - -.mb-3 { - margin-bottom: 1rem !important; } - -.mb-4 { - margin-bottom: 1.5rem !important; } - -.mb-5 { - margin-bottom: 3rem !important; } - -.mb-auto { - margin-bottom: auto !important; } - -.ms-0 { - margin-left: 0 !important; } - -.ms-1 { - margin-left: 0.25rem !important; } - -.ms-2 { - margin-left: 0.5rem !important; } - -.ms-3 { - margin-left: 1rem !important; } - -.ms-4 { - margin-left: 1.5rem !important; } - -.ms-5 { - margin-left: 3rem !important; } - -.ms-auto { - margin-left: auto !important; } - -.p-0 { - padding: 0 !important; } - -.p-1 { - padding: 0.25rem !important; } - -.p-2 { - padding: 0.5rem !important; } - -.p-3 { - padding: 1rem !important; } - -.p-4 { - padding: 1.5rem !important; } - -.p-5 { - padding: 3rem !important; } - -.px-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - -.px-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - -.px-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - -.px-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - -.px-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - -.px-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - -.py-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - -.py-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - -.py-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - -.py-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - -.py-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - -.py-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - -.pt-0 { - padding-top: 0 !important; } - -.pt-1 { - padding-top: 0.25rem !important; } - -.pt-2 { - padding-top: 0.5rem !important; } - -.pt-3 { - padding-top: 1rem !important; } - -.pt-4 { - padding-top: 1.5rem !important; } - -.pt-5 { - padding-top: 3rem !important; } - -.pe-0 { - padding-right: 0 !important; } - -.pe-1 { - padding-right: 0.25rem !important; } - -.pe-2 { - padding-right: 0.5rem !important; } - -.pe-3 { - padding-right: 1rem !important; } - -.pe-4 { - padding-right: 1.5rem !important; } - -.pe-5 { - padding-right: 3rem !important; } - -.pb-0 { - padding-bottom: 0 !important; } - -.pb-1 { - padding-bottom: 0.25rem !important; } - -.pb-2 { - padding-bottom: 0.5rem !important; } - -.pb-3 { - padding-bottom: 1rem !important; } - -.pb-4 { - padding-bottom: 1.5rem !important; } - -.pb-5 { - padding-bottom: 3rem !important; } - -.ps-0 { - padding-left: 0 !important; } - -.ps-1 { - padding-left: 0.25rem !important; } - -.ps-2 { - padding-left: 0.5rem !important; } - -.ps-3 { - padding-left: 1rem !important; } - -.ps-4 { - padding-left: 1.5rem !important; } - -.ps-5 { - padding-left: 3rem !important; } - -.gap-0 { - gap: 0 !important; } - -.gap-1 { - gap: 0.25rem !important; } - -.gap-2 { - gap: 0.5rem !important; } - -.gap-3 { - gap: 1rem !important; } - -.gap-4 { - gap: 1.5rem !important; } - -.gap-5 { - gap: 3rem !important; } - -.row-gap-0 { - row-gap: 0 !important; } - -.row-gap-1 { - row-gap: 0.25rem !important; } - -.row-gap-2 { - row-gap: 0.5rem !important; } - -.row-gap-3 { - row-gap: 1rem !important; } - -.row-gap-4 { - row-gap: 1.5rem !important; } - -.row-gap-5 { - row-gap: 3rem !important; } - -.column-gap-0 { - column-gap: 0 !important; } - -.column-gap-1 { - column-gap: 0.25rem !important; } - -.column-gap-2 { - column-gap: 0.5rem !important; } - -.column-gap-3 { - column-gap: 1rem !important; } - -.column-gap-4 { - column-gap: 1.5rem !important; } - -.column-gap-5 { - column-gap: 3rem !important; } - -.font-monospace { - font-family: var(--bs-font-monospace) !important; } - -.fs-1 { - font-size: calc(1.375rem + 1.5vw) !important; } - -.fs-2 { - font-size: calc(1.325rem + 0.9vw) !important; } - -.fs-3 { - font-size: calc(1.3rem + 0.6vw) !important; } - -.fs-4 { - font-size: calc(1.275rem + 0.3vw) !important; } - -.fs-5 { - font-size: 1.25rem !important; } - -.fs-6 { - font-size: 1rem !important; } - -.fst-italic { - font-style: italic !important; } - -.fst-normal { - font-style: normal !important; } - -.fw-lighter { - font-weight: lighter !important; } - -.fw-light { - font-weight: 300 !important; } - -.fw-normal { - font-weight: 400 !important; } - -.fw-medium { - font-weight: 500 !important; } - -.fw-semibold { - font-weight: 600 !important; } - -.fw-bold { - font-weight: 700 !important; } - -.fw-bolder { - font-weight: bolder !important; } - -.lh-1 { - line-height: 1 !important; } - -.lh-sm { - line-height: 1.25 !important; } - -.lh-base { - line-height: 1.5 !important; } - -.lh-lg { - line-height: 2 !important; } - -.text-start { - text-align: left !important; } - -.text-end { - text-align: right !important; } - -.text-center { - text-align: center !important; } - -.text-decoration-none { - text-decoration: none !important; } - -.text-decoration-underline { - text-decoration: underline !important; } - -.text-decoration-line-through { - text-decoration: line-through !important; } - -.text-lowercase { - text-transform: lowercase !important; } - -.text-uppercase { - text-transform: uppercase !important; } - -.text-capitalize { - text-transform: capitalize !important; } - -.text-wrap { - white-space: normal !important; } - -.text-nowrap { - white-space: nowrap !important; } - -/* rtl:begin:remove */ -.text-break { - word-wrap: break-word !important; - word-break: break-word !important; } - -/* rtl:end:remove */ -.text-primary { - --bs-text-opacity: 1; - color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important; } - -.text-secondary { - --bs-text-opacity: 1; - color: rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important; } - -.text-success { - --bs-text-opacity: 1; - color: rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important; } - -.text-info { - --bs-text-opacity: 1; - color: rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important; } - -.text-warning { - --bs-text-opacity: 1; - color: rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important; } - -.text-danger { - --bs-text-opacity: 1; - color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important; } - -.text-light { - --bs-text-opacity: 1; - color: rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important; } - -.text-dark { - --bs-text-opacity: 1; - color: rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important; } - -.text-black { - --bs-text-opacity: 1; - color: rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important; } - -.text-white { - --bs-text-opacity: 1; - color: rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important; } - -.text-body { - --bs-text-opacity: 1; - color: rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important; } - -.text-muted { - --bs-text-opacity: 1; - color: var(--bs-secondary-color) !important; } - -.text-black-50 { - --bs-text-opacity: 1; - color: rgba(25, 31, 39, 0.5) !important; } - -.text-white-50 { - --bs-text-opacity: 1; - color: rgba(255, 255, 255, 0.5) !important; } - -.text-body-secondary { - --bs-text-opacity: 1; - color: var(--bs-secondary-color) !important; } - -.text-body-tertiary { - --bs-text-opacity: 1; - color: var(--bs-tertiary-color) !important; } - -.text-body-emphasis { - --bs-text-opacity: 1; - color: var(--bs-emphasis-color) !important; } - -.text-reset { - --bs-text-opacity: 1; - color: inherit !important; } - -.text-opacity-25 { - --bs-text-opacity: 0.25; } - -.text-opacity-50 { - --bs-text-opacity: 0.5; } - -.text-opacity-75 { - --bs-text-opacity: 0.75; } - -.text-opacity-100 { - --bs-text-opacity: 1; } - -.text-primary-emphasis { - color: var(--bs-primary-text-emphasis) !important; } - -.text-secondary-emphasis { - color: var(--bs-secondary-text-emphasis) !important; } - -.text-success-emphasis { - color: var(--bs-success-text-emphasis) !important; } - -.text-info-emphasis { - color: var(--bs-info-text-emphasis) !important; } - -.text-warning-emphasis { - color: var(--bs-warning-text-emphasis) !important; } - -.text-danger-emphasis { - color: var(--bs-danger-text-emphasis) !important; } - -.text-light-emphasis { - color: var(--bs-light-text-emphasis) !important; } - -.text-dark-emphasis { - color: var(--bs-dark-text-emphasis) !important; } - -.link-opacity-10 { - --bs-link-opacity: 0.1; } - -.link-opacity-10-hover:hover { - --bs-link-opacity: 0.1; } - -.link-opacity-25 { - --bs-link-opacity: 0.25; } - -.link-opacity-25-hover:hover { - --bs-link-opacity: 0.25; } - -.link-opacity-50 { - --bs-link-opacity: 0.5; } - -.link-opacity-50-hover:hover { - --bs-link-opacity: 0.5; } - -.link-opacity-75 { - --bs-link-opacity: 0.75; } - -.link-opacity-75-hover:hover { - --bs-link-opacity: 0.75; } - -.link-opacity-100 { - --bs-link-opacity: 1; } - -.link-opacity-100-hover:hover { - --bs-link-opacity: 1; } - -.link-offset-1 { - text-underline-offset: 0.125em !important; } - -.link-offset-1-hover:hover { - text-underline-offset: 0.125em !important; } - -.link-offset-2 { - text-underline-offset: 0.25em !important; } - -.link-offset-2-hover:hover { - text-underline-offset: 0.25em !important; } - -.link-offset-3 { - text-underline-offset: 0.375em !important; } - -.link-offset-3-hover:hover { - text-underline-offset: 0.375em !important; } - -.link-underline-primary { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-primary-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-secondary { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-secondary-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-success { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-success-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-info { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-info-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-warning { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-warning-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-danger { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-danger-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-light { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-light-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline-dark { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-dark-rgb), var(--bs-link-underline-opacity)) !important; } - -.link-underline { - --bs-link-underline-opacity: 1; - text-decoration-color: rgba(var(--bs-link-color-rgb), var(--bs-link-underline-opacity, 1)) !important; } - -.link-underline-opacity-0 { - --bs-link-underline-opacity: 0; } - -.link-underline-opacity-0-hover:hover { - --bs-link-underline-opacity: 0; } - -.link-underline-opacity-10 { - --bs-link-underline-opacity: 0.1; } - -.link-underline-opacity-10-hover:hover { - --bs-link-underline-opacity: 0.1; } - -.link-underline-opacity-25 { - --bs-link-underline-opacity: 0.25; } - -.link-underline-opacity-25-hover:hover { - --bs-link-underline-opacity: 0.25; } - -.link-underline-opacity-50 { - --bs-link-underline-opacity: 0.5; } - -.link-underline-opacity-50-hover:hover { - --bs-link-underline-opacity: 0.5; } - -.link-underline-opacity-75 { - --bs-link-underline-opacity: 0.75; } - -.link-underline-opacity-75-hover:hover { - --bs-link-underline-opacity: 0.75; } - -.link-underline-opacity-100 { - --bs-link-underline-opacity: 1; } - -.link-underline-opacity-100-hover:hover { - --bs-link-underline-opacity: 1; } - -.bg-primary { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important; } - -.bg-secondary { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important; } - -.bg-success { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important; } - -.bg-info { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important; } - -.bg-warning { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important; } - -.bg-danger { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important; } - -.bg-light { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; } - -.bg-dark { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important; } - -.bg-black { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important; } - -.bg-white { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important; } - -.bg-body { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important; } - -.bg-transparent { - --bs-bg-opacity: 1; - background-color: transparent !important; } - -.bg-body-secondary { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-secondary-bg-rgb), var(--bs-bg-opacity)) !important; } - -.bg-body-tertiary { - --bs-bg-opacity: 1; - background-color: rgba(var(--bs-tertiary-bg-rgb), var(--bs-bg-opacity)) !important; } - -.bg-opacity-10 { - --bs-bg-opacity: 0.1; } - -.bg-opacity-25 { - --bs-bg-opacity: 0.25; } - -.bg-opacity-50 { - --bs-bg-opacity: 0.5; } - -.bg-opacity-75 { - --bs-bg-opacity: 0.75; } - -.bg-opacity-100 { - --bs-bg-opacity: 1; } - -.bg-primary-subtle { - background-color: var(--bs-primary-bg-subtle) !important; } - -.bg-secondary-subtle { - background-color: var(--bs-secondary-bg-subtle) !important; } - -.bg-success-subtle { - background-color: var(--bs-success-bg-subtle) !important; } - -.bg-info-subtle { - background-color: var(--bs-info-bg-subtle) !important; } - -.bg-warning-subtle { - background-color: var(--bs-warning-bg-subtle) !important; } - -.bg-danger-subtle { - background-color: var(--bs-danger-bg-subtle) !important; } - -.bg-light-subtle { - background-color: var(--bs-light-bg-subtle) !important; } - -.bg-dark-subtle { - background-color: var(--bs-dark-bg-subtle) !important; } - -.bg-gradient { - background-image: var(--bs-gradient) !important; } - -.user-select-all { - user-select: all !important; } - -.user-select-auto { - user-select: auto !important; } - -.user-select-none { - user-select: none !important; } - -.pe-none { - pointer-events: none !important; } - -.pe-auto { - pointer-events: auto !important; } - -.rounded { - border-radius: var(--bs-border-radius) !important; } - -.rounded-0 { - border-radius: 0 !important; } - -.rounded-1 { - border-radius: var(--bs-border-radius-sm) !important; } - -.rounded-2, .content blockquote, .gallery-item img, .btn { - border-radius: var(--bs-border-radius) !important; } - -.rounded-3 { - border-radius: var(--bs-border-radius-lg) !important; } - -.rounded-4 { - border-radius: var(--bs-border-radius-xl) !important; } - -.rounded-5 { - border-radius: var(--bs-border-radius-xxl) !important; } - -.rounded-circle { - border-radius: 50% !important; } - -.rounded-pill { - border-radius: var(--bs-border-radius-pill) !important; } - -.rounded-top { - border-top-left-radius: var(--bs-border-radius) !important; - border-top-right-radius: var(--bs-border-radius) !important; } - -.rounded-top-0 { - border-top-left-radius: 0 !important; - border-top-right-radius: 0 !important; } - -.rounded-top-1 { - border-top-left-radius: var(--bs-border-radius-sm) !important; - border-top-right-radius: var(--bs-border-radius-sm) !important; } - -.rounded-top-2 { - border-top-left-radius: var(--bs-border-radius) !important; - border-top-right-radius: var(--bs-border-radius) !important; } - -.rounded-top-3 { - border-top-left-radius: var(--bs-border-radius-lg) !important; - border-top-right-radius: var(--bs-border-radius-lg) !important; } - -.rounded-top-4 { - border-top-left-radius: var(--bs-border-radius-xl) !important; - border-top-right-radius: var(--bs-border-radius-xl) !important; } - -.rounded-top-5 { - border-top-left-radius: var(--bs-border-radius-xxl) !important; - border-top-right-radius: var(--bs-border-radius-xxl) !important; } - -.rounded-top-circle { - border-top-left-radius: 50% !important; - border-top-right-radius: 50% !important; } - -.rounded-top-pill { - border-top-left-radius: var(--bs-border-radius-pill) !important; - border-top-right-radius: var(--bs-border-radius-pill) !important; } - -.rounded-end { - border-top-right-radius: var(--bs-border-radius) !important; - border-bottom-right-radius: var(--bs-border-radius) !important; } - -.rounded-end-0 { - border-top-right-radius: 0 !important; - border-bottom-right-radius: 0 !important; } - -.rounded-end-1 { - border-top-right-radius: var(--bs-border-radius-sm) !important; - border-bottom-right-radius: var(--bs-border-radius-sm) !important; } - -.rounded-end-2 { - border-top-right-radius: var(--bs-border-radius) !important; - border-bottom-right-radius: var(--bs-border-radius) !important; } - -.rounded-end-3 { - border-top-right-radius: var(--bs-border-radius-lg) !important; - border-bottom-right-radius: var(--bs-border-radius-lg) !important; } - -.rounded-end-4 { - border-top-right-radius: var(--bs-border-radius-xl) !important; - border-bottom-right-radius: var(--bs-border-radius-xl) !important; } - -.rounded-end-5 { - border-top-right-radius: var(--bs-border-radius-xxl) !important; - border-bottom-right-radius: var(--bs-border-radius-xxl) !important; } - -.rounded-end-circle { - border-top-right-radius: 50% !important; - border-bottom-right-radius: 50% !important; } - -.rounded-end-pill { - border-top-right-radius: var(--bs-border-radius-pill) !important; - border-bottom-right-radius: var(--bs-border-radius-pill) !important; } - -.rounded-bottom { - border-bottom-right-radius: var(--bs-border-radius) !important; - border-bottom-left-radius: var(--bs-border-radius) !important; } - -.rounded-bottom-0 { - border-bottom-right-radius: 0 !important; - border-bottom-left-radius: 0 !important; } - -.rounded-bottom-1 { - border-bottom-right-radius: var(--bs-border-radius-sm) !important; - border-bottom-left-radius: var(--bs-border-radius-sm) !important; } - -.rounded-bottom-2 { - border-bottom-right-radius: var(--bs-border-radius) !important; - border-bottom-left-radius: var(--bs-border-radius) !important; } - -.rounded-bottom-3 { - border-bottom-right-radius: var(--bs-border-radius-lg) !important; - border-bottom-left-radius: var(--bs-border-radius-lg) !important; } - -.rounded-bottom-4 { - border-bottom-right-radius: var(--bs-border-radius-xl) !important; - border-bottom-left-radius: var(--bs-border-radius-xl) !important; } - -.rounded-bottom-5 { - border-bottom-right-radius: var(--bs-border-radius-xxl) !important; - border-bottom-left-radius: var(--bs-border-radius-xxl) !important; } - -.rounded-bottom-circle { - border-bottom-right-radius: 50% !important; - border-bottom-left-radius: 50% !important; } - -.rounded-bottom-pill { - border-bottom-right-radius: var(--bs-border-radius-pill) !important; - border-bottom-left-radius: var(--bs-border-radius-pill) !important; } - -.rounded-start { - border-bottom-left-radius: var(--bs-border-radius) !important; - border-top-left-radius: var(--bs-border-radius) !important; } - -.rounded-start-0 { - border-bottom-left-radius: 0 !important; - border-top-left-radius: 0 !important; } - -.rounded-start-1 { - border-bottom-left-radius: var(--bs-border-radius-sm) !important; - border-top-left-radius: var(--bs-border-radius-sm) !important; } - -.rounded-start-2 { - border-bottom-left-radius: var(--bs-border-radius) !important; - border-top-left-radius: var(--bs-border-radius) !important; } - -.rounded-start-3 { - border-bottom-left-radius: var(--bs-border-radius-lg) !important; - border-top-left-radius: var(--bs-border-radius-lg) !important; } - -.rounded-start-4 { - border-bottom-left-radius: var(--bs-border-radius-xl) !important; - border-top-left-radius: var(--bs-border-radius-xl) !important; } - -.rounded-start-5 { - border-bottom-left-radius: var(--bs-border-radius-xxl) !important; - border-top-left-radius: var(--bs-border-radius-xxl) !important; } - -.rounded-start-circle { - border-bottom-left-radius: 50% !important; - border-top-left-radius: 50% !important; } - -.rounded-start-pill { - border-bottom-left-radius: var(--bs-border-radius-pill) !important; - border-top-left-radius: var(--bs-border-radius-pill) !important; } - -.visible { - visibility: visible !important; } - -.invisible { - visibility: hidden !important; } - -.z-n1 { - z-index: -1 !important; } - -.z-0 { - z-index: 0 !important; } - -.z-1 { - z-index: 1 !important; } - -.z-2 { - z-index: 2 !important; } - -.z-3 { - z-index: 3 !important; } - -@media (min-width: 576px) { - .float-sm-start { - float: left !important; } - .float-sm-end { - float: right !important; } - .float-sm-none { - float: none !important; } - .object-fit-sm-contain { - object-fit: contain !important; } - .object-fit-sm-cover { - object-fit: cover !important; } - .object-fit-sm-fill { - object-fit: fill !important; } - .object-fit-sm-scale { - object-fit: scale-down !important; } - .object-fit-sm-none { - object-fit: none !important; } - .d-sm-inline { - display: inline !important; } - .d-sm-inline-block { - display: inline-block !important; } - .d-sm-block { - display: block !important; } - .d-sm-grid { - display: grid !important; } - .d-sm-inline-grid { - display: inline-grid !important; } - .d-sm-table { - display: table !important; } - .d-sm-table-row { - display: table-row !important; } - .d-sm-table-cell { - display: table-cell !important; } - .d-sm-flex { - display: flex !important; } - .d-sm-inline-flex { - display: inline-flex !important; } - .d-sm-none { - display: none !important; } - .flex-sm-fill { - flex: 1 1 auto !important; } - .flex-sm-row { - flex-direction: row !important; } - .flex-sm-column { - flex-direction: column !important; } - .flex-sm-row-reverse { - flex-direction: row-reverse !important; } - .flex-sm-column-reverse { - flex-direction: column-reverse !important; } - .flex-sm-grow-0 { - flex-grow: 0 !important; } - .flex-sm-grow-1 { - flex-grow: 1 !important; } - .flex-sm-shrink-0 { - flex-shrink: 0 !important; } - .flex-sm-shrink-1 { - flex-shrink: 1 !important; } - .flex-sm-wrap { - flex-wrap: wrap !important; } - .flex-sm-nowrap { - flex-wrap: nowrap !important; } - .flex-sm-wrap-reverse { - flex-wrap: wrap-reverse !important; } - .justify-content-sm-start { - justify-content: flex-start !important; } - .justify-content-sm-end { - justify-content: flex-end !important; } - .justify-content-sm-center { - justify-content: center !important; } - .justify-content-sm-between { - justify-content: space-between !important; } - .justify-content-sm-around { - justify-content: space-around !important; } - .justify-content-sm-evenly { - justify-content: space-evenly !important; } - .align-items-sm-start { - align-items: flex-start !important; } - .align-items-sm-end { - align-items: flex-end !important; } - .align-items-sm-center { - align-items: center !important; } - .align-items-sm-baseline { - align-items: baseline !important; } - .align-items-sm-stretch { - align-items: stretch !important; } - .align-content-sm-start { - align-content: flex-start !important; } - .align-content-sm-end { - align-content: flex-end !important; } - .align-content-sm-center { - align-content: center !important; } - .align-content-sm-between { - align-content: space-between !important; } - .align-content-sm-around { - align-content: space-around !important; } - .align-content-sm-stretch { - align-content: stretch !important; } - .align-self-sm-auto { - align-self: auto !important; } - .align-self-sm-start { - align-self: flex-start !important; } - .align-self-sm-end { - align-self: flex-end !important; } - .align-self-sm-center { - align-self: center !important; } - .align-self-sm-baseline { - align-self: baseline !important; } - .align-self-sm-stretch { - align-self: stretch !important; } - .order-sm-first { - order: -1 !important; } - .order-sm-0 { - order: 0 !important; } - .order-sm-1 { - order: 1 !important; } - .order-sm-2 { - order: 2 !important; } - .order-sm-3 { - order: 3 !important; } - .order-sm-4 { - order: 4 !important; } - .order-sm-5 { - order: 5 !important; } - .order-sm-last { - order: 6 !important; } - .m-sm-0 { - margin: 0 !important; } - .m-sm-1 { - margin: 0.25rem !important; } - .m-sm-2 { - margin: 0.5rem !important; } - .m-sm-3 { - margin: 1rem !important; } - .m-sm-4 { - margin: 1.5rem !important; } - .m-sm-5 { - margin: 3rem !important; } - .m-sm-auto { - margin: auto !important; } - .mx-sm-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - .mx-sm-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - .mx-sm-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - .mx-sm-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - .mx-sm-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - .mx-sm-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - .mx-sm-auto { - margin-right: auto !important; - margin-left: auto !important; } - .my-sm-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; } - .my-sm-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; } - .my-sm-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; } - .my-sm-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; } - .my-sm-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - .my-sm-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; } - .my-sm-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - .mt-sm-0 { - margin-top: 0 !important; } - .mt-sm-1 { - margin-top: 0.25rem !important; } - .mt-sm-2 { - margin-top: 0.5rem !important; } - .mt-sm-3 { - margin-top: 1rem !important; } - .mt-sm-4 { - margin-top: 1.5rem !important; } - .mt-sm-5 { - margin-top: 3rem !important; } - .mt-sm-auto { - margin-top: auto !important; } - .me-sm-0 { - margin-right: 0 !important; } - .me-sm-1 { - margin-right: 0.25rem !important; } - .me-sm-2 { - margin-right: 0.5rem !important; } - .me-sm-3 { - margin-right: 1rem !important; } - .me-sm-4 { - margin-right: 1.5rem !important; } - .me-sm-5 { - margin-right: 3rem !important; } - .me-sm-auto { - margin-right: auto !important; } - .mb-sm-0 { - margin-bottom: 0 !important; } - .mb-sm-1 { - margin-bottom: 0.25rem !important; } - .mb-sm-2 { - margin-bottom: 0.5rem !important; } - .mb-sm-3 { - margin-bottom: 1rem !important; } - .mb-sm-4 { - margin-bottom: 1.5rem !important; } - .mb-sm-5 { - margin-bottom: 3rem !important; } - .mb-sm-auto { - margin-bottom: auto !important; } - .ms-sm-0 { - margin-left: 0 !important; } - .ms-sm-1 { - margin-left: 0.25rem !important; } - .ms-sm-2 { - margin-left: 0.5rem !important; } - .ms-sm-3 { - margin-left: 1rem !important; } - .ms-sm-4 { - margin-left: 1.5rem !important; } - .ms-sm-5 { - margin-left: 3rem !important; } - .ms-sm-auto { - margin-left: auto !important; } - .p-sm-0 { - padding: 0 !important; } - .p-sm-1 { - padding: 0.25rem !important; } - .p-sm-2 { - padding: 0.5rem !important; } - .p-sm-3 { - padding: 1rem !important; } - .p-sm-4 { - padding: 1.5rem !important; } - .p-sm-5 { - padding: 3rem !important; } - .px-sm-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - .px-sm-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - .px-sm-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - .px-sm-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - .px-sm-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - .px-sm-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - .py-sm-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - .py-sm-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - .py-sm-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - .py-sm-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - .py-sm-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - .py-sm-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - .pt-sm-0 { - padding-top: 0 !important; } - .pt-sm-1 { - padding-top: 0.25rem !important; } - .pt-sm-2 { - padding-top: 0.5rem !important; } - .pt-sm-3 { - padding-top: 1rem !important; } - .pt-sm-4 { - padding-top: 1.5rem !important; } - .pt-sm-5 { - padding-top: 3rem !important; } - .pe-sm-0 { - padding-right: 0 !important; } - .pe-sm-1 { - padding-right: 0.25rem !important; } - .pe-sm-2 { - padding-right: 0.5rem !important; } - .pe-sm-3 { - padding-right: 1rem !important; } - .pe-sm-4 { - padding-right: 1.5rem !important; } - .pe-sm-5 { - padding-right: 3rem !important; } - .pb-sm-0 { - padding-bottom: 0 !important; } - .pb-sm-1 { - padding-bottom: 0.25rem !important; } - .pb-sm-2 { - padding-bottom: 0.5rem !important; } - .pb-sm-3 { - padding-bottom: 1rem !important; } - .pb-sm-4 { - padding-bottom: 1.5rem !important; } - .pb-sm-5 { - padding-bottom: 3rem !important; } - .ps-sm-0 { - padding-left: 0 !important; } - .ps-sm-1 { - padding-left: 0.25rem !important; } - .ps-sm-2 { - padding-left: 0.5rem !important; } - .ps-sm-3 { - padding-left: 1rem !important; } - .ps-sm-4 { - padding-left: 1.5rem !important; } - .ps-sm-5 { - padding-left: 3rem !important; } - .gap-sm-0 { - gap: 0 !important; } - .gap-sm-1 { - gap: 0.25rem !important; } - .gap-sm-2 { - gap: 0.5rem !important; } - .gap-sm-3 { - gap: 1rem !important; } - .gap-sm-4 { - gap: 1.5rem !important; } - .gap-sm-5 { - gap: 3rem !important; } - .row-gap-sm-0 { - row-gap: 0 !important; } - .row-gap-sm-1 { - row-gap: 0.25rem !important; } - .row-gap-sm-2 { - row-gap: 0.5rem !important; } - .row-gap-sm-3 { - row-gap: 1rem !important; } - .row-gap-sm-4 { - row-gap: 1.5rem !important; } - .row-gap-sm-5 { - row-gap: 3rem !important; } - .column-gap-sm-0 { - column-gap: 0 !important; } - .column-gap-sm-1 { - column-gap: 0.25rem !important; } - .column-gap-sm-2 { - column-gap: 0.5rem !important; } - .column-gap-sm-3 { - column-gap: 1rem !important; } - .column-gap-sm-4 { - column-gap: 1.5rem !important; } - .column-gap-sm-5 { - column-gap: 3rem !important; } - .text-sm-start { - text-align: left !important; } - .text-sm-end { - text-align: right !important; } - .text-sm-center { - text-align: center !important; } } - -@media (min-width: 768px) { - .float-md-start { - float: left !important; } - .float-md-end { - float: right !important; } - .float-md-none { - float: none !important; } - .object-fit-md-contain { - object-fit: contain !important; } - .object-fit-md-cover { - object-fit: cover !important; } - .object-fit-md-fill { - object-fit: fill !important; } - .object-fit-md-scale { - object-fit: scale-down !important; } - .object-fit-md-none { - object-fit: none !important; } - .d-md-inline { - display: inline !important; } - .d-md-inline-block { - display: inline-block !important; } - .d-md-block { - display: block !important; } - .d-md-grid { - display: grid !important; } - .d-md-inline-grid { - display: inline-grid !important; } - .d-md-table { - display: table !important; } - .d-md-table-row { - display: table-row !important; } - .d-md-table-cell { - display: table-cell !important; } - .d-md-flex { - display: flex !important; } - .d-md-inline-flex { - display: inline-flex !important; } - .d-md-none { - display: none !important; } - .flex-md-fill { - flex: 1 1 auto !important; } - .flex-md-row { - flex-direction: row !important; } - .flex-md-column { - flex-direction: column !important; } - .flex-md-row-reverse { - flex-direction: row-reverse !important; } - .flex-md-column-reverse { - flex-direction: column-reverse !important; } - .flex-md-grow-0 { - flex-grow: 0 !important; } - .flex-md-grow-1 { - flex-grow: 1 !important; } - .flex-md-shrink-0 { - flex-shrink: 0 !important; } - .flex-md-shrink-1 { - flex-shrink: 1 !important; } - .flex-md-wrap { - flex-wrap: wrap !important; } - .flex-md-nowrap { - flex-wrap: nowrap !important; } - .flex-md-wrap-reverse { - flex-wrap: wrap-reverse !important; } - .justify-content-md-start { - justify-content: flex-start !important; } - .justify-content-md-end { - justify-content: flex-end !important; } - .justify-content-md-center { - justify-content: center !important; } - .justify-content-md-between { - justify-content: space-between !important; } - .justify-content-md-around { - justify-content: space-around !important; } - .justify-content-md-evenly { - justify-content: space-evenly !important; } - .align-items-md-start { - align-items: flex-start !important; } - .align-items-md-end { - align-items: flex-end !important; } - .align-items-md-center { - align-items: center !important; } - .align-items-md-baseline { - align-items: baseline !important; } - .align-items-md-stretch { - align-items: stretch !important; } - .align-content-md-start { - align-content: flex-start !important; } - .align-content-md-end { - align-content: flex-end !important; } - .align-content-md-center { - align-content: center !important; } - .align-content-md-between { - align-content: space-between !important; } - .align-content-md-around { - align-content: space-around !important; } - .align-content-md-stretch { - align-content: stretch !important; } - .align-self-md-auto { - align-self: auto !important; } - .align-self-md-start { - align-self: flex-start !important; } - .align-self-md-end { - align-self: flex-end !important; } - .align-self-md-center { - align-self: center !important; } - .align-self-md-baseline { - align-self: baseline !important; } - .align-self-md-stretch { - align-self: stretch !important; } - .order-md-first { - order: -1 !important; } - .order-md-0 { - order: 0 !important; } - .order-md-1 { - order: 1 !important; } - .order-md-2 { - order: 2 !important; } - .order-md-3 { - order: 3 !important; } - .order-md-4 { - order: 4 !important; } - .order-md-5 { - order: 5 !important; } - .order-md-last { - order: 6 !important; } - .m-md-0 { - margin: 0 !important; } - .m-md-1 { - margin: 0.25rem !important; } - .m-md-2 { - margin: 0.5rem !important; } - .m-md-3 { - margin: 1rem !important; } - .m-md-4 { - margin: 1.5rem !important; } - .m-md-5 { - margin: 3rem !important; } - .m-md-auto { - margin: auto !important; } - .mx-md-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - .mx-md-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - .mx-md-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - .mx-md-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - .mx-md-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - .mx-md-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - .mx-md-auto { - margin-right: auto !important; - margin-left: auto !important; } - .my-md-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; } - .my-md-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; } - .my-md-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; } - .my-md-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; } - .my-md-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - .my-md-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; } - .my-md-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - .mt-md-0 { - margin-top: 0 !important; } - .mt-md-1 { - margin-top: 0.25rem !important; } - .mt-md-2 { - margin-top: 0.5rem !important; } - .mt-md-3 { - margin-top: 1rem !important; } - .mt-md-4 { - margin-top: 1.5rem !important; } - .mt-md-5 { - margin-top: 3rem !important; } - .mt-md-auto { - margin-top: auto !important; } - .me-md-0 { - margin-right: 0 !important; } - .me-md-1 { - margin-right: 0.25rem !important; } - .me-md-2 { - margin-right: 0.5rem !important; } - .me-md-3 { - margin-right: 1rem !important; } - .me-md-4 { - margin-right: 1.5rem !important; } - .me-md-5 { - margin-right: 3rem !important; } - .me-md-auto { - margin-right: auto !important; } - .mb-md-0 { - margin-bottom: 0 !important; } - .mb-md-1 { - margin-bottom: 0.25rem !important; } - .mb-md-2 { - margin-bottom: 0.5rem !important; } - .mb-md-3 { - margin-bottom: 1rem !important; } - .mb-md-4 { - margin-bottom: 1.5rem !important; } - .mb-md-5 { - margin-bottom: 3rem !important; } - .mb-md-auto { - margin-bottom: auto !important; } - .ms-md-0 { - margin-left: 0 !important; } - .ms-md-1 { - margin-left: 0.25rem !important; } - .ms-md-2 { - margin-left: 0.5rem !important; } - .ms-md-3 { - margin-left: 1rem !important; } - .ms-md-4 { - margin-left: 1.5rem !important; } - .ms-md-5 { - margin-left: 3rem !important; } - .ms-md-auto { - margin-left: auto !important; } - .p-md-0 { - padding: 0 !important; } - .p-md-1 { - padding: 0.25rem !important; } - .p-md-2 { - padding: 0.5rem !important; } - .p-md-3 { - padding: 1rem !important; } - .p-md-4 { - padding: 1.5rem !important; } - .p-md-5 { - padding: 3rem !important; } - .px-md-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - .px-md-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - .px-md-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - .px-md-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - .px-md-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - .px-md-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - .py-md-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - .py-md-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - .py-md-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - .py-md-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - .py-md-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - .py-md-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - .pt-md-0 { - padding-top: 0 !important; } - .pt-md-1 { - padding-top: 0.25rem !important; } - .pt-md-2 { - padding-top: 0.5rem !important; } - .pt-md-3 { - padding-top: 1rem !important; } - .pt-md-4 { - padding-top: 1.5rem !important; } - .pt-md-5 { - padding-top: 3rem !important; } - .pe-md-0 { - padding-right: 0 !important; } - .pe-md-1 { - padding-right: 0.25rem !important; } - .pe-md-2 { - padding-right: 0.5rem !important; } - .pe-md-3 { - padding-right: 1rem !important; } - .pe-md-4 { - padding-right: 1.5rem !important; } - .pe-md-5 { - padding-right: 3rem !important; } - .pb-md-0 { - padding-bottom: 0 !important; } - .pb-md-1 { - padding-bottom: 0.25rem !important; } - .pb-md-2 { - padding-bottom: 0.5rem !important; } - .pb-md-3 { - padding-bottom: 1rem !important; } - .pb-md-4 { - padding-bottom: 1.5rem !important; } - .pb-md-5 { - padding-bottom: 3rem !important; } - .ps-md-0 { - padding-left: 0 !important; } - .ps-md-1 { - padding-left: 0.25rem !important; } - .ps-md-2 { - padding-left: 0.5rem !important; } - .ps-md-3 { - padding-left: 1rem !important; } - .ps-md-4 { - padding-left: 1.5rem !important; } - .ps-md-5 { - padding-left: 3rem !important; } - .gap-md-0 { - gap: 0 !important; } - .gap-md-1 { - gap: 0.25rem !important; } - .gap-md-2 { - gap: 0.5rem !important; } - .gap-md-3 { - gap: 1rem !important; } - .gap-md-4 { - gap: 1.5rem !important; } - .gap-md-5 { - gap: 3rem !important; } - .row-gap-md-0 { - row-gap: 0 !important; } - .row-gap-md-1 { - row-gap: 0.25rem !important; } - .row-gap-md-2 { - row-gap: 0.5rem !important; } - .row-gap-md-3 { - row-gap: 1rem !important; } - .row-gap-md-4 { - row-gap: 1.5rem !important; } - .row-gap-md-5 { - row-gap: 3rem !important; } - .column-gap-md-0 { - column-gap: 0 !important; } - .column-gap-md-1 { - column-gap: 0.25rem !important; } - .column-gap-md-2 { - column-gap: 0.5rem !important; } - .column-gap-md-3 { - column-gap: 1rem !important; } - .column-gap-md-4 { - column-gap: 1.5rem !important; } - .column-gap-md-5 { - column-gap: 3rem !important; } - .text-md-start { - text-align: left !important; } - .text-md-end { - text-align: right !important; } - .text-md-center { - text-align: center !important; } } - -@media (min-width: 992px) { - .float-lg-start { - float: left !important; } - .float-lg-end { - float: right !important; } - .float-lg-none { - float: none !important; } - .object-fit-lg-contain { - object-fit: contain !important; } - .object-fit-lg-cover { - object-fit: cover !important; } - .object-fit-lg-fill { - object-fit: fill !important; } - .object-fit-lg-scale { - object-fit: scale-down !important; } - .object-fit-lg-none { - object-fit: none !important; } - .d-lg-inline { - display: inline !important; } - .d-lg-inline-block { - display: inline-block !important; } - .d-lg-block { - display: block !important; } - .d-lg-grid { - display: grid !important; } - .d-lg-inline-grid { - display: inline-grid !important; } - .d-lg-table { - display: table !important; } - .d-lg-table-row { - display: table-row !important; } - .d-lg-table-cell { - display: table-cell !important; } - .d-lg-flex { - display: flex !important; } - .d-lg-inline-flex { - display: inline-flex !important; } - .d-lg-none { - display: none !important; } - .flex-lg-fill { - flex: 1 1 auto !important; } - .flex-lg-row { - flex-direction: row !important; } - .flex-lg-column { - flex-direction: column !important; } - .flex-lg-row-reverse { - flex-direction: row-reverse !important; } - .flex-lg-column-reverse { - flex-direction: column-reverse !important; } - .flex-lg-grow-0 { - flex-grow: 0 !important; } - .flex-lg-grow-1 { - flex-grow: 1 !important; } - .flex-lg-shrink-0 { - flex-shrink: 0 !important; } - .flex-lg-shrink-1 { - flex-shrink: 1 !important; } - .flex-lg-wrap { - flex-wrap: wrap !important; } - .flex-lg-nowrap { - flex-wrap: nowrap !important; } - .flex-lg-wrap-reverse { - flex-wrap: wrap-reverse !important; } - .justify-content-lg-start { - justify-content: flex-start !important; } - .justify-content-lg-end { - justify-content: flex-end !important; } - .justify-content-lg-center { - justify-content: center !important; } - .justify-content-lg-between { - justify-content: space-between !important; } - .justify-content-lg-around { - justify-content: space-around !important; } - .justify-content-lg-evenly { - justify-content: space-evenly !important; } - .align-items-lg-start { - align-items: flex-start !important; } - .align-items-lg-end { - align-items: flex-end !important; } - .align-items-lg-center { - align-items: center !important; } - .align-items-lg-baseline { - align-items: baseline !important; } - .align-items-lg-stretch { - align-items: stretch !important; } - .align-content-lg-start { - align-content: flex-start !important; } - .align-content-lg-end { - align-content: flex-end !important; } - .align-content-lg-center { - align-content: center !important; } - .align-content-lg-between { - align-content: space-between !important; } - .align-content-lg-around { - align-content: space-around !important; } - .align-content-lg-stretch { - align-content: stretch !important; } - .align-self-lg-auto { - align-self: auto !important; } - .align-self-lg-start { - align-self: flex-start !important; } - .align-self-lg-end { - align-self: flex-end !important; } - .align-self-lg-center { - align-self: center !important; } - .align-self-lg-baseline { - align-self: baseline !important; } - .align-self-lg-stretch { - align-self: stretch !important; } - .order-lg-first { - order: -1 !important; } - .order-lg-0 { - order: 0 !important; } - .order-lg-1 { - order: 1 !important; } - .order-lg-2 { - order: 2 !important; } - .order-lg-3 { - order: 3 !important; } - .order-lg-4 { - order: 4 !important; } - .order-lg-5 { - order: 5 !important; } - .order-lg-last { - order: 6 !important; } - .m-lg-0 { - margin: 0 !important; } - .m-lg-1 { - margin: 0.25rem !important; } - .m-lg-2 { - margin: 0.5rem !important; } - .m-lg-3 { - margin: 1rem !important; } - .m-lg-4 { - margin: 1.5rem !important; } - .m-lg-5 { - margin: 3rem !important; } - .m-lg-auto { - margin: auto !important; } - .mx-lg-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - .mx-lg-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - .mx-lg-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - .mx-lg-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - .mx-lg-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - .mx-lg-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - .mx-lg-auto { - margin-right: auto !important; - margin-left: auto !important; } - .my-lg-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; } - .my-lg-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; } - .my-lg-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; } - .my-lg-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; } - .my-lg-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - .my-lg-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; } - .my-lg-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - .mt-lg-0 { - margin-top: 0 !important; } - .mt-lg-1 { - margin-top: 0.25rem !important; } - .mt-lg-2 { - margin-top: 0.5rem !important; } - .mt-lg-3 { - margin-top: 1rem !important; } - .mt-lg-4 { - margin-top: 1.5rem !important; } - .mt-lg-5 { - margin-top: 3rem !important; } - .mt-lg-auto { - margin-top: auto !important; } - .me-lg-0 { - margin-right: 0 !important; } - .me-lg-1 { - margin-right: 0.25rem !important; } - .me-lg-2 { - margin-right: 0.5rem !important; } - .me-lg-3 { - margin-right: 1rem !important; } - .me-lg-4 { - margin-right: 1.5rem !important; } - .me-lg-5 { - margin-right: 3rem !important; } - .me-lg-auto { - margin-right: auto !important; } - .mb-lg-0 { - margin-bottom: 0 !important; } - .mb-lg-1 { - margin-bottom: 0.25rem !important; } - .mb-lg-2 { - margin-bottom: 0.5rem !important; } - .mb-lg-3 { - margin-bottom: 1rem !important; } - .mb-lg-4 { - margin-bottom: 1.5rem !important; } - .mb-lg-5 { - margin-bottom: 3rem !important; } - .mb-lg-auto { - margin-bottom: auto !important; } - .ms-lg-0 { - margin-left: 0 !important; } - .ms-lg-1 { - margin-left: 0.25rem !important; } - .ms-lg-2 { - margin-left: 0.5rem !important; } - .ms-lg-3 { - margin-left: 1rem !important; } - .ms-lg-4 { - margin-left: 1.5rem !important; } - .ms-lg-5 { - margin-left: 3rem !important; } - .ms-lg-auto { - margin-left: auto !important; } - .p-lg-0 { - padding: 0 !important; } - .p-lg-1 { - padding: 0.25rem !important; } - .p-lg-2 { - padding: 0.5rem !important; } - .p-lg-3 { - padding: 1rem !important; } - .p-lg-4 { - padding: 1.5rem !important; } - .p-lg-5 { - padding: 3rem !important; } - .px-lg-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - .px-lg-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - .px-lg-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - .px-lg-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - .px-lg-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - .px-lg-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - .py-lg-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - .py-lg-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - .py-lg-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - .py-lg-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - .py-lg-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - .py-lg-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - .pt-lg-0 { - padding-top: 0 !important; } - .pt-lg-1 { - padding-top: 0.25rem !important; } - .pt-lg-2 { - padding-top: 0.5rem !important; } - .pt-lg-3 { - padding-top: 1rem !important; } - .pt-lg-4 { - padding-top: 1.5rem !important; } - .pt-lg-5 { - padding-top: 3rem !important; } - .pe-lg-0 { - padding-right: 0 !important; } - .pe-lg-1 { - padding-right: 0.25rem !important; } - .pe-lg-2 { - padding-right: 0.5rem !important; } - .pe-lg-3 { - padding-right: 1rem !important; } - .pe-lg-4 { - padding-right: 1.5rem !important; } - .pe-lg-5 { - padding-right: 3rem !important; } - .pb-lg-0 { - padding-bottom: 0 !important; } - .pb-lg-1 { - padding-bottom: 0.25rem !important; } - .pb-lg-2 { - padding-bottom: 0.5rem !important; } - .pb-lg-3 { - padding-bottom: 1rem !important; } - .pb-lg-4 { - padding-bottom: 1.5rem !important; } - .pb-lg-5 { - padding-bottom: 3rem !important; } - .ps-lg-0 { - padding-left: 0 !important; } - .ps-lg-1 { - padding-left: 0.25rem !important; } - .ps-lg-2 { - padding-left: 0.5rem !important; } - .ps-lg-3 { - padding-left: 1rem !important; } - .ps-lg-4 { - padding-left: 1.5rem !important; } - .ps-lg-5 { - padding-left: 3rem !important; } - .gap-lg-0 { - gap: 0 !important; } - .gap-lg-1 { - gap: 0.25rem !important; } - .gap-lg-2 { - gap: 0.5rem !important; } - .gap-lg-3 { - gap: 1rem !important; } - .gap-lg-4 { - gap: 1.5rem !important; } - .gap-lg-5 { - gap: 3rem !important; } - .row-gap-lg-0 { - row-gap: 0 !important; } - .row-gap-lg-1 { - row-gap: 0.25rem !important; } - .row-gap-lg-2 { - row-gap: 0.5rem !important; } - .row-gap-lg-3 { - row-gap: 1rem !important; } - .row-gap-lg-4 { - row-gap: 1.5rem !important; } - .row-gap-lg-5 { - row-gap: 3rem !important; } - .column-gap-lg-0 { - column-gap: 0 !important; } - .column-gap-lg-1 { - column-gap: 0.25rem !important; } - .column-gap-lg-2 { - column-gap: 0.5rem !important; } - .column-gap-lg-3 { - column-gap: 1rem !important; } - .column-gap-lg-4 { - column-gap: 1.5rem !important; } - .column-gap-lg-5 { - column-gap: 3rem !important; } - .text-lg-start { - text-align: left !important; } - .text-lg-end { - text-align: right !important; } - .text-lg-center { - text-align: center !important; } } - -@media (min-width: 1200px) { - .float-xl-start { - float: left !important; } - .float-xl-end { - float: right !important; } - .float-xl-none { - float: none !important; } - .object-fit-xl-contain { - object-fit: contain !important; } - .object-fit-xl-cover { - object-fit: cover !important; } - .object-fit-xl-fill { - object-fit: fill !important; } - .object-fit-xl-scale { - object-fit: scale-down !important; } - .object-fit-xl-none { - object-fit: none !important; } - .d-xl-inline { - display: inline !important; } - .d-xl-inline-block { - display: inline-block !important; } - .d-xl-block { - display: block !important; } - .d-xl-grid { - display: grid !important; } - .d-xl-inline-grid { - display: inline-grid !important; } - .d-xl-table { - display: table !important; } - .d-xl-table-row { - display: table-row !important; } - .d-xl-table-cell { - display: table-cell !important; } - .d-xl-flex { - display: flex !important; } - .d-xl-inline-flex { - display: inline-flex !important; } - .d-xl-none { - display: none !important; } - .flex-xl-fill { - flex: 1 1 auto !important; } - .flex-xl-row { - flex-direction: row !important; } - .flex-xl-column { - flex-direction: column !important; } - .flex-xl-row-reverse { - flex-direction: row-reverse !important; } - .flex-xl-column-reverse { - flex-direction: column-reverse !important; } - .flex-xl-grow-0 { - flex-grow: 0 !important; } - .flex-xl-grow-1 { - flex-grow: 1 !important; } - .flex-xl-shrink-0 { - flex-shrink: 0 !important; } - .flex-xl-shrink-1 { - flex-shrink: 1 !important; } - .flex-xl-wrap { - flex-wrap: wrap !important; } - .flex-xl-nowrap { - flex-wrap: nowrap !important; } - .flex-xl-wrap-reverse { - flex-wrap: wrap-reverse !important; } - .justify-content-xl-start { - justify-content: flex-start !important; } - .justify-content-xl-end { - justify-content: flex-end !important; } - .justify-content-xl-center { - justify-content: center !important; } - .justify-content-xl-between { - justify-content: space-between !important; } - .justify-content-xl-around { - justify-content: space-around !important; } - .justify-content-xl-evenly { - justify-content: space-evenly !important; } - .align-items-xl-start { - align-items: flex-start !important; } - .align-items-xl-end { - align-items: flex-end !important; } - .align-items-xl-center { - align-items: center !important; } - .align-items-xl-baseline { - align-items: baseline !important; } - .align-items-xl-stretch { - align-items: stretch !important; } - .align-content-xl-start { - align-content: flex-start !important; } - .align-content-xl-end { - align-content: flex-end !important; } - .align-content-xl-center { - align-content: center !important; } - .align-content-xl-between { - align-content: space-between !important; } - .align-content-xl-around { - align-content: space-around !important; } - .align-content-xl-stretch { - align-content: stretch !important; } - .align-self-xl-auto { - align-self: auto !important; } - .align-self-xl-start { - align-self: flex-start !important; } - .align-self-xl-end { - align-self: flex-end !important; } - .align-self-xl-center { - align-self: center !important; } - .align-self-xl-baseline { - align-self: baseline !important; } - .align-self-xl-stretch { - align-self: stretch !important; } - .order-xl-first { - order: -1 !important; } - .order-xl-0 { - order: 0 !important; } - .order-xl-1 { - order: 1 !important; } - .order-xl-2 { - order: 2 !important; } - .order-xl-3 { - order: 3 !important; } - .order-xl-4 { - order: 4 !important; } - .order-xl-5 { - order: 5 !important; } - .order-xl-last { - order: 6 !important; } - .m-xl-0 { - margin: 0 !important; } - .m-xl-1 { - margin: 0.25rem !important; } - .m-xl-2 { - margin: 0.5rem !important; } - .m-xl-3 { - margin: 1rem !important; } - .m-xl-4 { - margin: 1.5rem !important; } - .m-xl-5 { - margin: 3rem !important; } - .m-xl-auto { - margin: auto !important; } - .mx-xl-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - .mx-xl-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - .mx-xl-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - .mx-xl-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - .mx-xl-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - .mx-xl-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - .mx-xl-auto { - margin-right: auto !important; - margin-left: auto !important; } - .my-xl-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; } - .my-xl-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; } - .my-xl-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; } - .my-xl-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; } - .my-xl-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - .my-xl-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; } - .my-xl-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - .mt-xl-0 { - margin-top: 0 !important; } - .mt-xl-1 { - margin-top: 0.25rem !important; } - .mt-xl-2 { - margin-top: 0.5rem !important; } - .mt-xl-3 { - margin-top: 1rem !important; } - .mt-xl-4 { - margin-top: 1.5rem !important; } - .mt-xl-5 { - margin-top: 3rem !important; } - .mt-xl-auto { - margin-top: auto !important; } - .me-xl-0 { - margin-right: 0 !important; } - .me-xl-1 { - margin-right: 0.25rem !important; } - .me-xl-2 { - margin-right: 0.5rem !important; } - .me-xl-3 { - margin-right: 1rem !important; } - .me-xl-4 { - margin-right: 1.5rem !important; } - .me-xl-5 { - margin-right: 3rem !important; } - .me-xl-auto { - margin-right: auto !important; } - .mb-xl-0 { - margin-bottom: 0 !important; } - .mb-xl-1 { - margin-bottom: 0.25rem !important; } - .mb-xl-2 { - margin-bottom: 0.5rem !important; } - .mb-xl-3 { - margin-bottom: 1rem !important; } - .mb-xl-4 { - margin-bottom: 1.5rem !important; } - .mb-xl-5 { - margin-bottom: 3rem !important; } - .mb-xl-auto { - margin-bottom: auto !important; } - .ms-xl-0 { - margin-left: 0 !important; } - .ms-xl-1 { - margin-left: 0.25rem !important; } - .ms-xl-2 { - margin-left: 0.5rem !important; } - .ms-xl-3 { - margin-left: 1rem !important; } - .ms-xl-4 { - margin-left: 1.5rem !important; } - .ms-xl-5 { - margin-left: 3rem !important; } - .ms-xl-auto { - margin-left: auto !important; } - .p-xl-0 { - padding: 0 !important; } - .p-xl-1 { - padding: 0.25rem !important; } - .p-xl-2 { - padding: 0.5rem !important; } - .p-xl-3 { - padding: 1rem !important; } - .p-xl-4 { - padding: 1.5rem !important; } - .p-xl-5 { - padding: 3rem !important; } - .px-xl-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - .px-xl-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - .px-xl-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - .px-xl-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - .px-xl-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - .px-xl-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - .py-xl-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - .py-xl-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - .py-xl-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - .py-xl-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - .py-xl-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - .py-xl-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - .pt-xl-0 { - padding-top: 0 !important; } - .pt-xl-1 { - padding-top: 0.25rem !important; } - .pt-xl-2 { - padding-top: 0.5rem !important; } - .pt-xl-3 { - padding-top: 1rem !important; } - .pt-xl-4 { - padding-top: 1.5rem !important; } - .pt-xl-5 { - padding-top: 3rem !important; } - .pe-xl-0 { - padding-right: 0 !important; } - .pe-xl-1 { - padding-right: 0.25rem !important; } - .pe-xl-2 { - padding-right: 0.5rem !important; } - .pe-xl-3 { - padding-right: 1rem !important; } - .pe-xl-4 { - padding-right: 1.5rem !important; } - .pe-xl-5 { - padding-right: 3rem !important; } - .pb-xl-0 { - padding-bottom: 0 !important; } - .pb-xl-1 { - padding-bottom: 0.25rem !important; } - .pb-xl-2 { - padding-bottom: 0.5rem !important; } - .pb-xl-3 { - padding-bottom: 1rem !important; } - .pb-xl-4 { - padding-bottom: 1.5rem !important; } - .pb-xl-5 { - padding-bottom: 3rem !important; } - .ps-xl-0 { - padding-left: 0 !important; } - .ps-xl-1 { - padding-left: 0.25rem !important; } - .ps-xl-2 { - padding-left: 0.5rem !important; } - .ps-xl-3 { - padding-left: 1rem !important; } - .ps-xl-4 { - padding-left: 1.5rem !important; } - .ps-xl-5 { - padding-left: 3rem !important; } - .gap-xl-0 { - gap: 0 !important; } - .gap-xl-1 { - gap: 0.25rem !important; } - .gap-xl-2 { - gap: 0.5rem !important; } - .gap-xl-3 { - gap: 1rem !important; } - .gap-xl-4 { - gap: 1.5rem !important; } - .gap-xl-5 { - gap: 3rem !important; } - .row-gap-xl-0 { - row-gap: 0 !important; } - .row-gap-xl-1 { - row-gap: 0.25rem !important; } - .row-gap-xl-2 { - row-gap: 0.5rem !important; } - .row-gap-xl-3 { - row-gap: 1rem !important; } - .row-gap-xl-4 { - row-gap: 1.5rem !important; } - .row-gap-xl-5 { - row-gap: 3rem !important; } - .column-gap-xl-0 { - column-gap: 0 !important; } - .column-gap-xl-1 { - column-gap: 0.25rem !important; } - .column-gap-xl-2 { - column-gap: 0.5rem !important; } - .column-gap-xl-3 { - column-gap: 1rem !important; } - .column-gap-xl-4 { - column-gap: 1.5rem !important; } - .column-gap-xl-5 { - column-gap: 3rem !important; } - .text-xl-start { - text-align: left !important; } - .text-xl-end { - text-align: right !important; } - .text-xl-center { - text-align: center !important; } } - -@media (min-width: 1400px) { - .float-xxl-start { - float: left !important; } - .float-xxl-end { - float: right !important; } - .float-xxl-none { - float: none !important; } - .object-fit-xxl-contain { - object-fit: contain !important; } - .object-fit-xxl-cover { - object-fit: cover !important; } - .object-fit-xxl-fill { - object-fit: fill !important; } - .object-fit-xxl-scale { - object-fit: scale-down !important; } - .object-fit-xxl-none { - object-fit: none !important; } - .d-xxl-inline { - display: inline !important; } - .d-xxl-inline-block { - display: inline-block !important; } - .d-xxl-block { - display: block !important; } - .d-xxl-grid { - display: grid !important; } - .d-xxl-inline-grid { - display: inline-grid !important; } - .d-xxl-table { - display: table !important; } - .d-xxl-table-row { - display: table-row !important; } - .d-xxl-table-cell { - display: table-cell !important; } - .d-xxl-flex { - display: flex !important; } - .d-xxl-inline-flex { - display: inline-flex !important; } - .d-xxl-none { - display: none !important; } - .flex-xxl-fill { - flex: 1 1 auto !important; } - .flex-xxl-row { - flex-direction: row !important; } - .flex-xxl-column { - flex-direction: column !important; } - .flex-xxl-row-reverse { - flex-direction: row-reverse !important; } - .flex-xxl-column-reverse { - flex-direction: column-reverse !important; } - .flex-xxl-grow-0 { - flex-grow: 0 !important; } - .flex-xxl-grow-1 { - flex-grow: 1 !important; } - .flex-xxl-shrink-0 { - flex-shrink: 0 !important; } - .flex-xxl-shrink-1 { - flex-shrink: 1 !important; } - .flex-xxl-wrap { - flex-wrap: wrap !important; } - .flex-xxl-nowrap { - flex-wrap: nowrap !important; } - .flex-xxl-wrap-reverse { - flex-wrap: wrap-reverse !important; } - .justify-content-xxl-start { - justify-content: flex-start !important; } - .justify-content-xxl-end { - justify-content: flex-end !important; } - .justify-content-xxl-center { - justify-content: center !important; } - .justify-content-xxl-between { - justify-content: space-between !important; } - .justify-content-xxl-around { - justify-content: space-around !important; } - .justify-content-xxl-evenly { - justify-content: space-evenly !important; } - .align-items-xxl-start { - align-items: flex-start !important; } - .align-items-xxl-end { - align-items: flex-end !important; } - .align-items-xxl-center { - align-items: center !important; } - .align-items-xxl-baseline { - align-items: baseline !important; } - .align-items-xxl-stretch { - align-items: stretch !important; } - .align-content-xxl-start { - align-content: flex-start !important; } - .align-content-xxl-end { - align-content: flex-end !important; } - .align-content-xxl-center { - align-content: center !important; } - .align-content-xxl-between { - align-content: space-between !important; } - .align-content-xxl-around { - align-content: space-around !important; } - .align-content-xxl-stretch { - align-content: stretch !important; } - .align-self-xxl-auto { - align-self: auto !important; } - .align-self-xxl-start { - align-self: flex-start !important; } - .align-self-xxl-end { - align-self: flex-end !important; } - .align-self-xxl-center { - align-self: center !important; } - .align-self-xxl-baseline { - align-self: baseline !important; } - .align-self-xxl-stretch { - align-self: stretch !important; } - .order-xxl-first { - order: -1 !important; } - .order-xxl-0 { - order: 0 !important; } - .order-xxl-1 { - order: 1 !important; } - .order-xxl-2 { - order: 2 !important; } - .order-xxl-3 { - order: 3 !important; } - .order-xxl-4 { - order: 4 !important; } - .order-xxl-5 { - order: 5 !important; } - .order-xxl-last { - order: 6 !important; } - .m-xxl-0 { - margin: 0 !important; } - .m-xxl-1 { - margin: 0.25rem !important; } - .m-xxl-2 { - margin: 0.5rem !important; } - .m-xxl-3 { - margin: 1rem !important; } - .m-xxl-4 { - margin: 1.5rem !important; } - .m-xxl-5 { - margin: 3rem !important; } - .m-xxl-auto { - margin: auto !important; } - .mx-xxl-0 { - margin-right: 0 !important; - margin-left: 0 !important; } - .mx-xxl-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; } - .mx-xxl-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; } - .mx-xxl-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; } - .mx-xxl-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; } - .mx-xxl-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; } - .mx-xxl-auto { - margin-right: auto !important; - margin-left: auto !important; } - .my-xxl-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; } - .my-xxl-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; } - .my-xxl-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; } - .my-xxl-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; } - .my-xxl-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; } - .my-xxl-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; } - .my-xxl-auto { - margin-top: auto !important; - margin-bottom: auto !important; } - .mt-xxl-0 { - margin-top: 0 !important; } - .mt-xxl-1 { - margin-top: 0.25rem !important; } - .mt-xxl-2 { - margin-top: 0.5rem !important; } - .mt-xxl-3 { - margin-top: 1rem !important; } - .mt-xxl-4 { - margin-top: 1.5rem !important; } - .mt-xxl-5 { - margin-top: 3rem !important; } - .mt-xxl-auto { - margin-top: auto !important; } - .me-xxl-0 { - margin-right: 0 !important; } - .me-xxl-1 { - margin-right: 0.25rem !important; } - .me-xxl-2 { - margin-right: 0.5rem !important; } - .me-xxl-3 { - margin-right: 1rem !important; } - .me-xxl-4 { - margin-right: 1.5rem !important; } - .me-xxl-5 { - margin-right: 3rem !important; } - .me-xxl-auto { - margin-right: auto !important; } - .mb-xxl-0 { - margin-bottom: 0 !important; } - .mb-xxl-1 { - margin-bottom: 0.25rem !important; } - .mb-xxl-2 { - margin-bottom: 0.5rem !important; } - .mb-xxl-3 { - margin-bottom: 1rem !important; } - .mb-xxl-4 { - margin-bottom: 1.5rem !important; } - .mb-xxl-5 { - margin-bottom: 3rem !important; } - .mb-xxl-auto { - margin-bottom: auto !important; } - .ms-xxl-0 { - margin-left: 0 !important; } - .ms-xxl-1 { - margin-left: 0.25rem !important; } - .ms-xxl-2 { - margin-left: 0.5rem !important; } - .ms-xxl-3 { - margin-left: 1rem !important; } - .ms-xxl-4 { - margin-left: 1.5rem !important; } - .ms-xxl-5 { - margin-left: 3rem !important; } - .ms-xxl-auto { - margin-left: auto !important; } - .p-xxl-0 { - padding: 0 !important; } - .p-xxl-1 { - padding: 0.25rem !important; } - .p-xxl-2 { - padding: 0.5rem !important; } - .p-xxl-3 { - padding: 1rem !important; } - .p-xxl-4 { - padding: 1.5rem !important; } - .p-xxl-5 { - padding: 3rem !important; } - .px-xxl-0 { - padding-right: 0 !important; - padding-left: 0 !important; } - .px-xxl-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; } - .px-xxl-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; } - .px-xxl-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; } - .px-xxl-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; } - .px-xxl-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; } - .py-xxl-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; } - .py-xxl-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; } - .py-xxl-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; } - .py-xxl-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; } - .py-xxl-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; } - .py-xxl-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; } - .pt-xxl-0 { - padding-top: 0 !important; } - .pt-xxl-1 { - padding-top: 0.25rem !important; } - .pt-xxl-2 { - padding-top: 0.5rem !important; } - .pt-xxl-3 { - padding-top: 1rem !important; } - .pt-xxl-4 { - padding-top: 1.5rem !important; } - .pt-xxl-5 { - padding-top: 3rem !important; } - .pe-xxl-0 { - padding-right: 0 !important; } - .pe-xxl-1 { - padding-right: 0.25rem !important; } - .pe-xxl-2 { - padding-right: 0.5rem !important; } - .pe-xxl-3 { - padding-right: 1rem !important; } - .pe-xxl-4 { - padding-right: 1.5rem !important; } - .pe-xxl-5 { - padding-right: 3rem !important; } - .pb-xxl-0 { - padding-bottom: 0 !important; } - .pb-xxl-1 { - padding-bottom: 0.25rem !important; } - .pb-xxl-2 { - padding-bottom: 0.5rem !important; } - .pb-xxl-3 { - padding-bottom: 1rem !important; } - .pb-xxl-4 { - padding-bottom: 1.5rem !important; } - .pb-xxl-5 { - padding-bottom: 3rem !important; } - .ps-xxl-0 { - padding-left: 0 !important; } - .ps-xxl-1 { - padding-left: 0.25rem !important; } - .ps-xxl-2 { - padding-left: 0.5rem !important; } - .ps-xxl-3 { - padding-left: 1rem !important; } - .ps-xxl-4 { - padding-left: 1.5rem !important; } - .ps-xxl-5 { - padding-left: 3rem !important; } - .gap-xxl-0 { - gap: 0 !important; } - .gap-xxl-1 { - gap: 0.25rem !important; } - .gap-xxl-2 { - gap: 0.5rem !important; } - .gap-xxl-3 { - gap: 1rem !important; } - .gap-xxl-4 { - gap: 1.5rem !important; } - .gap-xxl-5 { - gap: 3rem !important; } - .row-gap-xxl-0 { - row-gap: 0 !important; } - .row-gap-xxl-1 { - row-gap: 0.25rem !important; } - .row-gap-xxl-2 { - row-gap: 0.5rem !important; } - .row-gap-xxl-3 { - row-gap: 1rem !important; } - .row-gap-xxl-4 { - row-gap: 1.5rem !important; } - .row-gap-xxl-5 { - row-gap: 3rem !important; } - .column-gap-xxl-0 { - column-gap: 0 !important; } - .column-gap-xxl-1 { - column-gap: 0.25rem !important; } - .column-gap-xxl-2 { - column-gap: 0.5rem !important; } - .column-gap-xxl-3 { - column-gap: 1rem !important; } - .column-gap-xxl-4 { - column-gap: 1.5rem !important; } - .column-gap-xxl-5 { - column-gap: 3rem !important; } - .text-xxl-start { - text-align: left !important; } - .text-xxl-end { - text-align: right !important; } - .text-xxl-center { - text-align: center !important; } } - -@media (min-width: 1200px) { - .fs-1 { - font-size: 2.5rem !important; } - .fs-2 { - font-size: 2rem !important; } - .fs-3 { - font-size: 1.75rem !important; } - .fs-4 { - font-size: 1.5rem !important; } } - -@media print { - .d-print-inline { - display: inline !important; } - .d-print-inline-block { - display: inline-block !important; } - .d-print-block { - display: block !important; } - .d-print-grid { - display: grid !important; } - .d-print-inline-grid { - display: inline-grid !important; } - .d-print-table { - display: table !important; } - .d-print-table-row { - display: table-row !important; } - .d-print-table-cell { - display: table-cell !important; } - .d-print-flex { - display: flex !important; } - .d-print-inline-flex { - display: inline-flex !important; } - .d-print-none { - display: none !important; } } - -html { - font-family: "Poppins", sans-serif; - font-size: 1.125rem; - font-weight: 400; - line-height: 1.75; - scroll-behavior: smooth; } - @media (max-width: 991px) { - html { - font-size: 1rem; } } -body { - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; } - -p { - margin-bottom: 0.25rem; } - -ul { - margin-bottom: 0; } - -a, -a:hover, -a:focus { - text-decoration: none; } - -a, -button, -select { - cursor: pointer; - transition: 0.2s ease; } - a:focus, - button:focus, - select:focus { - outline: 0; } - -a:hover { - color: #18b0a2; } - -h1, .h1, -h2, -.h2, -h3, -.h3, -h4, -.h4, -h5, -.h5, -h6, -.h6 { - font-family: "Poppins", sans-serif; - font-weight: 700; - color: #fff; } - -small, -.small { - font-size: 85%; } - -h6, -.h6 { - font-size: 20.16px; - line-height: calc(2px + 2ex + 2px); - margin-bottom: 0.65em; } - @media (max-width: 991px) { - h6:not(h5, .h5, h6, .h6), - .h6:not(h5, .h5, h6, .h6) { - font-size: calc(20.16px * 0.9); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h6:not(h5, .h5, h6, .h6), - .h6:not(h5, .h5, h6, .h6) { - font-size: calc(20.16px * 0.8); } } - @media (max-width: 991px) { - h6, - .h6 { - font-size: calc(20.16px * 0.95); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h6, - .h6 { - font-size: calc(20.16px * 0.9); } } -h5, -.h5 { - font-size: 25.4016px; - line-height: calc(2px + 2ex + 2px); - margin-bottom: 0.65em; } - @media (max-width: 991px) { - h5:not(h5, .h5, h6, .h6), - .h5:not(h5, .h5, h6, .h6) { - font-size: calc(25.4016px * 0.9); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h5:not(h5, .h5, h6, .h6), - .h5:not(h5, .h5, h6, .h6) { - font-size: calc(25.4016px * 0.8); } } - @media (max-width: 991px) { - h5, - .h5 { - font-size: calc(25.4016px * 0.95); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h5, - .h5 { - font-size: calc(25.4016px * 0.9); } } -h4, -.h4 { - font-size: 32.006016px; - line-height: calc(2px + 2ex + 2px); - margin-bottom: 0.65em; } - @media (max-width: 991px) { - h4:not(h5, .h5, h6, .h6), - .h4:not(h5, .h5, h6, .h6) { - font-size: calc(32.006016px * 0.9); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h4:not(h5, .h5, h6, .h6), - .h4:not(h5, .h5, h6, .h6) { - font-size: calc(32.006016px * 0.8); } } - @media (max-width: 991px) { - h4, - .h4 { - font-size: calc(32.006016px * 0.95); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h4, - .h4 { - font-size: calc(32.006016px * 0.9); } } -h3, -.h3 { - font-size: 40.32758016px; - line-height: calc(2px + 2ex + 2px); - margin-bottom: 0.65em; } - @media (max-width: 991px) { - h3:not(h5, .h5, h6, .h6), - .h3:not(h5, .h5, h6, .h6) { - font-size: calc(40.32758016px * 0.9); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h3:not(h5, .h5, h6, .h6), - .h3:not(h5, .h5, h6, .h6) { - font-size: calc(40.32758016px * 0.8); } } - @media (max-width: 991px) { - h3, - .h3 { - font-size: calc(40.32758016px * 0.95); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h3, - .h3 { - font-size: calc(40.32758016px * 0.9); } } -h2, -.h2 { - font-size: 50.812751px; - line-height: calc(2px + 2ex + 2px); - margin-bottom: 0.65em; } - @media (max-width: 991px) { - h2:not(h5, .h5, h6, .h6), - .h2:not(h5, .h5, h6, .h6) { - font-size: calc(50.812751px * 0.9); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h2:not(h5, .h5, h6, .h6), - .h2:not(h5, .h5, h6, .h6) { - font-size: calc(50.812751px * 0.8); } } - @media (max-width: 991px) { - h2, - .h2 { - font-size: calc(50.812751px * 0.95); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h2, - .h2 { - font-size: calc(50.812751px * 0.9); } } -h1, -.h1 { - font-size: 64.02406626px; - line-height: calc(2px + 2ex + 2px); - margin-bottom: 0.65em; } - @media (max-width: 991px) { - h1:not(h5, .h5, h6, .h6), - .h1:not(h5, .h5, h6, .h6) { - font-size: calc(64.02406626px * 0.9); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h1:not(h5, .h5, h6, .h6), - .h1:not(h5, .h5, h6, .h6) { - font-size: calc(64.02406626px * 0.8); } } - @media (max-width: 991px) { - h1, - .h1 { - font-size: calc(64.02406626px * 0.95); - margin-bottom: 0.55em; } } - @media (max-width: 767px) { - h1, - .h1 { - font-size: calc(64.02406626px * 0.9); } } -html.light { - color: #555; } - html.light h1, html.light .h1, - html.light h2, - html.light .h2, - html.light h3, - html.light .h3, - html.light h4, - html.light .h4, - html.light h5, - html.light .h5, - html.light h6, - html.light .h6 { - color: #222222; } - -/* Button style */ -.btn { - font-size: 0.9rem; - padding: 0.7rem 1.25rem; - position: relative; - overflow: hidden; - z-index: 1; - transition: 0.3s; } - .btn:hover, .btn:active, .btn.active, .btn:focus, .btn.focus { - outline: 0; - box-shadow: none !important; - background-color: transparent !important; } - -.btn-primary { - color: #fff; - border-color: #18b0a2 !important; - background-color: #18b0a2; } - .btn-primary:hover, .btn-primary:active, .btn-primary.active, .btn-primary:focus, .btn-primary.focus { - color: #fff; - border-color: #18b0a2 !important; - background-color: #18b0a2 !important; } - .btn-primary:hover::before, .btn-primary:active::before, .btn-primary.active::before, .btn-primary:focus::before, .btn-primary.focus::before { - height: 200%; - bottom: -25px; } - .btn-primary::before { - content: ""; - width: 100%; - height: 100%; - position: absolute; - bottom: -70px; - left: 0; - z-index: -1; - transition: 0.35s cubic-bezier(0.65, 0.05, 0.36, 1); - background-color: rgba(25, 31, 39, 0.2); - transform: skewY(10deg); } - -.btn-outline-primary { - background-color: transparent; - color: #18b0a2; - border-color: rgba(24, 176, 162, 0.2) !important; } - .btn-outline-primary:hover, .btn-outline-primary:active, .btn-outline-primary.active, .btn-outline-primary:focus, .btn-outline-primary.focus { - color: #18b0a2 !important; - border-color: rgba(24, 176, 162, 0.4) !important; } - .btn-outline-primary:hover::before, .btn-outline-primary:active::before, .btn-outline-primary.active::before, .btn-outline-primary:focus::before, .btn-outline-primary.focus::before { - height: 200%; - bottom: -25px; } - .btn-outline-primary::before { - content: ""; - width: 100%; - height: 100%; - position: absolute; - bottom: -70px; - left: 0; - z-index: -1; - transition: 0.35s cubic-bezier(0.65, 0.05, 0.36, 1); - background-color: rgba(24, 176, 162, 0.1); - transform: skewY(10deg); } - -.dark { - color-scheme: dark; } - -.light { - color-scheme: light; } - -::-webkit-scrollbar { - width: 10px; } - -::-webkit-scrollbar-track { - background: transparent; } - -::-webkit-scrollbar-thumb { - background: #313847; - border-radius: 8px; } - -::-webkit-scrollbar-thumb:hover { - background: #3f4759; } - -.dark body { - color: #bbb; - background-color: #0e1015; } - -.light body { - color: #555 !important; - background-color: #FFFFFF; } - -main { - width: calc(100% - 320px); - margin-left: auto; } - @media (max-width: 1199px) { - main { - width: 100%; } } - @media (max-width: 991px) { - main { - width: auto; } } -footer { - padding-top: 2rem; } - -.section { - padding-top: 4rem; - padding-bottom: 4rem; } - @media (max-width: 767px) { - .section { - padding-top: 3rem; - padding-bottom: 3rem; } } -.section-title { - margin-bottom: 4rem; } - @media (max-width: 767px) { - .section-title { - margin-bottom: 2.5rem; } } - .section-title h1 strong, .section-title .h1 strong, - .section-title h2 strong, - .section-title .h2 strong, - .section-title h3 strong, - .section-title .h3 strong { - color: #18b0a2; } - .section-title h2, .section-title .h2 { - margin: auto; - width: fit-content; - text-align: center; - position: relative; - font-weight: 500; } - @media (max-width: 767px) { - .section-title h2, .section-title .h2 { - padding-left: 40px; - font-size: 1.6rem !important; - text-align: start; - margin: 0; } } - .section-title h2::before, .section-title .h2::before, .section-title h2::after, .section-title .h2::after { - content: "⭓"; - font-weight: bold; - position: absolute; - color: #18b0a2; - letter-spacing: 2px; - left: -55px; - top: 50%; - line-height: 0; - font-size: 85%; } - @media (max-width: 767px) { - .section-title h2::before, .section-title .h2::before, .section-title h2::after, .section-title .h2::after { - left: 0; } } - .section-title h2::after, .section-title .h2::after { - left: auto; - right: -55px; } - @media (max-width: 767px) { - .section-title h2::after, .section-title .h2::after { - display: none; } } - .section-title .sub-title { - font-size: 1rem; - padding: 20px 0px; - margin-top: 10px; - text-align: center; } - @media (max-width: 575px) { - .section-title .sub-title { - text-align: start; } } -.social-links a { - width: 40px; - height: 40px; - line-height: 40px; - text-align: center; - background-color: transparent !important; - color: #eee !important; - border: 1px solid rgba(24, 176, 162, 0.15) !important; - transition: all 0.3s; } - .social-links a:hover { - background-color: #18b0a2 !important; - color: #fff !important; - border-color: transparent !important; } - -.light .social-links a { - color: #222 !important; } - .light .social-links a:hover { - color: #fff !important; } - -.fw-medium { - font-weight: 500; } - -.bg-dark { - background-color: #151923 !important; } - -.text-primary { - color: #18b0a2 !important; } - -.bg-primary { - background-color: #18b0a2 !important; } - -.bg-primary-soft { - background-color: rgba(24, 176, 162, 0.2) !important; } - -.light .text-white { - color: #222 !important; } - -.light .bg-primary-soft { - background-color: rgba(24, 176, 162, 0.1) !important; } - -.light .bg-dark { - background-color: #f6f6f6 !important; } - -.form-control { - padding: 0.6rem 1rem !important; - color: #fff !important; - border: 1px solid rgba(24, 176, 162, 0.15) !important; - box-shadow: none !important; - background-color: #191f27 !important; } - .form-control:focus { - border-color: rgba(24, 176, 162, 0.8) !important; } - -.light .form-control { - color: #222 !important; - background-color: #eee !important; } - -textarea { - resize: none; } - -.back-to-top { - position: fixed; - right: 25px; - bottom: 15px; - width: 46px; - height: 46px; - z-index: 50; - visibility: visible; - transform: translateY(30px); - transition: all 0.2s ease-out; - background-color: rgba(255, 255, 255, 0.1); - opacity: 0; - color: #fff; } - @media (max-width: 991px) { - .back-to-top { - background-color: #18b0a2; } } - @media (max-width: 767px) { - .back-to-top { - right: 10px; } } - .back-to-top.active { - transform: translateY(-10px); - opacity: 1; } - .back-to-top:hover { - background-color: rgba(24, 176, 162, 0.15) !important; } - -.light .back-to-top { - background-color: rgba(34, 34, 34, 0.1); - color: #222; } - @media (max-width: 991px) { - .light .back-to-top { - color: #fff; - background-color: #18b0a2; } } -.content h1, -.content .h1, -.content h2, -.content .h2, -.content h3, -.content .h3, -.content h4, -.content .h4, -.content h5, -.content .h5, -.content h6, -.content .h6 { - font-weight: 400; } - -.content p { - margin-bottom: 1rem !important; } - -.content a { - color: #959595; } - .content a:hover { - color: #18b0a2; } - -.content img { - border-radius: 6px; } - -.content ol, -.content ul { - padding-left: 1.5rem; } - .content ol li, - .content ul li { - margin-bottom: 0.7rem; } - -.content ul { - padding-left: 0; - margin-bottom: 1.5rem; - list-style-type: none; } - .content ul li { - padding-left: 1.5rem; - position: relative; } - .content ul li::before { - position: absolute; - content: ""; - height: 0.5rem; - width: 0.5rem; - border-radius: 50%; - background-color: #18b0a2; - left: 3px; - top: 0.5rem; } - -.content table { - width: 100%; - max-width: 100%; - margin-bottom: 1rem; - border-radius: 6px; - overflow: hidden; } - -.content table td, -.content table th { - padding: 0.75rem; - vertical-align: top; - margin-bottom: 0; } - -.content tr:not(:last-child) { - border-bottom: 1px solid rgba(24, 176, 162, 0.15); } - -.content th { - font-weight: 500; } - -.content thead { - background-color: #191f27; - margin-bottom: 0; } - .content thead tr { - border-bottom: 1px solid rgba(24, 176, 162, 0.15); } - -.content tbody { - background-color: #151923; - margin-bottom: 0; } - -.content .notices p { - border-radius: 5px; - color: #191f27; } - .content .notices p::before { - content: "⭓"; - border: 0px !important; } - -.content .accordion-item { - border: 0; } - -.content .accordion-button { - padding: 0.7rem 1.25rem; - color: #bbb; - background-color: #eee; } - .content .accordion-button::after { - background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 16 16%22 fill=%22%23000000%22%3E%3Cpath fill-rule=%22evenodd%22 d=%22M1.646 4.646a.5.5.0 01.708.0L8 10.293l5.646-5.647a.5.5.0 01.708.708l-6 6a.5.5.0 01-.708.0l-6-6a.5.5.0 010-.708z%22/%3E%3C/svg%3E"); } - .content .accordion-button:focus { - border-color: inherit; - box-shadow: none; } - .content .accordion-button:not(.collapsed) { - color: #bbb; - box-shadow: none; } - -.content blockquote { - color: #eee; - padding: 1.2rem 30px; - border: 1px solid rgba(24, 176, 162, 0.4); - border-left: 3px solid rgba(24, 176, 162, 0.8); - margin: 2rem 0; - background: transparent; - font-weight: 400; } - .content blockquote p { - margin-bottom: 0 !important; } - .content blockquote cite { - display: inline-block; - margin-top: 1rem; } - -.content pre { - display: block; - padding: 20px; - margin: 0.7rem 0; - white-space: pre-wrap; - border-radius: 6px; } - -.content code { - margin-bottom: 0 !important; - font-size: 100%; } - -.content iframe { - border-radius: 6px; } - -.light .content thead { - background-color: #eee; } - -.light .content tbody { - background-color: #f6f6f6; } - -.dark .card { - color: #bbb; } - -.light .card { - color: #555; } - -#sidebarContent { - background-color: #191f27; - padding: 45px 45px 0 45px; - max-width: 320px; - overflow-y: auto; } - #sidebarContent::-webkit-scrollbar-thumb { - background: transparent; } - #sidebarContent:hover::-webkit-scrollbar-thumb { - background: #2b313e; } - @media (max-width: 1199px) { - #sidebarContent.hidden { - top: 0px; - max-width: 100%; - left: -100%; - max-width: 300px; - padding-left: 20px; - transition: all 0.4s ease-out; - z-index: 777; } - #sidebarContent.hidden.active { - left: 0px; } } - #sidebarContent .navbar-nav .nav-item a { - font-weight: 400; - font-size: 1.1rem; - margin-bottom: 10px; - color: rgba(255, 255, 255, 0.75); - transition: color 0.3s; } - #sidebarContent .navbar-nav .nav-item a i { - font-size: 0.9em; - color: rgba(255, 255, 255, 0.5); - transition: 0.3s; } - #sidebarContent .navbar-nav .nav-item a.nav-link.active, - #sidebarContent .navbar-nav .nav-item a.nav-link:hover { - color: #fff; } - #sidebarContent .navbar-nav .nav-item a.nav-link.active i, - #sidebarContent .navbar-nav .nav-item a.nav-link:hover i { - color: #fff; } - -.theme-switcher { - position: relative; } - .theme-switcher span { - position: absolute; - height: 30px; - width: 50px; - border-radius: 30px; - background-color: #222; - cursor: pointer; - z-index: 99; - transform: rotateZ(180deg) rotateX(180deg); - transform-origin: center; } - .theme-switcher span::before { - position: absolute; - left: 5px; - bottom: 5px; - height: 20px; - width: 20px; - content: ""; - border-radius: 50%; - background-color: #fff; - transition: 0.3s; } - .theme-switcher #toggler { - opacity: 0; - display: none; - touch-action: none; } - .theme-switcher #toggler:checked ~ span { - background-color: #2d3846; } - .theme-switcher #toggler:checked ~ span::before { - background-color: #2d3846; - box-shadow: inset -8px -3px 0 0px #fff; - transform: translate(18px, 0px); } - -.navbar-toggler { - background-color: rgba(255, 255, 255, 0.2); - transition: background-color 0.3s; - padding: 2px; - position: fixed; - top: 30px; - right: 25px; - z-index: 9999; } - @media (max-width: 991px) { - .navbar-toggler { - background-color: #18b0a2; } } - @media (max-width: 767px) { - .navbar-toggler { - right: 10px; } } - .navbar-toggler:focus { - box-shadow: none; } - .navbar-toggler label { - display: block; - cursor: pointer; - position: absolute; - width: 40px; - height: 40px; - bottom: 0; - right: 0; } - .navbar-toggler label svg { - transform: scale(1.5); } - .navbar-toggler.active .line--1, - .navbar-toggler.active .line--3 { - stroke-dasharray: 22.627416998 126.64183044433594; } - .navbar-toggler.active .line--2 { - stroke-dasharray: 0 126.64183044433594; } - .navbar-toggler.active .line--1, - .navbar-toggler.active .line--3 { - stroke-dashoffset: -94.1149185097; } - .navbar-toggler.active .line--2 { - stroke-dashoffset: -50; } - .navbar-toggler path { - fill: none; - stroke: white; - stroke-width: 3; - stroke-linecap: round; - stroke-linejoin: round; - stroke-dasharray: 24 126.64183044433594; - stroke-dashoffset: -38; - transition: all 0.4s cubic-bezier(0.645, 0.045, 0.355, 1); } - -.navbar-show { - overflow-y: hidden; } - -.tf-backdrop { - display: none !important; } - @media (max-width: 1199px) { - .tf-backdrop { - display: block !important; } } -html.light #sidebarContent { - background-color: rgba(188, 188, 188, 0.2) !important; } - html.light #sidebarContent:hover::-webkit-scrollbar-thumb { - background: rgba(188, 188, 188, 0.7); } - -html.light .navbar-nav .nav-item a { - color: rgba(34, 34, 34, 0.6) !important; } - html.light .navbar-nav .nav-item a i { - color: rgba(34, 34, 34, 0.4) !important; } - -html.light .navbar-nav .nav-item a.nav-link.active, -html.light .navbar-nav .nav-item a.nav-link:hover { - color: #222 !important; } - html.light .navbar-nav .nav-item a.nav-link.active i, - html.light .navbar-nav .nav-item a.nav-link:hover i { - color: #222 !important; } - -#banner { - padding: 8rem 0; } - @media (max-width: 767px) { - #banner { - padding-top: 5rem; - padding-bottom: 5rem; } } - #banner::after { - content: ""; - position: absolute; - width: 690px; - height: 690px; - left: 5%; - top: -30%; - background: linear-gradient(180deg, rgba(250, 209, 65, 0.5) 0%, rgba(0, 71, 255, 0.2) 33.85%, rgba(24, 176, 162, 0.7) 67.71%, rgba(233, 65, 0, 0.5) 100%); - opacity: 0.4; - filter: blur(75px); - z-index: -1; } - -.image-block { - border: 1px solid rgba(24, 176, 162, 0.2); - padding: 20px; } - @media (max-width: 1199px) { - .image-block { - padding: 10px; } } - @media (max-width: 991px) { - .image-block { - border: 0; - padding: 0; } - .image-block img { - padding: 0; - height: 160px; - width: 150px !important; - object-fit: cover; - object-position: top; } } -.additional-info { - margin-bottom: 35px; } - .additional-info tr { - display: block; - margin-bottom: 7px; } - .additional-info tr td { - position: relative; - vertical-align: top; } - .additional-info tr td:first-child { - width: 130px; } - .additional-info tr td:last-child { - padding-left: 30px; } - @media (max-width: 400px) { - .additional-info tr td { - word-break: break-word; - font-size: 0.9rem; } } - .additional-info tr td:nth-child(2)::before { - content: ":"; - position: absolute; - left: 0px; - font-weight: bold; - opacity: 0.75; } - -#skill { - z-index: 1; } - #skill::before { - content: ""; - position: absolute; - width: 600px; - height: 400px; - right: -10%; - bottom: 30%; - background: linear-gradient(180deg, rgba(250, 209, 65, 0.5) 0%, rgba(0, 71, 255, 0.2) 33.85%, #18b0a2 67.71%, rgba(233, 65, 0, 0.5) 100%); - opacity: 0.4; - filter: blur(200px); - z-index: -1; - pointer-events: none; } - #skill .progress-item > div > span:last-child { - color: #18b0a2; } - #skill .progress-item .progress { - height: 10px; - background-color: rgba(24, 176, 162, 0.3); } - #skill .progress-item .progress .progress-bar { - background-color: #18b0a2; - height: 100%; - line-height: 10px; - font-size: 0; - padding: 0; } - @media (max-width: 400px) { - #skill .progress-item .progress { - height: 10px; } } -#resume { - z-index: 1; } - #resume::before { - content: ""; - position: absolute; - width: 400px; - height: 400px; - left: 5%; - bottom: 30%; - background-color: #18b0a2; - background-image: radial-gradient(at 81% 18%, #eedc77 0px, transparent 50%), radial-gradient(at 71% 74%, #ede882 0px, transparent 50%), radial-gradient(at 63% 28%, #da5885 0px, transparent 50%), radial-gradient(at 26% 98%, #96bbe9 0px, transparent 50%), radial-gradient(at 99% 53%, #9191e3 0px, transparent 50%), radial-gradient(at 78% 85%, #bd8ced 0px, transparent 50%), radial-gradient(at 15% 55%, #4ef4a6 0px, transparent 50%); - opacity: 0.4; - filter: blur(200px); - z-index: -1; - pointer-events: none; } - #resume .divider { - padding: 0; - position: absolute; - width: 1px; - height: calc(100% - 180px); - background-color: rgba(24, 176, 162, 0.2); - bottom: 40px; - left: 50%; } - #resume .divider::after, #resume .divider::before { - content: ""; - position: absolute; - width: 20px; - height: 20px; - border: 1px solid rgba(24, 176, 162, 0.3); - border-radius: 50%; - bottom: -30px; - left: -10px; } - #resume .divider::before { - bottom: auto; - top: -30px; } - #resume .card { - padding: 30px; - color: #bbb; } - #resume .card .icon { - height: 50px; - width: 50px; - text-align: center; - line-height: 50px; - color: #18b0a2; - background-color: rgba(24, 176, 162, 0.15); - border-top-left-radius: 0 !important; - border-top-right-radius: 0 !important; } - #resume .card .card-body p { - font-size: 1rem; } - #resume .card .card-body strong { - font-weight: normal; - color: #18b0a2; } - -.projects, -.blog-wrapper { - column-count: 3; - column-gap: 1.5rem; } - @media (max-width: 991px) { - .projects, - .blog-wrapper { - column-count: 2; } } - @media (max-width: 767px) { - .projects, - .blog-wrapper { - column-count: 1; } } -.meta-link:hover { - color: #18b0a2 !important; - text-decoration: underline !important; } - -.project-item .card, -.blog-post .card { - border: 1px solid rgba(24, 176, 162, 0.15); - overflow: hidden; } - .project-item .card > a:first-child img, - .blog-post .card > a:first-child img { - transition: all 0.2s; - display: block; - border: none; } - .project-item .card > a:first-child:hover img, - .blog-post .card > a:first-child:hover img { - transform: scale(1.02); } - .project-item .card .card-title, - .blog-post .card .card-title { - margin-bottom: 0.8rem; } - .project-item .card .card-title a, - .blog-post .card .card-title a { - text-decoration-color: #18b0a2; } - .project-item .card .card-title a:hover, - .blog-post .card .card-title a:hover { - text-decoration: underline; - text-decoration-color: #18b0a2; } - .project-item .card .card-text, - .blog-post .card .card-text { - font-size: 1rem; - font-weight: 300; - line-height: 160%; } - .project-item .card .card-btn i, - .blog-post .card .card-btn i { - transition: all 0.4s; - font-size: 14px; - text-align: center; - line-height: 12px; - margin-left: 5px; } - .project-item .card .card-btn:hover i, - .blog-post .card .card-btn:hover i { - transform: translateX(5px); - color: #18b0a2 !important; } - -.blog-post .post-meta li:not(:first-child)::before { - content: "-"; - font-size: 10px; - margin-right: 5px; } - -.blog-post .post-meta a, -.blog-post .post-meta li { - font-size: 0.875rem; - color: rgba(255, 255, 255, 0.7); } - -.blog-post .post-meta span { - font-size: 0.875rem; - color: rgba(255, 255, 255, 0.7); } - -.blog-post .card > a:first-child { - border-radius: 10px 10px 0px 0px; } - -.blog-post .card .card-btn { - color: #fff; } - .blog-post .card .card-btn img { - transition: all 0.4s; } - .blog-post .card .card-btn:hover { - color: #18b0a2 !important; } - .blog-post .card .card-btn:hover img { - margin-left: 15px; } - .blog-post .card .card-btn img { - margin-left: 10px; } - -.light .blog-post .post-meta a, -.light .blog-post .post-meta li { - color: rgba(34, 34, 34, 0.7) !important; } - -.post-meta a, -.post-meta li, -.post-meta span { - font-size: 0.975rem; - color: rgba(255, 255, 255, 0.7); } - -.post-meta li:not(:first-child)::before { - content: "-"; - font-size: 10px; - margin-right: 5px; } - -.featured-image { - max-height: 600px; - object-fit: cover; } - -#blog { - position: relative; } - #blog::before { - content: ""; - position: absolute; - z-index: -1; - width: 1159px; - height: 644px; - left: -60%; - top: 10%; - background: #34d71b; - opacity: 0.1; - filter: blur(200px); - transform: rotate(30deg); } - @media (max-width: 991px) { - #blog::before { - display: none; } } -#contact::before { - content: ""; - position: absolute; - width: 1058.89px; - height: 540.7px; - left: -60%; - bottom: 30%; - background-color: #24ff00; - opacity: 0.1; - filter: blur(200px); - transform: rotate(30deg); - z-index: -1; } - @media (max-width: 1399px) { - #contact::before { - display: none; } } -#contact::after { - content: ""; - position: absolute; - width: 561px; - height: 683px; - left: 1359px; - top: 0px; - background: linear-gradient(180deg, rgba(250, 209, 65, 0.5) 0%, rgba(0, 71, 255, 0.5) 33.85%, rgba(0, 255, 56, 0.5) 67.71%, rgba(233, 65, 0, 0.5) 100%); - opacity: 0.4; - filter: blur(175px); - z-index: -1; } - @media (max-width: 1399px) { - #contact::after { - display: none; } } -#contact form { - z-index: 1; - border: 1px solid rgba(24, 176, 162, 0.15); } - -footer a, -footer p { - color: rgba(255, 255, 255, 0.7); } - -footer p { - font-size: 0.9375rem; - line-height: 140%; } - -footer .list-inline { - text-align: center; } - footer .list-inline li a { - width: 40px; - height: 40px; - transition: all 0.3s; - border: 1px solid rgba(24, 176, 162, 0.15); - color: rgba(255, 255, 255, 0.7); } - footer .list-inline li a:hover { - background-color: rgba(24, 176, 162, 0.2); } - footer .list-inline li a i { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); } - -footer .contact-list img { - width: 25px; - height: 25px; - object-fit: contain; - object-position: center; } - -footer .copyright-info { - border-top: 1px solid rgba(24, 176, 162, 0.15); } - -.light footer a, -.light footer p { - color: rgba(34, 34, 34, 0.7) !important; } - -.notice { - margin-bottom: 1.5rem; - border: 1px solid #e5e7eb; - padding: 1.5rem; } - -.notice-head { - display: flex; - align-items: center; } - -.notice-head svg { - margin-right: 0.75rem; } - -.notice-head p { - font-size: 1.25rem; - font-weight: 600; - color: #1f2937; - margin: 0; - line-height: 1; } - -.notice-body { - margin-top: 0.75rem; } - -.notice-body p { - margin: 0; } - -.notice.note { - color: #1b83e2; - border-color: currentColor; } - -.notice.tip { - color: #40d294; - border-color: currentColor; } - -.notice.info { - color: #e3a72c; - border-color: currentColor; } - -.notice.warning { - color: #db2c23; - border-color: currentColor; } - -.dark .notice-head p { - color: #d1d5db; } - -.tab-nav { - list-style: none; - padding: 0; - margin: 0 !important; - list-style-type: none !important; - display: flex; - border-bottom: 1px solid #aaa; - overflow-x: auto; } - .tab-nav::-webkit-scrollbar { - width: 2px; } - -.tab-nav-item { - padding: 0.5rem 1rem !important; - cursor: pointer; - opacity: 0.8; - margin: 0 !important; - white-space: nowrap; } - -.tab-nav-item::before { - display: none !important; } - -.tab-nav-item.active { - border-bottom: 3px solid #aaa; - opacity: 1; } - -.tab-content .tab-content-panel { - display: none; - padding: 1rem 0.5rem; } - -.tab-content .tab-content-panel p { - margin-bottom: 0 !important; } - -.tab-content .tab-content-panel.active { - display: block; } - -.img { - max-width: 100%; - height: auto; } - -.img-light { - display: initial; } - -.img-dark { - display: none; } - -.dark .img-light { - display: none; } - -.dark .img-dark { - display: initial; } - -.content img { - max-width: 100%; - margin-bottom: 1.5rem; - height: auto; - display: inline-block; } - .content img.glightbox { - cursor: pointer; } - .content img.img-center { - display: block; - margin-left: auto; - margin-right: auto; } - .content img.img-left { - display: block; - margin-left: 0; - margin-right: auto; } - .content img.img-right { - display: block; - margin-left: auto; - margin-right: 0; } - .content img.img-float-left { - float: left; - margin-right: 1.5rem; } - .content img.img-float-right { - float: right; - margin-left: 1.5rem; } - -.content figure { - display: inline-block; - margin-bottom: 1.5rem; } - .content figure img { - margin-bottom: 0.7rem; } - .content figure.img-center { - display: block; - text-align: center; } - .content figure.img-left { - display: block; - text-align: left; } - .content figure.img-right { - display: block; - text-align: right; } - .content figure.img-float-left { - float: left; - margin-right: 1.5rem; } - .content figure.img-float-right { - float: right; - margin-left: 1.5rem; } - -.img { - max-width: 100%; - height: auto; } - -/*! - * Justified gallery style - */ -.gallery { - display: flex; - flex-wrap: wrap; - margin-left: -10px; - margin-right: -10px; } - -.gallery .gallery-item { - margin: 0 10px; - margin-bottom: 20px; - overflow: hidden; - max-width: calc(100% - 20px); } - -.gallery .gallery-item img { - user-select: none; - width: 100%; - vertical-align: middle; - transition: 0.3s; } - -.gallery.zoomable .gallery-item:hover img { - transform: scale(1.05); - cursor: zoom-in; } - -.gallery::after { - content: ""; - flex-grow: 99999; - min-width: calc(100vw / 3); } - -@media (max-width: 460px) { - .gallery { - flex-direction: column; } - .gallery .gallery-item { - width: calc(100% - 20px) !important; } } - -.gallery-slider .swiper-slide img { - width: 100%; } - -.gallery-slider .swiper-button-prev, -.gallery-slider .swiper-button-next { - color: white; - opacity: 0; - transition: 0.3s; } - -.gallery-slider:hover .swiper-button-prev, -.gallery-slider:hover .swiper-button-next { - opacity: 1; } - -.gallery-slider:hover .swiper-button-prev { - left: 30px; } - -.gallery-slider:hover .swiper-button-next { - right: 30px; } - -.table-of-content { - margin: 1rem 0 1.5rem; } - .table-of-content summary { - font-size: 18px; - color: #fff; - background-color: #555; - padding: 5px 20px; - margin-bottom: 0 !important; } - .table-of-content ul li::before { - display: none; } - .table-of-content #TableOfContents { - padding: 10px; - background-color: #f7f7f7; } - .table-of-content #TableOfContents li, - .table-of-content #TableOfContents a { - color: #333 !important; } - .table-of-content #TableOfContents a { - text-decoration: none; } - .table-of-content #TableOfContents a:hover { - text-decoration: underline; } - -.content .table-of-content ul li, -.content .table-of-content ol li { - margin-bottom: 6px !important; } - -.dark #TableOfContents { - background-color: #333; } - .dark #TableOfContents li, - .dark #TableOfContents a { - color: #fff !important; } diff --git a/public/images/blog/blog-1.jpg b/public/images/blog/blog-1.jpg deleted file mode 100644 index d2a9a28..0000000 Binary files a/public/images/blog/blog-1.jpg and /dev/null differ diff --git a/public/images/blog/blog-10.jpg b/public/images/blog/blog-10.jpg deleted file mode 100644 index 9fec9e5..0000000 Binary files a/public/images/blog/blog-10.jpg and /dev/null differ diff --git a/public/images/blog/blog-10_hu_35c38cc09be1cad4.jpg b/public/images/blog/blog-10_hu_35c38cc09be1cad4.jpg deleted file mode 100644 index 66bd130..0000000 Binary files a/public/images/blog/blog-10_hu_35c38cc09be1cad4.jpg and /dev/null differ diff --git a/public/images/blog/blog-10_hu_4379874c5f05b59f.webp b/public/images/blog/blog-10_hu_4379874c5f05b59f.webp deleted file mode 100644 index 61d3273..0000000 Binary files a/public/images/blog/blog-10_hu_4379874c5f05b59f.webp and /dev/null differ diff --git a/public/images/blog/blog-10_hu_7491d1d603de5dcf.webp b/public/images/blog/blog-10_hu_7491d1d603de5dcf.webp deleted file mode 100644 index 2c18b38..0000000 Binary files a/public/images/blog/blog-10_hu_7491d1d603de5dcf.webp and /dev/null differ diff --git a/public/images/blog/blog-10_hu_a3b0ec28e3d5779b.webp b/public/images/blog/blog-10_hu_a3b0ec28e3d5779b.webp deleted file mode 100644 index 0b1fd1a..0000000 Binary files a/public/images/blog/blog-10_hu_a3b0ec28e3d5779b.webp and /dev/null differ diff --git a/public/images/blog/blog-10_hu_bb979f59174514ec.jpg b/public/images/blog/blog-10_hu_bb979f59174514ec.jpg deleted file mode 100644 index f30cbb5..0000000 Binary files a/public/images/blog/blog-10_hu_bb979f59174514ec.jpg and /dev/null differ diff --git a/public/images/blog/blog-10_hu_d525f0cd93d6fcb1.webp b/public/images/blog/blog-10_hu_d525f0cd93d6fcb1.webp deleted file mode 100644 index 63364d8..0000000 Binary files a/public/images/blog/blog-10_hu_d525f0cd93d6fcb1.webp and /dev/null differ diff --git a/public/images/blog/blog-10_hu_e27e2f85e226178c.webp b/public/images/blog/blog-10_hu_e27e2f85e226178c.webp deleted file mode 100644 index 0274884..0000000 Binary files a/public/images/blog/blog-10_hu_e27e2f85e226178c.webp and /dev/null differ diff --git a/public/images/blog/blog-1_hu_4b1782fd1a15e83b.webp b/public/images/blog/blog-1_hu_4b1782fd1a15e83b.webp deleted file mode 100644 index 05ac5cd..0000000 Binary files a/public/images/blog/blog-1_hu_4b1782fd1a15e83b.webp and /dev/null differ diff --git a/public/images/blog/blog-1_hu_8dd81870b6dccbe7.jpg b/public/images/blog/blog-1_hu_8dd81870b6dccbe7.jpg deleted file mode 100644 index a648ef0..0000000 Binary files a/public/images/blog/blog-1_hu_8dd81870b6dccbe7.jpg and /dev/null differ diff --git a/public/images/blog/blog-1_hu_8def6289c64a2dc8.webp b/public/images/blog/blog-1_hu_8def6289c64a2dc8.webp deleted file mode 100644 index d2df11c..0000000 Binary files a/public/images/blog/blog-1_hu_8def6289c64a2dc8.webp and /dev/null differ diff --git a/public/images/blog/blog-1_hu_c69497547b6be0b8.webp b/public/images/blog/blog-1_hu_c69497547b6be0b8.webp deleted file mode 100644 index 761b202..0000000 Binary files a/public/images/blog/blog-1_hu_c69497547b6be0b8.webp and /dev/null differ diff --git a/public/images/blog/blog-1_hu_d77be45b273e444.jpg b/public/images/blog/blog-1_hu_d77be45b273e444.jpg deleted file mode 100644 index 8166702..0000000 Binary files a/public/images/blog/blog-1_hu_d77be45b273e444.jpg and /dev/null differ diff --git a/public/images/blog/blog-1_hu_dcdbc2fa445f98d0.webp b/public/images/blog/blog-1_hu_dcdbc2fa445f98d0.webp deleted file mode 100644 index c3c9b92..0000000 Binary files a/public/images/blog/blog-1_hu_dcdbc2fa445f98d0.webp and /dev/null differ diff --git a/public/images/blog/blog-1_hu_f9ab0f5f2b4013b3.webp b/public/images/blog/blog-1_hu_f9ab0f5f2b4013b3.webp deleted file mode 100644 index 504f0cc..0000000 Binary files a/public/images/blog/blog-1_hu_f9ab0f5f2b4013b3.webp and /dev/null differ diff --git a/public/images/blog/blog-3.jpg b/public/images/blog/blog-3.jpg deleted file mode 100644 index a042ca9..0000000 Binary files a/public/images/blog/blog-3.jpg and /dev/null differ diff --git a/public/images/blog/blog-3_hu_2ce558f2693339dd.webp b/public/images/blog/blog-3_hu_2ce558f2693339dd.webp deleted file mode 100644 index 3f9f9de..0000000 Binary files a/public/images/blog/blog-3_hu_2ce558f2693339dd.webp and /dev/null differ diff --git a/public/images/blog/blog-3_hu_3ede4323b8664a75.webp b/public/images/blog/blog-3_hu_3ede4323b8664a75.webp deleted file mode 100644 index 6616eef..0000000 Binary files a/public/images/blog/blog-3_hu_3ede4323b8664a75.webp and /dev/null differ diff --git a/public/images/blog/blog-3_hu_67e89b89a8dc0de1.jpg b/public/images/blog/blog-3_hu_67e89b89a8dc0de1.jpg deleted file mode 100644 index 760bacc..0000000 Binary files a/public/images/blog/blog-3_hu_67e89b89a8dc0de1.jpg and /dev/null differ diff --git a/public/images/blog/blog-3_hu_7893dc97eea078f.webp b/public/images/blog/blog-3_hu_7893dc97eea078f.webp deleted file mode 100644 index 49db1e9..0000000 Binary files a/public/images/blog/blog-3_hu_7893dc97eea078f.webp and /dev/null differ diff --git a/public/images/blog/blog-3_hu_8d0001f985ca2e5e.webp b/public/images/blog/blog-3_hu_8d0001f985ca2e5e.webp deleted file mode 100644 index 630c450..0000000 Binary files a/public/images/blog/blog-3_hu_8d0001f985ca2e5e.webp and /dev/null differ diff --git a/public/images/blog/blog-3_hu_c932299ff2fa7067.jpg b/public/images/blog/blog-3_hu_c932299ff2fa7067.jpg deleted file mode 100644 index fc01faf..0000000 Binary files a/public/images/blog/blog-3_hu_c932299ff2fa7067.jpg and /dev/null differ diff --git a/public/images/blog/blog-3_hu_fdd9e13d0370b160.webp b/public/images/blog/blog-3_hu_fdd9e13d0370b160.webp deleted file mode 100644 index e935be9..0000000 Binary files a/public/images/blog/blog-3_hu_fdd9e13d0370b160.webp and /dev/null differ diff --git a/public/images/blog/blog-4.jpg b/public/images/blog/blog-4.jpg deleted file mode 100644 index 2391197..0000000 Binary files a/public/images/blog/blog-4.jpg and /dev/null differ diff --git a/public/images/blog/blog-4_hu_2f5acf67112899f5.webp b/public/images/blog/blog-4_hu_2f5acf67112899f5.webp deleted file mode 100644 index 251d46e..0000000 Binary files a/public/images/blog/blog-4_hu_2f5acf67112899f5.webp and /dev/null differ diff --git a/public/images/blog/blog-4_hu_8ddea2f052660626.webp b/public/images/blog/blog-4_hu_8ddea2f052660626.webp deleted file mode 100644 index 6626080..0000000 Binary files a/public/images/blog/blog-4_hu_8ddea2f052660626.webp and /dev/null differ diff --git a/public/images/blog/blog-4_hu_91f1b60de32f3a0d.jpg b/public/images/blog/blog-4_hu_91f1b60de32f3a0d.jpg deleted file mode 100644 index b14567b..0000000 Binary files a/public/images/blog/blog-4_hu_91f1b60de32f3a0d.jpg and /dev/null differ diff --git a/public/images/blog/blog-4_hu_96cadc46e7508592.jpg b/public/images/blog/blog-4_hu_96cadc46e7508592.jpg deleted file mode 100644 index dece064..0000000 Binary files a/public/images/blog/blog-4_hu_96cadc46e7508592.jpg and /dev/null differ diff --git a/public/images/blog/blog-4_hu_a14b7dcdb6d8d5d6.webp b/public/images/blog/blog-4_hu_a14b7dcdb6d8d5d6.webp deleted file mode 100644 index 43fbeb1..0000000 Binary files a/public/images/blog/blog-4_hu_a14b7dcdb6d8d5d6.webp and /dev/null differ diff --git a/public/images/blog/blog-4_hu_a611bbe12accd648.webp b/public/images/blog/blog-4_hu_a611bbe12accd648.webp deleted file mode 100644 index b11aa37..0000000 Binary files a/public/images/blog/blog-4_hu_a611bbe12accd648.webp and /dev/null differ diff --git a/public/images/blog/blog-4_hu_a9f77e15e51fe13e.webp b/public/images/blog/blog-4_hu_a9f77e15e51fe13e.webp deleted file mode 100644 index 16644b0..0000000 Binary files a/public/images/blog/blog-4_hu_a9f77e15e51fe13e.webp and /dev/null differ diff --git a/public/images/blog/blog-5.jpg b/public/images/blog/blog-5.jpg deleted file mode 100644 index deb50a9..0000000 Binary files a/public/images/blog/blog-5.jpg and /dev/null differ diff --git a/public/images/blog/blog-5_hu_1fa9c9461e8a5b22.webp b/public/images/blog/blog-5_hu_1fa9c9461e8a5b22.webp deleted file mode 100644 index f6c8ec0..0000000 Binary files a/public/images/blog/blog-5_hu_1fa9c9461e8a5b22.webp and /dev/null differ diff --git a/public/images/blog/blog-5_hu_2496163d8ca0be9a.jpg b/public/images/blog/blog-5_hu_2496163d8ca0be9a.jpg deleted file mode 100644 index 9a5abde..0000000 Binary files a/public/images/blog/blog-5_hu_2496163d8ca0be9a.jpg and /dev/null differ diff --git a/public/images/blog/blog-5_hu_3f20fe629de38114.webp b/public/images/blog/blog-5_hu_3f20fe629de38114.webp deleted file mode 100644 index 25cd0b3..0000000 Binary files a/public/images/blog/blog-5_hu_3f20fe629de38114.webp and /dev/null differ diff --git a/public/images/blog/blog-5_hu_4618aa5e6342cf5b.webp b/public/images/blog/blog-5_hu_4618aa5e6342cf5b.webp deleted file mode 100644 index 0db51f3..0000000 Binary files a/public/images/blog/blog-5_hu_4618aa5e6342cf5b.webp and /dev/null differ diff --git a/public/images/blog/blog-5_hu_54124c601931f717.webp b/public/images/blog/blog-5_hu_54124c601931f717.webp deleted file mode 100644 index 42af1ba..0000000 Binary files a/public/images/blog/blog-5_hu_54124c601931f717.webp and /dev/null differ diff --git a/public/images/blog/blog-5_hu_84904f4853785c5f.webp b/public/images/blog/blog-5_hu_84904f4853785c5f.webp deleted file mode 100644 index 4f72de7..0000000 Binary files a/public/images/blog/blog-5_hu_84904f4853785c5f.webp and /dev/null differ diff --git a/public/images/blog/blog-5_hu_cc034401e2f1274e.jpg b/public/images/blog/blog-5_hu_cc034401e2f1274e.jpg deleted file mode 100644 index 8f5a314..0000000 Binary files a/public/images/blog/blog-5_hu_cc034401e2f1274e.jpg and /dev/null differ diff --git a/public/images/blog/blog-5_hu_e31b752cd8166a9a.webp b/public/images/blog/blog-5_hu_e31b752cd8166a9a.webp deleted file mode 100644 index c9d362a..0000000 Binary files a/public/images/blog/blog-5_hu_e31b752cd8166a9a.webp and /dev/null differ diff --git a/public/images/blog/blog-5_hu_e4f7343564430a7c.webp b/public/images/blog/blog-5_hu_e4f7343564430a7c.webp deleted file mode 100644 index df7e933..0000000 Binary files a/public/images/blog/blog-5_hu_e4f7343564430a7c.webp and /dev/null differ diff --git a/public/images/blog/blog-5_hu_f181e5573eb2a3e0.jpg b/public/images/blog/blog-5_hu_f181e5573eb2a3e0.jpg deleted file mode 100644 index 48b0a1e..0000000 Binary files a/public/images/blog/blog-5_hu_f181e5573eb2a3e0.jpg and /dev/null differ diff --git a/public/images/blog/blog-6.jpg b/public/images/blog/blog-6.jpg deleted file mode 100644 index 09d93b2..0000000 Binary files a/public/images/blog/blog-6.jpg and /dev/null differ diff --git a/public/images/blog/blog-6_hu_49f98f56b956af12.webp b/public/images/blog/blog-6_hu_49f98f56b956af12.webp deleted file mode 100644 index 69a07f2..0000000 Binary files a/public/images/blog/blog-6_hu_49f98f56b956af12.webp and /dev/null differ diff --git a/public/images/blog/blog-6_hu_4ef932f257939b99.jpg b/public/images/blog/blog-6_hu_4ef932f257939b99.jpg deleted file mode 100644 index 37622d9..0000000 Binary files a/public/images/blog/blog-6_hu_4ef932f257939b99.jpg and /dev/null differ diff --git a/public/images/blog/blog-6_hu_6e570c8b5b77b366.webp b/public/images/blog/blog-6_hu_6e570c8b5b77b366.webp deleted file mode 100644 index 1fc2eae..0000000 Binary files a/public/images/blog/blog-6_hu_6e570c8b5b77b366.webp and /dev/null differ diff --git a/public/images/blog/blog-6_hu_738eea9b9eff29e3.webp b/public/images/blog/blog-6_hu_738eea9b9eff29e3.webp deleted file mode 100644 index fe6a6dd..0000000 Binary files a/public/images/blog/blog-6_hu_738eea9b9eff29e3.webp and /dev/null differ diff --git a/public/images/blog/blog-6_hu_a7e61da859c97057.webp b/public/images/blog/blog-6_hu_a7e61da859c97057.webp deleted file mode 100644 index 49f09bf..0000000 Binary files a/public/images/blog/blog-6_hu_a7e61da859c97057.webp and /dev/null differ diff --git a/public/images/blog/blog-6_hu_ad7d9ec3689102a3.webp b/public/images/blog/blog-6_hu_ad7d9ec3689102a3.webp deleted file mode 100644 index a8618ec..0000000 Binary files a/public/images/blog/blog-6_hu_ad7d9ec3689102a3.webp and /dev/null differ diff --git a/public/images/blog/blog-6_hu_b448f44c73a1e092.webp b/public/images/blog/blog-6_hu_b448f44c73a1e092.webp deleted file mode 100644 index ef0bdfa..0000000 Binary files a/public/images/blog/blog-6_hu_b448f44c73a1e092.webp and /dev/null differ diff --git a/public/images/blog/blog-6_hu_c559f46af58d7b01.jpg b/public/images/blog/blog-6_hu_c559f46af58d7b01.jpg deleted file mode 100644 index 2c2e01a..0000000 Binary files a/public/images/blog/blog-6_hu_c559f46af58d7b01.jpg and /dev/null differ diff --git a/public/images/blog/blog-6_hu_e56d383386eb66f4.jpg b/public/images/blog/blog-6_hu_e56d383386eb66f4.jpg deleted file mode 100644 index 93bcc51..0000000 Binary files a/public/images/blog/blog-6_hu_e56d383386eb66f4.jpg and /dev/null differ diff --git a/public/images/blog/blog-6_hu_f695abdc0daeefc5.webp b/public/images/blog/blog-6_hu_f695abdc0daeefc5.webp deleted file mode 100644 index 0b57554..0000000 Binary files a/public/images/blog/blog-6_hu_f695abdc0daeefc5.webp and /dev/null differ diff --git a/public/images/blog/blog-7.jpg b/public/images/blog/blog-7.jpg deleted file mode 100644 index 13defa2..0000000 Binary files a/public/images/blog/blog-7.jpg and /dev/null differ diff --git a/public/images/blog/blog-7_hu_32818c24ea07902c.webp b/public/images/blog/blog-7_hu_32818c24ea07902c.webp deleted file mode 100644 index 778a5a8..0000000 Binary files a/public/images/blog/blog-7_hu_32818c24ea07902c.webp and /dev/null differ diff --git a/public/images/blog/blog-7_hu_35062733e5b10c39.webp b/public/images/blog/blog-7_hu_35062733e5b10c39.webp deleted file mode 100644 index 10e85b6..0000000 Binary files a/public/images/blog/blog-7_hu_35062733e5b10c39.webp and /dev/null differ diff --git a/public/images/blog/blog-7_hu_3c4ad455eb02f8ec.jpg b/public/images/blog/blog-7_hu_3c4ad455eb02f8ec.jpg deleted file mode 100644 index d349259..0000000 Binary files a/public/images/blog/blog-7_hu_3c4ad455eb02f8ec.jpg and /dev/null differ diff --git a/public/images/blog/blog-7_hu_a100653844898565.jpg b/public/images/blog/blog-7_hu_a100653844898565.jpg deleted file mode 100644 index ddf1a26..0000000 Binary files a/public/images/blog/blog-7_hu_a100653844898565.jpg and /dev/null differ diff --git a/public/images/blog/blog-7_hu_cc5c86d0bdb969fb.webp b/public/images/blog/blog-7_hu_cc5c86d0bdb969fb.webp deleted file mode 100644 index a442d46..0000000 Binary files a/public/images/blog/blog-7_hu_cc5c86d0bdb969fb.webp and /dev/null differ diff --git a/public/images/blog/blog-7_hu_e1c9231db481941.webp b/public/images/blog/blog-7_hu_e1c9231db481941.webp deleted file mode 100644 index 0e255d2..0000000 Binary files a/public/images/blog/blog-7_hu_e1c9231db481941.webp and /dev/null differ diff --git a/public/images/blog/blog-7_hu_fe6a5eccb44e6265.webp b/public/images/blog/blog-7_hu_fe6a5eccb44e6265.webp deleted file mode 100644 index 9827694..0000000 Binary files a/public/images/blog/blog-7_hu_fe6a5eccb44e6265.webp and /dev/null differ diff --git a/public/images/blog/blog-8.jpg b/public/images/blog/blog-8.jpg deleted file mode 100644 index aa971ae..0000000 Binary files a/public/images/blog/blog-8.jpg and /dev/null differ diff --git a/public/images/blog/blog-8_hu_40fa8739755bb615.webp b/public/images/blog/blog-8_hu_40fa8739755bb615.webp deleted file mode 100644 index 2c96862..0000000 Binary files a/public/images/blog/blog-8_hu_40fa8739755bb615.webp and /dev/null differ diff --git a/public/images/blog/blog-8_hu_877dea591168f6c9.webp b/public/images/blog/blog-8_hu_877dea591168f6c9.webp deleted file mode 100644 index b0ba81b..0000000 Binary files a/public/images/blog/blog-8_hu_877dea591168f6c9.webp and /dev/null differ diff --git a/public/images/blog/blog-8_hu_8926a4b5230a89f0.webp b/public/images/blog/blog-8_hu_8926a4b5230a89f0.webp deleted file mode 100644 index 8974393..0000000 Binary files a/public/images/blog/blog-8_hu_8926a4b5230a89f0.webp and /dev/null differ diff --git a/public/images/blog/blog-8_hu_8aae514cbdf57851.webp b/public/images/blog/blog-8_hu_8aae514cbdf57851.webp deleted file mode 100644 index a4056c1..0000000 Binary files a/public/images/blog/blog-8_hu_8aae514cbdf57851.webp and /dev/null differ diff --git a/public/images/blog/blog-8_hu_a605adb3511bef5f.webp b/public/images/blog/blog-8_hu_a605adb3511bef5f.webp deleted file mode 100644 index 8167047..0000000 Binary files a/public/images/blog/blog-8_hu_a605adb3511bef5f.webp and /dev/null differ diff --git a/public/images/blog/blog-8_hu_aad970f07ba40e8a.jpg b/public/images/blog/blog-8_hu_aad970f07ba40e8a.jpg deleted file mode 100644 index 582eec5..0000000 Binary files a/public/images/blog/blog-8_hu_aad970f07ba40e8a.jpg and /dev/null differ diff --git a/public/images/blog/blog-8_hu_bc03a607701d5da7.webp b/public/images/blog/blog-8_hu_bc03a607701d5da7.webp deleted file mode 100644 index 0ab9dbc..0000000 Binary files a/public/images/blog/blog-8_hu_bc03a607701d5da7.webp and /dev/null differ diff --git a/public/images/blog/blog-8_hu_c5615396480723ed.jpg b/public/images/blog/blog-8_hu_c5615396480723ed.jpg deleted file mode 100644 index e4611eb..0000000 Binary files a/public/images/blog/blog-8_hu_c5615396480723ed.jpg and /dev/null differ diff --git a/public/images/blog/blog-8_hu_d73c30ce77a83a1a.webp b/public/images/blog/blog-8_hu_d73c30ce77a83a1a.webp deleted file mode 100644 index 57d87db..0000000 Binary files a/public/images/blog/blog-8_hu_d73c30ce77a83a1a.webp and /dev/null differ diff --git a/public/images/blog/blog-8_hu_de52e2b1d1fcdc3e.webp b/public/images/blog/blog-8_hu_de52e2b1d1fcdc3e.webp deleted file mode 100644 index d03a334..0000000 Binary files a/public/images/blog/blog-8_hu_de52e2b1d1fcdc3e.webp and /dev/null differ diff --git a/public/images/blog/blog-8_hu_e22a20688925a560.webp b/public/images/blog/blog-8_hu_e22a20688925a560.webp deleted file mode 100644 index 53a9a6b..0000000 Binary files a/public/images/blog/blog-8_hu_e22a20688925a560.webp and /dev/null differ diff --git a/public/images/blog/blog-8_hu_f7b5a18e65e50561.jpg b/public/images/blog/blog-8_hu_f7b5a18e65e50561.jpg deleted file mode 100644 index 4bb3b4c..0000000 Binary files a/public/images/blog/blog-8_hu_f7b5a18e65e50561.jpg and /dev/null differ diff --git a/public/images/blog/blog-9.jpg b/public/images/blog/blog-9.jpg deleted file mode 100644 index 7cf88fe..0000000 Binary files a/public/images/blog/blog-9.jpg and /dev/null differ diff --git a/public/images/blog/blog-9_hu_14af2878d62e6e4e.webp b/public/images/blog/blog-9_hu_14af2878d62e6e4e.webp deleted file mode 100644 index b45a65b..0000000 Binary files a/public/images/blog/blog-9_hu_14af2878d62e6e4e.webp and /dev/null differ diff --git a/public/images/blog/blog-9_hu_18953a22f9755bfc.webp b/public/images/blog/blog-9_hu_18953a22f9755bfc.webp deleted file mode 100644 index a8af6e4..0000000 Binary files a/public/images/blog/blog-9_hu_18953a22f9755bfc.webp and /dev/null differ diff --git a/public/images/blog/blog-9_hu_25ae63d53027b3fe.jpg b/public/images/blog/blog-9_hu_25ae63d53027b3fe.jpg deleted file mode 100644 index 9ae0692..0000000 Binary files a/public/images/blog/blog-9_hu_25ae63d53027b3fe.jpg and /dev/null differ diff --git a/public/images/blog/blog-9_hu_26100c6d555ed19e.webp b/public/images/blog/blog-9_hu_26100c6d555ed19e.webp deleted file mode 100644 index c84cc87..0000000 Binary files a/public/images/blog/blog-9_hu_26100c6d555ed19e.webp and /dev/null differ diff --git a/public/images/blog/blog-9_hu_37b697b4c00fe908.webp b/public/images/blog/blog-9_hu_37b697b4c00fe908.webp deleted file mode 100644 index da02d57..0000000 Binary files a/public/images/blog/blog-9_hu_37b697b4c00fe908.webp and /dev/null differ diff --git a/public/images/blog/blog-9_hu_bae9a262462e5d36.webp b/public/images/blog/blog-9_hu_bae9a262462e5d36.webp deleted file mode 100644 index f95920a..0000000 Binary files a/public/images/blog/blog-9_hu_bae9a262462e5d36.webp and /dev/null differ diff --git a/public/images/blog/blog-9_hu_e62b76c2afdef019.jpg b/public/images/blog/blog-9_hu_e62b76c2afdef019.jpg deleted file mode 100644 index fb6d4ad..0000000 Binary files a/public/images/blog/blog-9_hu_e62b76c2afdef019.jpg and /dev/null differ diff --git a/public/images/blog/post-2/binexpl.png b/public/images/blog/post-2/binexpl.png deleted file mode 100644 index 0ee5464..0000000 Binary files a/public/images/blog/post-2/binexpl.png and /dev/null differ diff --git a/public/images/blog/post-2/binexpl_hu_2b8858450dae90c.png b/public/images/blog/post-2/binexpl_hu_2b8858450dae90c.png deleted file mode 100644 index e3691c5..0000000 Binary files a/public/images/blog/post-2/binexpl_hu_2b8858450dae90c.png and /dev/null differ diff --git a/public/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp b/public/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp deleted file mode 100644 index 414541a..0000000 Binary files a/public/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp and /dev/null differ diff --git a/public/images/blog/post-2/binexpl_hu_62abc2aca7882dbf.webp b/public/images/blog/post-2/binexpl_hu_62abc2aca7882dbf.webp deleted file mode 100644 index f55ed6d..0000000 Binary files a/public/images/blog/post-2/binexpl_hu_62abc2aca7882dbf.webp and /dev/null differ diff --git a/public/images/blog/post-2/binexpl_hu_6c7b74fb7ea6923.webp b/public/images/blog/post-2/binexpl_hu_6c7b74fb7ea6923.webp deleted file mode 100644 index 3eb0f51..0000000 Binary files a/public/images/blog/post-2/binexpl_hu_6c7b74fb7ea6923.webp and /dev/null differ diff --git a/public/images/blog/post-2/binexpl_hu_87c8bee28ebae804.webp b/public/images/blog/post-2/binexpl_hu_87c8bee28ebae804.webp deleted file mode 100644 index 339aabf..0000000 Binary files a/public/images/blog/post-2/binexpl_hu_87c8bee28ebae804.webp and /dev/null differ diff --git a/public/images/blog/post-2/binexpl_hu_935160fb8df57d09.webp b/public/images/blog/post-2/binexpl_hu_935160fb8df57d09.webp deleted file mode 100644 index f21d026..0000000 Binary files a/public/images/blog/post-2/binexpl_hu_935160fb8df57d09.webp and /dev/null differ diff --git a/public/images/blog/post-2/binexpl_hu_afca672637b6b98d.png b/public/images/blog/post-2/binexpl_hu_afca672637b6b98d.png deleted file mode 100644 index 977496e..0000000 Binary files a/public/images/blog/post-2/binexpl_hu_afca672637b6b98d.png and /dev/null differ diff --git a/public/images/blog/post-2/binexpl_hu_c4ad8346ff8a0dac.webp b/public/images/blog/post-2/binexpl_hu_c4ad8346ff8a0dac.webp deleted file mode 100644 index 88ab527..0000000 Binary files a/public/images/blog/post-2/binexpl_hu_c4ad8346ff8a0dac.webp and /dev/null differ diff --git a/public/images/blog/post-2/binexpl_hu_fd757ee89fe03225.png b/public/images/blog/post-2/binexpl_hu_fd757ee89fe03225.png deleted file mode 100644 index 95551cf..0000000 Binary files a/public/images/blog/post-2/binexpl_hu_fd757ee89fe03225.png and /dev/null differ diff --git a/public/images/blog/post-2/infiniteluck_hu_953e025153d002b1.webp b/public/images/blog/post-2/infiniteluck_hu_953e025153d002b1.webp deleted file mode 100644 index 321f5fb..0000000 Binary files a/public/images/blog/post-2/infiniteluck_hu_953e025153d002b1.webp and /dev/null differ diff --git a/public/images/blog/post-2/infiniteluck_hu_b9a0d6c771061779.png b/public/images/blog/post-2/infiniteluck_hu_b9a0d6c771061779.png deleted file mode 100644 index 4eecc04..0000000 Binary files a/public/images/blog/post-2/infiniteluck_hu_b9a0d6c771061779.png and /dev/null differ diff --git a/public/images/blog/post-2/infiniteluck_solved_hu_a866f113a85dec5c.png b/public/images/blog/post-2/infiniteluck_solved_hu_a866f113a85dec5c.png deleted file mode 100644 index e2b5a7b..0000000 Binary files a/public/images/blog/post-2/infiniteluck_solved_hu_a866f113a85dec5c.png and /dev/null differ diff --git a/public/images/blog/post-2/infiniteluck_solved_hu_d93ed737be1e3c68.webp b/public/images/blog/post-2/infiniteluck_solved_hu_d93ed737be1e3c68.webp deleted file mode 100644 index b68c392..0000000 Binary files a/public/images/blog/post-2/infiniteluck_solved_hu_d93ed737be1e3c68.webp and /dev/null differ diff --git a/public/images/blog/post-2/ourencissec_hu_12ab834545d390f3.png b/public/images/blog/post-2/ourencissec_hu_12ab834545d390f3.png deleted file mode 100644 index 94d7490..0000000 Binary files a/public/images/blog/post-2/ourencissec_hu_12ab834545d390f3.png and /dev/null differ diff --git a/public/images/blog/post-2/ourencissec_hu_d55d42cf9aa95894.webp b/public/images/blog/post-2/ourencissec_hu_d55d42cf9aa95894.webp deleted file mode 100644 index 5514534..0000000 Binary files a/public/images/blog/post-2/ourencissec_hu_d55d42cf9aa95894.webp and /dev/null differ diff --git a/public/images/blog/post-9/kanji_hu_20d5b55e73e6647f.webp b/public/images/blog/post-9/kanji_hu_20d5b55e73e6647f.webp deleted file mode 100644 index 08ff3cc..0000000 Binary files a/public/images/blog/post-9/kanji_hu_20d5b55e73e6647f.webp and /dev/null differ diff --git a/public/images/blog/post-9/kanji_hu_b5aa293dad257f82.jpg b/public/images/blog/post-9/kanji_hu_b5aa293dad257f82.jpg deleted file mode 100644 index faaaadd..0000000 Binary files a/public/images/blog/post-9/kanji_hu_b5aa293dad257f82.jpg and /dev/null differ diff --git a/public/images/blog/post-9/kanji_hu_cb94278c2a4893cd.webp b/public/images/blog/post-9/kanji_hu_cb94278c2a4893cd.webp deleted file mode 100644 index c144d3c..0000000 Binary files a/public/images/blog/post-9/kanji_hu_cb94278c2a4893cd.webp and /dev/null differ diff --git a/public/images/blog/post-9/kanji_hu_cccb2aeff2a8cb2.jpg b/public/images/blog/post-9/kanji_hu_cccb2aeff2a8cb2.jpg deleted file mode 100644 index 554527a..0000000 Binary files a/public/images/blog/post-9/kanji_hu_cccb2aeff2a8cb2.jpg and /dev/null differ diff --git a/public/images/blog/post-9/lume-datechange_hu_32920abe347fe0ea.webp b/public/images/blog/post-9/lume-datechange_hu_32920abe347fe0ea.webp deleted file mode 100644 index fa11ed8..0000000 Binary files a/public/images/blog/post-9/lume-datechange_hu_32920abe347fe0ea.webp and /dev/null differ diff --git a/public/images/blog/post-9/lume-datechange_hu_4959a4689892aa3d.jpg b/public/images/blog/post-9/lume-datechange_hu_4959a4689892aa3d.jpg deleted file mode 100644 index ce58dce..0000000 Binary files a/public/images/blog/post-9/lume-datechange_hu_4959a4689892aa3d.jpg and /dev/null differ diff --git a/public/images/blog/post-9/lume-datechange_hu_797322be2becf270.webp b/public/images/blog/post-9/lume-datechange_hu_797322be2becf270.webp deleted file mode 100644 index fa11ed8..0000000 Binary files a/public/images/blog/post-9/lume-datechange_hu_797322be2becf270.webp and /dev/null differ diff --git a/public/images/blog/post-9/lume-datechange_hu_e8adf7e2924f376a.jpg b/public/images/blog/post-9/lume-datechange_hu_e8adf7e2924f376a.jpg deleted file mode 100644 index ce58dce..0000000 Binary files a/public/images/blog/post-9/lume-datechange_hu_e8adf7e2924f376a.jpg and /dev/null differ diff --git a/public/images/favicon.png b/public/images/favicon.png deleted file mode 100644 index d1f1382..0000000 Binary files a/public/images/favicon.png and /dev/null differ diff --git a/public/images/favicon_hu_302f3e1abb47ae13.png b/public/images/favicon_hu_302f3e1abb47ae13.png deleted file mode 100644 index 77bacc3..0000000 Binary files a/public/images/favicon_hu_302f3e1abb47ae13.png and /dev/null differ diff --git a/public/images/favicon_hu_50a8dfcefba7e8a8.png b/public/images/favicon_hu_50a8dfcefba7e8a8.png deleted file mode 100644 index 916bebe..0000000 Binary files a/public/images/favicon_hu_50a8dfcefba7e8a8.png and /dev/null differ diff --git a/public/images/favicon_hu_6da0167f32a32123.png b/public/images/favicon_hu_6da0167f32a32123.png deleted file mode 100644 index 8a5588d..0000000 Binary files a/public/images/favicon_hu_6da0167f32a32123.png and /dev/null differ diff --git a/public/images/favicon_hu_78447c6bde7c0620.png b/public/images/favicon_hu_78447c6bde7c0620.png deleted file mode 100644 index 878b60b..0000000 Binary files a/public/images/favicon_hu_78447c6bde7c0620.png and /dev/null differ diff --git a/public/images/favicon_hu_8fe24b8d7739e95a.png b/public/images/favicon_hu_8fe24b8d7739e95a.png deleted file mode 100644 index 8a5588d..0000000 Binary files a/public/images/favicon_hu_8fe24b8d7739e95a.png and /dev/null differ diff --git a/public/images/favicon_hu_997547777bc65c3.png b/public/images/favicon_hu_997547777bc65c3.png deleted file mode 100644 index 4e0bb9c..0000000 Binary files a/public/images/favicon_hu_997547777bc65c3.png and /dev/null differ diff --git a/public/images/favicon_hu_a0382c90d2ab5755.png b/public/images/favicon_hu_a0382c90d2ab5755.png deleted file mode 100644 index 916bebe..0000000 Binary files a/public/images/favicon_hu_a0382c90d2ab5755.png and /dev/null differ diff --git a/public/images/favicon_hu_d4d33babbe6805bc.png b/public/images/favicon_hu_d4d33babbe6805bc.png deleted file mode 100644 index 96695f9..0000000 Binary files a/public/images/favicon_hu_d4d33babbe6805bc.png and /dev/null differ diff --git a/public/images/favicon_hu_e23ec60231f79d1f.png b/public/images/favicon_hu_e23ec60231f79d1f.png deleted file mode 100644 index 878b60b..0000000 Binary files a/public/images/favicon_hu_e23ec60231f79d1f.png and /dev/null differ diff --git a/public/images/hero-image.png b/public/images/hero-image.png deleted file mode 100644 index 6129038..0000000 Binary files a/public/images/hero-image.png and /dev/null differ diff --git a/public/images/hero-image_hu_f3923c21a722e39f.webp b/public/images/hero-image_hu_f3923c21a722e39f.webp deleted file mode 100644 index 018bc8a..0000000 Binary files a/public/images/hero-image_hu_f3923c21a722e39f.webp and /dev/null differ diff --git a/public/images/project/project-1.jpg b/public/images/project/project-1.jpg deleted file mode 100644 index 887cdc3..0000000 Binary files a/public/images/project/project-1.jpg and /dev/null differ diff --git a/public/images/project/project-1_hu_3db5ce4165d1b6f3.webp b/public/images/project/project-1_hu_3db5ce4165d1b6f3.webp deleted file mode 100644 index 2ff7d06..0000000 Binary files a/public/images/project/project-1_hu_3db5ce4165d1b6f3.webp and /dev/null differ diff --git a/public/images/project/project-1_hu_68d5a2119239b167.webp b/public/images/project/project-1_hu_68d5a2119239b167.webp deleted file mode 100644 index 1c6d203..0000000 Binary files a/public/images/project/project-1_hu_68d5a2119239b167.webp and /dev/null differ diff --git a/public/images/project/project-1_hu_7691192a371c30a3.jpg b/public/images/project/project-1_hu_7691192a371c30a3.jpg deleted file mode 100644 index 69e16c3..0000000 Binary files a/public/images/project/project-1_hu_7691192a371c30a3.jpg and /dev/null differ diff --git a/public/images/project/project-1_hu_813aa01d28c91be8.webp b/public/images/project/project-1_hu_813aa01d28c91be8.webp deleted file mode 100644 index 4979647..0000000 Binary files a/public/images/project/project-1_hu_813aa01d28c91be8.webp and /dev/null differ diff --git a/public/images/project/project-1_hu_91234f21b7fc2747.webp b/public/images/project/project-1_hu_91234f21b7fc2747.webp deleted file mode 100644 index 48ef6ee..0000000 Binary files a/public/images/project/project-1_hu_91234f21b7fc2747.webp and /dev/null differ diff --git a/public/images/project/project-1_hu_dec4815bd5f71510.jpg b/public/images/project/project-1_hu_dec4815bd5f71510.jpg deleted file mode 100644 index 359c8e8..0000000 Binary files a/public/images/project/project-1_hu_dec4815bd5f71510.jpg and /dev/null differ diff --git a/public/images/project/project-1_hu_ed479168e0ab0a0a.webp b/public/images/project/project-1_hu_ed479168e0ab0a0a.webp deleted file mode 100644 index b8918c8..0000000 Binary files a/public/images/project/project-1_hu_ed479168e0ab0a0a.webp and /dev/null differ diff --git a/public/images/project/project-2.jpg b/public/images/project/project-2.jpg deleted file mode 100644 index 9275996..0000000 Binary files a/public/images/project/project-2.jpg and /dev/null differ diff --git a/public/images/project/project-2_hu_17a4dfbfbd1fe131.webp b/public/images/project/project-2_hu_17a4dfbfbd1fe131.webp deleted file mode 100644 index 806e223..0000000 Binary files a/public/images/project/project-2_hu_17a4dfbfbd1fe131.webp and /dev/null differ diff --git a/public/images/project/project-2_hu_303041cb15e8f076.webp b/public/images/project/project-2_hu_303041cb15e8f076.webp deleted file mode 100644 index 5989c3c..0000000 Binary files a/public/images/project/project-2_hu_303041cb15e8f076.webp and /dev/null differ diff --git a/public/images/project/project-2_hu_3550dd40bf159427.jpg b/public/images/project/project-2_hu_3550dd40bf159427.jpg deleted file mode 100644 index adc72de..0000000 Binary files a/public/images/project/project-2_hu_3550dd40bf159427.jpg and /dev/null differ diff --git a/public/images/project/project-2_hu_424fc483821e09a4.webp b/public/images/project/project-2_hu_424fc483821e09a4.webp deleted file mode 100644 index e729f91..0000000 Binary files a/public/images/project/project-2_hu_424fc483821e09a4.webp and /dev/null differ diff --git a/public/images/project/project-2_hu_8a064f4fe83cadf4.webp b/public/images/project/project-2_hu_8a064f4fe83cadf4.webp deleted file mode 100644 index 76b2e2f..0000000 Binary files a/public/images/project/project-2_hu_8a064f4fe83cadf4.webp and /dev/null differ diff --git a/public/images/project/project-2_hu_b10de0491c6514dc.webp b/public/images/project/project-2_hu_b10de0491c6514dc.webp deleted file mode 100644 index a804028..0000000 Binary files a/public/images/project/project-2_hu_b10de0491c6514dc.webp and /dev/null differ diff --git a/public/images/project/project-2_hu_d49d4c029294e7e.jpg b/public/images/project/project-2_hu_d49d4c029294e7e.jpg deleted file mode 100644 index dd2c282..0000000 Binary files a/public/images/project/project-2_hu_d49d4c029294e7e.jpg and /dev/null differ diff --git a/public/images/project/project-3.jpg b/public/images/project/project-3.jpg deleted file mode 100644 index 84733de..0000000 Binary files a/public/images/project/project-3.jpg and /dev/null differ diff --git a/public/images/project/project-3_hu_180054984159acb.webp b/public/images/project/project-3_hu_180054984159acb.webp deleted file mode 100644 index a90fe04..0000000 Binary files a/public/images/project/project-3_hu_180054984159acb.webp and /dev/null differ diff --git a/public/images/project/project-3_hu_40eec1330ef232bd.webp b/public/images/project/project-3_hu_40eec1330ef232bd.webp deleted file mode 100644 index f2bd468..0000000 Binary files a/public/images/project/project-3_hu_40eec1330ef232bd.webp and /dev/null differ diff --git a/public/images/project/project-3_hu_62a13caff8a630c2.webp b/public/images/project/project-3_hu_62a13caff8a630c2.webp deleted file mode 100644 index 411bea2..0000000 Binary files a/public/images/project/project-3_hu_62a13caff8a630c2.webp and /dev/null differ diff --git a/public/images/project/project-3_hu_64d37c2e369de612.jpg b/public/images/project/project-3_hu_64d37c2e369de612.jpg deleted file mode 100644 index 923ee26..0000000 Binary files a/public/images/project/project-3_hu_64d37c2e369de612.jpg and /dev/null differ diff --git a/public/images/project/project-3_hu_6ffef74af2881d50.webp b/public/images/project/project-3_hu_6ffef74af2881d50.webp deleted file mode 100644 index 88d412e..0000000 Binary files a/public/images/project/project-3_hu_6ffef74af2881d50.webp and /dev/null differ diff --git a/public/images/project/project-3_hu_74a5edf51d9d285d.jpg b/public/images/project/project-3_hu_74a5edf51d9d285d.jpg deleted file mode 100644 index fdb9bb2..0000000 Binary files a/public/images/project/project-3_hu_74a5edf51d9d285d.jpg and /dev/null differ diff --git a/public/images/project/project-3_hu_9535a5ff19541788.webp b/public/images/project/project-3_hu_9535a5ff19541788.webp deleted file mode 100644 index 96fb108..0000000 Binary files a/public/images/project/project-3_hu_9535a5ff19541788.webp and /dev/null differ diff --git a/public/images/project/project-3_hu_9a71e7d65d0c4faf.jpg b/public/images/project/project-3_hu_9a71e7d65d0c4faf.jpg deleted file mode 100644 index c3e1158..0000000 Binary files a/public/images/project/project-3_hu_9a71e7d65d0c4faf.jpg and /dev/null differ diff --git a/public/images/project/project-3_hu_9d6702f14e8f2c3b.jpg b/public/images/project/project-3_hu_9d6702f14e8f2c3b.jpg deleted file mode 100644 index 375c49b..0000000 Binary files a/public/images/project/project-3_hu_9d6702f14e8f2c3b.jpg and /dev/null differ diff --git a/public/images/project/project-3_hu_a2e987e158776bbc.webp b/public/images/project/project-3_hu_a2e987e158776bbc.webp deleted file mode 100644 index dd598c4..0000000 Binary files a/public/images/project/project-3_hu_a2e987e158776bbc.webp and /dev/null differ diff --git a/public/images/project/project-3_hu_a68548c55de36b1f.webp b/public/images/project/project-3_hu_a68548c55de36b1f.webp deleted file mode 100644 index f6d98c6..0000000 Binary files a/public/images/project/project-3_hu_a68548c55de36b1f.webp and /dev/null differ diff --git a/public/images/project/project-3_hu_b90c24b136494fce.webp b/public/images/project/project-3_hu_b90c24b136494fce.webp deleted file mode 100644 index edfce82..0000000 Binary files a/public/images/project/project-3_hu_b90c24b136494fce.webp and /dev/null differ diff --git a/public/images/project/project-3_hu_cdba049d937c2697.webp b/public/images/project/project-3_hu_cdba049d937c2697.webp deleted file mode 100644 index fd93627..0000000 Binary files a/public/images/project/project-3_hu_cdba049d937c2697.webp and /dev/null differ diff --git a/public/images/project/project-3_hu_e67ec575b7f17bcf.webp b/public/images/project/project-3_hu_e67ec575b7f17bcf.webp deleted file mode 100644 index e7148f7..0000000 Binary files a/public/images/project/project-3_hu_e67ec575b7f17bcf.webp and /dev/null differ diff --git a/public/index.html b/public/index.html deleted file mode 100644 index 2ef8931..0000000 --- a/public/index.html +++ /dev/null @@ -1,12070 +0,0 @@ - - - - - - - -Home | Joren - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Home | Joren - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - -
-
-
-
-
-

My Skills

-
- - - -
- -
-
-
-
- Linux Systems & Bash - 90% -
-
-
-
-
-
-
- -
-
-
-
- Go Programming - 75% -
-
-
-
-
-
-
- -
-
-
-
- Python Development - 85% -
-
-
-
-
-
-
- -
-
-
-
- C# / Java (OOP) - 70% -
-
-
-
-
-
-
- -
-
-
-
- Pentesting Tools (e.g. Burp, Nmap) - 80% -
-
-
-
-
-
-
- -
-
-
-
- SIEM Setup & Monitoring - 75% -
-
-
-
-
-
-
- -
-
-
-
- Networking & Firewalls - 80% -
-
-
-
-
-
-
- -
-
-
-
- Hardware Troubleshooting - 85% -
-
-
-
-
-
-
- -
- -
-
-
-
- - - - - -
-
-
-
-
- - -
-
-

- Experiences -

-
-
- -
- -
- -
- - - -
-

- Cybersecurity Intern -

- -

- Initeam, Izegem -

- - - - Feb 2025 – May 2025 - - - - -
Worked as part of the internal IT and security team focusing on pentesting, SIEM setup, and detection rule testing. Gained practical experience in threat analysis, vulnerability assessments, and configuring security monitoring tools in a real-world business environment. -
- -
-
- -
- -
- -
- - - -
-

- IT Student Worker -

- -

- CAPAC/HVW, Brussels -

- - - - Jun 2022 – Aug 2022 - - - - -
Provided first-line support in a government IT department, managing user accounts in Active Directory, performing hardware repairs, and handling end-user issues with professionalism and efficiency. -
- -
-
- -
- -
- -
- - - -
-

- IT Intern -

- -

- CAPAC/HVW, Brussels -

- - - - 2021 – 2022 - - - - -
Contributed to laptop renewal initiatives and user onboarding. Gained practical exposure to enterprise IT operations, helpdesk workflows, and deployment automation. -
- -
-
- -
-
- - - - - -
-
-

- Education -

-
-
- -
- -
- -
- - - -
-

- Bachelor in Applied Computer Science - Cybersecurity -

- - - - 2022 – Present - - - - -
Focused on secure software development, ethical hacking, digital forensics, and network defense. Regularly participate in cybersecurity labs and capture-the-flag (CTF) events to hone hands-on skills. -
- -
-
- -
- -
- -
- - - -
-

- Industrial ICT -

- - - - 2020 – 2022 - - - - -
Developed a strong foundation in embedded systems, networking, and software-hardware interfacing. Engaged in technical projects that integrated electronics with programming. -
- -
-
- -
- -
- -
- - - -
-

- Secondary Education - Mathematics and Sciences -

- - - - 2016 – 2020 - - - - -
Solid academic training in analytical thinking, logic, and scientific methodology. Sparked initial interest in computing and problem-solving. -
- -
-
- -
-
- - - - -
-
-
-
-
-
- - - - - - -
-
-
-
-
-

Recent Projects

-
- - - - - - -
-
-
-
- - - - - - - - -
-
-
-
-
-

Recent Posts

-
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- - -
- All Blogs -
- -
-
-
-
- - - - - - - -
-
-
-
-
-

Get in Touch

-
- -
-
-
-
-
-
- - -
-
- - -
- -
- - -
-
- - -
- -
- - -
-
- -
-
-
-
-
- -
-
-

Contact

-

Feel free to reach out, I’m always open to new opportunities and collaborations.

-
-
-
-
- -
- -
-

- Mail -

- -
-
- -
- -
-

- Location -

-
- Mechelen -
-
-
- -
- -
-

- LinkedIn -

- -
-
- -
-
-
- -
-
-
-
-
- - - - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/index.json b/public/index.json deleted file mode 100644 index 32e8752..0000000 --- a/public/index.json +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -[{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["watches","jdm","seiko"],"contents":"In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.\nDesign \u0026amp; Build Quality The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o\u0026rsquo;clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.\nThe case is protected by Seiko\u0026rsquo;s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch\u0026rsquo;s mechanical heart.\nMovement \u0026amp; Performance At its core, the SARV001 is powered by Seiko\u0026rsquo;s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it\u0026rsquo;s not designed for diving.\nWearability \u0026amp; Versatility The watch\u0026rsquo;s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.\nValue Proposition Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.\nFinal Thoughts The Seiko SARV001 exemplifies the brand\u0026rsquo;s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-9_hu_18953a22f9755bfc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-9_hu_e62b76c2afdef019.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-9/","title":"Seiko SARV001: The JDM Sleeper That Punches Above Its Weight"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"},{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["watches","jdm","seiko"],"contents":"In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.\nDesign \u0026amp; Build Quality The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o\u0026rsquo;clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.\nSARV001 Kanji\rThe case is protected by Seiko\u0026rsquo;s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch\u0026rsquo;s mechanical heart.\nMovement \u0026amp; Performance At its core, the SARV001 is powered by Seiko\u0026rsquo;s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it\u0026rsquo;s not designed for diving.\nWearability \u0026amp; Versatility The watch\u0026rsquo;s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.\nValue Proposition Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.\nFinal Thoughts The Seiko SARV001 exemplifies the brand\u0026rsquo;s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-9_hu_18953a22f9755bfc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-9_hu_e62b76c2afdef019.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-9/","title":"Seiko SARV001: The JDM Sleeper That Punches Above Its Weight"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"},{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"},{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["watches","jdm","seiko"],"contents":"In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.\nDesign \u0026amp; Build Quality The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o\u0026rsquo;clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.\nSARV001 Kanji\rSARV001 Lume whilst changing day\rThe case is protected by Seiko\u0026rsquo;s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch\u0026rsquo;s mechanical heart.\nMovement \u0026amp; Performance At its core, the SARV001 is powered by Seiko\u0026rsquo;s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it\u0026rsquo;s not designed for diving.\nWearability \u0026amp; Versatility The watch\u0026rsquo;s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.\nValue Proposition Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.\nFinal Thoughts The Seiko SARV001 exemplifies the brand\u0026rsquo;s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-9_hu_18953a22f9755bfc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-9_hu_e62b76c2afdef019.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-9/","title":"Seiko SARV001: The JDM Sleeper That Punches Above Its Weight"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"},{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["watches","jdm","seiko"],"contents":"In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.\nDesign \u0026amp; Build Quality The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o\u0026rsquo;clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.\nSARV001 Kanji\rSARV001 Lume whilst changing day\rThe case is protected by Seiko\u0026rsquo;s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch\u0026rsquo;s mechanical heart.\nMovement \u0026amp; Performance At its core, the SARV001 is powered by Seiko\u0026rsquo;s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it\u0026rsquo;s not designed for diving.\nWearability \u0026amp; Versatility The watch\u0026rsquo;s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.\nValue Proposition Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.\nFinal Thoughts The Seiko SARV001 exemplifies the brand\u0026rsquo;s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-9_hu_18953a22f9755bfc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-9_hu_e62b76c2afdef019.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-9/","title":"Seiko SARV001: The JDM Sleeper That Punches Above Its Weight"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"},{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["watches","jdm","seiko"],"contents":"In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.\nDesign \u0026amp; Build Quality The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o\u0026rsquo;clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.\nSARV001 Kanji\rSARV001 Lume whilst changing day\rThe case is protected by Seiko\u0026rsquo;s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch\u0026rsquo;s mechanical heart.\nMovement \u0026amp; Performance At its core, the SARV001 is powered by Seiko\u0026rsquo;s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it\u0026rsquo;s not designed for diving.\nWearability \u0026amp; Versatility The watch\u0026rsquo;s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.\nValue Proposition Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.\nFinal Thoughts The Seiko SARV001 exemplifies the brand\u0026rsquo;s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-9_hu_18953a22f9755bfc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-9_hu_e62b76c2afdef019.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-9/","title":"Seiko SARV001: The JDM Sleeper That Punches Above Its Weight"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"},{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["watches","jdm","seiko"],"contents":"In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.\nDesign \u0026amp; Build Quality The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o\u0026rsquo;clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.\nSARV001 Kanji\rSARV001 Lume whilst changing day\rThe case is protected by Seiko\u0026rsquo;s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch\u0026rsquo;s mechanical heart.\nMovement \u0026amp; Performance At its core, the SARV001 is powered by Seiko\u0026rsquo;s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it\u0026rsquo;s not designed for diving.\nWearability \u0026amp; Versatility The watch\u0026rsquo;s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.\nValue Proposition Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.\nFinal Thoughts The Seiko SARV001 exemplifies the brand\u0026rsquo;s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-9_hu_18953a22f9755bfc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-9_hu_e62b76c2afdef019.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-9/","title":"Seiko SARV001: The JDM Sleeper That Punches Above Its Weight"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"},{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["watches","jdm","seiko"],"contents":"In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.\nDesign \u0026amp; Build Quality The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o\u0026rsquo;clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.\nSARV001 Kanji\rSARV001 Lume whilst changing day\rThe case is protected by Seiko\u0026rsquo;s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch\u0026rsquo;s mechanical heart.\nMovement \u0026amp; Performance At its core, the SARV001 is powered by Seiko\u0026rsquo;s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it\u0026rsquo;s not designed for diving.\nWearability \u0026amp; Versatility The watch\u0026rsquo;s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.\nValue Proposition Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.\nFinal Thoughts The Seiko SARV001 exemplifies the brand\u0026rsquo;s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-9_hu_18953a22f9755bfc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-9_hu_e62b76c2afdef019.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-9/","title":"Seiko SARV001: The JDM Sleeper That Punches Above Its Weight"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"},{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["watches","jdm","seiko"],"contents":"In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.\nDesign \u0026amp; Build Quality The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o\u0026rsquo;clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.\nSARV001 Kanji\rSARV001 Lume whilst changing day\rThe case is protected by Seiko\u0026rsquo;s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch\u0026rsquo;s mechanical heart.\nMovement \u0026amp; Performance At its core, the SARV001 is powered by Seiko\u0026rsquo;s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it\u0026rsquo;s not designed for diving.\nWearability \u0026amp; Versatility The watch\u0026rsquo;s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.\nValue Proposition Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.\nFinal Thoughts The Seiko SARV001 exemplifies the brand\u0026rsquo;s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-9_hu_18953a22f9755bfc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-9_hu_e62b76c2afdef019.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-9/","title":"Seiko SARV001: The JDM Sleeper That Punches Above Its Weight"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"},{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["watches","jdm","seiko"],"contents":"In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.\nDesign \u0026amp; Build Quality The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o\u0026rsquo;clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.\nSARV001 Kanji\rSARV001 Lume whilst changing day\rThe case is protected by Seiko\u0026rsquo;s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch\u0026rsquo;s mechanical heart.\nMovement \u0026amp; Performance At its core, the SARV001 is powered by Seiko\u0026rsquo;s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it\u0026rsquo;s not designed for diving.\nWearability \u0026amp; Versatility The watch\u0026rsquo;s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.\nValue Proposition Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.\nFinal Thoughts The Seiko SARV001 exemplifies the brand\u0026rsquo;s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-9_hu_18953a22f9755bfc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-9_hu_e62b76c2afdef019.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-9/","title":"Seiko SARV001: The JDM Sleeper That Punches Above Its Weight"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"},{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["watches","jdm","seiko"],"contents":"In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.\nDesign \u0026amp; Build Quality The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o\u0026rsquo;clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.\nSARV001 Kanji\rSARV001 Lume\rThe case is protected by Seiko\u0026rsquo;s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch\u0026rsquo;s mechanical heart.\nMovement \u0026amp; Performance At its core, the SARV001 is powered by Seiko\u0026rsquo;s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it\u0026rsquo;s not designed for diving.\nWearability \u0026amp; Versatility The watch\u0026rsquo;s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.\nValue Proposition Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.\nFinal Thoughts The Seiko SARV001 exemplifies the brand\u0026rsquo;s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-9_hu_18953a22f9755bfc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-9_hu_e62b76c2afdef019.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-9/","title":"Seiko SARV001: The JDM Sleeper That Punches Above Its Weight"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"},{"categories":["iot","hardware","reverse engineering"],"contents":"When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?\nThis post documents a hands-on assessment of the LSC SMART PTZ Camera (Model IPC167), a low-cost, Tuya-based IoT device sold at Action. While it ticks many boxes on paper, TLS, OTA updates, encrypted storage, physical access opens a completely different chapter.\nTriggering Debug Mode with a MicroSD Card Under normal operation, the camera exposes a single LAN control port and requires authentication. But the real surprise lies in how it reacts to external media.\nInsert a specially crafted SD card containing certain files, and the device silently enables Telnet and FTP services at boot, with root access using credentials from the card. No prompt. No warning. The system trusts the card implicitly.\nThis is intended for factory debugging, but it still exists in the retail device, and there are no warnings in the user manual. Once active, Telnet gives full shell access with UID 0. All processes run as root. It’s not just insecure, it’s reckless.\nUART Interface: Disabled Login, But Still There A quick teardown revealed a UART interface on the PCB. While login is currently disabled, its presence adds another attack vector. UART could enable firmware dumping, memory access, or even re-enabling local shells in earlier firmware revisions.\nCombined with the SD card behavior, it paints a clear picture: if you can touch the device, you own it.\nWhat Could Go Wrong? Plenty. With root access via SD card:\nYou can replace binaries or inject backdoors. Extract credentials, keys, or tokens stored in the SQLite database. Modify the video stream, disable motion detection, or proxy footage. Use the device as a pivot point in a local network attack. All of this without triggering any alarms, logs, or user notifications.\nBut It Encrypts Traffic? Yes. TLS over MQTT for telemetry. Encrypted UDP for video. Encrypted SQLite storage. From a remote attacker’s perspective, it looks secure.\nBut physical access breaks the whole model. And physical attacks are not just theoretical, especially for devices placed outdoors or in public environments.\nWhat Can Be Done? Fixing this requires more than software updates. It’s about rethinking assumptions.\nFactory debug hooks should be disabled or removed before shipment. Bootloaders should verify signatures, not blindly trust SD cards. Telnet should never be enabled automatically, ever. Sensitive functions should not run as root unless absolutely required. Until then, buyers are getting more than they bargained for.\nFinal Thoughts This was a cheap camera. It delivered on video quality and mobile app UX. But under the surface, it’s a wide-open platform for attackers with a screwdriver and a microSD card.\nIf you’re building IoT gear: assume physical access and plan for it. If you’re buying IoT gear: assume nothing until you’ve torn it apart.\nSecurity is more than encryption and TLS. It’s what happens when someone walks up, pops the back cover, and flips the whole threat model on its head.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-8_hu_a605adb3511bef5f.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-8_hu_c5615396480723ed.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-8/","title":"Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera"},{"categories":["cybersecurity","offensive","windows"],"contents":"Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like Kerberoasting, delegation abuse, and ticket impersonation.\nHow Kerberos Actually Works Authentication starts when a user logs in and the Key Distribution Center (KDC), a service on the domain controller, issues a TGT (Ticket Granting Ticket) encrypted with the user’s secret. This lets the user request service tickets to access other services without sending credentials again.\nFrom a security model perspective, this is elegant. Credentials never cross the wire. Everything is based on secret keys and symmetric encryption. But this also assumes every piece in the chain, from domain users to service accounts, is configured securely.\nSpoiler: they rarely are.\nKerberoasting: Plaintext Passwords in Disguise If a service account uses a weak password, it\u0026rsquo;s game over.\nService tickets are encrypted with the service account’s password hash. Any domain user can request a ticket to any SPN (Service Principal Name), even without legitimate access. The attacker just needs to capture the ticket and brute-force it offline.\nRequest SPN ticket → Extract ticket → Crack with hashcat Kerberoasting doesn’t require elevated rights. Just domain access. And if that SPN maps to a privileged account (e.g. Domain Admin used for SQL service), cracking that password opens the domain.\nDefault AD configs don’t restrict this. Detection? Hard. Ticket requests look normal. Mitigation? Use strong, random passwords for service accounts. Monitor ticket requests for unusual patterns.\nDelegation: More Trust, More Problems Kerberos supports delegation, allowing services to act on behalf of users. Useful for SSO scenarios like web apps accessing databases, but dangerous if abused.\nUnconstrained Delegation lets a service impersonate any user who authenticates to it. If an attacker compromises such a host, they can extract users’ TGTs and use them elsewhere, effectively becoming them. Golden ticket territory.\nConstrained Delegation tries to limit this to specific services. But it’s often misconfigured. And worse, Resource-Based Constrained Delegation (RBCD) lets target systems define who can delegate to them, opening up attack chains where a low-priv user adds a rogue computer object and escalates.\nThese trust edges form a privilege escalation graph. BloodHound maps this beautifully.\nTicket Forgery and Impersonation Once an attacker gets the KRBTGT account’s hash (e.g. via DCSync), they can create Golden Tickets, valid TGTs for any user, any group, any time. Total domain compromise.\nMore subtle is Silver Ticketing. Here, the attacker forges only the service ticket, not the TGT. Requires the service account’s hash, not KRBTGT. Harder to detect. Ideal for lateral movement.\nTools like Rubeus automate this: asktgt, s4u, tgtdeleg, kerberoast, golden, and silver.\nWorked Example: Kerberoasting with Rubeus Rubeus.exe kerberoast /format:hashcat /user:svc_sql /domain:corp.local → Dumps service tickets in hashcat format.\nhashcat -m 13100 hashes.txt rockyou.txt → Cracks the SPN ticket. If the password is weak, you’re in.\nThis is achievable from any domain user account. No alerts triggered, unless you’ve configured ticket monitoring.\nFinal Thoughts Kerberos isn’t broken. But it’s trust-heavy. And Windows environments are often too trusting.\nStrong service account hygiene, strict delegation configs, and monitoring ticket activity are the bare minimum. Defensive tools like klist, event ID 4769, and Kerberoast detection rules help, but only if actively used.\nIn red team ops, Kerberos attacks are quiet, credential-free, and highly effective. They don’t break the protocol. They exploit how admins use it.\nWant to defend the kingdom? Start by defending the keys.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-7_hu_35062733e5b10c39.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"371\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-7_hu_a100653844898565.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-7/","title":"Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains"},{"categories":["self-hosting","networking","alpine-linux","vpn","dns"],"contents":"Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.\nWhy Diskless? The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.\nBase Setup The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.\nDNS and Ad Blocking: Blocky Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.\nHighlights:\nLocal resolution for custom domains like directme.in Cloudflare, Google as upstream resolvers Per-IP blocking rules Prometheus metrics for monitoring Example config:\nblocking: denylists: ads: - https://big.oisd.nl/domainswild vtm: - /home/joren/dns/vtmgo.txt clientGroupsBlock: default: - ads 192.168.178.123: - vtm VPN: WireGuard via PiVPN WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.\nKey benefits in this setup:\nClient management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:\npivpn -a # add client pivpn -r # remove client pivpn -off \u0026lt;name\u0026gt; # temporarily disable Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.\nMonitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.\nBackups included. One command backs up all configs: pivpn -bk.\nExample output:\n::: Connected Clients List ::: Name Remote IP Virtual IP Bytes Received Bytes Sent Last Seen Phone 84.199.x.x:60042 10.60.150.2 439MiB 3.3GiB May 29 2025 - 22:39:56 In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.\nIRC: ngIRCd For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.\nThe server is configured to:\nAutojoin clients to a default #General channel Support cloaking for user privacy Restrict joins per user/IP to prevent abuse Provide operator access with predefined credentials Disable DNS and Ident lookups for speed and reduced leakage Here\u0026rsquo;s a snapshot of the active configuration:\n[Global] Name = irc.alpine4071 Info = RAM-only IRC Server Listen = 0.0.0.0 Ports = 6667 MotdPhrase = \u0026#34;Welcome to our RAM-only IRC server!\u0026#34; AdminInfo1 = IRC Server AdminInfo2 = Anywhere On Earth AdminEMail = admin@irc.alpine4071 [SSL] CertFile = /home/joren/certs/fullchain1.pem KeyFile = /home/joren/certs/privkey1.pem Ports = 6697, 6698 Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:\n[Channel] Name = #General Topic = General Channel Autojoin = yes Why ngIRCd?\nIt works well on memory-constrained systems. It doesn’t require database backends or scripting engines. It supports modern essentials like TLS, cloaking, and structured limits. It’s simple to secure and configure, even when exposed to the open internet. This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.\nYou can connect today via:\nirc://alpine-4071.duckdns.org:6667 (plaintext) ircs://alpine-4071.duckdns.org:6697 (TLS) Making It Stick: LBU To persist changes in a stateless system, I use Alpine’s lbu:\nlbu include /etc/blocky/config.yml lbu include /etc/ngircd/ngircd.conf lbu commit -d This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.\nRunlevel Integration All services are enabled through OpenRC:\nrc-update add blocky default rc-update add wg-quick default rc-update add ngircd default rc-update add iptables default Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.\nFinal Thoughts Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-3_hu_180054984159acb.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"464\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-3_hu_64d37c2e369de612.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-3/","title":"Lean and Local: DNS, VPN, IRC and Ad Blocking"},{"categories":["cybersecurity","communication","decentralization"],"contents":"If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn\u0026rsquo;t trapped in walled gardens.\nIn this post, we explore what Matrix is, how it works, where it\u0026rsquo;s being used, how you can adopt it yourself, and why it matters for the future of cybersecurity, collaboration, and digital sovereignty.\nWhat is Matrix? Matrix is an open standard for interoperable, real-time communication over IP, designed to provide a decentralized alternative to proprietary messaging platforms. Just like email or the web, Matrix is federated, anyone can host a homeserver, and users on different homeservers can still talk to each other.\nMatrix isn’t an app. It’s a protocol. There are many clients (like Element) and server implementations (like Synapse) built on top of it. Communication is handled via JSON over HTTPS, using persistent rooms and event-based message history, with eventual consistency across the federation.\nMatrix supports:\nText messaging (1:1 and group) End-to-end encryption (Olm/Megolm) Voice and video calls (WebRTC) File sharing Threaded conversations Bridging to other networks (Slack, IRC, Telegram, WhatsApp, etc.) Bots, widgets, and integrations Federation and Interoperability The power of Matrix lies in federation. Just like you don’t need a Gmail account to email someone using Outlook, you don’t need to be on the same Matrix server to chat. This model distributes control across the network, eliminating single points of failure and censorship risk.\nBridges extend this idea further by connecting Matrix rooms to non-Matrix platforms. Want to keep your team on Matrix but still message a colleague on Slack? You can. Matrix becomes a universal glue layer for all communication.\nSupported bridge targets include:\nSlack Discord Microsoft Teams IRC Telegram WhatsApp Signal (community bridges) Security: End-to-End Encryption by Default Matrix takes security seriously. Its end-to-end encryption (E2EE) is based on the Olm and Megolm ratchets, inspired by the Double Ratchet used by Signal. In private rooms, encryption is enabled by default.\nEncryption features include:\nForward secrecy Device verification and cross-signing Secure backup with recovery keys Key sharing and gossiping for reliable message delivery Support for multiple devices per user In contrast to Signal, Matrix\u0026rsquo;s E2EE is multi-device aware by design. You can log in from your phone, laptop, and tablet, and still maintain encryption with all peers.\nReal-World Usage Matrix is not just experimental, it’s deployed at scale:\nThe French government built Tchap, a Matrix-based internal messaging system used by over 30 ministries. German Bundeswehr and healthcare services use Matrix to comply with national data sovereignty and security standards. Mozilla, KDE, F-Droid, and many FOSS communities use Matrix for open collaboration. The European Commission and NATO-affiliated organizations explore Matrix for secure, federated communication in cyber operations. Matrix in Cybersecurity Contexts In red team/blue team simulations, robust and flexible comms are critical. Matrix excels in:\nOut-of-band communication when primary networks are compromised. C2 channel simulation in adversary emulation labs. Logging and transparency during incident response (Matrix rooms retain full audit trails). Bridging internal and external teams (e.g., SOC ↔ pentest team ↔ management). Security testing: Matrix clients and bridges offer exploitable surfaces for training scenarios. In exercises like Locked Shields, where real-time coordination under pressure is key, Matrix could function as a fault-tolerant, cross-team coordination layer, especially when bridged to legacy systems.\nRunning Your Own Homeserver Matrix is self-hostable. This gives full control over identity, data, and federation policies. The most popular server implementation is Synapse, but others like Dendrite (Go, lightweight) and Conduit (Rust, performance-focused) are gaining traction.\nMinimum Setup:\nSynapse (Python-based) PostgreSQL backend Reverse proxy (NGINX) DNS (SRV + .well-known for federation) TLS via Let’s Encrypt Optional: SSO, LDAP, backup, TURN server for VoIP Pro Tips:\nUse https://element.io/pricing for managed hosting if self-hosting is too much overhead. Enable E2EE backup to retain message history across devices. Harden your server: rate-limit federation, restrict registration, enforce TLS ciphers. Limitations and Workarounds Matrix is powerful, but not perfect:\nFederation sync can be resource-heavy on large rooms. Encrypted rooms sometimes lag on low-powered clients. Bridges can break when third-party APIs change. Identity is room-based, no global handles like @user across servers. Message ordering across federated servers is eventually consistent, not immediate. Work is ongoing on Matrix 2.0, which includes faster sync (Sliding Sync), a new media repo spec, and better thread handling.\nFinal Thoughts Matrix is what the future of communication could, and should, look like: open, secure, decentralized, and user-controlled. As central platforms tighten their grip on data and limit interoperability, Matrix flips the script. It\u0026rsquo;s not just a protocol. It\u0026rsquo;s a philosophy of sovereignty, transparency, and trustless interoperability.\nWhether you\u0026rsquo;re building a secure system, training the next generation of cyber professionals, or just tired of fragmented messaging, Matrix offers a future where you own your conversations.\nTip\nVisit matrix.org to learn more, or get started today at element.io.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-6_hu_738eea9b9eff29e3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"333\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-6_hu_c559f46af58d7b01.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-6/","title":"Matrix: Building a Decentralized Communication Future"},{"categories":["watches","jdm","seiko"],"contents":"In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.\nDesign \u0026amp; Build Quality The SARV001 boasts a 42mm stainless steel case with a thickness of 11.6mm, offering a balanced presence on the wrist. Its white sunburst dial exudes a subtle elegance, complemented by applied indices and luminous dauphine hands for enhanced legibility. The watch features a day-date complication at 3 o\u0026rsquo;clock, with the unique option to display the day in either English or Japanese Kanji, adding a distinctive JDM touch.\nSARV001 Kanji\rSARV001 Lume\rThe case is protected by Seiko\u0026rsquo;s proprietary Hardlex crystal, known for its durability and resistance to shattering. A see-through case back reveals the inner workings of the movement, providing a glimpse into the watch\u0026rsquo;s mechanical heart.\nMovement \u0026amp; Performance At its core, the SARV001 is powered by Seiko\u0026rsquo;s in-house 4R36 automatic movement, featuring 24 jewels and a 41-hour power reserve. This movement supports both hacking and hand-winding, offering versatility for daily wear. With a water resistance of 100 meters, the watch is well-suited for everyday activities, though it\u0026rsquo;s not designed for diving.\nWearability \u0026amp; Versatility The watch\u0026rsquo;s 22mm lug width and drilled lugs make strap changes straightforward, allowing for customization to suit various occasions. Whether paired with its original stainless steel bracelet or a leather strap, the SARV001 transitions seamlessly from casual to formal settings.\nValue Proposition Priced under 150 EUR, the SARV001 offers features typically found in higher-end models. Its combination of classic aesthetics, reliable mechanics, and thoughtful details like the Kanji day display make it a standout choice for both novice and seasoned collectors seeking a quality timepiece without breaking the bank.\nFinal Thoughts The Seiko SARV001 exemplifies the brand\u0026rsquo;s commitment to craftsmanship and value. Its understated design, robust movement, and unique JDM characteristics make it a compelling option for those looking to add a versatile and reliable watch to their collection.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-9_hu_18953a22f9755bfc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"650\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-9_hu_e62b76c2afdef019.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-9/","title":"Seiko SARV001: The JDM Sleeper That Punches Above Its Weight"},{"categories":["cybersecurity","offensive","network"],"contents":"In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using Responder and mitm6.\nName Resolution Chaos When Windows can\u0026rsquo;t resolve a hostname via DNS, it falls back on legacy protocols: LLMNR (Link-Local Multicast Name Resolution), NBT-NS (NetBIOS Name Service), and increasingly mDNS in mixed environments. These protocols ask anyone nearby: “Do you know who somehost is?”\nAn attacker on the local network can answer \u0026ldquo;yes\u0026rdquo; and claim to be that host. That’s exactly what Responder does. It listens for these requests and pretends to be the missing server, prompting clients to authenticate, typically using NTLM.\nIPv6: Enabled by Default, Forgotten by Admins Even in IPv4-only networks, most Windows clients have IPv6 enabled. If there\u0026rsquo;s no DHCPv6 server, they use router advertisements to configure themselves. mitm6 abuses this by spoofing a rogue IPv6 router, setting itself as the DNS server for all hosts.\nOnce clients start resolving names through the attacker\u0026rsquo;s DNS, the attacker can spoof responses and trick clients into connecting over SMB, LDAPS, or HTTP, exposing NTLM hashes.\nCapturing vs. Relaying Responder captures credentials (NTLMv1/v2), which can be cracked offline with tools like hashcat. But it\u0026rsquo;s often more powerful to relay them live to a legitimate service.\nTools like ntlmrelayx allow relaying to:\nSMB: for file access, command execution, or dumping secrets via secretsdump.py LDAP/LDAPS: to enumerate AD users, modify objects, or create backdoor accounts HTTP/WSMAN: to access internal web apps or trigger remote code execution The success of the relay depends on the target’s configuration. If SMB signing or LDAP channel binding is enforced, the relay will fail. But in many networks, it isn’t.\nRealistic Attack Chain Launch mitm6 to poison IPv6 and become DNS for the subnet. Run ntlmrelayx with appropriate targets (e.g., --smb2support --target smb://10.0.0.5). Wait: a victim resolves an internal name (e.g., fileshare), the attacker responds. The client connects to the attacker thinking it’s the fileshare and sends NTLM credentials. ntlmrelayx relays these to the actual target server. If successful, the attacker gains authenticated access. In parallel, Responder can be used for LLMNR/NBT-NS-based interception in IPv4 networks.\nMitigation This isn\u0026rsquo;t new, but it\u0026rsquo;s often neglected. To prevent these attacks:\nDisable LLMNR and NBT-NS via Group Policy. Disable IPv6 on clients if it\u0026rsquo;s not explicitly required. Enforce SMB signing and LDAP channel binding. Segment your network to reduce the blast radius. Prefer Kerberos authentication over NTLM where possible. Monitor for rogue IPv6 RAs and anomalous name resolution. Final Thoughts If you’re in a flat network with legacy protocols enabled, an attacker doesn’t need exploits, just presence. These are silent, no-packet attacks that rely on trust and misconfiguration. The tools are public. The fixes are known. Yet the exposure is still widespread.\nResponder and mitm6 aren’t magic. They just reveal what’s already broken.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-5_hu_e31b752cd8166a9a.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"343\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-5_hu_2496163d8ca0be9a.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-5/","title":"Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks"},{"categories":["networking","iot","cybersecurity"],"contents":"Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you\u0026rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.\nWhy Segmentation Matters Most people treat their home network like a trust zone. All devices are equal. But they’re not. You wouldn’t let your robot vacuum log into your online banking, yet they live on the same flat LAN. That’s the fundamental issue.\nIoT vendors prioritize cost and features, not security. Devices often ship with:\nDefault credentials No software updates Open ports and broadcast protocols Aggressive telemetry to unknown hosts A compromise is inevitable. The only question is: does that compromise stay local, or pivot deeper into your network?\nVLANs 101 A VLAN (Virtual Local Area Network) logically segments traffic on the same physical infrastructure. Think of it as creating isolated “subnet bubbles” where traffic can be controlled and filtered.\nVLANs let you:\nGroup devices by function (IoT, work, guest) Apply granular rules between segments Limit broadcast traffic and discovery protocols Deny unnecessary cross-talk And you don’t need enterprise gear to do this. Many consumer-grade routers and access points already support VLANs, especially if you install OpenWRT, OPNSense, or just Linux. Even some ISP-provided devices have basic VLAN tagging features tucked away in their advanced menus. You might not need new hardware at all, just better firmware.\nSample Home Setup Let’s say you have a smart home with:\nA Nest thermostat A Samsung smart TV A couple of Tuya smart plugs A doorbell camera Your personal laptop and NAS Step 1: Define VLANs\nVLAN ID Purpose Example Devices 10 LAN (trusted) Laptop, NAS 20 IoT Smart TV, plugs, doorbell 30 Guest WiFi Friends’ phones Step 2: Assign Interfaces\nMost routers allow you to map VLANs to interfaces or SSIDs. Use one SSID per VLAN for WiFi. Wire VLAN-tagged ports for wired devices.\nStep 3: Firewall Rules\nOn VLAN 20 (IoT):\nBlock → LAN (VLAN 10) Block → VLAN 20 (intra-IoT) Allow → DNS, NTP, and cloud endpoints Allow → Internet (443) Log → Any unknown destination Optional: Use static DHCP leases and force DNS through Pi-hole for logging and filtering.\nReal-World Examples Case 1: Smart TV\nBlocked LAN access. Within 5 minutes of boot, it tried to contact:\nSamsung cloud Akamai CDN Google DNS DoubleClick Random advertising domains Video streaming still worked fine. Everything else was noise.\nCase 2: IP Camera\nOn the LAN, it had access to the NAS and router UI. After VLAN isolation, its access was limited to outbound 443 and NTP. Still worked. Couldn’t snoop.\nCaveats \u0026amp; Limitations Some IoT devices rely on MDNS or SSDP for pairing/setup. Consider temporarily whitelisting during setup, then blocking. Chromecast-style devices need special rules if you want casting from your main network. VLANs require managed switches or VLAN-aware APs. Guest VLANs may need bandwidth limits or isolation tweaks. Still, the benefits far outweigh the complexity.\nFinal Thoughts If you’ve ever installed a smart plug and noticed it phones home every few minutes, you\u0026rsquo;re not alone. And if you haven\u0026rsquo;t noticed, maybe you should.\nSecurity in small networks doesn’t need to be complex. VLANs are one of the most powerful tools you can deploy for minimal cost. Set it up once. Sleep better forever.\nYour lightbulb shouldn’t have access to your tax documents.\nTip\nLooking for OpenWRT-compatible routers? Check the OpenWRT Table of Hardware for supported devices.\n","date":"May 30, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-10_hu_e27e2f85e226178c.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"406\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-10_hu_35c38cc09be1cad4.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-10/","title":"The Smart Home Trap: Isolate or Be Owned"},{"categories":null,"contents":"I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.\nCreating the Hugo Site On my development machine, I created a new Hugo site:\nhugo new site howest-blog I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.\nAll content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.\nCustomization I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo\u0026rsquo;s pipeline. Static files like favicons are placed in static/.\nTo preview the site locally:\nhugo server To build the static site:\nhugo This generates everything in the public/ folder.\nVPS Deployment I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:\nscp -r public/* user@my-vps:/var/www/html On the VPS, I installed nginx:\napk add nginx And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:\nrc-service nginx start rc-update add nginx Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.\nWhy Alpine + Hugo? Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.\nThis setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.\n","date":"May 29, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-2_hu_b10de0491c6514dc.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"278\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-2_hu_3550dd40bf159427.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-2/","title":"Building My Hugo Website on a VPS"},{"categories":null,"contents":"DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.\nWhat’s New DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.\nGoals and Use Case The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.\nHow .drmd Files Work A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.\nEach item includes:\nMPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use. Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags. Filename: The name to be used for the final output file. Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file. Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season). Description and Poster: Optional fields used only for display in the web UI. Example .drmd Structure { \u0026#34;Items\u0026#34;: [ { \u0026#34;MPD\u0026#34;: \u0026#34;aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk\u0026#34;, \u0026#34;Keys\u0026#34;: \u0026#34;abcd1234ef567890:00112233445566778899aabbccddeeff\u0026#34;, \u0026#34;Filename\u0026#34;: \u0026#34;ExampleShow.S01E01\u0026#34;, \u0026#34;Subtitles\u0026#34;: \u0026#34;https://example.com/sub1.vtt,https://example.com/sub2.vtt\u0026#34;, \u0026#34;Metadata\u0026#34;: \u0026#34;Example Show;serie;1\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;Pilot episode\u0026#34;, \u0026#34;Poster\u0026#34;: \u0026#34;\u0026#34; } ] } Processing Steps Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket. These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.\nArchitecture Overview The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.\nWeb UI \u0026amp; CLI To use:\n./drmdtool Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:\n./drmdtool -f /path/to/file.drmd Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.\nEnhanced Download Logic DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.\nRepository Code and setup instructions are hosted here: https://git.directme.in/Joren/DRMDTool\nDRMDtool For advanced usage details, customization, and API structure, refer to the README.md in the repository.\n","date":"May 21, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/project/project-1_hu_3db5ce4165d1b6f3.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"396\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/project\\/project-1_hu_7691192a371c30a3.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/project/project-1/","title":"DRMDTool Project"},{"categories":["cybersecurity","podcast","interview"],"contents":"In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met Thomas Castronovo, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.\nVan Interesse tot Loopbaan Thomas deelt hoe zijn interesse in cybersecurity begon tijdens zijn opleiding, met hands-on projecten zoals het hacken van virtuele machines. Een stage bij Deloitte in 2019 zette hem op het pad naar een voltijdse functie binnen het Offensive Security Team. Vandaag werkt hij al drie jaar bij Deloitte België en specialiseert hij zich in offensieve testen.\nOffensive vs. Defensive Security Hoewel zijn hart bij offensieve security ligt, kreeg hij recent ook ervaring aan de defensieve kant. Het leverde hem een breder perspectief op: “Het geeft een heel ander zicht op hoe aanvallen eruitzien vanuit de andere kant.” Toch blijft het red team werk zijn voorkeur behouden.\nWat doet een pentester nu echt? Thomas legt uit hoe een typische pentest verloopt: van het ontvangen van de scope, over het scannen van het netwerk en het zoeken naar kwetsbaarheden, tot het rapporteren van bevindingen. Tools zoals Nessus, BloodHound en PingCastle worden ingezet, vaak gecombineerd met zelfgebouwde scripts die de output analyseren en structureren.\nKwetsbaarheden in Active Directory Een groot deel van zijn werk focust op Active Directory (AD), waar hij telkens weer dezelfde pijnpunten tegenkomt: legacy-instellingen, onvoldoende gepatchte systemen, en misconfiguraties die vaak pas worden rechtgezet na een echte aanval. Twee voorbeelden die hij aanhaalt:\nLLMNR/MDNS/NetBIOS poisoning om credentials te verkrijgen DNS wildcard records die leiden tot man-in-the-middle aanvallen Tools, Tips en Oefenen Voor wie zelf wil beginnen raadt hij aan om zelf een AD op te zetten en tools als PingCastle en BloodHound uit te proberen. De meeste kennis verwerf je volgens Thomas door zelf te oefenen, dingen stuk te maken, en vooral: blijven proberen.\nDe Praktijk vs. Certificaten Hoewel certificaten nuttig zijn (zoals WPT voor webapp testing), benadrukt Thomas dat de echte leerschool het werkveld is. “90% van wat ik weet, heb ik geleerd door het gewoon te doen,” zegt hij. Oefenen op Hack The Box, zelf een netwerk opzetten, en leren van collega’s zijn voor hem essentieel.\nAfsluiter De aflevering toont hoe breed het vakgebied offensive security is: van interne pentests tot phishingcampagnes, van legacy exploits tot zero-days. Maar vooral: het is een vak waar creativiteit en nieuwsgierigheid centraal staan.\n","date":"May 20, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-4_hu_8ddea2f052660626.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-4_hu_96cadc46e7508592.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-4/","title":"Red Team Talk: Een Blik Achter de Schermen bij Offensive Security"},{"categories":["cybersecurity","event"],"contents":"On a Mission with NATO: Cyber Defence on the Frontline Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO\u0026rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.\nThe Exercise: Locked Shields Locked Shields is no ordinary simulation. It is a full-scale, live-fire cyber defence exercise involving more than 6,000 machines and a narrative scenario so detailed it includes geopolitics, disinformation and even fictional countries. This year, the Blue Team 03 (our team) defended a simulated nation’s critical infrastructure including power plants, satellites, 5G networks and banking systems, all while under constant attack from a coordinated Red Team using automated scripts and over 28,000 attacks across two days.\nAnd yes, every team (Red, Blue, Yellow, White) uses Ansible. For everything.\nHigh Stakes, Real Lessons What do you do when a rogue process might be malware, or maybe just a poorly named service? What happens when your teammate refuses to act unless something is “officially malicious”? The team faced cultural clashes, communication breakdowns and stress-testing of both systems and people.\nThe exercise required more than technical fixes. It demanded communication with simulated commanders, media and public stakeholders. Reporting became just as important as patching. It taught participants how to translate technical impact into real-world consequences. Not \u0026ldquo;port 8443 unreachable\u0026rdquo;, but \u0026ldquo;our air defence system is degraded, and we cannot fly planes\u0026rdquo;.\nThe Black Team: Rapid Response in Action A new but powerful presence in the simulation was the Black Team, a rapid-response unit deployed when problems became too complex for any single team. Acting like special forces, they jumped in when incidents crossed team boundaries or demanded unconventional solutions. Their mission was to find out what was happening, assess the impact and suggest fast, creative responses. Introduced just last year, this team quickly proved its value again in 2025. They even embraced the role with style “you can wear sunglasses inside” became their unofficial motto.\nTheir presence underlined a critical lesson: not every problem fits neatly within a team’s silo. Real-world defence requires flexibility, speed and lateral thinking.\nHighlights and Blooper Reel There were plenty of mishaps. Misfired scripts, team mix-ups, and one case where a DNS setup from a previous year was reused by mistake. Someone tried renaming cut to shutdown, breaking essential operations until it was fixed. Systems rebooted into chaos, a manual was uploaded to public GitHub, and the team had to quickly learn the difference between symbolic links and real binaries.\nHuman Factors and Growth From detecting malware with Velociraptor and Q9, to encountering teammates who took orders literally, the learning was intense. One participant noted that while Belgian and Luxembourg teams prioritized knowledge sharing, others preferred strict protocol. This highlighted cultural differences and the importance of interpersonal skills.\nThe biggest lesson? You are never fully prepared. Every iteration of Locked Shields is different. But each one sharpens not only your skills, but also your ability to function as a team under extreme conditions.\nFrom the Battlefield to the Classroom This experience directly impacts the classroom. Inspired by the exercise, Howest is introducing new hands-on courses. Students will be dropped into realistic broken networks, with misconfigurations, fake firewalls and simulated threats. It is chaos, but controlled. And that is the point.\nAs one speaker said: “You don’t win Locked Shields. You just survive it better than the rest.”\nFinal Thoughts The exercise teaches more than just cybersecurity. It builds trust. It proves that knowing your teammates can be as important as knowing the tools. Whether that comes from a shared flight or a pre-exercise barbecue, it all matters when the pressure hits.\nWant to see how cyber defence works in real life? This is it.\n","date":"May 13, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-1_hu_8def6289c64a2dc8.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-1_hu_d77be45b273e444.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-1/","title":"Cyber Defence on the Digital Frontline: A Mission with NATO"},{"categories":["cybersecurity","CTF","education"],"contents":"On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.\nWhat follows is a recap of the challenges I personally worked on, some I solved, some I didn’t, but all of them left me with new skills and new ideas.\nA Buffer Overflow to Warm Up One of the first challenges I picked involved a binary with a basic stack overflow. I used standard techniques, finding the offset, hijacking the return address, and injecting shellcode. Tools like pwntools helped automate the payload crafting. It was a great warm-up and a confidence boost once it worked.\nBinary Exploitation Flag\rOurEncIsSec: Zip Bombs and OEIS Then there was a more elaborate cryptography challenge: 18 zip files, each password-protected. We cracked the first three passwords using John the Ripper and got numeric values from them. I searched the sequence in OEIS and found it matched A007408, which gave us the full pattern of passwords.\nUsing this, I could extract all zip contents automatically, reconstruct the password-protected message, and finally reveal the flag.\nPicture of the solution\rInfinite Luck: One in a Million? One challenge involved “guessing” a thousand random numbers between 1 and 10. The banner claimed it required infinite luck, but of course, the randomness was seeded. After inspecting the generator, I realized it was deterministic. By precomputing seeds and output sequences, I could match the challenge’s banner to a specific seed and regenerate the entire solution.\nChallange picture\rCorrect number order\rAndroid Reversing: FRIDA and JADX Several APKs were part of the qualifier set. I used JADX to decompile them and FRIDA to patch logic at runtime. In one challenge, I bypassed license validation by forcing key methods to return true and unlocking hidden functionality.\nThe Challenge That Stuck with Me: Rebuilding a Split DEX This one stood out.\nThe app used a 4×8 button grid. Pressing buttons loaded a sequence of blockXX files from assets. These were concatenated in-memory and passed into InMemoryDexClassLoader to load a class called be.dauntless.flag.Flag.\nClass loadClass = new InMemoryDexClassLoader(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()), getClassLoader()) .loadClass(\u0026#34;be.dauntless.flag.Flag\u0026#34;); Each block was a fragment of a DEX file, but the app didn’t tell you the right order. I tried manually inspecting the fragments, identifying methods, string constants, and offsets, to infer how to reassemble the full file. I got close, but didn’t crack it in time.\nThat challenge stuck with me because it combined static analysis, runtime introspection, and logic reconstruction. It wasn’t just technical, it was creative.\nThe One That Got Away: TLS Fingerprinting Another challenge involved a Go-based TLS server that rejected all client connections unless they matched a specific fingerprint. I used Go’s tls.Config to replicate the version, cipher suites, and ALPN:\ntls.Config{ MinVersion: tls.VersionTLS13, CipherSuites: []uint16{ tls.TLS_AES_128_GCM_SHA256, // ... }, NextProtos: []string{\u0026#34;h2\u0026#34;}, } Despite that, the server still refused the connection. I suspect it was using JA4 or similar TLS fingerprinting techniques we couldn’t fully emulate. We had to move on, but I’d love to revisit that one someday.\nFinal Thoughts I didn’t solve everything. But that wasn’t the point. Every challenge was a practical puzzle, something to decode, reverse, bypass, or just understand a little better.\nWorking as a team with Evarist, Nathan, and Waut made it even more valuable. We bounced ideas off each other, divided tasks, and got a much broader set of challenges covered.\nThe Cyber Security Challenge Belgium qualifiers weren’t easy. But they were the best kind of difficult, the kind that teaches you something whether you solve the problem or not.\n","date":"March 15, 2025","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/post-2/binexpl_hu_3d36b409c72f3586.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"160\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/post-2\\/binexpl_hu_afca672637b6b98d.png';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-2/","title":"Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience"},{"categories":["cybersecurity","event","defense"],"contents":"On November 12, we had the opportunity to attend a Tech\u0026amp;Meet session unlike any other. The speaker was Colonel Gunther Godefridis, Director for Development \u0026amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.\nHeld at Howest Campus Brugge Station, the event drew students, researchers, and professionals eager to understand how military-grade cybersecurity operations are run, and why they matter more than ever.\nDefending in the Digital Age Colonel Godefridis began by outlining the core mission of Belgian Cyber Command: protecting Defense’s networks and weapon systems, supporting intelligence operations (ADIV), and conducting defensive and offensive operations in cyberspace. In short, Cyber Command isn’t just watching traffic, it’s actively shaping Belgium’s digital resilience.\nWith society’s increasing reliance on digital infrastructure, the risks of espionage, disinformation, and attacks on critical systems are no longer theoretical. Godefridis highlighted the urgency of being able to respond to, not just detect, those threats.\nWorking Together: Academia, Industry, Government One theme that stood out was collaboration. Cyber Command doesn’t operate in a vacuum. It works closely with national agencies, NATO partners, academic institutions, and the private sector. The colonel emphasized that defending cyberspace requires broad cooperation, and Belgium’s approach is to engage across domains, military, civil, and industrial.\nHe also made it clear that this isn’t just about defense systems or classified data. As the line between civil and military digital infrastructure blurs, vulnerabilities in civilian systems can become national security issues. That’s where cooperation becomes essential.\nLeading with Innovation With over 20 years in military service, Colonel Godefridis brings a unique perspective. From artillery innovation to defense technology strategy, and now to cyber development, his background reflects the evolving nature of conflict and the military\u0026rsquo;s response.\nHe discussed how innovation, including artificial intelligence, is becoming central to cyber defense. Cyber Command is investing in tools and skills to automate threat detection, analyze large datasets, and simulate attack scenarios. It’s not just about building walls, it’s about staying several moves ahead.\nA Transparent, Human Conversation The Q\u0026amp;A session at the end made the evening especially memorable. Questions ranged from technical details of cyber defense capabilities to the human side of cyber careers: how people are trained, what skills are valued, and how students might contribute.\nColonel Godefridis was honest about the challenges. Cyber operations evolve quickly, and so do adversaries. But he was equally clear about the opportunity: Belgium is building a capability that matters, and it needs talent.\nFinal Thoughts If you walked into this talk expecting a dry presentation on military infrastructure, you were wrong. This session was a deep, realistic, and engaging look into how Belgium is preparing for cyber conflict, and how students like us could be a part of that mission.\nWhether you’re in cybersecurity, software development, or systems engineering, there’s a growing role to play. And as Colonel Godefridis made clear: it’s not just a job. It’s part of defending a society that’s more vulnerable, and more connected, than ever before.\nTip\nWant to learn more about Cyber Command? Visit the official website at mil.be\n","date":"November 12, 2024","image":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n \n\n \n \n \n \n \n\n\n \n \n\n\n \n \n \n \n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n\n\n \n \n\n\n \u003cimg\n \n src=\"/images/blog/blog-3_hu_fdd9e13d0370b160.webp\" loading=\"lazy\"\n decoding=\"async\"\n \n\n alt=\"\"\n class=\" img\"\n width=\"650\"\n height=\"433\"\n onerror=\"this.onerror='null';\n this.src='\\/images\\/blog\\/blog-3_hu_c932299ff2fa7067.jpg';\" /\u003e\n\n \n \n \n \n \n \n\n\n \n\n","permalink":"/blog/post-3/","title":"Securing Cyberspace: Belgian Cyber Command at Howest"}] \ No newline at end of file diff --git a/public/index.xml b/public/index.xml deleted file mode 100644 index 6108e60..0000000 --- a/public/index.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - Home | Joren on Joren's Site - http://localhost:1313/ - Recent content in Home | Joren on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Cheap Camera, Expensive Risk: Hacking an IoT PTZ Camera - http://localhost:1313/blog/post-8/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-8/ - <p>When you pay €22.95 for a pan-tilt-zoom security camera, you’re not buying enterprise-grade security. But what if you’re also buying root access through an SD card?</p> - - - Kerberos Under Siege: Abusing the Trust Backbone of Windows Domains - http://localhost:1313/blog/post-7/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-7/ - <p>Kerberos, introduced to Windows with Active Directory in 2000, is widely seen as a secure, modern replacement for NTLM. And yet, in the hands of an attacker, it becomes a double-edged sword. This post explores how Kerberos works, and how it can be abused through techniques like <strong>Kerberoasting</strong>, <strong>delegation abuse</strong>, and <strong>ticket impersonation</strong>.</p> - - - Lean and Local: DNS, VPN, IRC and Ad Blocking - http://localhost:1313/project/project-3/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/project/project-3/ - <p>Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.</p> - - - Matrix: Building a Decentralized Communication Future - http://localhost:1313/blog/post-6/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-6/ - <p>If you’ve ever switched between Slack, WhatsApp, Discord, Teams, Signal and Telegram in a single day, you’ve felt the cost of digital fragmentation. We live in a world where communication is siloed into centralized apps, each with its own rules, limits and vulnerabilities. Matrix proposes an alternative: a universal, open, decentralized protocol for real-time communication, where users control their data and messaging isn&rsquo;t trapped in walled gardens.</p> - - - Seiko SARV001: The JDM Sleeper That Punches Above Its Weight - http://localhost:1313/blog/post-9/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-9/ - <p>In the world of horology, the Japanese Domestic Market (JDM) often hides treasures that fly under the radar. One such gem is the Seiko SARV001, a watch that combines classic design, reliable mechanics, and exceptional value.</p> - - - Silent Interception: Exploiting LLMNR, NBT-NS, mDNS and IPv6 in Modern Networks - http://localhost:1313/blog/post-5/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-5/ - <p>In many internal networks, outdated or misconfigured protocols silently create attack surfaces. This post explores how attackers abuse name resolution fallbacks and IPv6 autoconfiguration to capture and relay NTLM credentials using <code>Responder</code> and <code>mitm6</code>.</p> - - - The Smart Home Trap: Isolate or Be Owned - http://localhost:1313/blog/post-10/ - Fri, 30 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-10/ - <p>Smart homes are convenient. But with convenience comes risk. If your doorbell runs Linux, talks to Chinese cloud servers, and sits on the same network as your work laptop, you&rsquo;ve got a problem. The fix? Segmentation. This post explores how to use VLANs and firewall rules to quarantine IoT devices and minimize lateral movement, even on a home budget.</p> - - - Building My Hugo Website on a VPS - http://localhost:1313/project/project-2/ - Thu, 29 May 2025 00:00:00 +0000 - http://localhost:1313/project/project-2/ - <p>I built my personal blog using <a href="https://gohugo.io/" target="_blank" >Hugo</a> and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.</p> - - - DRMDTool Project - http://localhost:1313/project/project-1/ - Wed, 21 May 2025 00:00:00 +0000 - http://localhost:1313/project/project-1/ - <p>DRMDTool is an automation-centric utility designed to streamline the processing of <code>.drmd</code> files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.</p> - - - Red Team Talk: Een Blik Achter de Schermen bij Offensive Security - http://localhost:1313/blog/post-4/ - Tue, 20 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-4/ - <p>In Red Team Talk nemen wij, Joren Schipman en Mattia Punjwani, studenten Cybersecurity aan Howest, jullie mee in een gesprek met <strong>Thomas Castronovo</strong>, ethical hacker en consultant bij Deloitte. Samen duiken we in de wereld van offensieve security, red teaming, en de realiteit van een carrière als pentester.</p> - - - Cyber Defence on the Digital Frontline: A Mission with NATO - http://localhost:1313/blog/post-1/ - Tue, 13 May 2025 00:00:00 +0000 - http://localhost:1313/blog/post-1/ - <h4 id="on-a-mission-with-nato-cyber-defence-on-the-frontline">On a Mission with NATO: Cyber Defence on the Frontline</h4> <p>Howest’s ongoing commitment to world-class cybersecurity training took center stage again as six lecturers from the Cyber Security program joined forces with experts from Latvia, Luxembourg and Belgium in one of NATO&rsquo;s most intensive simulations: the Locked Shields exercise, hosted by the Cooperative Cyber Defence Centre of Excellence (CCDCOE). Now in its fifth year of participation, the Howest team shared their firsthand experiences at a special evening talk at Howest Bruges.</p> - - - Reversing, Rebuilding, and Failing Better: My Cyber Security Challenge Belgium Qualifier Experience - http://localhost:1313/blog/post-2/ - Sat, 15 Mar 2025 00:00:00 +0000 - http://localhost:1313/blog/post-2/ - <p>On March 14 and 15, I joined the Cyber Security Challenge Belgium qualifiers with three teammates. For two days, we threw ourselves at CTF challenges covering binary exploitation, Android reversing, cryptography, and more.</p> - - - Securing Cyberspace: Belgian Cyber Command at Howest - http://localhost:1313/blog/post-3/ - Tue, 12 Nov 2024 00:00:00 +0000 - http://localhost:1313/blog/post-3/ - <p>On November 12, we had the opportunity to attend a Tech&amp;Meet session unlike any other. The speaker was <strong>Colonel Gunther Godefridis</strong>, Director for Development &amp; Readiness at Belgian Cyber Command, and the topic: safeguarding our country in the digital domain.</p> - - - diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest deleted file mode 100644 index c8cb539..0000000 --- a/public/manifest.webmanifest +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "Joren's Site", - "short_name": "Joren's Site", - "lang": "en", - "display": "fullscreen", - "orientation" : "portrait", - "start_url": "http://localhost:1313/?utm_source=web_app_manifest", - "background_color": "#0e1015", - "theme_color": "#18b0a2", - - - - - - - - - - - - "icons": [ - { - "src": "/images/favicon_hu_6da0167f32a32123.png", - "sizes": "48x48", - "type": "image/png" - }, - { - "src": "/images/favicon_hu_d4d33babbe6805bc.png", - "sizes": "72x72", - "type": "image/png" - }, - { - "src": "/images/favicon_hu_78447c6bde7c0620.png", - "sizes": "96x96", - "type": "image/png" - }, - { - "src": "/images/favicon_hu_50a8dfcefba7e8a8.png", - "sizes": "144x144", - "type": "image/png" - }, - { - "src": "/images/favicon_hu_302f3e1abb47ae13.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "any maskable" - }, - { - "src": "/images/favicon_hu_997547777bc65c3.png", - "sizes": "512x512", - "type": "image/png" - } - ] - - -} \ No newline at end of file diff --git a/public/project/index.html b/public/project/index.html deleted file mode 100644 index 378738d..0000000 --- a/public/project/index.html +++ /dev/null @@ -1,9611 +0,0 @@ - - - - - - -Recent Projects - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Recent Projects - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- -

//Recent Projects

-
- - -
-
-
-
- - -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/project/index.xml b/public/project/index.xml deleted file mode 100644 index 00d5e48..0000000 --- a/public/project/index.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - Recent Projects on Joren's Site - https://joren.blog/project/ - Recent content in Recent Projects on Joren's Site - Hugo - en - Fri, 30 May 2025 00:00:00 +0000 - - - Lean and Local: DNS, VPN, IRC and Ad Blocking - https://joren.blog/project/project-3/ - Fri, 30 May 2025 00:00:00 +0000 - https://joren.blog/project/project-3/ - <p>Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.</p> - - - Building My Hugo Website on a VPS - https://joren.blog/project/project-2/ - Thu, 29 May 2025 00:00:00 +0000 - https://joren.blog/project/project-2/ - <p>I built my personal blog using <a href="https://gohugo.io/" target="_blank" >Hugo</a> and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.</p> - - - DRMDTool Project - https://joren.blog/project/project-1/ - Wed, 21 May 2025 00:00:00 +0000 - https://joren.blog/project/project-1/ - <p>DRMDTool is an automation-centric utility designed to streamline the processing of <code>.drmd</code> files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.</p> - - - diff --git a/public/project/project-1/index.html b/public/project/project-1/index.html deleted file mode 100644 index 74f99cb..0000000 --- a/public/project/project-1/index.html +++ /dev/null @@ -1,9398 +0,0 @@ - - - - - - -DRMDTool Project - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -DRMDTool Project - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
- -
-

DRMDTool Project

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DRMDTool Project - - - - - - - - - - - -
- - -
-

DRMDTool is an automation-centric utility designed to streamline the processing of .drmd files by tightly integrating with the N_m3u8DL-RE downloader. The tool offers robust automation via a watch folder and an intuitive web-based interface, significantly reducing the friction for managing and processing DRM-protected streaming content.

-
-

What’s New

-

DRMDTool has evolved into a comprehensive platform for batch downloading with enhanced support for user interaction and background processing. It features granular job tracking, dynamic download control (pause, resume, abort), and a refined WebSocket-based console for real-time command output. Subtitle handling now includes automatic downloading and conversion from VTT to SRT, and the downloader adapts based on metadata, organizing content into categorized directories.

-
-

Goals and Use Case

-

The primary aim is to automate .drmd file processing with minimal manual input. Users can configure download formats, specify directories, and enable real-time command broadcasting. DRMDTool is suitable for both interactive use through a web UI and headless automation in pipelines, supporting inotify or polling-based folder watching.

-
-

How .drmd Files Work

-

A .drmd file is a structured JSON document that defines one or more encrypted media items to be processed by DRMDTool. It contains an Items array, with each item representing a specific media job. DRMDTool parses these entries to generate download commands for N_m3u8DL-RE.

-

Each item includes:

-
    -
  • MPD: A DASH manifest, either a direct URL or a base64-encoded version. If base64-encoded, DRMDTool decodes and temporarily saves it before use.
  • -
  • Keys: A comma-separated list of KID:key pairs (e.g., abcd1234ef567890:00112233445566778899aabbccddeeff). These are required for decrypting encrypted media streams and are passed directly to N_m3u8DL-RE using --key flags.
  • -
  • Filename: The name to be used for the final output file.
  • -
  • Subtitles: Comma-separated list of subtitle URLs in .vtt format. DRMDTool downloads and converts these to .srt, then muxes them into the final file.
  • -
  • Metadata: A semicolon-separated string like Title;Type;Season (e.g., Example Show;serie;1) used to determine directory structure (Movies/Title or Series/Title/Season).
  • -
  • Description and Poster: Optional fields used only for display in the web UI.
  • -
-

Example .drmd Structure

-
{
-  "Items": [
-    {
-      "MPD": "aHR0cHM6Ly9leGFtcGxlLmNvbS9zdHJlYW0ubXBk",
-      "Keys": "abcd1234ef567890:00112233445566778899aabbccddeeff",
-      "Filename": "ExampleShow.S01E01",
-      "Subtitles": "https://example.com/sub1.vtt,https://example.com/sub2.vtt",
-      "Metadata": "Example Show;serie;1",
-      "Description": "Pilot episode",
-      "Poster": ""
-    }
-  ]
-}
-

Processing Steps

-
    -
  1. Detection: DRMDTool either watches a folder or receives .drmd uploads through the web UI.
  2. -
  3. Validation: It waits for the file to finish writing (based on file size stability), then parses its contents.
  4. -
  5. MPD Handling: If base64-encoded, the MPD is decoded and written to a temp file; otherwise, the URL is fetched or passed as-is.
  6. -
  7. Command Generation: Using the MPD, KID:key pairs, output paths, and subtitles, DRMDTool builds a command line for N_m3u8DL-RE.
  8. -
  9. Execution: The download is launched with live progress tracking. Users can pause, resume, or abort jobs, and optionally stream console output via WebSocket.
  10. -
-

These files serve as portable job definitions. When DRMDTool detects or receives a .drmd file, it parses the items, decodes or downloads the MPD, applies the keys, and builds a download command using N_m3u8DL-RE. Files are saved in organized directories like Movies/Title or Series/Title/Season, and subtitles are embedded if available. Pausing, resuming, and aborting downloads is supported per file.

-
-

Architecture Overview

-

The configuration is handled via config.toml, with environment variable overrides for containerized or dynamic deployments. Once started, the tool can either monitor a specified folder or allow file uploads through the UI. Each .drmd file is parsed, grouped by series and season (if applicable), and processed sequentially with support for job pausing and resuming.

-
-

Web UI & CLI

-

To use:

-
./drmdtool
-

Visit http://localhost:8080 for the web interface, which supports drag-and-drop uploads, selection of episodes or movies, and real-time progress tracking. For headless operation:

-
./drmdtool -f /path/to/file.drmd
-

Jobs can be paused, resumed, or aborted through the web interface, which reflects the backend state via live updates.

-
-

Enhanced Download Logic

-

DRMDTool dynamically builds download commands using metadata from .drmd files and user preferences. It ensures that only the highest quality streams are kept, removing ad periods and duplicate segments from the MPD files. Subtitles are fetched and embedded automatically. Jobs are tracked with robust state management and logs for debugging and visibility.

-
-

Repository

-

Code and setup instructions are hosted here: -https://git.directme.in/Joren/DRMDTool

-

DRMDtool

-

For advanced usage details, customization, and API structure, refer to the README.md in the repository.

- -
-
-
-
-
-
- -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/project/project-2/index.html b/public/project/project-2/index.html deleted file mode 100644 index 8fbb007..0000000 --- a/public/project/project-2/index.html +++ /dev/null @@ -1,9367 +0,0 @@ - - - - - - -Building My Hugo Website on a VPS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Building My Hugo Website on a VPS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
- -
-

Building My Hugo Website on a VPS

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Building My Hugo Website on a VPS - - - - - - - - - - - -
- - -
-

I built my personal blog using Hugo and deployed it on a lightweight Alpine Linux VPS. I chose this setup to have full control, keep things simple, and avoid bloated platforms or services. Here’s how the process went from site generation to live deployment.

-
-

Creating the Hugo Site

-

On my development machine, I created a new Hugo site:

-
hugo new site howest-blog
-

I used the professors-hugo theme and copied its exampleSite content into my project. I customized the layout, structure, and styling by editing content files, SCSS in assets/scss/custom.scss, and partial templates in the theme directory.

-

All content lives under content/, with separate folders for blog/ and project/, each containing .md files with front matter and Markdown content.

-
-

Customization

-

I edited the config/_default/hugo.toml to configure site parameters like the base URL, theme, language, and menus. SCSS and image assets go in assets/, and are processed by Hugo’s pipeline. Static files like favicons are placed in static/.

-

To preview the site locally:

-
hugo server
-

To build the static site:

-
hugo
-

This generates everything in the public/ folder.

-
-

VPS Deployment

-

I rented a minimal Alpine Linux VPS and installed only what I needed. After setting up SSH and a basic nginx web server, I copied the public/ folder over using scp:

-
scp -r public/* user@my-vps:/var/www/html
-

On the VPS, I installed nginx:

-
apk add nginx
-

And configured /etc/nginx/conf.d/default.conf to serve files from /var/www/html. Then I enabled and started nginx:

-
rc-service nginx start
-rc-update add nginx
-

Now my Hugo site is live and served directly as static files, no backend, no database, just HTML, CSS, and JS.

-
-

Why Alpine + Hugo?

-

Alpine Linux is minimal and fast, perfect for serving static sites with low resource usage. Combined with Hugo’s speed and flexibility, I get a complete, performant setup that I fully control. It’s secure, lightweight, and easy to update, just rebuild and re-upload the public/ folder.

-
-

This setup is perfect if you want full control and minimal overhead for a personal blog or portfolio.

- -
-
-
-
-
-
- -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/project/project-3/index.html b/public/project/project-3/index.html deleted file mode 100644 index 490e4de..0000000 --- a/public/project/project-3/index.html +++ /dev/null @@ -1,9444 +0,0 @@ - - - - - - -Lean and Local: DNS, VPN, IRC and Ad Blocking - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Lean and Local: DNS, VPN, IRC and Ad Blocking - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
- -
-

Lean and Local: DNS, VPN, IRC and Ad Blocking

- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Lean and Local: DNS, VPN, IRC and Ad Blocking - - - - - - - - - - - -
- - -
-

Running a full-featured network stack on old hardware isn’t just possible, it’s efficient. This post covers how I configured Alpine Linux as a diskless system hosting DNS resolution, ad blocking, VPN access, and a local IRC server.

-
-

Why Diskless?

-

The system boots entirely from RAM using Alpine’s diskless mode. This eliminates wear on flash storage, improves startup speed, and ensures a clean slate on each reboot. Changes are persisted manually using lbu, making the setup both robust and disposable, perfect for low-power hardware with limited write endurance.

-
-

Base Setup

-

The machine is an old D-Class thin client with 4 GB RAM and an AMD G-T48E CPU. Alpine Linux 3.21 is installed with only essential packages (229 total). Services are configured via OpenRC and restored from compressed overlays on boot.

-
-

DNS and Ad Blocking: Blocky

-

Blocky handles all local DNS queries, with DoT upstreams, custom mappings, and deny lists per client.

-

Highlights:

-
    -
  • Local resolution for custom domains like directme.in
  • -
  • Cloudflare, Google as upstream resolvers
  • -
  • Per-IP blocking rules
  • -
  • Prometheus metrics for monitoring
  • -
-

Example config:

-
blocking:
-  denylists:
-    ads:
-      - https://big.oisd.nl/domainswild
-    vtm:
-      - /home/joren/dns/vtmgo.txt
-  clientGroupsBlock:
-    default:
-      - ads
-    192.168.178.123:
-      - vtm
-

-

VPN: WireGuard via PiVPN

-

WireGuard provides encrypted access to the local network, and PiVPN makes managing it trivial. While WireGuard itself is minimal, PiVPN adds essential automation without requiring a full control panel or web UI.

-

Key benefits in this setup:

-
    -
  • -

    Client management is simple and scriptable. Adding, disabling, or revoking peers takes seconds:

    -
    pivpn -a  # add client
    -pivpn -r  # remove client
    -pivpn -off <name>  # temporarily disable
    -
  • -
  • -

    Mobile-friendly. Each config can be exported as a QR code with pivpn -qr, which is perfect for importing into the WireGuard mobile app.

    -
  • -
  • -

    Monitoring support. View live connections with pivpn -c, or audit all issued keys with pivpn -l.

    -
  • -
  • -

    Backups included. One command backs up all configs: pivpn -bk.

    -
  • -
-

Example output:

-
::: Connected Clients List :::
-Name     Remote IP           Virtual IP     Bytes Received     Bytes Sent     Last Seen
-Phone    84.199.x.x:60042    10.60.150.2     439MiB             3.3GiB         May 29 2025 - 22:39:56
-

In this context, PiVPN reduces the friction of managing WireGuard while remaining fully compatible with Alpine’s diskless, CLI-centric philosophy. No services are wasted, and all changes remain under user control.

-
-
-

IRC: ngIRCd

-

For real-time messaging, I run a public-facing ngIRCd instance accessible over both plaintext (port 6667) and encrypted TLS (ports 6697, 6698). Despite its modest footprint, ngIRCd is stable, portable, and well-suited for both LAN and internet-facing deployments.

-

The server is configured to:

-
    -
  • Autojoin clients to a default #General channel
  • -
  • Support cloaking for user privacy
  • -
  • Restrict joins per user/IP to prevent abuse
  • -
  • Provide operator access with predefined credentials
  • -
  • Disable DNS and Ident lookups for speed and reduced leakage
  • -
-

Here’s a snapshot of the active configuration:

-
[Global]
-Name = irc.alpine4071
-Info = RAM-only IRC Server
-Listen = 0.0.0.0
-Ports = 6667
-MotdPhrase = "Welcome to our RAM-only IRC server!"
-AdminInfo1 = IRC Server
-AdminInfo2 = Anywhere On Earth
-AdminEMail = admin@irc.alpine4071
-
-[SSL]
-CertFile = /home/joren/certs/fullchain1.pem
-KeyFile = /home/joren/certs/privkey1.pem
-Ports = 6697, 6698
-

Authentication and moderation are handled via the [Operator] block, and all users are dropped into a predefined channel:

-
[Channel]
-Name = #General
-Topic = General Channel
-Autojoin = yes
-

Why ngIRCd?

-
    -
  • It works well on memory-constrained systems.
  • -
  • It doesn’t require database backends or scripting engines.
  • -
  • It supports modern essentials like TLS, cloaking, and structured limits.
  • -
  • It’s simple to secure and configure, even when exposed to the open internet.
  • -
-

This makes ngIRCd a perfect fit for remote support, small private networks, or just having your own IRC node to tinker with, without touching a gigabyte of storage.

-

You can connect today via:

-
irc://alpine-4071.duckdns.org:6667   (plaintext)
-ircs://alpine-4071.duckdns.org:6697  (TLS)
-

-

Making It Stick: LBU

-

To persist changes in a stateless system, I use Alpine’s lbu:

-
lbu include /etc/blocky/config.yml
-lbu include /etc/ngircd/ngircd.conf
-lbu commit -d
-

This updates the overlay that Alpine loads at each boot. All runtime data stays in RAM.

-
-

Runlevel Integration

-

All services are enabled through OpenRC:

-
rc-update add blocky default
-rc-update add wg-quick default
-rc-update add ngircd default
-rc-update add iptables default
-

Boot time is under 10 seconds, with full network stack active by the time DHCP finishes.

-
-

Final Thoughts

-

Alpine’s diskless approach is perfect for resilient, low-maintenance edge systems. Combined with fast tools like Blocky and WireGuard, even minimal hardware becomes a capable, efficient network node, quietly resolving DNS, filtering traffic, handling VPN access, and hosting IRC.

- -
-
-
-
-
-
- -
- - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/service-worker.js b/public/service-worker.js deleted file mode 100644 index d39fc31..0000000 --- a/public/service-worker.js +++ /dev/null @@ -1,10 +0,0 @@ -importScripts( - "https://storage.googleapis.com/workbox-cdn/releases/6.0.2/workbox-sw.js" -); - -workbox.setConfig({ debug: false }); - -workbox.routing.registerRoute( - ({ request }) => request.destination === "image", - new workbox.strategies.NetworkFirst() -); diff --git a/public/sitemap.xml b/public/sitemap.xml deleted file mode 100644 index ccab998..0000000 --- a/public/sitemap.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - https://joren.blog/categories/alpine-linux/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/blog/post-8/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/communication/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/cybersecurity/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/decentralization/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/dns/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/hardware/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/iot/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/jdm/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/blog/post-7/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/project/project-3/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/blog/post-6/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/network/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/networking/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/offensive/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/blog/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/project/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/reverse-engineering/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/seiko/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/blog/post-9/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/self-hosting/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/blog/post-5/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/blog/post-10/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/vpn/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/watches/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/categories/windows/ - 2025-05-30T00:00:00+00:00 - - https://joren.blog/project/project-2/ - 2025-05-29T00:00:00+00:00 - - https://joren.blog/project/project-1/ - 2025-05-21T00:00:00+00:00 - - https://joren.blog/categories/interview/ - 2025-05-20T00:00:00+00:00 - - https://joren.blog/categories/podcast/ - 2025-05-20T00:00:00+00:00 - - https://joren.blog/blog/post-4/ - 2025-05-20T00:00:00+00:00 - - https://joren.blog/blog/post-1/ - 2025-05-13T00:00:00+00:00 - - https://joren.blog/categories/event/ - 2025-05-13T00:00:00+00:00 - - https://joren.blog/categories/ctf/ - 2025-03-15T00:00:00+00:00 - - https://joren.blog/categories/education/ - 2025-03-15T00:00:00+00:00 - - https://joren.blog/blog/post-2/ - 2025-03-15T00:00:00+00:00 - - https://joren.blog/categories/defense/ - 2024-11-12T00:00:00+00:00 - - https://joren.blog/blog/post-3/ - 2024-11-12T00:00:00+00:00 - - https://joren.blog/tags/ - - diff --git a/public/tags/index.html b/public/tags/index.html deleted file mode 100644 index b542a65..0000000 --- a/public/tags/index.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/public/tags/index.xml b/public/tags/index.xml deleted file mode 100644 index 5feb1c2..0000000 --- a/public/tags/index.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - Tags on Joren's Site - https://joren.blog/tags/ - Recent content in Tags on Joren's Site - Hugo - en - - - diff --git a/resources/_gen/assets/scss/style.scss_d9077b5cab49df084fb1a39ad4b1e75d.content b/resources/_gen/assets/scss/style.scss_d9077b5cab49df084fb1a39ad4b1e75d.content index af9aae3..51f2b37 100644 --- a/resources/_gen/assets/scss/style.scss_d9077b5cab49df084fb1a39ad4b1e75d.content +++ b/resources/_gen/assets/scss/style.scss_d9077b5cab49df084fb1a39ad4b1e75d.content @@ -8650,16 +8650,83 @@ html.light .navbar-nav .nav-item a.nav-link:hover { .projects, .blog-wrapper { - column-count: 3; - column-gap: 1.5rem; } - @media (max-width: 991px) { - .projects, - .blog-wrapper { - column-count: 2; } } - @media (max-width: 767px) { - .projects, - .blog-wrapper { - column-count: 1; } } + display: grid !important; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + grid-auto-flow: row; + gap: 2rem; } + +.blog-wrapper > .blog-post { + display: flex; + flex-direction: column; + height: 100%; } + +.blog-post .card { + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 8px; + padding: 1.5rem; + display: flex; + flex-direction: column; + height: 100%; + background-color: transparent; } + +/* Consistent image ratio and sizing */ +.blog-post .card > a:first-child { + display: block; + width: 100%; + aspect-ratio: 16 / 9; + overflow: hidden; + border-radius: 8px; } + +.blog-post .card > a:first-child img { + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; + display: block; } + +.blog-post .card-body { + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: space-between; + padding-top: 1rem; } + +.card-body .post-meta { + margin-bottom: 1rem; + font-size: 0.85rem; + color: rgba(255, 255, 255, 0.6); + line-height: 1.4; } + +.card-body .card-title { + min-height: 3.5em; + /* equal title height */ + margin-bottom: 1rem; } + +.card-body .card-text { + flex-grow: 1; + font-size: 0.95rem; + line-height: 1.6; + margin-bottom: 1rem; } + +.card-btn { + margin-top: auto; + font-weight: 500; } + +.card-body .post-meta { + font-size: 0.85rem; + color: rgba(255, 255, 255, 0.6); + line-height: 1.5; } + .card-body .post-meta .post-date, + .card-body .post-meta .post-categories { + display: block; + margin-bottom: 0.2rem; } + .card-body .post-meta .meta-link { + color: rgba(255, 255, 255, 0.6); + text-decoration: none; } + .card-body .post-meta .meta-link:hover { + color: #18b0a2; + text-decoration: underline; } + .meta-link:hover { color: #18b0a2 !important; text-decoration: underline !important; } @@ -8750,6 +8817,46 @@ html.light .navbar-nav .nav-item a.nav-link:hover { max-height: 600px; object-fit: cover; } +.project-item { + display: flex; + flex-direction: column; + height: 100%; } + +.project-item > a { + position: relative; + overflow: hidden; + border-radius: 8px; + display: block; + width: 100%; + aspect-ratio: 16 / 9; } + +.project-item > a img { + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; + display: block; + transition: transform 0.4s ease; } + +.project-item > a:hover img { + transform: scale(1.05); } + +.project-item h3, .project-item .h3 { + min-height: 3.5em; + margin-bottom: 1rem; + font-size: 1.125rem; + font-weight: 500; } + +.project-item .card-text { + flex-grow: 1; + font-size: 0.95rem; + line-height: 1.6; + margin-bottom: 1rem; } + +.project-item .card-btn { + font-weight: 500; + margin-top: auto; } + #blog { position: relative; } #blog::before { diff --git a/themes/professors-hugo/assets/scss/custom.scss b/themes/professors-hugo/assets/scss/custom.scss index dd4e307..7294bba 100755 --- a/themes/professors-hugo/assets/scss/custom.scss +++ b/themes/professors-hugo/assets/scss/custom.scss @@ -1,2 +1,4 @@ // This file is empty within the template // You can use it to override CSS from within your project + + diff --git a/themes/professors-hugo/assets/scss/templates/_main.scss b/themes/professors-hugo/assets/scss/templates/_main.scss index beb4ca0..f4eaff2 100755 --- a/themes/professors-hugo/assets/scss/templates/_main.scss +++ b/themes/professors-hugo/assets/scss/templates/_main.scss @@ -210,16 +210,100 @@ // ----------------------- .projects, .blog-wrapper { - column-count: 3; - column-gap: 1.5rem; - @include desktop { - column-count: 2; + display: grid !important; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + grid-auto-flow: row; + gap: 2rem; +} + +.blog-wrapper > .blog-post { + display: flex; + flex-direction: column; + height: 100%; +} + +.blog-post .card { + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 8px; + padding: 1.5rem; + display: flex; + flex-direction: column; + height: 100%; + background-color: transparent; +} + +/* Consistent image ratio and sizing */ +.blog-post .card > a:first-child { + display: block; + width: 100%; + aspect-ratio: 16 / 9; + overflow: hidden; + border-radius: 8px; +} + +.blog-post .card > a:first-child img { + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; + display: block; +} + +.blog-post .card-body { + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: space-between; + padding-top: 1rem; +} + +.card-body .post-meta { + margin-bottom: 1rem; + font-size: 0.85rem; + color: rgba(255, 255, 255, 0.6); + line-height: 1.4; +} + +.card-body .card-title { + min-height: 3.5em; /* equal title height */ + margin-bottom: 1rem; +} + +.card-body .card-text { + flex-grow: 1; + font-size: 0.95rem; + line-height: 1.6; + margin-bottom: 1rem; +} + +.card-btn { + margin-top: auto; + font-weight: 500; +} + +.card-body .post-meta { + font-size: 0.85rem; + color: rgba(255, 255, 255, 0.6); + line-height: 1.5; + + .post-date, + .post-categories { + display: block; + margin-bottom: 0.2rem; } - @include tablet { - column-count: 1; + + .meta-link { + color: rgba(255, 255, 255, 0.6); + text-decoration: none; + + &:hover { + color: $color-primary; + text-decoration: underline; + } } } + .meta-link { &:hover { color: $color-primary !important; @@ -358,6 +442,55 @@ object-fit: cover; } +.project-item { + display: flex; + flex-direction: column; + height: 100%; +} + +.project-item > a { + position: relative; + overflow: hidden; + border-radius: 8px; + display: block; + width: 100%; + aspect-ratio: 16 / 9; +} + +.project-item > a img { + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; + display: block; + transition: transform 0.4s ease; +} + +.project-item > a:hover img { + transform: scale(1.05); +} + + +.project-item h3 { + min-height: 3.5em; // equal height titles + margin-bottom: 1rem; + font-size: 1.125rem; + font-weight: 500; +} + +.project-item .card-text { + flex-grow: 1; + font-size: 0.95rem; + line-height: 1.6; + margin-bottom: 1rem; +} + +.project-item .card-btn { + font-weight: 500; + margin-top: auto; +} + + // ----------------------- // Blog Single // ----------------------- diff --git a/themes/professors-hugo/layouts/_default/blog-card.html b/themes/professors-hugo/layouts/_default/blog-card.html index daeabdc..cc51157 100644 --- a/themes/professors-hugo/layouts/_default/blog-card.html +++ b/themes/professors-hugo/layouts/_default/blog-card.html @@ -7,20 +7,19 @@ {{ end }}
- +
+ +
+ + {{ range $index, $cat := .Params.categories }} + {{ if $index }}, {{ end }} + {{ $cat | title }} + {{ end }} +
+
+

{{.Params.title | markdownify}} @@ -31,4 +30,4 @@ Read More

-
\ No newline at end of file + diff --git a/themes/professors-hugo/layouts/_default/project-card.html b/themes/professors-hugo/layouts/_default/project-card.html index 13de18c..70ebfb1 100644 --- a/themes/professors-hugo/layouts/_default/project-card.html +++ b/themes/professors-hugo/layouts/_default/project-card.html @@ -1,21 +1,18 @@
-
- {{if .Params.image}} - - {{ partial "image.html" (dict "Src" .Params.image "Alt" .Params.title "Class" `rounded-2`) }} - - {{ end }} -
-
-
-

- {{.Params.title | markdownify}} -

-

{{.Params.description | truncate 115}}

-
- - Discover -
-
+ {{ if .Params.image }} + + {{ partial "image.html" (dict "Src" .Params.image "Alt" .Params.title "Class" "rounded-2 w-100") }} + + {{ end }} +
+

+ {{ .Params.title | markdownify }} +

+

{{ .Params.description | truncate 115 }}

-
\ No newline at end of file + + + Discover + +
+ diff --git a/themes/professors-hugo/layouts/index.html b/themes/professors-hugo/layouts/index.html index f10f252..c959712 100755 --- a/themes/professors-hugo/layouts/index.html +++ b/themes/professors-hugo/layouts/index.html @@ -259,7 +259,7 @@
- {{ range .Pages.Reverse }} + {{ range .Pages.ByDate.Reverse }} {{ .Render "project-card" }} {{ end }}
@@ -293,7 +293,7 @@
- {{ range .Pages.Reverse }} + {{ range .Pages.ByDate.Reverse }} {{ .Render "blog-card" }} {{ end }}