Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 0 additions & 44 deletions .github/workflows/ci.yml

This file was deleted.

235 changes: 93 additions & 142 deletions frontend/app/[locale]/contact/page.module.css
Original file line number Diff line number Diff line change
@@ -1,168 +1,119 @@
.page {
--gray-rgb: 0, 0, 0;
--gray-alpha-200: rgba(var(--gray-rgb), 0.08);
--gray-alpha-100: rgba(var(--gray-rgb), 0.05);

--button-primary-hover: #383838;
--button-secondary-hover: #f2f2f2;

display: grid;
grid-template-rows: 20px 1fr 20px;
align-items: center;
justify-items: center;
min-height: 100svh;
padding: 80px;
gap: 64px;
font-family: var(--font-geist-sans);
.container {
max-width: 960px;
margin: 40px auto;
padding: 20px;
text-align: center;
}

@media (prefers-color-scheme: dark) {
.page {
--gray-rgb: 255, 255, 255;
--gray-alpha-200: rgba(var(--gray-rgb), 0.145);
--gray-alpha-100: rgba(var(--gray-rgb), 0.06);

--button-primary-hover: #ccc;
--button-secondary-hover: #1a1a1a;
}
}

.main {
display: flex;
flex-direction: column;
gap: 32px;
grid-row-start: 2;
}

.main ol {
font-family: var(--font-geist-mono);
padding-left: 0;
margin: 0;
font-size: 14px;
line-height: 24px;
letter-spacing: -0.01em;
list-style-position: inside;
.title {
font-size: 2.5rem;
font-weight: bold;
margin-bottom: 1rem;
color: var(--foreground);
}

.main li:not(:last-of-type) {
margin-bottom: 8px;
.subtitle {
font-size: 1.2rem;
color: var(--muted-foreground);
margin-bottom: 3rem;
}

.main code {
font-family: inherit;
background: var(--gray-alpha-100);
padding: 2px 4px;
border-radius: 4px;
font-weight: 600;
}

.ctas {
display: flex;
gap: 16px;
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
text-align: left;
}

.ctas a {
appearance: none;
border-radius: 128px;
height: 48px;
padding: 0 20px;
border: none;
border: 1px solid transparent;
transition:
background 0.2s,
color 0.2s,
border-color 0.2s;
cursor: pointer;
.card {
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
line-height: 20px;
font-weight: 500;
gap: 1.5rem;
background-color: var(--card);
padding: 1.5rem;
border-radius: 12px;
border: 1px solid var(--border);
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
text-decoration: none;
color: inherit;
}

a.primary {
background: var(--foreground);
color: var(--background);
gap: 8px;
.card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
}

a.secondary {
border-color: var(--gray-alpha-200);
min-width: 180px;
.dark .card:hover {
box-shadow: 0 8px 25px rgba(255, 255, 255, 0.08);
}

.footer {
grid-row-start: 3;
display: flex;
gap: 24px;
}

.footer a {
.iconWrapper {
flex-shrink: 0;
display: flex;
align-items: center;
gap: 8px;
justify-content: center;
width: 64px;
height: 64px;
/* Для светлой темы фон остается прежним */
background-color: var(--muted);
border-radius: 50%;
transition: background-color 0.3s ease-in-out;
}

/*
НОВЫЙ БЛОК: Правило для фона иконки в темной теме.
Вместо светло-серого мы используем var(--secondary),
который является темно-серым и лучше вписывается в фон карточки.
*/
.dark .iconWrapper {
background-color: var(--secondary);
}

.icon {
width: 40px;
height: 40px;
object-fit: contain;
/* Добавляем плавный переход для фильтра и прозрачности */
transition: filter 0.3s ease-in-out, opacity 0.3s ease-in-out;
}

/*
ИЗМЕНЕННЫЙ БЛОК: Улучшенная адаптация иконки.
Мы по-прежнему инвертируем ее, чтобы сделать белой,
но добавляем прозрачность. Это убирает резкость и делает
иконку похожей по яркости на основной текст.
*/
.dark .invertOnDark {
/* filter: brightness(0);
opacity: 1; */
color: white;
background-color: white;
}

.cardContent {
display: flex;
flex-direction: column;
}

.footer img {
flex-shrink: 0;
.cardTitle {
font-size: 1.25rem;
font-weight: 600;
color: var(--foreground);
margin: 0;
}

/* Enable hover only on non-touch devices */
@media (hover: hover) and (pointer: fine) {
a.primary:hover {
background: var(--button-primary-hover);
border-color: transparent;
}

a.secondary:hover {
background: var(--button-secondary-hover);
border-color: transparent;
}

.footer a:hover {
text-decoration: underline;
text-underline-offset: 4px;
}
.cardHandle {
font-size: 1rem;
color: var(--muted-foreground);
margin: 0;
word-break: break-all;
}

@media (max-width: 600px) {
.page {
padding: 32px;
padding-bottom: 80px;
@media (max-width: 640px) {
.title {
font-size: 2rem;
}

.main {
align-items: center;
}

.main ol {
text-align: center;
.grid {
grid-template-columns: 1fr;
}

.ctas {
flex-direction: column;
}

.ctas a {
font-size: 14px;
height: 40px;
padding: 0 16px;
}

a.secondary {
min-width: auto;
}

.footer {
flex-wrap: wrap;
align-items: center;
justify-content: center;
}
}

@media (prefers-color-scheme: dark) {
.logo {
filter: invert();
}
}
}
76 changes: 71 additions & 5 deletions frontend/app/[locale]/contact/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,75 @@
import styles from "./page.module.css";
'use client';

import Image from 'next/image';
import { useTranslations } from 'next-intl';
import styles from './page.module.css';

const contacts = [
{
name: 'Telegram',
handle: '@diametrfq',
url: 'https://t.me/diametrfq',
iconUrl: '/logo/telegram.svg',
},
{
name: 'LinkedIn',
handle: 'Dmitry Khokhlov',
url: 'https://www.linkedin.com/in/diametrfq',
iconUrl: '/logo/linkedin.svg',
},
{
name: 'GitHub',
handle: 'DiametrFQ',
url: 'https://github.com/DiametrFQ',
iconUrl: 'https://cdn.worldvectorlogo.com/logos/github-icon-1.svg',
themeBehavior: 'invertOnDark',
},
{
name: 'Email',
handle: 'hohlov.03@inbox.ru',
url: 'mailto:hohlov.03@inbox.ru',
iconUrl: '/logo/email.png',
},
{
name: 'Steam',
handle: 'diametrfq',
url: 'https://steamcommunity.com/id/diametrfq/',
iconUrl: '/logo/steam.png',
},
];

export default function Contact() {
const t = useTranslations('ContactPage');

export default function Portfolio() {
return (
<div className={styles.page}>
contact
<div className={styles.container}>
<h1 className={styles.title}>{t('title')}</h1>
<p className={styles.subtitle}>{t('subtitle')}</p>
<div className={styles.grid}>
{contacts.map((contact) => (
<a
key={contact.name}
href={contact.url}
target="_blank"
rel="noopener noreferrer"
className={styles.card}
>
<div className={styles.iconWrapper}>
<Image
src={contact.iconUrl}
alt={`${contact.name} logo`}
width={48}
height={48}
className={`${styles.icon} ${contact.themeBehavior ? styles[contact.themeBehavior] : ''}`}
/>
</div>
<div className={styles.cardContent}>
<h2 className={styles.cardTitle}>{contact.name}</h2>
<p className={styles.cardHandle}>{contact.handle}</p>
</div>
</a>
))}
</div>
</div>
);
}
}
Loading