diff --git a/app.js b/app.js new file mode 100644 index 0000000..5f1981a --- /dev/null +++ b/app.js @@ -0,0 +1,89 @@ +/* ════════════════════════════════════════════════ + MasterCruelty — render + tab logic + ════════════════════════════════════════════════ */ + +const esc = (s) => String(s).replace(/[&<>"']/g, (c) => ({ + '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', +}[c])); + +const projectCard = (p) => ` + +
+ ${esc(p.tag)} + +
+

${esc(p.title)}

+

${esc(p.desc)}

+
${p.tech.map((t) => `${esc(t)}`).join('')}
+
+`; + +const socialCard = (s) => ` + +
+ ${esc(s.tag)} + +
+

${esc(s.title)}

+

${esc(s.desc)}

+ ${esc(s.cta)} +
+`; + +const pressCard = (p) => ` + +
+ ${esc(p.tag)} + +
+

${esc(p.title)}

+

${esc(p.desc)}

+ ${esc(p.cta)} +
+`; + +const pill = (s) => `${esc(s)}`; + +const linkRow = (l) => ` + + ${esc(l.key)} + ${esc(l.val)} + + +`; + +const stat = (s) => ` +
+
${esc(s.num)}${s.plus ? '+' : ''}
+
${esc(s.label)}
+
+`; + +const fill = (id, html) => { + const el = document.getElementById(id); + if (el) el.innerHTML = html; +}; + +fill('pills', SITE.skills.map(pill).join('')); +fill('links', SITE.links.map(linkRow).join('')); +fill('stats', SITE.stats.map(stat).join('')); +fill('university', SITE.university.map(projectCard).join('')); +fill('personal', SITE.personal.map(projectCard).join('')); +fill('socials', SITE.socials.map(socialCard).join('')); +fill('press', SITE.press.map(pressCard).join('')); + +const tabs = document.querySelectorAll('.tab-btn'); +const panels = document.querySelectorAll('.tab-panel'); +const hero = document.getElementById('hero'); + +tabs.forEach((btn) => { + btn.addEventListener('click', () => { + const target = btn.dataset.tab; + tabs.forEach((b) => b.classList.toggle('active', b === btn)); + panels.forEach((p) => p.classList.toggle('active', p.id === 'tab-' + target)); + hero.classList.toggle('visible', target === 'home'); + window.scrollTo({ top: 0, behavior: 'smooth' }); + }); +}); + +document.getElementById('year').textContent = new Date().getFullYear(); diff --git a/data.js b/data.js new file mode 100644 index 0000000..bfc4847 --- /dev/null +++ b/data.js @@ -0,0 +1,173 @@ +/* ════════════════════════════════════════════════ + MasterCruelty — site content + Edit the data here; markup is generated in app.js + ════════════════════════════════════════════════ */ + +const SITE = { + skills: [ + 'Python', 'Telegram Bots', 'Linux', 'Data Analysis', 'C / Go', 'Cloud', + ], + + links: [ + { key: 'github', val: '@MasterCruelty', href: 'https://github.com/MasterCruelty' }, + { key: 'telegram', val: 'atm channel', href: 'https://t.me/atmshitpostingChannel' }, + { key: 'facebook', val: 'atm shitposting', href: 'https://www.facebook.com/atmshitposting/' }, + { key: 'instagram', val: '@atm_shitposting', href: 'https://www.instagram.com/atm_shitposting' }, + ], + + stats: [ + { num: '15', plus: true, label: 'public repos' }, + { num: '2017', label: 'atm shitposting founded' }, + { num: '∞', label: 'cups of coffee' }, + ], + + university: [ + { + tag: 'embedded', + title: 'Alarm Project', + desc: 'Embedded systems coursework — a small alarm built around a microcontroller.', + tech: ['C', 'Arduino'], + href: 'https://github.com/MasterCruelty/alarm-project', + }, + { + tag: 'architecture', + title: 'Half-Life Assembly', + desc: 'Computer architecture project, working close to the metal in assembly.', + tech: ['Assembly', 'x86'], + href: 'https://github.com/MasterCruelty/halflifeassembly', + }, + { + tag: 'software-eng', + title: 'Bike Sharing', + desc: 'Full software engineering exercise — from requirements to a working prototype.', + tech: ['Java', 'UML'], + href: 'https://github.com/MasterCruelty/bikesharingproject', + }, + { + tag: 'thesis', + title: "Bachelor's Thesis — IAC", + desc: "Final dissertation work for the bachelor's degree.", + tech: ['Research', 'LaTeX'], + href: 'https://github.com/MasterCruelty/Thesis-IAC', + }, + { + tag: 'notes', + title: 'Statistic Stuffs', + desc: 'A growing pile of notes and exercises on statistics.', + tech: ['Stats', 'R'], + href: 'https://github.com/MasterCruelty/StatisticStuffs', + }, + { + tag: 'algorithms', + title: 'C / Go Algorithms', + desc: 'Notes and source code for classic algorithms, in C and Go.', + tech: ['C', 'Go'], + href: 'https://github.com/MasterCruelty/C-Go-Algorithms', + }, + { + tag: 'cloud', + title: 'Cloud Computing', + desc: 'A simple cloud architecture project for the cloud computing course.', + tech: ['Cloud', 'Docker'], + href: 'https://github.com/MasterCruelty/cloud-computing-technologies', + }, + ], + + personal: [ + { + tag: 'telegram', + title: 'my-tg-app', + desc: 'A Telegram userbot packed with utilities I use every day.', + tech: ['Python', 'Telethon'], + href: 'https://github.com/MasterCruelty/my-tg-app', + }, + { + tag: 'telegram', + title: 'robbot', + desc: 'My personal Telegram bot — group helper and tinker playground.', + tech: ['Python', 'Bot API'], + href: 'https://github.com/MasterCruelty/robbot', + }, + { + tag: 'linux', + title: 'eMerger', + desc: 'A handy CLI tool for Linux devices, built with the Mergers crew.', + tech: ['Shell', 'Linux'], + href: 'https://github.com/TheMergers/emerger', + }, + { + tag: 'transit', + title: 'Metro Flow Router', + desc: 'Calculates routes and fetches live data about metro systems.', + tech: ['Python', 'Graphs'], + href: 'https://github.com/MasterCruelty/MetroFlowRouter', + }, + { + tag: 'data', + title: 'GoKart Data Hub', + desc: 'Data analysis on go-kart races — telemetry meets weekend hobby.', + tech: ['Python', 'Pandas'], + href: 'https://github.com/MasterCruelty/gokart-data-hub', + }, + { + tag: 'data', + title: 'Telegram Chat Insights', + desc: 'Userbot that runs simple analytics on your personal chat interactions.', + tech: ['Python', 'Telethon'], + href: 'https://github.com/MasterCruelty/TelegramChatInsights', + }, + { + tag: 'template', + title: 'tg-bot-skeleton', + desc: 'A starter template to spin up a Telegram bot or userbot fast.', + tech: ['Python', 'Boilerplate'], + href: 'https://github.com/MasterCruelty/tg-bot-skeleton', + }, + ], + + socials: [ + { + brand: 'facebook', + tag: 'main', + title: 'Facebook', + desc: "The community's main page — original memes and chronicles.", + cta: 'visit on facebook →', + href: 'https://www.facebook.com/atmshitposting/', + }, + { + brand: 'instagram', + tag: 'visual', + title: 'Instagram', + desc: 'Visual content and a steady feed of fresh memes.', + cta: 'visit on instagram →', + href: 'https://www.instagram.com/atm_shitposting', + }, + { + brand: 'telegram', + tag: 'updates', + title: 'Telegram', + desc: 'Official channel for updates and behind-the-scenes posts.', + cta: 'visit on telegram →', + href: 'https://t.me/atmshitpostingChannel', + rel: 'noopener noreferrer nofollow', + }, + ], + + press: [ + { + tag: 'interview', + title: 'Linea Diretta — Medium', + desc: 'ATM themselves interviewing the community and its memes.', + cta: 'read the interview →', + href: 'https://medium.com/lineadiretta/atm-incontra-suo-figlio-nato-a-suon-di-meme-cb6d82baaaea', + rel: 'noopener noreferrer nofollow', + }, + { + tag: 'video', + title: 'Milano AllNews — YouTube', + desc: 'Video interview by Milano AllNews on the page and its origins.', + cta: 'watch the video →', + href: 'https://www.youtube.com/watch?v=d8mGHGavPSk&ab_channel=MilanoAllNews', + }, + ], +}; diff --git a/index.html b/index.html index 5a7165b..8620e82 100644 --- a/index.html +++ b/index.html @@ -4,8 +4,10 @@ MasterCruelty + - + + @@ -14,15 +16,9 @@
@@ -32,82 +28,87 @@
+

personal space

-

Hello,
I'm MasterCruelty

-

Welcome to my little corner of the internet.

+

Hello,
I'm MasterCruelty_

+

Welcome to my little corner of the internet — a place to collect academic work, side projects, and a community I've been running since 2017.

-
- -
-
-
-
-
-
-
-
-
mastercruelty.github.io/src/home.html
-
- -
-
+
-
-
-
-
-
-
-
-
-
mastercruelty.github.io/src/progetti.html
-
- -
-
+ +
+
~/ home
-
-
-
-
-
-
-
-
-
mastercruelty.github.io/src/atmshitposting.html
+
+
+ +

Software, side-projects & a bit of mischief.

+

+ I'm a developer with a soft spot for Telegram bots, Linux tooling, and small data + projects. This site is where I park academic work, personal experiments, and the + ATM Shitposting community I've kept alive since 2017. +

+
- + +
-
-
+
+
+ + +
+
~/ progetti
+ + +

Academic projects

+

Coursework, labs, and the bachelor's thesis.

+
+ +
+ + +

Personal projects

+

Tools, bots, and experiments built for fun.

+
+
+ + +
+
~/ at-m-shitposting
+ + +

AT/M Shitposting

+

+ Founded on 27 January 2017 — satire and memes about ATM + (Azienda Trasporti Milanesi S.p.A) and the wider Milano universe. +

+
- + + diff --git a/src/atmshitposting.html b/src/atmshitposting.html deleted file mode 100644 index 9def38f..0000000 --- a/src/atmshitposting.html +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - AT/M Shitposting - - - - - - - - -

AT/M Shitposting

- -

- Pagina creata il 27 Gennaio 2017 con lo scopo di fare satira - e disegnare memes focalizzati su ATM (Azienda Trasporti Milanesi S.p.A) - e sulla sfera di Milano e dintorni. -

- -
- -
-
-

Facebook

-

Pagina principale della community.

- → Visita su Facebook -
-
-

Instagram

-

Memes e contenuti visivi.

- → Visita su Instagram -
-
-

Telegram

-

Canale ufficiale di aggiornamenti.

- → Visita su Telegram -
-
- -
- - - -
-
-

Linea Diretta — Medium

-

Intervista da parte di ATM stessa sulla community e i memes.

- → Leggi l'intervista -
-
-

Milano AllNews — YouTube

-

Video intervista da parte di Milano AllNews.

- → Guarda il video -
-
- - - diff --git a/src/home.html b/src/home.html deleted file mode 100644 index 4bc9018..0000000 --- a/src/home.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - Home Page - - - - -
-

Home Page

-
-
-
-
-

Welcome to my personal website, a place I'm using to show any academic and personal projects.

-
-
-
- - diff --git a/src/progetti.html b/src/progetti.html deleted file mode 100644 index 0bc3960..0000000 --- a/src/progetti.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - University and Personal Projects - - - - -
-

Academic and Personal Projects

-
-
-
-

University Projects

-
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
-
-
-

Personal Projects

-
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
-
-
- - diff --git a/src/style.css b/src/style.css deleted file mode 100644 index ec0029f..0000000 --- a/src/style.css +++ /dev/null @@ -1,158 +0,0 @@ -/* ════════════════════════════════════════════════ - MasterCruelty — src/style.css (inner pages) - ════════════════════════════════════════════════ */ - -/* @import DEVE stare in cima, prima di qualsiasi regola */ -@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;700&family=Syne:wght@400;700;800&display=swap'); - -/* ── TOKENS ─────────────────────────────────────── */ -:root { - --bg: #0b0e13; - --bg1: #111520; - --bg2: #181d2a; - --border: rgba(255, 255, 255, .07); - --accent: #e8ff47; - --txt: #c8cdd8; - --txt-dim: #4a5060; - --white: #f0f2f5; -} - -/* ── RESET ──────────────────────────────────────── */ -*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } - -/* ── BASE ───────────────────────────────────────── */ -body { - background-color: #0b0e13; - color: #c8cdd8; - font-family: 'JetBrains Mono', monospace; - padding: 32px 36px 48px; - line-height: 1.7; -} - -h1, h2, h3, h4, h5, h6 { - font-family: 'Syne', sans-serif; - font-weight: 800; - color: #f0f2f5; - letter-spacing: -.02em; - line-height: 1.15; -} - -h1 { font-size: clamp(1.8rem, 4vw, 2.8rem); margin-bottom: 16px; } -h2 { font-size: 1.4rem; margin-bottom: 12px; } -h3 { font-size: 1.05rem; margin-bottom: 8px; } - -p { - font-size: .9rem; - color: #c8cdd8; - margin-bottom: 1em; -} - -a { color: #e8ff47; text-decoration: none; transition: opacity .15s; } -a:hover { opacity: .75; text-decoration: underline; } - -strong, b { color: #f0f2f5; font-weight: 700; } - -hr { - border: none; height: 1px; - background: linear-gradient(90deg, #e8ff47, rgba(232,255,71,.1), transparent); - margin: 28px 0; opacity: .5; -} - -ul, ol { padding-left: 20px; margin-bottom: 1em; } -li { font-size: .9rem; color: #c8cdd8; margin-bottom: .35em; } -li::marker { color: #e8ff47; } - -code { - font-family: 'JetBrains Mono', monospace; - font-size: .82rem; padding: 2px 6px; - background: #181d2a; border: 1px solid rgba(255,255,255,.07); - border-radius: 3px; color: #e8ff47; -} - -pre { - font-family: 'JetBrains Mono', monospace; - padding: 16px 20px; overflow-x: auto; - font-size: .82rem; line-height: 1.6; color: #c8cdd8; - background: #181d2a; border: 1px solid rgba(255,255,255,.07); - margin-bottom: 1.2em; -} -pre code { background: none; border: none; padding: 0; color: inherit; } - -/* ── SECTION LABEL ──────────────────────────────── */ -.section-label { - font-size: .68rem; letter-spacing: .2em; text-transform: uppercase; - color: #e8ff47; display: flex; align-items: center; gap: 10px; - margin-bottom: 20px; -} -.section-label::before { - content: ''; width: 24px; height: 1px; background: #e8ff47; opacity: .6; -} - -/* ── CARD ───────────────────────────────────────── */ -.card { - background: #111520; - border: 1px solid rgba(255, 255, 255, .07); - padding: 20px 24px; - position: relative; - transition: border-color .2s, background .2s; - margin-bottom: 16px; -} -.card:hover { border-color: rgba(232,255,71,.3); background: rgba(232,255,71,.03); } -.card::before { - content: ''; position: absolute; top: -1px; left: -1px; - width: 10px; height: 10px; - border-top: 2px solid #e8ff47; border-left: 2px solid #e8ff47; - opacity: 0; transition: opacity .2s; -} -.card:hover::before { opacity: 1; } -.card h3 { font-size: 1rem; margin-bottom: 6px; color: #f0f2f5; } -.card p { font-size: .85rem; color: #4a5060; margin-bottom: 12px; } - -/* ── CARD GRID ──────────────────────────────────── */ -.card-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); - gap: 16px; margin-bottom: 16px; -} - -/* ── TABLE ──────────────────────────────────────── */ -table { width: 100%; border-collapse: collapse; font-size: .85rem; margin-bottom: 1.2em; } -thead tr { border-bottom: 1px solid rgba(232,255,71,.3); } -th { - font-family: 'JetBrains Mono', monospace; font-size: .68rem; - letter-spacing: .12em; text-transform: uppercase; - color: #e8ff47; padding: 8px 12px; text-align: left; font-weight: 400; -} -td { padding: 9px 12px; border-bottom: 1px solid rgba(255,255,255,.07); color: #c8cdd8; vertical-align: top; } -tr:hover td { background: rgba(232,255,71,.03); } - -/* ── BUTTON ─────────────────────────────────────── */ -.btn { - display: inline-flex; align-items: center; gap: 8px; - font-family: 'JetBrains Mono', monospace; font-size: .78rem; - letter-spacing: .08em; text-transform: lowercase; - padding: 9px 20px; border: 1px solid rgba(255,255,255,.07); - background: transparent; color: #c8cdd8; - cursor: pointer; transition: border-color .2s, color .2s, background .2s; - text-decoration: none; -} -.btn:hover { - border-color: #e8ff47; color: #e8ff47; - background: rgba(232,255,71,.05); text-decoration: none; opacity: 1; -} -.btn.primary { border-color: #e8ff47; color: #e8ff47; } - -/* ── TAG ────────────────────────────────────────── */ -.tag { - display: inline-block; font-size: .68rem; letter-spacing: .08em; - text-transform: uppercase; padding: 3px 10px; - border: 1px solid rgba(255,255,255,.07); color: #4a5060; - margin-right: 6px; margin-bottom: 6px; -} -.tag.accent { border-color: rgba(232,255,71,.4); color: #e8ff47; } - -/* ── RESPONSIVE ─────────────────────────────────── */ -@media (max-width: 600px) { - body { padding: 20px 18px 40px; } - .card-grid { grid-template-columns: 1fr; } -} diff --git a/style.css b/style.css index 71a3a71..6aab638 100644 --- a/style.css +++ b/style.css @@ -1,5 +1,5 @@ /* ════════════════════════════════════════════════ - MasterCruelty — style.css (root shell) + MasterCruelty — style.css ════════════════════════════════════════════════ */ /* ── TOKENS ─────────────────────────────────────── */ @@ -7,17 +7,22 @@ --bg: #0b0e13; --bg1: #111520; --bg2: #181d2a; + --bg3: #1d2334; --border: rgba(255, 255, 255, .07); + --border-strong: rgba(255, 255, 255, .12); --accent: #e8ff47; + --accent-soft: rgba(232, 255, 71, .14); --accent2: #ff4757; --txt: #c8cdd8; - --txt-dim: #4a5060; + --txt-dim: #6b7184; + --txt-faint: #4a5060; --white: #f0f2f5; --mono: 'JetBrains Mono', monospace; --sans: 'Syne', sans-serif; --nav-h: 62px; - --max-w: 1100px; + --max-w: 1180px; --pad-x: 40px; + --ease: cubic-bezier(.2, .8, .2, 1); } /* ── RESET ──────────────────────────────────────── */ @@ -38,9 +43,13 @@ body { font-family: var(--mono); min-height: 100vh; overflow-x: hidden; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; } -/* ── GRID OVERLAY ───────────────────────────────── */ +::selection { background: var(--accent); color: var(--bg); } + +/* ── GRID + GLOW OVERLAY ────────────────────────── */ body::before { content: ''; position: fixed; @@ -51,7 +60,18 @@ body::before { linear-gradient(var(--border) 1px, transparent 1px), linear-gradient(90deg, var(--border) 1px, transparent 1px); background-size: 48px 48px; - mask-image: radial-gradient(ellipse 80% 70% at 50% 0%, black 40%, transparent 100%); + mask-image: radial-gradient(ellipse 90% 70% at 50% 0%, black 30%, transparent 90%); +} + +body::after { + content: ''; + position: fixed; + inset: 0; + z-index: 0; + pointer-events: none; + background: + radial-gradient(600px 400px at 12% -10%, rgba(232, 255, 71, .07), transparent 60%), + radial-gradient(700px 500px at 95% 110%, rgba(255, 71, 87, .05), transparent 60%); } /* ── HEADER ─────────────────────────────────────── */ @@ -59,8 +79,9 @@ header { position: sticky; top: 0; z-index: 100; - background: rgba(11, 14, 19, .88); + background: rgba(11, 14, 19, .82); backdrop-filter: blur(14px) saturate(1.6); + -webkit-backdrop-filter: blur(14px) saturate(1.6); border-bottom: 1px solid var(--border); height: var(--nav-h); display: flex; @@ -135,7 +156,6 @@ nav { opacity: 1; } -/* animated underline */ .tab-btn::after { content: ''; position: absolute; @@ -144,7 +164,7 @@ nav { right: 50%; height: 2px; background: var(--accent); - transition: left .25s ease, right .25s ease; + transition: left .25s var(--ease), right .25s var(--ease); } .tab-btn.active::after, @@ -153,7 +173,6 @@ nav { right: 12px; } -/* spacer + status */ .header-spacer { flex: 1; } @@ -185,7 +204,7 @@ nav { .hero { position: relative; z-index: 1; - padding: 72px var(--pad-x) 0; + padding: 88px var(--pad-x) 0; max-width: var(--max-w); margin: 0 auto; display: none; @@ -193,7 +212,19 @@ nav { .hero.visible { display: block; - animation: slide-in .4s ease both; + animation: slide-in .55s var(--ease) both; +} + +.hero-glow { + position: absolute; + top: 40px; + left: 20%; + width: 520px; + height: 320px; + background: radial-gradient(closest-side, rgba(232,255,71,.18), transparent 70%); + filter: blur(40px); + pointer-events: none; + z-index: -1; } .hero-tag { @@ -201,7 +232,7 @@ nav { letter-spacing: .18em; text-transform: uppercase; color: var(--accent); - margin-bottom: 16px; + margin-bottom: 18px; display: flex; align-items: center; gap: 10px; @@ -218,7 +249,7 @@ nav { .hero-name { font-family: var(--sans); font-weight: 800; - font-size: clamp(2.4rem, 6vw, 4.5rem); + font-size: clamp(2.4rem, 6vw, 4.8rem); color: var(--white); line-height: 1; letter-spacing: -.03em; @@ -226,20 +257,37 @@ nav { .hero-name .accent-txt { color: var(--accent); + background: linear-gradient(180deg, var(--accent), #b8d000); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; +} + +.hero-name .caret { + display: inline-block; + color: var(--accent); + margin-left: 6px; + -webkit-text-fill-color: var(--accent); + animation: caret 1.1s steps(2) infinite; +} + +@keyframes caret { + 0%, 50% { opacity: 1; } + 51%, 100% { opacity: 0; } } .hero-sub { - margin-top: 18px; - font-size: .88rem; - color: var(--txt-dim); - max-width: 480px; + margin-top: 22px; + font-size: .92rem; + color: var(--txt); + max-width: 580px; line-height: 1.75; } .hero-divider { width: 100%; height: 1px; - margin: 48px 0 0; + margin: 56px 0 0; background: linear-gradient( 90deg, var(--accent) 0%, @@ -260,12 +308,12 @@ nav { /* ── TAB PANELS ─────────────────────────────────── */ .tab-panel { display: none; - padding-top: 40px; - animation: slide-in .35s ease both; + padding-top: 48px; } .tab-panel.active { display: block; + animation: slide-in .45s var(--ease) both; } @keyframes slide-in { @@ -273,93 +321,425 @@ nav { to { opacity: 1; transform: translateY(0); } } -/* ── IFRAME WRAPPER ─────────────────────────────── */ -.iframe-wrap { - position: relative; - width: 100%; - border: 1px solid var(--border); +/* ── BREADCRUMB ─────────────────────────────────── */ +.crumb { + font-family: var(--mono); + font-size: .72rem; + letter-spacing: .08em; + color: var(--txt-dim); + margin-bottom: 32px; + padding-bottom: 14px; + border-bottom: 1px dashed var(--border); +} + +.crumb-prompt { + color: var(--accent); + margin-right: 6px; +} + +/* ── SECTION LABEL ──────────────────────────────── */ +.section-label { + font-size: .68rem; + letter-spacing: .2em; + text-transform: uppercase; + color: var(--accent); + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 16px; +} + +.section-label::before { + content: ''; + width: 24px; + height: 1px; + background: var(--accent); + opacity: .6; +} + +/* ── BLOCK HEADERS ──────────────────────────────── */ +.block-title { + font-family: var(--sans); + font-weight: 800; + font-size: clamp(1.4rem, 2.6vw, 1.8rem); + color: var(--white); + letter-spacing: -.02em; + margin-bottom: 10px; +} + +.block-sub { + font-size: .88rem; + color: var(--txt-dim); + margin-bottom: 28px; + max-width: 640px; + line-height: 1.7; +} + +.block-sub strong { color: var(--white); } + +.block-divider { + height: 1px; + background: linear-gradient(90deg, transparent, var(--border), transparent); + margin: 56px 0; +} + +/* ── HOME: GRID + ABOUT/LINKS ───────────────────── */ +.home-grid { + display: grid; + grid-template-columns: 1.6fr 1fr; + gap: 24px; + margin-bottom: 40px; +} + +.about-card, +.links-card { background: var(--bg1); + border: 1px solid var(--border); + padding: 32px; + position: relative; overflow: hidden; } -/* corner accents */ -.iframe-wrap::before, -.iframe-wrap::after { +.about-card::before, +.links-card::before { content: ''; position: absolute; - width: 14px; - height: 14px; - z-index: 2; - pointer-events: none; + top: 0; + left: 0; + width: 12px; + height: 12px; + border-top: 2px solid var(--accent); + border-left: 2px solid var(--accent); +} + +.about-card::after, +.links-card::after { + content: ''; + position: absolute; + bottom: 0; + right: 0; + width: 12px; + height: 12px; + border-bottom: 2px solid var(--accent); + border-right: 2px solid var(--accent); + opacity: .35; +} + +.lede { + font-size: .95rem; + color: var(--txt); + line-height: 1.8; + margin-bottom: 24px; + max-width: 560px; +} + +.pill-row { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.pill { + font-family: var(--mono); + font-size: .7rem; + letter-spacing: .08em; + text-transform: lowercase; + padding: 6px 12px; + border: 1px solid var(--border-strong); + color: var(--txt); + background: rgba(255, 255, 255, .02); + transition: border-color .2s, color .2s, background .2s; +} + +.pill:hover { + border-color: var(--accent); + color: var(--accent); + background: var(--accent-soft); +} + +/* ── HOME: LINK ROWS ────────────────────────────── */ +.link-row { + display: grid; + grid-template-columns: 80px 1fr 16px; + align-items: center; + gap: 12px; + padding: 14px 0; + border-bottom: 1px solid var(--border); + text-decoration: none; + color: var(--txt); + font-size: .82rem; + transition: color .2s, padding .25s var(--ease); +} + +.link-row:last-of-type { border-bottom: none; } + +.link-row:hover { + color: var(--accent); + padding-left: 8px; +} + +.link-key { + font-size: .65rem; + letter-spacing: .14em; + text-transform: uppercase; + color: var(--txt-dim); +} + +.link-row:hover .link-key { color: var(--accent); } + +.link-val { + font-family: var(--mono); +} + +.link-arrow { + color: var(--accent); + opacity: 0; + transform: translateX(-4px); + transition: opacity .2s, transform .25s var(--ease); +} + +.link-row:hover .link-arrow { + opacity: 1; + transform: translateX(0); } -.iframe-wrap::before { +/* ── HOME: STATS ────────────────────────────────── */ +.stat-row { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 0; + border: 1px solid var(--border); + background: var(--bg1); +} + +.stat { + padding: 28px 24px; + border-right: 1px solid var(--border); + position: relative; +} + +.stat:last-child { border-right: none; } + +.stat-num { + font-family: var(--sans); + font-weight: 800; + font-size: 2.4rem; + color: var(--white); + line-height: 1; + letter-spacing: -.02em; +} + +.stat-plus { + color: var(--accent); + font-size: 1.4rem; + vertical-align: top; + margin-left: 2px; +} + +.stat-label { + margin-top: 10px; + font-size: .68rem; + letter-spacing: .14em; + text-transform: uppercase; + color: var(--txt-dim); +} + +/* ── CARD GRID ──────────────────────────────────── */ +.card-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 16px; + margin-bottom: 16px; +} + +.card { + background: var(--bg1); + border: 1px solid var(--border); + padding: 22px 24px; + position: relative; + display: flex; + flex-direction: column; + text-decoration: none; + color: inherit; + transition: transform .25s var(--ease), border-color .2s, background .2s, box-shadow .25s; + overflow: hidden; +} + +.card::before { + content: ''; + position: absolute; top: -1px; left: -1px; + width: 12px; + height: 12px; border-top: 2px solid var(--accent); border-left: 2px solid var(--accent); + opacity: 0; + transition: opacity .25s; } -.iframe-wrap::after { +.card::after { + content: ''; + position: absolute; bottom: -1px; right: -1px; + width: 12px; + height: 12px; border-bottom: 2px solid var(--accent); border-right: 2px solid var(--accent); + opacity: 0; + transition: opacity .25s; } -/* faux browser chrome */ -.iframe-chrome { - background: var(--bg2); - border-bottom: 1px solid var(--border); - padding: 10px 16px; +.card:hover { + transform: translateY(-3px); + border-color: rgba(232, 255, 71, .35); + background: rgba(232, 255, 71, .03); + box-shadow: 0 12px 32px -16px rgba(232, 255, 71, .25); +} + +.card:hover::before, +.card:hover::after { + opacity: 1; +} + +.card h3 { + font-family: var(--sans); + font-weight: 800; + font-size: 1.05rem; + color: var(--white); + letter-spacing: -.01em; + margin-bottom: 8px; +} + +.card p { + font-size: .82rem; + color: var(--txt-dim); + line-height: 1.6; + margin-bottom: 14px; + flex: 1; +} + +.card-head { display: flex; + justify-content: space-between; align-items: center; - gap: 12px; + margin-bottom: 14px; } -.chrome-dots { - display: flex; - gap: 6px; +.card-tag { + font-size: .62rem; + letter-spacing: .14em; + text-transform: uppercase; + color: var(--accent); + padding: 3px 8px; + border: 1px solid rgba(232, 255, 71, .3); + background: var(--accent-soft); } -.chrome-dot { - width: 10px; - height: 10px; - border-radius: 50%; +.card-ext { + color: var(--txt-faint); + font-size: .9rem; + transition: color .2s, transform .25s var(--ease); } -.chrome-dot:nth-child(1) { background: #ff5f57; } -.chrome-dot:nth-child(2) { background: #febc2e; } -.chrome-dot:nth-child(3) { background: #28c840; } +.card:hover .card-ext { + color: var(--accent); + transform: translate(2px, -2px); +} -.chrome-url { - flex: 1; - background: rgba(255, 255, 255, .04); - border: 1px solid var(--border); - border-radius: 4px; - padding: 4px 12px; - font-size: .72rem; +.card-tech { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.card-tech span { + font-family: var(--mono); + font-size: .62rem; + letter-spacing: .08em; + text-transform: lowercase; + padding: 3px 8px; + border: 1px solid var(--border-strong); color: var(--txt-dim); - letter-spacing: .04em; + background: rgba(255, 255, 255, .02); } -iframe { - display: block; +.card-cta { + font-family: var(--mono); + font-size: .76rem; + letter-spacing: .06em; + color: var(--accent); + margin-top: auto; + transition: letter-spacing .25s var(--ease); +} + +.card:hover .card-cta { letter-spacing: .12em; } + +/* ── SOCIAL ACCENT STRIPS ───────────────────────── */ +.social-card { position: relative; } + +.social-card::before { + opacity: 1; width: 100%; - height: calc(100vh - var(--nav-h) - 120px); - min-height: 520px; + height: 2px; border: none; - background: var(--bg1); + top: 0; + left: 0; + background: var(--social-color, var(--accent)); +} + +.social-card.facebook { --social-color: #4f73e3; } +.social-card.instagram { --social-color: #e1416f; } +.social-card.telegram { --social-color: #2aabee; } + +.social-card:hover { border-color: var(--social-color, var(--accent)); } +.social-card:hover .card-tag, +.social-card:hover .card-cta, +.social-card:hover .card-ext { + color: var(--social-color, var(--accent)); +} +.social-card:hover .card-tag { + border-color: var(--social-color, var(--accent)); + background: color-mix(in srgb, var(--social-color, var(--accent)) 14%, transparent); } +/* ── FOOTER ─────────────────────────────────────── */ +.site-footer { + position: relative; + z-index: 1; + max-width: var(--max-w); + margin: 0 auto; + padding: 32px var(--pad-x) 40px; + font-size: .72rem; + color: var(--txt-faint); + display: flex; + gap: 12px; + align-items: center; + border-top: 1px solid var(--border); +} + +.footer-dot { color: var(--accent); } + /* ── RESPONSIVE ─────────────────────────────────── */ +@media (max-width: 880px) { + .home-grid { grid-template-columns: 1fr; } + .stat-row { grid-template-columns: 1fr; } + .stat { border-right: none; border-bottom: 1px solid var(--border); } + .stat:last-child { border-bottom: none; } +} + @media (max-width: 640px) { :root { --pad-x: 20px; } header { padding: 0 16px; } .logo-sep { margin: 0 14px; } .tab-btn { padding: 0 12px; font-size: .72rem; } + .tab-btn .tab-idx { display: none; } .status { display: none; } - iframe { height: 70vh; min-height: 400px; } - .hero { padding-top: 48px; } + .hero { padding-top: 56px; } + .hero-glow { left: 0; width: 100%; } + .about-card, + .links-card { padding: 22px; } + .stat-num { font-size: 1.9rem; } }