# dzanan.net — "Dark & technical" redesign Date: 2026-09-06 · Status: approved by Amar (direction C of three mockups) ## Goal Replace the current warm/editorial design of dzanan.net with the "Dark & technical" direction: near-black surfaces with a faint grid, monospace labels, a terminal-style profile panel, and a single glowing green accent. The site serves both employers and consulting clients equally. The CV becomes a PDF that Amar provides; the site links to it. Non-goals: new content for the case studies (text stays), a light theme, a CMS, new routes. ## Scope Kept: Angular 22 app structure, SSR + prerendering, `SeoService`, `PageShellComponent` (restyled), landing page, four `/work/*` case-study pages, `SystemDiagramComponent` (recoloured), not-found page, Tailwind v4 install, Docker deploy. Removed: `CvPageComponent` + its spec, `ThemeService`, `ThemeToggleComponent`, the theme bootstrap script in `src/index.html`, the `cv` client route, the `cv` prerender route. Added: `public/cv.pdf` (placeholder until Amar supplies the file), a 301 from `/cv` to `/cv.pdf` in `src/server.ts`, self-hosted fonts. ## Visual system Defined as CSS custom properties on `:root` in `src/styles.scss`; no `.dark` variant. | token | value | use | |---|---|---| | `--bg` | `#0D1015` | page background | | `--panel` | `#12161D` | cards, list panel, code panel | | `--panel-2` | `#0F1318` | panel headers / inset | | `--line` | `#232A33` | borders, dividers | | `--line-strong` | `#2A323D` | tag borders, button outline | | `--text` | `#E6EAF0` | primary text | | `--muted` | `#8B95A5` | secondary text | | `--dim` | `#5C6672` | tertiary text, comments | | `--accent` | `#8BE04A` | labels, links, primary button, status dot | | `--accent-glow` | `rgba(139,224,74,.22)` | button and dot glow | | `--code-key` / `--code-str` / `--code-num` | `#7AA2F7` / `#C3E88D` / `#F78C6C` | profile.json panel | Grid: `linear-gradient` lines at 2.8% white, 64px cell, fixed to the page background. Type: JetBrains Mono (labels, nav, meta, code, buttons) and IBM Plex Sans (headings and body), self-hosted via `@fontsource-variable/jetbrains-mono` and `@fontsource/ibm-plex-sans` (weights 400/500/600) imported in `styles.scss`. Fallbacks: Consolas/Menlo/monospace and "Segoe UI"/system-ui/sans-serif. Base body 16px; headline scale `clamp(2.4rem, 5vw, 3.9rem)` for h1, `clamp(1.75rem, 3vw, 2.1rem)` for h2, letter-spacing -0.03em/-0.025em, weight 600. Labels (`.label`): mono, 12px, uppercase, 0.08em tracking, accent colour, prefixed with `// ` in markup (e.g. `// selected work`). Tags (`.tag`): mono 12px, 24px tall, 1px `--line-strong` border, 4px radius. Panels (`.panel`): `--panel` fill, 1px `--line` border, 10px radius. Buttons: 46px tall, 6px radius, mono 14px; `.btn-accent` accent fill with dark text and glow, `.btn-line` outlined. Container: `.shell` = `min(1160px, 100% - 40px)` centred. Section spacing 96px desktop, 64px below 720px. ## Pages ### Shell (header, footer, mobile menu) Header: sticky, `--bg` at 92% with blur, bottom border. Left: mono wordmark `~/` (accent) + `dzanan.net` (600). Right (desktop): mono nav `work · experience · contact · cv.pdf`, then a divider and the status `● available` (accent dot with glow). `cv.pdf` is an `` with a download icon, opens in a new tab. Below 720px the nav collapses to the existing signal-driven menu button; the status stays visible. Navigation config: `[{work,'/',#work},{experience,'/',#experience},{contact,'/',#contact}]` plus the CV link rendered separately as a plain anchor (not a `SectionNavItem`). Footer: mono 12px, `Amar Džanan · Sarajevo, Bosnia and Herzegovina` left; email and LinkedIn right. ### Landing (`/`) 1. Hero — two columns (1.05fr / .95fr, 64px gap), stacks below 1024px. Left: label `Senior full-stack engineer — .NET · Angular · MCP`; h1 "Complex systems, understood before changed."; lead paragraph "I modernize enterprise software and connect it to AI through narrow, validated, verified interfaces — the kind you can run in production and sleep at night."; buttons `amar@dzanan.net` (accent, mailto) and `cv.pdf` (outline, download). Right: `profile.json` terminal panel — title bar with three dots and file name, then a `$ whoami --json` line and a JSON object: name, role, stack `[".NET","Angular", "TypeScript"]`, focus `["modernization","safe AI integration"]`, since `2018`, location `"Sarajevo · CET"`, open_to `["senior roles","consulting"]`, closing prompt with a blinking cursor. Rendered from a small typed data structure in the component so it can change without touching markup. 2. `// selected work` (`#work`) — heading "Production systems, anonymized." and a right-aligned mono count `4 case studies`. One `.panel` containing four rows (`data-testid="project-row"`, `routerLink` to `/work/`): index (accent on the featured first row), title + one-line summary (a new short `tagline` field on `PortfolioProject`, ~60 chars), up to four stack tags (first four of `stack`), arrow. Hover: row background `--panel-2`, arrow turns accent. Below 720px: grid collapses to index+title, tagline, tags stacked. 3. `// experience` (`#experience`) — grid 340px / 1fr. Left: 96px square grayscale portrait (`NgOptimizedImage`, 8px radius, 1px border), label, h2 "Eight years, one product at a time.", about paragraph, LinkedIn link. Right: four role rows (period mono `2025 — now`, title + company, focus sentence), 1px dividers. 4. `// capabilities` — three equal `.panel` cards: `01 System modernization`, `02 Full-stack product delivery`, `03 Safe AI integration`, each with the existing detail text. Single column below 720px. 5. Contact (`#contact`) — a `.panel` with a 1px accent-tinted border and inner glow: label `// contact`, h2 "Need a senior engineer who can understand the system before changing it?", `.btn-accent` mailto button, mono `Sarajevo · CET / CEST`. Structured data (schema.org Person) unchanged. ### Case study (`/work/:slug`) Breadcrumb as a path: `~/work/` (dim) + slug (text), mono. Header: label ` · `, h1 title, lead summary, then a meta strip in a `.panel`: `role`, `period`, stack tags. Sections keep content; labels become `// 01 context`, `// 02 delivery`, `// 03 architecture`, `// 04 result`; contributions as a numbered list with mono indices; decisions as a 2×2 `.panel` grid (single column < 720px); technology as a tag row. `SystemDiagramComponent` stays, recoloured: node fill `--panel`, stroke `--line-strong`, accent node stroke/text `--accent`, lines `--line-strong`, notes `--dim`, mono text. Prev/next as two `.panel` links. Contact block reused. The "View full CV" link points to `/cv.pdf`. ### Not found Terminal panel: `$ open ` then `command not found: ` in `--code-num`, a short sentence, and a `.btn-line` back to `/`. Server still returns 404. ## Behaviour - Motion: hero children fade-up (opacity 0→1, translateY 12px→0, 480ms, 80ms stagger) once on load; cursor blink 1s step; row hover transitions 150ms. All wrapped in `@media (prefers-reduced-motion: no-preference)`. - Smooth anchor scrolling with `scroll-padding-top` for the sticky header (kept). - Focus rings: 2px accent outline, 3px offset. - `` → `#0D1015`; `color-scheme: dark`. ## Server `src/server.ts`: before the Angular handler, `app.get('/cv', (_, res) => res.redirect(301, '/cv.pdf'))`. `public/cv.pdf` is served by the existing static middleware. Until Amar supplies the file, a one-page placeholder PDF saying "CV coming soon — amar@dzanan.net" is committed so the link never 404s. `public/sitemap.xml` drops `/cv`. ## Files Modified: `styles.scss`, `index.html`, `server.ts`, `app.ts`, `app.routes.ts`, `app.routes.server.ts`, `app.routes.spec.ts`, `page-shell.component.ts`, `navigation.config.ts`, `landing-page.component.ts` + spec, `portfolio-page.component.ts` + spec, `system-diagram.component.ts`, `not-found-page.component.ts`, `portfolio-project.model.ts`, `portfolio-projects.data.ts`, `public/sitemap.xml`, `package.json`/lock (fontsource packages). Removed: `features/cv/cv-page.component.ts`, `features/cv/cv-page.component.spec.ts`, `core/services/theme.service.ts`, `shared/ui/theme-toggle/theme-toggle.component.ts`. Added: `public/cv.pdf` (placeholder), this spec, the implementation plan. ## Testing - Unit: route spec lists routes without `cv`; landing spec asserts the new h1, four project rows, `a[href="/cv.pdf"]`, mailto and LinkedIn links, the four role titles; portfolio spec unchanged in intent; new not-found assertion optional. Run with headless Chromium. - Build: `ng build` (production, SSR, prerender of `/` and the four work pages) with zero errors and within budgets (component styles are inline SCSS; keep under 8kB each). - Visual: serve `dist` and screenshot `/`, one case study and `/404` at 1440px and 390px; fix wrapping, overflow and contrast issues found. - Smoke: `curl -I /cv` → 301 to `/cv.pdf`; `/cv.pdf` → 200. ## Delivery Work happens in the cloud copy of the repo; changed and new files are written back to the `dzanan.net` folder on Amar's machine, removed files are moved into `_to_delete/`. Amar runs `npm install` locally afterwards (new font packages) and drops the real PDF over `public/cv.pdf`.