mirror of
https://github.com/adam-benyekkou/my_portfolio.git
synced 2026-01-15 20:20:09 +00:00
Refactoring contact page in smaller components
This commit is contained in:
@@ -39,12 +39,6 @@
|
|||||||
to { opacity: 1; }
|
to { opacity: 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes scanLine {
|
|
||||||
from { transform: translate3d(-100%, 0, 0); opacity: 0; }
|
|
||||||
50% { opacity: 1; }
|
|
||||||
to { transform: translate3d(100%, 0, 0); opacity: 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===================== CONTACT ELEMENTS ===================== */
|
/* ===================== CONTACT ELEMENTS ===================== */
|
||||||
|
|
||||||
/* Content container */
|
/* Content container */
|
||||||
@@ -71,59 +65,6 @@
|
|||||||
animation: slideInUp 0.8s ease-out 0.8s forwards;
|
animation: slideInUp 0.8s ease-out 0.8s forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Contact items */
|
|
||||||
.contact-item {
|
|
||||||
opacity: 0;
|
|
||||||
animation: scaleIn 0.8s ease-out forwards;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-item:nth-child(1) { animation-delay: 1.0s; }
|
|
||||||
.contact-item:nth-child(2) { animation-delay: 1.1s; }
|
|
||||||
.contact-item:nth-child(3) { animation-delay: 1.2s; }
|
|
||||||
|
|
||||||
/* Scan line effect */
|
|
||||||
.contact-item::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: -100%;
|
|
||||||
width: 100%;
|
|
||||||
height: 2px;
|
|
||||||
background: linear-gradient(90deg, transparent, var(--color-nier-accent), transparent);
|
|
||||||
animation: scanLine 1.5s ease-out forwards;
|
|
||||||
z-index: 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-item:nth-child(1)::before { animation-delay: 1.2s; }
|
|
||||||
.contact-item:nth-child(2)::before { animation-delay: 1.3s; }
|
|
||||||
.contact-item:nth-child(3)::before { animation-delay: 1.4s; }
|
|
||||||
|
|
||||||
/* Contact icons */
|
|
||||||
.contact-icon {
|
|
||||||
opacity: 0;
|
|
||||||
animation: scaleIn 0.5s ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-item:nth-child(1) .contact-icon { animation-delay: 1.3s; }
|
|
||||||
.contact-item:nth-child(2) .contact-icon { animation-delay: 1.4s; }
|
|
||||||
.contact-item:nth-child(3) .contact-icon { animation-delay: 1.5s; }
|
|
||||||
|
|
||||||
/* Contact labels and values */
|
|
||||||
.contact-label,
|
|
||||||
.contact-value {
|
|
||||||
opacity: 0;
|
|
||||||
animation: slideInLeft 0.4s ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-item:nth-child(1) .contact-label { animation-delay: 1.4s; }
|
|
||||||
.contact-item:nth-child(2) .contact-label { animation-delay: 1.5s; }
|
|
||||||
.contact-item:nth-child(3) .contact-label { animation-delay: 1.6s; }
|
|
||||||
|
|
||||||
.contact-item:nth-child(1) .contact-value { animation-delay: 1.5s; }
|
|
||||||
.contact-item:nth-child(2) .contact-value { animation-delay: 1.6s; }
|
|
||||||
.contact-item:nth-child(3) .contact-value { animation-delay: 1.7s; }
|
|
||||||
|
|
||||||
/* Info panels container */
|
/* Info panels container */
|
||||||
.info-panels-container {
|
.info-panels-container {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@@ -156,22 +97,6 @@
|
|||||||
.info-panel:nth-child(1) .info-panel-content { animation-delay: 1.9s; }
|
.info-panel:nth-child(1) .info-panel-content { animation-delay: 1.9s; }
|
||||||
.info-panel:nth-child(2) .info-panel-content { animation-delay: 2.0s; }
|
.info-panel:nth-child(2) .info-panel-content { animation-delay: 2.0s; }
|
||||||
|
|
||||||
/* ===================== HOVER EFFECTS ===================== */
|
|
||||||
|
|
||||||
.contact-item:hover {
|
|
||||||
transform: translateY(-3px);
|
|
||||||
box-shadow:
|
|
||||||
0 8px 25px rgba(0, 0, 0, 0.2),
|
|
||||||
0 0 20px rgba(90, 90, 80, 0.1);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-item:hover .contact-icon {
|
|
||||||
transform: scale(1.05);
|
|
||||||
box-shadow: 0 0 15px rgba(90, 90, 80, 0.3);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===================== BACKGROUND PATTERN ===================== */
|
/* ===================== BACKGROUND PATTERN ===================== */
|
||||||
|
|
||||||
.contact-content-container::before {
|
.contact-content-container::before {
|
||||||
@@ -196,11 +121,6 @@
|
|||||||
.contact-content-container { animation-delay: 0.3s; }
|
.contact-content-container { animation-delay: 0.3s; }
|
||||||
.availability-status { animation-delay: 0.4s; }
|
.availability-status { animation-delay: 0.4s; }
|
||||||
.contact-grid { animation-delay: 0.6s; }
|
.contact-grid { animation-delay: 0.6s; }
|
||||||
|
|
||||||
.contact-item:nth-child(1) { animation-delay: 0.8s; }
|
|
||||||
.contact-item:nth-child(2) { animation-delay: 0.9s; }
|
|
||||||
\contact-item:nth-child(3) { animation-delay: 1.0s; }
|
|
||||||
|
|
||||||
.info-panels-container { animation-delay: 1.2s; }
|
.info-panels-container { animation-delay: 1.2s; }
|
||||||
.info-panel:nth-child(1) { animation-delay: 1.3s; }
|
.info-panel:nth-child(1) { animation-delay: 1.3s; }
|
||||||
.info-panel:nth-child(2) { animation-delay: 1.4s; }
|
.info-panel:nth-child(2) { animation-delay: 1.4s; }
|
||||||
@@ -209,16 +129,12 @@
|
|||||||
.contact-content-container,
|
.contact-content-container,
|
||||||
.availability-status,
|
.availability-status,
|
||||||
.contact-grid,
|
.contact-grid,
|
||||||
.contact-item,
|
|
||||||
.info-panels-container,
|
.info-panels-container,
|
||||||
.info-panel {
|
.info-panel {
|
||||||
animation-duration: 0.6s;
|
animation-duration: 0.6s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-dot,
|
.status-dot,
|
||||||
.contact-icon,
|
|
||||||
.contact-label,
|
|
||||||
.contact-value,
|
|
||||||
.info-panel-title,
|
.info-panel-title,
|
||||||
.info-panel-content {
|
.info-panel-content {
|
||||||
animation-duration: 0.3s;
|
animation-duration: 0.3s;
|
||||||
@@ -237,12 +153,7 @@
|
|||||||
transform: none !important;
|
transform: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contact-item::before,
|
|
||||||
.contact-content-container::before {
|
.contact-content-container::before {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contact-item:hover {
|
|
||||||
transform: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,97 +1,56 @@
|
|||||||
<!-- Contact content with proper container structure -->
|
<!-- Contact content with proper container structure -->
|
||||||
<div class="max-w-6xl mx-auto contact-content-container">
|
<div class="max-w-6xl mx-auto contact-content-container">
|
||||||
<!-- Availability Status -->
|
<!-- Availability Status -->
|
||||||
<div class="inline-flex items-center gap-2 bg-nier-dark text-nier-light px-5 py-3 border border-nier-border mb-12 font-terminal text-xs uppercase tracking-wide availability-status mx-6">
|
<div
|
||||||
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse status-dot"></div>
|
class="inline-flex items-center gap-2 bg-nier-dark text-nier-light px-5 py-3 border border-nier-border mb-12 font-terminal text-xs uppercase tracking-wide availability-status mx-6"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="w-2 h-2 bg-green-500 rounded-full animate-pulse status-dot"
|
||||||
|
></div>
|
||||||
AVAILABLE FOR OPPORTUNITIES
|
AVAILABLE FOR OPPORTUNITIES
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Contact Grid -->
|
<!-- Contact Grid -->
|
||||||
<div class="grid grid-cols-1 gap-6 w-full max-w-md mx-auto md:max-w-none contact-grid px-6">
|
<div
|
||||||
<!-- Primary Communication Channel -->
|
class="grid grid-cols-1 gap-6 w-full max-w-md mx-auto md:max-w-none contact-grid px-6"
|
||||||
<a
|
>
|
||||||
href="mailto:adam.benyekkou.pro@hotmail.com"
|
<app-link-card
|
||||||
class="bg-nier-bg border border-nier-border p-8 flex items-center gap-6 text-nier-dark no-underline transition-all duration-200 hover:bg-nier-highlight hover:text-nier-light hover:border-nier-accent group contact-item relative"
|
title="EMAIL COMMUNICATION CHANNEL"
|
||||||
>
|
contact_link="mailto:adam.benyekkou.pro@hotmail.com"
|
||||||
<div class="w-14 h-14 bg-nier-mid border border-nier-border flex items-center justify-center text-xl text-nier-dark flex-shrink-0 transition-all duration-200 group-hover:bg-nier-light group-hover:text-nier-dark contact-icon">
|
description="Secure encrypted transmission protocol"
|
||||||
<i class="fas fa-envelope"></i>
|
/>
|
||||||
</div>
|
<app-link-card
|
||||||
<div class="flex-1">
|
title="PROFESSIONAL NETWORK ACCESS"
|
||||||
<div class="font-terminal font-medium text-base text-nier-dark uppercase tracking-wide mb-2 group-hover:text-nier-light contact-label">
|
contact_link="https://linkedin.com/in/adambnk"
|
||||||
PRIMARY COMMUNICATION CHANNEL
|
description="LinkedIn professional interface<br>
|
||||||
</div>
|
Connect for career opportunities and networking"
|
||||||
<div class="font-noto-jp text-base text-nier-mid leading-relaxed group-hover:text-nier-light contact-value">
|
/>
|
||||||
Email Access Granted<br>
|
<app-link-card
|
||||||
Secure encrypted transmission protocol enabled
|
title="SOURCE CODE REPOSITORY"
|
||||||
</div>
|
contact_link="https://github.com/adam-benyekkou"
|
||||||
</div>
|
description="GitHub development archives<br />
|
||||||
</a>
|
Access project source files and contribution history"
|
||||||
|
/>
|
||||||
<!-- Professional Network Access -->
|
|
||||||
<a
|
|
||||||
href="https://linkedin.com/in/adambnk"
|
|
||||||
target="_blank"
|
|
||||||
class="bg-nier-bg border border-nier-border p-8 flex items-center gap-6 text-nier-dark no-underline transition-all duration-200 hover:bg-nier-highlight hover:text-nier-light hover:border-nier-accent group contact-item relative"
|
|
||||||
>
|
|
||||||
<div class="w-14 h-14 bg-nier-mid border border-nier-border flex items-center justify-center text-xl text-nier-dark flex-shrink-0 transition-all duration-200 group-hover:bg-nier-light group-hover:text-nier-dark contact-icon">
|
|
||||||
<i class="fab fa-linkedin-in"></i>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1">
|
|
||||||
<div class="font-terminal font-medium text-base text-nier-dark uppercase tracking-wide mb-2 group-hover:text-nier-light contact-label">
|
|
||||||
PROFESSIONAL NETWORK ACCESS
|
|
||||||
</div>
|
|
||||||
<div class="font-noto-jp text-base text-nier-mid leading-relaxed group-hover:text-nier-light contact-value">
|
|
||||||
LinkedIn professional interface<br>
|
|
||||||
Connect for career opportunities and networking
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Source Code Repository -->
|
|
||||||
<a
|
|
||||||
href="https://github.com/adam-benyekkou"
|
|
||||||
target="_blank"
|
|
||||||
class="bg-nier-bg border border-nier-border p-8 flex items-center gap-6 text-nier-dark no-underline transition-all duration-200 hover:bg-nier-highlight hover:text-nier-light hover:border-nier-accent group contact-item relative"
|
|
||||||
>
|
|
||||||
<div class="w-14 h-14 bg-nier-mid border border-nier-border flex items-center justify-center text-xl text-nier-dark flex-shrink-0 transition-all duration-200 group-hover:bg-nier-light group-hover:text-nier-dark contact-icon">
|
|
||||||
<i class="fab fa-github"></i>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1">
|
|
||||||
<div class="font-terminal font-medium text-base text-nier-dark uppercase tracking-wide mb-2 group-hover:text-nier-light contact-label">
|
|
||||||
SOURCE CODE REPOSITORY
|
|
||||||
</div>
|
|
||||||
<div class="font-noto-jp text-base text-nier-mid leading-relaxed group-hover:text-nier-light contact-value">
|
|
||||||
GitHub development archives<br>
|
|
||||||
Access project source files and contribution history
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Info Panels -->
|
<!-- Info Panels -->
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mt-12 w-full info-panels-container px-6">
|
<div
|
||||||
|
class="grid grid-cols-1 md:grid-cols-2 gap-6 mt-12 w-full info-panels-container px-6"
|
||||||
|
>
|
||||||
<!-- Response Protocol -->
|
<!-- Response Protocol -->
|
||||||
<div class="bg-nier-mid border border-nier-border p-6 info-panel">
|
<app-info-panel
|
||||||
<div class="font-terminal text-base font-medium text-nier-dark mb-3 uppercase tracking-wide info-panel-title">
|
title="RESPONSE PROTOCOL"
|
||||||
RESPONSE PROTOCOL
|
description="Standard response time: 24-48 hour cycle<br />
|
||||||
</div>
|
Emergency contact: Email protocol recommended<br />
|
||||||
<div class="font-noto-jp text-base text-nier-dark leading-relaxed info-panel-content">
|
Priority inquiries: LinkedIn messaging for urgent requests"
|
||||||
Standard response time: 24-48 hour cycle<br>
|
/>
|
||||||
Emergency contact: Email protocol recommended<br>
|
|
||||||
Priority inquiries: LinkedIn messaging for urgent requests
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Collaboration Status -->
|
<app-info-panel
|
||||||
<div class="bg-nier-mid border border-nier-border p-6 info-panel mb-8">
|
class="mb-8"
|
||||||
<div class="font-terminal text-base font-medium text-nier-dark mb-3 uppercase tracking-wide info-panel-title">
|
title="COLLABORATION STATUS"
|
||||||
COLLABORATION STATUS
|
description="Currently seeking: Full-time opportunities, internships<br />
|
||||||
</div>
|
Specialization: Web development, Angular, PHP, Python<br />
|
||||||
<div class="font-noto-jp text-base text-nier-dark leading-relaxed info-panel-content">
|
Location: Remote-ready, Toulouse, France"
|
||||||
Currently seeking: Full-time opportunities, internships, freelance projects<br>
|
/>
|
||||||
Specialization: Web development, Angular, modern tech stack<br>
|
|
||||||
Location: Remote-ready, French hideout base of operations
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
import { InfoPanelComponent } from './info-panel/info-panel.component';
|
||||||
|
import { LinkCardComponent } from './link-card/link-card.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-contact-content',
|
selector: 'app-contact-content',
|
||||||
imports: [],
|
imports: [InfoPanelComponent, LinkCardComponent],
|
||||||
templateUrl: './contact-content.component.html',
|
templateUrl: './contact-content.component.html',
|
||||||
styleUrl: './contact-content.component.css'
|
styleUrl: './contact-content.component.css',
|
||||||
})
|
})
|
||||||
export class ContactContentComponent {
|
export class ContactContentComponent {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/* ===================== CONTACT PAGE ANIMATIONS ===================== */
|
||||||
|
|
||||||
|
/* Core keyframes - reused across components */
|
||||||
|
@keyframes slideInLeft {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(-30px, 0, 0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes scaleIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===================== INFO PANELS ===================== */
|
||||||
|
|
||||||
|
/* Info panels */
|
||||||
|
.info-panel {
|
||||||
|
opacity: 0;
|
||||||
|
animation: scaleIn 0.6s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-panel:nth-child(1) { animation-delay: 1.6s; }
|
||||||
|
.info-panel:nth-child(2) { animation-delay: 1.7s; }
|
||||||
|
|
||||||
|
/* Info panel titles and content */
|
||||||
|
.info-panel-title {
|
||||||
|
opacity: 0;
|
||||||
|
animation: slideInLeft 0.4s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-panel-content {
|
||||||
|
opacity: 0;
|
||||||
|
animation: fadeIn 0.4s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-panel:nth-child(1) .info-panel-title { animation-delay: 1.8s; }
|
||||||
|
.info-panel:nth-child(2) .info-panel-title { animation-delay: 1.9s; }
|
||||||
|
|
||||||
|
.info-panel:nth-child(1) .info-panel-content { animation-delay: 1.9s; }
|
||||||
|
.info-panel:nth-child(2) .info-panel-content { animation-delay: 2.0s; }
|
||||||
|
|
||||||
|
/* ===================== RESPONSIVE DESIGN ===================== */
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.info-panel:nth-child(1) { animation-delay: 1.3s; }
|
||||||
|
.info-panel:nth-child(2) { animation-delay: 1.4s; }
|
||||||
|
|
||||||
|
/* Faster animations on mobile */
|
||||||
|
.info-panel {
|
||||||
|
animation-duration: 0.6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-panel-title,
|
||||||
|
.info-panel-content {
|
||||||
|
animation-duration: 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===================== ACCESSIBILITY ===================== */
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
*[class*="info-"] {
|
||||||
|
animation: none !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<div class="bg-nier-mid border border-nier-border p-6 info-panel">
|
||||||
|
<div
|
||||||
|
class="font-terminal text-base font-medium text-nier-dark mb-3 uppercase tracking-wide info-panel-title"
|
||||||
|
>
|
||||||
|
{{ title() }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="font-noto-jp text-base text-nier-dark leading-relaxed info-panel-content"
|
||||||
|
[innerHTML]="description()"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Component, input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-info-panel',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './info-panel.component.html',
|
||||||
|
styleUrl: './info-panel.component.css',
|
||||||
|
})
|
||||||
|
export class InfoPanelComponent {
|
||||||
|
title = input.required<string>();
|
||||||
|
description = input.required<string>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
/* ===================== CONTACT PAGE ANIMATIONS ===================== */
|
||||||
|
|
||||||
|
/* Core keyframes - reused across components */
|
||||||
|
@keyframes scaleIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes scanLine {
|
||||||
|
from { transform: translate3d(-100%, 0, 0); opacity: 0; }
|
||||||
|
50% { opacity: 1; }
|
||||||
|
to { transform: translate3d(100%, 0, 0); opacity: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===================== CONTACT ELEMENTS ===================== */
|
||||||
|
|
||||||
|
/* Contact items */
|
||||||
|
.contact-item {
|
||||||
|
opacity: 0;
|
||||||
|
animation: scaleIn 0.8s ease-out forwards;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item:nth-child(1) { animation-delay: 1.0s; }
|
||||||
|
.contact-item:nth-child(2) { animation-delay: 1.1s; }
|
||||||
|
.contact-item:nth-child(3) { animation-delay: 1.2s; }
|
||||||
|
|
||||||
|
/* Scan line effect */
|
||||||
|
.contact-item::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: -100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(90deg, transparent, var(--color-nier-accent), transparent);
|
||||||
|
animation: scanLine 1.5s ease-out forwards;
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item:nth-child(1)::before { animation-delay: 1.2s; }
|
||||||
|
.contact-item:nth-child(2)::before { animation-delay: 1.3s; }
|
||||||
|
.contact-item:nth-child(3)::before { animation-delay: 1.4s; }
|
||||||
|
|
||||||
|
/* Contact icons */
|
||||||
|
.contact-icon {
|
||||||
|
opacity: 0;
|
||||||
|
animation: scaleIn 0.5s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item:nth-child(1) .contact-icon { animation-delay: 1.3s; }
|
||||||
|
.contact-item:nth-child(2) .contact-icon { animation-delay: 1.4s; }
|
||||||
|
.contact-item:nth-child(3) .contact-icon { animation-delay: 1.5s; }
|
||||||
|
|
||||||
|
/* Contact labels and values */
|
||||||
|
.contact-label,
|
||||||
|
.contact-value {
|
||||||
|
opacity: 0;
|
||||||
|
animation: slideInLeft 0.4s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideInLeft {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(-30px, 0, 0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item:nth-child(1) .contact-label { animation-delay: 1.4s; }
|
||||||
|
.contact-item:nth-child(2) .contact-label { animation-delay: 1.5s; }
|
||||||
|
.contact-item:nth-child(3) .contact-label { animation-delay: 1.6s; }
|
||||||
|
|
||||||
|
.contact-item:nth-child(1) .contact-value { animation-delay: 1.5s; }
|
||||||
|
.contact-item:nth-child(2) .contact-value { animation-delay: 1.6s; }
|
||||||
|
.contact-item:nth-child(3) .contact-value { animation-delay: 1.7s; }
|
||||||
|
|
||||||
|
/* ===================== HOVER EFFECTS ===================== */
|
||||||
|
|
||||||
|
.contact-item:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow:
|
||||||
|
0 8px 25px rgba(0, 0, 0, 0.2),
|
||||||
|
0 0 20px rgba(90, 90, 80, 0.1);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item:hover .contact-icon {
|
||||||
|
transform: scale(1.05);
|
||||||
|
box-shadow: 0 0 15px rgba(90, 90, 80, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===================== RESPONSIVE DESIGN ===================== */
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.contact-item:nth-child(1) { animation-delay: 0.8s; }
|
||||||
|
.contact-item:nth-child(2) { animation-delay: 0.9s; }
|
||||||
|
.contact-item:nth-child(3) { animation-delay: 1.0s; }
|
||||||
|
|
||||||
|
/* Faster animations on mobile */
|
||||||
|
.contact-item {
|
||||||
|
animation-duration: 0.6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-icon,
|
||||||
|
.contact-label,
|
||||||
|
.contact-value {
|
||||||
|
animation-duration: 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===================== ACCESSIBILITY ===================== */
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.contact-item,
|
||||||
|
.contact-icon,
|
||||||
|
.contact-label,
|
||||||
|
.contact-value {
|
||||||
|
animation: none !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item::before {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item:hover {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<a
|
||||||
|
[href]="contact_link()" target="_blank"
|
||||||
|
class="bg-nier-bg border border-nier-border p-8 flex items-center gap-6 text-nier-dark no-underline transition-all duration-200 hover:bg-nier-highlight hover:text-nier-light hover:border-nier-accent group contact-item relative"
|
||||||
|
>
|
||||||
|
<div class="w-14 h-14 bg-nier-mid border border-nier-border flex items-center justify-center text-xl text-nier-dark flex-shrink-0 transition-all duration-200 group-hover:bg-nier-light group-hover:text-nier-dark contact-icon">
|
||||||
|
<i class="fas fa-envelope"></i>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="font-terminal font-medium text-base text-nier-dark uppercase tracking-wide mb-2 group-hover:text-nier-light contact-label">
|
||||||
|
{{ title() }}
|
||||||
|
</div>
|
||||||
|
<div class="font-noto-jp text-base text-nier-mid leading-relaxed group-hover:text-nier-light contact-value" [innerHTML]="description()">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Component, input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-link-card',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './link-card.component.html',
|
||||||
|
styleUrl: './link-card.component.css',
|
||||||
|
})
|
||||||
|
export class LinkCardComponent {
|
||||||
|
title = input.required<string>();
|
||||||
|
contact_link = input.required<string>();
|
||||||
|
description = input.required<string>();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user