Files
imen_pishghaman/app/assets/css/main.css
T
S. EsmaeiliandClaude Opus 4.6 e31ef5a21f feat: migrate landing from Next.js to Nuxt 4 (Vue 3)
Full 1:1 migration preserving all visuals, animations and behavior:
- Nuxt 4 + Vue 3 (script setup, TypeScript strict) with SSG output
- Tailwind CSS v4 with @tailwindcss/vite
- Ant Design Vue 4 (dark theme, RTL, Persian locale) for design system
- Pinia for state management (ui + contact stores)
- motion-v (framer-motion port) for all animations
- lucide-vue-next for icons
- SEO improvements: og:image, canonical fix, real 404 page, JSON-LD services
- JS bundle reduced from 302KB to 239KB gzip
- Docker/nginx deployment preserved (out/ -> nginx)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-10-06 16:28:05 +03:30

220 lines
5.3 KiB
CSS

@import "tailwindcss";
/* ---- local fonts (replaces next/font/local) ----
Same family names, fallback faces and metric overrides that next/font generated, so text
(including Persian glyphs inside font-mono, which fall back to the size-adjusted Arial face)
renders exactly as before. */
@font-face {
font-family: "vazirmatn";
src: url("/fonts/Vazirmatn-Variable.woff2") format("woff2");
font-weight: 100 900;
font-display: swap;
}
@font-face {
font-family: "vazirmatn Fallback";
src: local("Arial");
ascent-override: 102.54%;
descent-override: 53.71%;
line-gap-override: 0%;
size-adjust: 100%;
}
@font-face {
font-family: "ibmPlexMono";
src: url("/fonts/IBMPlexMono-Regular.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "ibmPlexMono";
src: url("/fonts/IBMPlexMono-Medium.woff2") format("woff2");
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "ibmPlexMono";
src: url("/fonts/IBMPlexMono-SemiBold.woff2") format("woff2");
font-weight: 600;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "ibmPlexMono Fallback";
src: local("Arial");
ascent-override: 77.95%;
descent-override: 20.91%;
line-gap-override: 0%;
size-adjust: 131.49%;
}
:root {
--font-vazirmatn: "vazirmatn", "vazirmatn Fallback", Tahoma, system-ui, sans-serif;
--font-ibm-plex-mono: "ibmPlexMono", "ibmPlexMono Fallback", ui-monospace, monospace;
}
@theme {
--font-sans: var(--font-vazirmatn), ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; /* font variables defined in :root above */
--font-mono: var(--font-ibm-plex-mono), "Vazirmatn", ui-monospace, monospace; /* font variables defined in :root above */
--color-bg: #0a0a0c;
--color-panel: #121216;
--color-panel-2: #17171c;
--color-ink: #edede6;
--color-muted: #8e8e96;
--color-accent: #ff5a00;
--color-accent-soft: #ff7a2a;
--color-hazard: #ffb800;
--color-line: #232329;
--animate-marquee: marquee 32s linear infinite;
--animate-spin-slow: spin-slow 18s linear infinite;
--animate-blink: blink 1.1s steps(2, start) infinite;
--animate-fade-up: fade-up 1s cubic-bezier(0.22, 1, 0.36, 1) both;
@keyframes marquee {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
@keyframes spin-slow {
to {
transform: rotate(360deg);
}
}
@keyframes blink {
to {
visibility: hidden;
}
}
@keyframes fade-up {
from {
opacity: 0;
transform: translateY(44px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
}
/* added for migration: CSS-only entrance animation for Hero (no JS dependency, content visible in server HTML) */
.animate-fade-up-1 {
animation: var(--animate-fade-up);
animation-delay: 0.15s;
}
.animate-fade-up-2 {
animation: var(--animate-fade-up);
animation-delay: 0.28s;
}
.animate-fade-up-3 {
animation: var(--animate-fade-up);
animation-delay: 0.42s;
}
.animate-fade-up-4 {
animation: var(--animate-fade-up);
animation-delay: 0.55s;
}
.animate-fade-up-5 {
animation: var(--animate-fade-up);
animation-delay: 0.68s;
}
.animate-fade-up-6 {
animation: var(--animate-fade-up);
animation-delay: 0.7s;
}
.animate-fade-up-7 {
animation: var(--animate-fade-up);
animation-delay: 0.82s;
}
.animate-fade-up-8 {
animation: var(--animate-fade-up);
animation-delay: 0.9s;
}
.animate-fade-up-9 {
animation: var(--animate-fade-up);
animation-delay: 1s;
}
html {
scroll-behavior: smooth;
}
body {
background-color: var(--color-bg);
color: var(--color-ink);
overflow-x: hidden;
}
::selection {
background: var(--color-accent);
color: var(--color-bg);
}
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-track {
background: var(--color-bg);
}
::-webkit-scrollbar-thumb {
background: #2c2c33;
border-radius: 8px;
border: 2px solid var(--color-bg);
}
::-webkit-scrollbar-thumb:hover {
background: var(--color-accent);
}
/* ---- hazard tape (yellow/black diagonal stripes) ---- */
.hazard {
background-image: repeating-linear-gradient(
-45deg,
#ffb800 0 14px,
#0a0a0c 14px 28px
);
}
/* ---- blueprint grid ---- */
.bg-grid {
background-image:
linear-gradient(to left, rgba(237, 237, 230, 0.045) 1px, transparent 1px),
linear-gradient(to bottom, rgba(237, 237, 230, 0.045) 1px, transparent 1px);
background-size: 72px 72px;
}
.bg-grid-fine {
background-image:
linear-gradient(to left, rgba(237, 237, 230, 0.03) 1px, transparent 1px),
linear-gradient(to bottom, rgba(237, 237, 230, 0.03) 1px, transparent 1px);
background-size: 28px 28px;
}
/* ---- film grain ---- */
.noise {
position: fixed;
inset: 0;
z-index: 90;
pointer-events: none;
opacity: 0.05;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* ---- outlined display text ---- */
.text-outline {
color: transparent;
-webkit-text-stroke: 1px rgba(237, 237, 230, 0.16);
}
/* ---- vertical safety tape strip ---- */
.tape-v {
background-image: repeating-linear-gradient(
45deg,
#ffb800 0 10px,
#0a0a0c 10px 20px
);
}