/** * globals.css — Novarix Networks * * Design tokens and base styles for the Novarix Networks marketing site. * * Structure: * 1. Design tokens (CSS custom properties) * 2. CSS reset & base element styles * 3. Layout utilities (.container, .narrow) * 4. Ambient background layer * 5. Site header * 6. Hero section * 7. Shared section / card / direction-list styles * 8. Footer * 9. Intro overlay (first-visit splash animation) * 10. Keyframe animations * 11. Responsive breakpoints (980 → 720 → 560 px) * 12. Reduced-motion overrides */ /* ───────────────────────────────────────────── 1. Design tokens ───────────────────────────────────────────── */ :root { color-scheme: light dark; /* Backgrounds */ --bg: #fbfcfb; --bg-elevated: rgba(248, 250, 252, 0.78); /* card / panel surfaces */ --bg-strong: #071014; /* Text */ --text: #0b1418; --text-soft: #4b5c63; /* secondary / body copy */ /* Borders */ --border: rgba(15, 23, 42, 0.10); --border-strong: rgba(15, 23, 42, 0.18); /* hover / active states */ /* Buttons — primary (filled) */ --button: #0f172a; --button-text: #ffffff; /* Buttons — secondary (outlined) */ --button-secondary-bg: transparent; --button-secondary-text: #0f172a; --button-secondary-border: rgba(15, 23, 42, 0.20); /* Brand accent (eyebrows, phase labels, hover links) */ --accent: #218ba0; --accent-strong: #38d1d4; --accent-lime: #c8f05a; /* Layout */ --max-width: 1200px; --header-height: 96px; --radius: 8px; /* card border-radius */ --radius-sm: 6px; /* button / small element radius */ /* Elevation */ --shadow: 0 18px 40px rgba(15, 23, 42, 0.08); --shadow-sm: 0 4px 16px rgba(15, 23, 42, 0.06); /* Transitions */ --transition-fast: 160ms ease; --transition-base: 220ms ease; } /* ── Dark-mode token overrides ── */ @media (prefers-color-scheme: dark) { :root { --bg: #071014; --bg-elevated: rgba(9, 21, 27, 0.76); --bg-strong: #03090d; --text: #eef7f7; --text-soft: #a3b5bc; --border: rgba(148, 163, 184, 0.14); --border-strong: rgba(148, 163, 184, 0.26); --button: #e5e7eb; --button-text: #020617; --button-secondary-bg: transparent; --button-secondary-text: #e5e7eb; --button-secondary-border: rgba(148, 163, 184, 0.28); --accent: #38d1d4; --accent-strong: #69e6e8; --accent-lime: #d7f76f; --shadow: 0 18px 40px rgba(0, 0, 0, 0.28); --shadow-sm: 0 4px 16px rgba(0, 0, 0, 0.20); } } /* ───────────────────────────────────────────── 2. CSS reset & base element styles ───────────────────────────────────────────── */ *, *::before, *::after { box-sizing: border-box; } html { scroll-behavior: smooth; /* Reserve gutter for scrollbar so content doesn't shift on overflow toggle */ scrollbar-gutter: stable; } html, body { margin: 0; padding: 0; background: var(--bg); color: var(--text); font-family: var(--font-dm-sans), ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } body { overflow-x: hidden; } /* ── Focus-visible — keyboard navigation indicator ── */ /* * Visible outline for keyboard users only. Mouse/touch interactions do not * trigger :focus-visible, so this does not affect pointer-driven UX. */ :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-sm); } :focus:not(:focus-visible) { outline: none; } /* Inherit colour from parent; text-decoration handled per component */ a { color: inherit; text-decoration: none; } /* Prevent images from overflowing their containers */ img { display: block; max-width: 100%; } /* ───────────────────────────────────────────── 3. Layout utilities ───────────────────────────────────────────── */ /* Centred, max-width container with responsive horizontal padding */ .container { width: min(var(--max-width), calc(100% - 48px)); margin: 0 auto; } /* Narrow variant for text-heavy sections (Direction, Contact) */ .narrow { max-width: 880px; } /* ───────────────────────────────────────────── 4. Ambient background layer ───────────────────────────────────────────── */ /** * .site-shell * * Full-page wrapper that renders two layered radial gradients. Their focal * points follow the cursor via --mx / --my CSS custom properties, which are * updated by a mousemove handler in page.tsx. */ .site-shell { position: relative; isolation: isolate; min-height: 100vh; background: radial-gradient( circle at var(--mx, 50%) var(--my, 22%), rgba(56, 209, 212, 0.12), transparent 18% ), radial-gradient( circle at calc(var(--mx, 50%) * 0.65) calc(var(--my, 22%) * 1.2), rgba(200, 240, 90, 0.06), transparent 22% ), var(--bg); } /** * .ambient-layer * * Fixed, non-interactive overlay rendered behind all page content. * Contains: * • .ambient-orb-a / .ambient-orb-b — blurred colour blobs * • .ambient-grid — subtle perspective grid */ .ambient-layer { position: fixed; inset: 0; pointer-events: none; z-index: -1; overflow: hidden; } /* Fine grid that fades out toward the bottom of the viewport */ .ambient-grid { position: absolute; inset: 0; background-image: linear-gradient(to right, rgba(148, 163, 184, 0.07) 1px, transparent 1px), linear-gradient(to bottom, rgba(148, 163, 184, 0.07) 1px, transparent 1px); background-size: 56px 56px; mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.4), transparent 80%); } /* Shared base for the slow ambient sweeps behind the page content */ .ambient-orb { position: absolute; filter: blur(54px); opacity: 0.16; animation: drift 16s ease-in-out infinite; will-change: transform; /* promote to GPU layer */ } .ambient-orb-a { width: 42rem; height: 18rem; top: 7rem; right: -14rem; transform: rotate(-14deg); background: linear-gradient( 135deg, rgba(56, 209, 212, 0.55), rgba(32, 92, 140, 0.12) ); } .ambient-orb-b { width: 36rem; height: 14rem; top: 28rem; left: -12rem; transform: rotate(18deg); background: linear-gradient( 135deg, rgba(200, 240, 90, 0.28), rgba(34, 211, 238, 0.12) ); animation-duration: 22s; } /* ───────────────────────────────────────────── 5. Site header ───────────────────────────────────────────── */ /** * Sticky frosted-glass header. * z-index: 1000 keeps it above section content; the intro overlay uses * z-index: 2000 so it still renders on top during the splash sequence. */ .site-header { position: sticky; top: 0; z-index: 1000; min-height: var(--header-height); background: color-mix(in srgb, var(--bg) 80%, transparent); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border-bottom: 1px solid var(--border); transition: border-color var(--transition-fast); } /* Flexbox row: brand on the left, nav on the right */ .header-inner { min-height: var(--header-height); display: flex; align-items: center; justify-content: space-between; gap: 32px; } .brand-link { display: inline-flex; align-items: center; min-width: 0; flex: 0 1 auto; } .brand-image { width: auto; height: 52px; max-width: min(540px, 40vw); object-fit: contain; } /* Light / dark wordmark swap ── Default: show colour wordmark (light mode) Dark mode: swap to white wordmark */ .brand-image-dark, .intro-wordmark-dark { display: none; } @media (prefers-color-scheme: dark) { .brand-image-light, .intro-wordmark-light { display: none; } .brand-image-dark, .intro-wordmark-dark { display: block; } } /* Primary navigation */ .nav { display: flex; align-items: center; gap: 32px; flex-shrink: 0; } .nav a { font-size: 0.92rem; font-weight: 500; letter-spacing: 0.01em; color: var(--text-soft); transition: color var(--transition-fast); } .nav a:hover { color: var(--text); } /* ───────────────────────────────────────────── 6. Hero section ───────────────────────────────────────────── */ .hero { position: relative; overflow: hidden; padding: 112px 0 58px; } /* Constrain hero copy for comfortable line length at wide viewports */ .hero-copy { position: relative; z-index: 1; max-width: 930px; } .hero-mark { position: absolute; inset: 20px -12vw auto auto; width: min(72rem, 86vw); height: min(48rem, 58vw); background-image: url("/branding/animated_logo_intro.svg"); background-position: center; background-repeat: no-repeat; background-size: contain; opacity: 0.075; pointer-events: none; transform: rotate(-2deg); } /* Small all-caps service category label */ .eyebrow { margin: 0 0 20px; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent); } .hero h1 { margin: 0; max-width: 1040px; font-size: 4.8rem; line-height: 0.98; letter-spacing: 0; font-weight: 700; } .hero-text { margin: 28px 0 0; max-width: 760px; font-size: 1.16rem; line-height: 1.78; color: var(--text-soft); } .hero-actions { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 38px; } .signal-strip { position: relative; z-index: 1; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px; margin-top: 56px; border: 1px solid var(--border); background: var(--border); box-shadow: var(--shadow-sm); } .signal-item { min-height: 112px; padding: 22px; background: color-mix(in srgb, var(--bg) 88%, transparent); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); } .signal-item span { display: block; margin-bottom: 10px; color: var(--text-soft); font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; } .signal-item strong { display: block; color: var(--text); font-size: 1.08rem; line-height: 1.35; } /* ───────────────────────────────────────────── 7. Shared section / card / direction-list styles ───────────────────────────────────────────── */ /* ── Buttons ── */ .button { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 48px; padding: 0 22px; border-radius: var(--radius-sm); border: 1px solid transparent; font-size: 0.92rem; font-weight: 600; letter-spacing: 0.01em; cursor: pointer; transition: transform var(--transition-fast), border-color var(--transition-fast), background-color var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast); } .button:hover { transform: translateY(-2px); } .button-primary { background: var(--button); color: var(--button-text); box-shadow: var(--shadow-sm); } .button-primary:hover { background: color-mix(in srgb, var(--button) 88%, var(--accent-strong)); box-shadow: var(--shadow); } .button-secondary { background: var(--button-secondary-bg); color: var(--button-secondary-text); border-color: var(--button-secondary-border); } /* ── Sections ── */ .section { position: relative; padding: 92px 0; } .statement-section { padding: 56px 0; background: var(--bg-strong); color: #ffffff; } .statement-section p { margin: 0; max-width: 1040px; font-size: 2rem; line-height: 1.28; font-weight: 650; } /* Visual divider between page sections */ .section-border { border-top: 1px solid var(--border); } /* Shared heading block (h2 + optional sub-text) */ .section-heading h2 { margin: 0; font-size: 2.6rem; line-height: 1.1; letter-spacing: 0; } .section-heading p { margin: 18px 0 0; max-width: 760px; font-size: 1.02rem; line-height: 1.78; color: var(--text-soft); } /* ── Service cards ── */ /* 3-column grid; collapses to single column below 980 px */ .card-grid { margin-top: 44px; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; } /** * Glass-surface card. * backdrop-filter keeps the card legible against the animated * ambient background while allowing colour bleed through. */ .card { padding: 32px 28px; border: 1px solid var(--border); border-radius: var(--radius); background: color-mix(in srgb, var(--bg) 82%, transparent); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); box-shadow: var(--shadow); transition: transform var(--transition-base), border-color var(--transition-base), box-shadow var(--transition-base); } .card:hover { transform: translateY(-3px); border-color: var(--border-strong); box-shadow: 0 24px 48px rgba(15, 23, 42, 0.12); } /* Accent-tinted icon container rendered above card title */ .card-eyebrow { display: inline-flex; margin-bottom: 42px; color: var(--accent); font-size: 0.78rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; } .card h3 { margin: 0; font-size: 1.18rem; line-height: 1.25; font-weight: 600; } .card p { margin: 14px 0 0; font-size: 0.97rem; line-height: 1.82; color: var(--text-soft); } .card-points { display: grid; gap: 10px; margin: 24px 0 0; padding: 20px 0 0; border-top: 1px solid var(--border); list-style: none; } .card-points li { display: flex; gap: 10px; align-items: flex-start; color: var(--text); font-size: 0.9rem; font-weight: 650; line-height: 1.45; } .card-points li::before { content: ""; width: 7px; height: 7px; margin-top: 0.48em; flex: 0 0 auto; background: var(--accent-strong); } .network-section { padding: 92px 0; background: color-mix(in srgb, var(--bg-strong) 96%, var(--accent)); color: #ffffff; } .network-layout { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(320px, 1.1fr); gap: 64px; align-items: start; } .network-section .section-heading p { color: rgba(255, 255, 255, 0.70); } .network-stack { display: grid; border-top: 1px solid rgba(255, 255, 255, 0.14); } .network-stack-item { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 22px; padding: 28px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.14); } .network-stack-item span { color: var(--accent-lime); font-size: 0.82rem; font-weight: 800; } .network-stack-item strong { display: block; font-size: 1.24rem; line-height: 1.25; } .network-stack-item p { margin: 10px 0 0; color: rgba(255, 255, 255, 0.68); line-height: 1.72; } /* ── Platform direction list ── */ .direction-list { margin-top: 44px; display: grid; gap: 0; /* dividers provided by border-top on each item */ } .direction-item { padding: 28px 0; border-top: 1px solid var(--border); } .direction-item:first-child { border-top: 0; padding-top: 0; } /* "Phase N" label */ .direction-phase { display: inline-block; margin-bottom: 10px; font-size: 0.76rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); } .direction-item h3 { margin: 0; font-size: 1.18rem; line-height: 1.3; font-weight: 600; } .direction-item p { margin: 12px 0 0; font-size: 0.98rem; line-height: 1.8; color: var(--text-soft); } /* ── Contact ── */ .contact-link { display: inline-block; margin-top: 24px; font-size: 1.08rem; font-weight: 600; letter-spacing: 0; transition: color var(--transition-fast); } .contact-link:hover { color: var(--accent); } /* ───────────────────────────────────────────── 8. Footer ───────────────────────────────────────────── */ .footer { padding: 28px 0 52px; } .footer-inner { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; color: var(--text-soft); font-size: 0.88rem; } /* ───────────────────────────────────────────── 9. Intro overlay (first-visit splash) ───────────────────────────────────────────── */ /** * .intro-overlay * * Full-screen fixed overlay displayed only on the first page view within a * browser session (controlled via sessionStorage in page.tsx). * * Animation sequence: * 0 ms — overlay visible; Lottie animation begins * 350 ms — wordmark slides up (intro-wordmark keyframe) * 2 450 ms — overlay begins fading out (intro-fade-out, 620 ms) * ~3 070 ms — overlay fully hidden; pointer-events removed * * z-index: 2000 — above sticky header (1000) */ .intro-overlay { position: fixed; inset: 0; z-index: 2000; display: grid; place-items: center; animation: intro-fade-out 620ms ease 2.45s forwards; } /* Solid background fill behind Lottie / wordmark */ .intro-backdrop { position: absolute; inset: 0; background: var(--bg); } /* Vertical stack: Lottie above, wordmark below */ .intro-shell { position: relative; display: grid; justify-items: center; gap: 26px; padding: 32px; } /* Responsive container for the Lottie animation */ .intro-lottie-wrap { width: min(58vw, 700px); display: grid; place-items: center; } .intro-lottie { width: 100%; height: auto; } /* Clips the upward slide of the wordmark */ .intro-wordmark-wrap { overflow: hidden; } /* Wordmark enters by sliding up from the clip boundary */ .intro-wordmark { width: min(54rem, 78vw); height: auto; animation: intro-wordmark 1s cubic-bezier(0.2, 0.8, 0.2, 1) 0.35s both; } /** * .intro-running * * Applied to
while the intro overlay is visible. * Hides page sections without removing them from the accessibility tree, * preventing a content flash beneath the overlay. */ .intro-running .site-header, .intro-running .hero, .intro-running .statement-section, .intro-running .section, .intro-running .network-section, .intro-running .footer { opacity: 0; } /* ───────────────────────────────────────────── 10. Keyframe animations ───────────────────────────────────────────── */ /* Slow vertical drift for ambient colour blobs */ @keyframes drift { 0%, 100% { transform: translate3d(0, 0, 0) scale(1); } 50% { transform: translate3d(0, 18px, 0) scale(1.06); } } /* Intro wordmark: slide up with scale from clip boundary */ @keyframes intro-wordmark { 0% { opacity: 0; transform: translateY(110%) scale(0.98); } 100% { opacity: 1; transform: translateY(0) scale(1); } } /* Fade the entire intro overlay out after the splash completes */ @keyframes intro-fade-out { to { opacity: 0; visibility: hidden; pointer-events: none; } } /* ───────────────────────────────────────────── 11. Responsive breakpoints ───────────────────────────────────────────── */ /* ── Tablet / narrow desktop (≤ 980 px) ── */ @media (max-width: 980px) { .card-grid { grid-template-columns: 1fr; /* stack cards vertically */ } .hero h1 { font-size: 3.8rem; } .signal-strip, .network-layout { grid-template-columns: 1fr; } .statement-section p { font-size: 1.65rem; } .hero { padding-top: 88px; } .brand-image { height: 46px; max-width: min(440px, 50vw); } .intro-lottie-wrap { width: min(72vw, 560px); } } /* ── Mobile (≤ 720 px) ── */ @media (max-width: 720px) { :root { --header-height: 80px; } .container { width: min(var(--max-width), calc(100% - 32px)); } .nav { gap: 18px; } .nav a { font-size: 0.88rem; } .brand-image { height: 36px; max-width: 54vw; } .hero { padding: 72px 0 80px; } .section { padding: 72px 0; } .hero h1 { font-size: 3.1rem; line-height: 1.02; } .hero-mark { inset: 80px -38vw auto auto; width: 54rem; height: 34rem; opacity: 0.065; } .signal-strip { margin-top: 40px; } .signal-item { min-height: auto; padding: 18px; } .statement-section { padding: 42px 0; } .statement-section p { font-size: 1.35rem; } .section-heading h2 { font-size: 2.15rem; } .network-section { padding: 72px 0; } .network-stack-item { grid-template-columns: 42px minmax(0, 1fr); } .hero-text, .section-heading p, .direction-item p { font-size: 0.98rem; line-height: 1.72; } .intro-lottie-wrap { width: min(82vw, 420px); } .intro-wordmark { width: 86vw; } } /* ── Small mobile (≤ 560 px) ── */ @media (max-width: 560px) { .header-inner { gap: 16px; } .nav { gap: 12px; } .brand-image { height: 30px; max-width: 50vw; } .hero h1 { font-size: 2.55rem; } .nav { display: none; } .hero-text { margin-top: 22px; } .network-stack-item { grid-template-columns: 1fr; gap: 10px; } .intro-lottie-wrap { width: min(88vw, 340px); } /* Stack CTA buttons to full-width on small screens */ .hero-actions { flex-direction: column; align-items: flex-start; } .button { width: 100%; justify-content: center; } } /* ───────────────────────────────────────────── 12. Reduced-motion overrides ───────────────────────────────────────────── */ /** * Honour the OS "Reduce Motion" accessibility setting. * Animations are disabled and the intro overlay is immediately hidden * so users are not blocked waiting for the splash to complete. */ @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .ambient-orb { animation: none !important; } /* Skip the intro entirely for users who prefer reduced motion */ .intro-overlay { animation: none !important; opacity: 0; visibility: hidden; pointer-events: none; } .intro-wordmark { animation: none !important; opacity: 1; transform: none; } .button, .card { transition: none !important; } }