jassinta-creative-portfolio

byJassinta Roid Triniti

C0. PERAN & ATURAN KERJA UNTUK AI Kamu adalah Senior Creative Frontend Engineer + Art Director. Tugasmu: membangun website portfolio one-page untuk Jassinta Roid Triniti (Social Media Specialist, Content Creator, Videographer, Graphic Designer) sebagai web app siap deploy ke Vercel. Aturan kerja (wajib): Ikuti spesifikasi ini secara harfiah dan lengkap. Jangan merangkum, menyingkat, atau menghilangkan fitur. Jika sebuah fitur sulit, bangun versi terbaik yang mungkin lalu beri komentar // TODO: yang jelas — jangan menghapusnya diam-diam. Semua teks yang tampil di website: Bahasa Inggris penuh. Semua kode, nama variabel, nama komponen, dan komentar kode: Bahasa Inggris. (Judul karya/artikel tertentu memang berbahasa Indonesia karena itu judul aslinya — tampilkan apa adanya.) Bangun modular: satu komponen per section, data terpisah di src/data/*.ts. Jangan menaruh data konten di dalam komponen. Jika ada hal ambigu, pilih keputusan yang tertulis di spesifikasi; jika belum tertulis, pilih opsi yang paling dekat dengan tema (girly, playful, textured) dan catat keputusannya di DECISIONS.md. Kerjakan bertahap bila diminta ("Stage N"). Saat mengerjakan satu stage, jangan mengubah file section lain kecuali untuk integrasi minimal. Aset (gambar/video/PDF) dipanggil lewat path /assets/... (lihat C5). Jika file belum ada, tampilkan fallback yang rapi (bukan ikon rusak, bukan teks error) sesuai aturan tiap section. Tidak ada API key di sisi klien. Website ini tidak membutuhkan API apa pun. Setelah selesai tiap stage, tulis ringkasan singkat: apa yang dibuat, apa yang masih TODO, dan cara mengetesnya. C1. RINGKASAN PROYEK & TEKNOLOGI Jenis: One-page website (satu halaman panjang). Tidak ada page reload. Navigasi antar bagian memakai scroll halus + daftar isi. Halaman "pop-up" barang di loker (Participation, Achievement, dll.) berupa overlay layar penuh (bukan route baru), dengan tombol tutup, tombol Esc, dan dukungan tombol Back browser (gunakan hash seperti #/participation). Tema: playful, girly, textured. Elegan namun ceria; terasa seperti loker sekolah, kertas, sticker, majalah, dan scrapbook. Stack wajib: React 18 + Vite + TypeScript + Tailwind CSS Animasi: Framer Motion (atau GSAP + ScrollTrigger bila lebih cocok untuk scroll-driven). Pilih satu pendekatan konsisten per kebutuhan. Smooth/inertial scroll: Lenis (atau setara) — harus bisa dimatikan pada saat scroll-lock di Opening dan saat overlay terbuka. Flipbook: page-flip (StPageFlip) atau react-pageflip; render PDF dengan pdfjs-dist. 3D loker: CSS 3D transforms (perspective, transform-style: preserve-3d), BUKAN Three.js (agar ringan di HP). Font: Fontshare (Sentient), Google Fonts (lainnya). Build menghasilkan folder dist/ (static) agar bisa di-deploy ke Vercel tanpa server. Prinsip kualitas: 60fps pada laptop menengah; tidak ada horizontal scrollbar yang tidak disengaja; tidak ada elemen keluar dari container; tidak ada layout shift besar. C2. DESIGN SYSTEM C2.1 Palet warna lengkap (gunakan sebagai tone warna seluruh website) Definisikan sebagai CSS variables di :root dan sebagai warna kustom Tailwind. Nama token = nama di tabel. Pink (warna utama girly) Token Hex Pemakaian --hot-pink #FF2E93 Tombol utama, glow reveal, aksen kuat (terinspirasi referensi Elle) --barbie-pink #E91E8C Hover tombol, teks aksen, sticker --raspberry #D81B72 Garis aksen, ikon --bubblegum #FF8DC7 Blok highlight, badge --candy-pink #FFB3D9 Badan loker terbuka, sticker --blush #FFD6E8 Latar section lembut, blok highlight --rose-quartz #F7CAD0 Kartu, kertas --powder-pink #FDE4EC Latar section terang --dusty-rose #E8A5B8 Bayangan berwarna, detail --cherry-red #E5173F Warna merah headline italic (The Campus, The Story, The Microphone), staple, pin --lipstick-red #C8102E Elemen majalah (bibir, pita) --coral-pop #FF6F6F Aksen playful --peach-fizz #FFB38A Blok highlight, label --apricot #FFD3B0 Highlight lembut Ungu / Lavender Token Hex Pemakaian --lavender #BFA8E5 Amplop, kartu, loker --lilac #D4C1F5 Latar section, blok highlight --wisteria #A98BDA Aksen sekunder --orchid #DA9AF2 Glow, gradient --grape-soda #7B4FB8 Teks di atas pastel --berry #7A2E5C Interior loker terbuka, panel gelap hangat --aubergine #4B1D4F Gradient gelap --plum-night #2A0F2E Latar gelap utama ("plum night gradient") Mint / Hijau / Biru pastel Token Hex Pemakaian --mint-cream #D4F2E4 Latar lembut --pastel-mint #A8E6CF Blok highlight, kamera, kartu --matcha #B7D9A8 Detail tanaman/aksen --sage #A9C4A0 Aksen netral --baby-blue #BFE3F5 Blok highlight, ikon --sky-pastel #A7D8F5 Aksen --periwinkle #B8C4F2 Aksen --notebook-blue #8FB8E8 Garis kertas bergaris --steel-lilac #B9B8CC Loker tertutup (logam abu-lavender) Kuning / Krem / Kertas Token Hex Pemakaian --butter #FFF1A8 Blok highlight, sticky note --lemon-chiffon #FFF6C9 Highlight lembut --vanilla #FFF8EE Latar krem hangat --aged-paper #F3E3B8 Kertas kekuningan (papan pin foto) --honey #F6D76B Aksen --milk-white #FFFDF9 Kertas putih, teks di atas gelap --pure-white #FFFFFF Kanvas Personal Brand (wajib pure white) Netral & Logam Token Hex Pemakaian --ink #1B1017 Teks utama --espresso #2B1B17 Teks pada kertas --cocoa #5A3A2E Detail kayu/cokelat --walnut #7A4A32 Gagang payung, rak kayu --pearl #F4EFF1 Netral terang --warm-grey #D9D3D6 Garis, bayangan --chrome #C9CCD5 Logam (gagang, kunci, ventilasi) --gold #D4A64A Bingkai, piala --champagne #EBD08C Highlight emas --staple-red #D7263D Staple/pin di kertas Gradient bernama --grad-plum-night: linear-gradient(160deg, #2A0F2E 0%, #4B1D4F 55%, #7A2E5C 100%) --grad-cotton-candy: linear-gradient(135deg, #FFD6E8 0%, #E3D4FA 50%, #CDEBF8 100%) --grad-bubblegum: linear-gradient(135deg, #FF8DC7 0%, #FF2E93 100%) --grad-lilac-mint: linear-gradient(135deg, #D4C1F5 0%, #D4F2E4 100%) C2.2 Peta warna per section Section Latar Teks Aksen Opening (tertutup) Dinding ruang --pearl→--warm-grey; loker --steel-lilac --ink Blok kata warna-warni, tombol --hot-pink Opening (terbuka) Loker --candy-pink; interior --berry; rak --blush --ink / --milk-white --hot-pink Personal Brand --pure-white --ink --cherry-red, kertas dokumen putih Writing Portfolio hero --powder-pink + grain --ink --hot-pink Cassette disc --blush→--lilac + grain --ink --hot-pink Content Marketing --grad-plum-night + film grain --milk-white glow --hot-pink Example Strategy hero --lilac + grain --ink --hot-pink Example Strategy video reveal --grad-plum-night, lantai pink-checker --milk-white --hot-pink Project Campus --vanilla + rak kayu --walnut --ink --cherry-red Podcast --blush --ink --cherry-red Archive --grad-plum-night --milk-white --hot-pink Contact --grad-plum-night + glow --milk-white --bubblegum C2.3 Tipografi Peran Font Fallback Display / headline serif Sentient (Fontshare) — Regular, Italic, Bold, Bold Italic 'Fraunces', Georgia, serif Body/narasi Poppins italic untuk narasi (ukuran 24,9px maks), Poppins regular 400/500/600 untuk UI system-ui, sans-serif Giant sans (Personal Brand) Anton (ultra-bold condensed) 'Archivo Black', Impact, sans-serif Handwriting (surat) Caveat (terbaca jelas) 'Patrick Hand', cursive Script "Fashion" (majalah) Pinyon Script 'Great Vibes', cursive VOGUE elegan Bodoni Moda 700–900 (atau Playfair Display) serif OOTD tegas Bebas Neue Oswald, Impact, sans-serif Label/typewriter (kartu arsip, tag, kredit) DM Mono / Special Elite monospace Caption polaroid Permanent Marker atau Caveat cursive Muat Sentient via Fontshare, mis. https://api.fontshare.com/v2/css?f[]=sentient@300,301,400,401,500,501,700,701&display=swap (periksa nomor varian di halaman Sentient di fontshare.com; angka ganjil = italic). Tambahkan font-display: swap, preconnect, dan fallback agar tidak ada layout shift. Aturan ukuran fluid (maks desktop → min mobile): Headline 66px: font-size: clamp(2.1rem, 1.2rem + 3.6vw, 4.125rem); line-height: 1.02; letter-spacing: -0.01em; text-wrap: balance. Narasi 24,9px: font-size: clamp(1rem, 0.85rem + 0.7vw, 1.556rem); Poppins italic; line-height: 1.5; text-wrap: pretty; lebar maksimum ~58ch. Jarak narasi dari headline: --headline-narration-gap: 1.5rem.

No preview

Comments (0)

No comments yet. Be the first!

System Requirements

Page 1 of 25

System Requirements Document for jassinta-creative-portfolio

1. Introduction

This document specifies jassinta-creative-portfolio, a one-page creative portfolio website for Jassinta Roid Triniti — a Social Media Specialist, Content Creator, Videographer, and Graphic Designer. The site is a static web application, deploy-ready to Vercel, that presents her personal brand, writing portfolio, content marketing work, example strategy, campus projects, podcast work, archive, and contact information inside a single long-scroll page.

The product intent is to make a prospective client, collaborator, or creative-industry peer feel that they have stepped into a tactile, playful, girly, textured world — a school locker, paper, stickers, magazines, and a scrapbook — while still being able to evaluate her professional range and reach her easily. The site is deliberately interactive: a CSS-3D locker that opens, full-screen locker-item overlays, a draggable PDF flipbook, a cassette disc, a video reveal, and expressive scroll-driven motion. It is not a corporate template and must never read as one.

The audience is prospective clients, collaborators, and creative-industry peers. The site is publicly reachable with no account, no login, and no API.

Page 2 of 25

2. System Overview

The product is a single long-scroll page with no page reloads. Navigation between sections uses smooth/inertial scrolling plus a table of contents. Locker "pop-up" items (Participation, Achievement, and similar) open as full-screen overlays rather than new routes, with a close button, Escape-key support, and browser Back-button support via hashes such as #/participation.

The page is composed of one component per section, with all content data separated into src/data/*.ts files. Assets (images, videos, PDFs) are referenced through /assets/... paths; when a referenced file is missing, each section shows a tidy fallback rather than a broken icon or error text.

The visual system is a full custom palette of pink, lavender, mint/blue, cream/paper, and neutral/metal tokens defined as CSS variables in :root and as custom Tailwind colors, plus four named gradients. Each section owns a specified background, text, and accent mapping. Typography mixes Sentient (Fontshare) display serif, Poppins body/UI, Anton giant sans, Caveat handwriting, Pinyon Script, Bodoni Moda, Bebas Neue, DM Mono / Special Elite, and Permanent Marker, with fluid clamp-based sizing rules.

The build produces a static dist/ folder deployable to Vercel without a server. There are no API keys on the client side and the website requires no API.

Page 3 of 25

2a. Product Interpretation and Delivery Boundary

Everything in this product is delivered as a first-party static front-end experience. The visitor arrives anonymously at the Opening section, which is the explanatory entry to the page; no account, login, or identity is required anywhere in the product. There is no server-side component, no authentication, no user-generated content, and no external data service. All content is authored by the Portfolio Owner and shipped as static data and assets.

The current delivery horizon covers the complete one-page portfolio: the Opening locker experience, the Personal Brand canvas, the Writing Portfolio with its PDF flipbook, Content Marketing, Example Strategy with its video reveal, Project Campus, Podcast, Archive, and Contact. Locker-item overlays are in-page full-screen states, not separate routes, and are reachable by hash so that the browser Back button and Escape key behave correctly.

No future-horizon features are specified in the authoritative requirements. Nothing in this document authorizes additional pages, routes, accounts, APIs, or adjacent capabilities.

2b. Source Content Inventory

No reference directive declares content_source; the single reference directive is a brand_source for the Sentient font family. No content inventory is therefore included.

2c. Page Content and Component Coverage

The page contract is versioned and final. The following nine destinations are the complete, ordered page inventory, each anonymously reachable.

Page 4 of 25

Opening

  • Information / state: The first screen is the school corridor. A pearl-to-warm-grey wall sits behind one steel-lilac locker bank that fills the viewport. The name JASSINTA ROID TRINITI is set in Anton at clamp(3rem, 12vw, 9rem), spanning the full width above the locker bank, with each word sitting on its own flat color block (hot-pink, butter, pastel-mint, lavender). A DM Mono strip of rotating role labels (Social Media Specialist / Videographer / Graphic Designer) marquees along the bottom edge. The composition is off-axis and poster-like, with grain over the whole frame. Closed state: wall --pearl→--warm-grey, locker --steel-lilac, text --ink, multi-color word blocks, --hot-pink button. Open state: locker --candy-pink, interior --berry, rack --blush, text --ink / --milk-white, accent --hot-pink.
  • Primary actions: "Open the locker" hot-pink pill button pinned bottom-left; the CSS-3D locker door opens to reveal the interior rack; locker items on the rack launch their full-screen overlays; the table of contents provides smooth-scroll navigation to every section.
  • Supporting actions: Close the locker; scroll-lock is engaged while the locker is in its opening state and released afterward; the table of contents rail is sticky on desktop and collapses to a pill chip bar on mobile.
  • Domain entities: Locker bank, locker door, interior rack, locker items (Participation, Achievement, and similar), role labels, table-of-contents entries.
  • Component responsibilities: OpeningSection (one component per section), Locker3D (CSS 3D transforms with perspective and transform-style: preserve-3d; explicitly not Three.js), LockerItemOverlay (full-screen overlay with close button, Escape handling, hash history, scroll lock), TableOfContents (sticky desktop rail / mobile pill chip bar), RoleMarquee (DM Mono role strip).
  • States: Loading — fonts and grain textures resolve with font-display: swap and preconnect so there is no large layout shift. Empty — not applicable; the locker bank and its items are authored content. Success — the locker opens, the interior rack is revealed, and items are selectable. Error / recovery — if a locker item's referenced asset is missing, the overlay still opens and shows the tidy fallback for that item rather than a broken icon or error text. Reduced motion — the role marquee stops and wraps or sits in an overflow-x: auto row; reveals become instant states.

Personal Brand

  • Information / state: The personal brand canvas on a mandatory pure-white ground (--pure-white), text --ink, accents --cherry-red and white document paper. The name is set in Anton ultra-condensed all-caps at viewport-spanning scale. Supporting composition uses flat poster type and white paper documents.
  • Primary actions: Read the personal brand statement; scroll onward to the next section.
  • Supporting actions: Table-of-contents navigation into and out of the section.
  • Domain entities: Personal brand statement, name wordmark, document-paper elements.
  • Component responsibilities: PersonalBrandSection; Anton giant-sans type treatment; white paper surfaces.
  • States: Loading — Anton resolves with its fallback stack ('Archivo Black', Impact, sans-serif) so the giant statement does not shift. Empty — not applicable. Success — the statement renders fully inside the viewport at 375px, 768px, and 1280px. Error / recovery — if a referenced document image is missing, a tidy paper fallback is shown. Reduced motion — reveals become instant states.

Writing Portfolio

  • Information / state: Hero on --powder-pink with grain, text --ink, accent --hot-pink. The section owns the writing portfolio destination and its independently revisitable PDF flipbook. A cassette disc composition sits on a --blush→--lilac ground with grain, text --ink, accent --hot-pink.
  • Primary actions: Flip through the PDF flipbook by dragging pages; revisit the flipbook independently; read the writing portfolio hero copy.
  • Supporting actions: Table-of-contents navigation; return to the flipbook at a later point in the visit.
  • Domain entities: Writing portfolio entries, PDF documents, flipbook pages, cassette disc.
  • Component responsibilities: WritingPortfolioSection; Flipbook built with page-flip (StPageFlip) or react-pageflip, rendering PDFs with pdfjs-dist, with visible paper edges and grain; CassetteDisc rendered as a physical object.
  • States: Loading — PDF pages load progressively; the flipbook shows a tidy loading state rather than a broken frame. Empty — if no PDF is available, the flipbook area shows the tidy fallback. Success — pages turn realistically on drag and the reader can move forward and back. Error / recovery — if a referenced PDF asset is missing, the section shows the tidy fallback (not a broken icon, not error text) and the rest of the section remains usable. Reduced motion — page turns become instant transitions rather than animated flips.
Page 5 of 25

Content Marketing

  • Information / state: Ground is --grad-plum-night with film grain, text --milk-white, accent is a --hot-pink glow.
  • Primary actions: Read the content marketing work; scroll onward.
  • Supporting actions: Table-of-contents navigation.
  • Domain entities: Content marketing case entries, supporting media references.
  • Component responsibilities: ContentMarketingSection; dark-ground glow treatment.
  • States: Loading — grain and glow layers resolve without layout shift. Empty — not applicable. Success — content renders legibly on the dark ground. Error / recovery — missing media shows the tidy fallback. Reduced motion — reveals become instant states.

Example Strategy

  • Information / state: Hero on --lilac with grain, text --ink, accent --hot-pink. The video reveal sits on --grad-plum-night with a pink-checker floor, text --milk-white, accent --hot-pink.
  • Primary actions: Read the example strategy; trigger and watch the video reveal.
  • Supporting actions: Table-of-contents navigation.
  • Domain entities: Strategy document, video asset, pink-checker floor composition.
  • Component responsibilities: ExampleStrategySection; VideoReveal with the pink-checker floor under the reveal.
  • States: Loading — the video area shows a tidy loading state. Empty — if the video asset is missing, the reveal area shows the tidy fallback. Success — the video plays within the reveal composition. Error / recovery — a failed video load falls back tidily and the section remains readable. Reduced motion — the reveal appears as an instant state.

Project Campus

  • Information / state: Ground is --vanilla with a --walnut wood rack, text --ink, accent --cherry-red. The section headline uses cherry-red Sentient italic treatment for "The Campus".
  • Primary actions: Browse campus project items on the wood rack; read project details.
  • Supporting actions: Table-of-contents navigation.
  • Domain entities: Campus project items, wood rack, project media.
  • Component responsibilities: ProjectCampusSection; wood-rack composition.
  • States: Loading — rack and items resolve without layout shift. Empty — not applicable. Success — items render on the rack and are readable. Error / recovery — missing project media shows the tidy fallback. Reduced motion — reveals become instant states.
Page 6 of 25

Podcast

  • Information / state: Ground is --blush, text --ink, accent --cherry-red. The section headline uses cherry-red Sentient italic treatment for "The Microphone".
  • Primary actions: Read the podcast work; review episode or series details.
  • Supporting actions: Table-of-contents navigation.
  • Domain entities: Podcast entries, episode metadata, supporting media.
  • Component responsibilities: PodcastSection.
  • States: Loading — content resolves without layout shift. Empty — not applicable. Success — podcast content renders legibly. Error / recovery — missing media shows the tidy fallback. Reduced motion — reveals become instant states.

Archive

  • Information / state: Ground is --grad-plum-night, text --milk-white, accent --hot-pink. Archive labels use DM Mono uppercase with wide letterspacing.
  • Primary actions: Browse archived work and assets; read archive labels and credits.
  • Supporting actions: Table-of-contents navigation.
  • Domain entities: Archive cards, labels, credits, referenced assets.
  • Component responsibilities: ArchiveSection; DM Mono label treatment.
  • States: Loading — archive cards resolve without layout shift. Empty — if the archive has no items, a tidy empty state is shown. Success — archive items render with readable labels. Error / recovery — missing archive assets show the tidy fallback per section rules. Reduced motion — reveals become instant states.

Contact

  • Information / state: Ground is --grad-plum-night with glow, text --milk-white, accent --bubblegum.
  • Primary actions: Reach the contact actions and get in touch.
  • Supporting actions: Table-of-contents navigation back into the page.
  • Domain entities: Contact details and contact actions.
  • Component responsibilities: ContactSection.
  • States: Loading — contact content resolves without layout shift. Empty — not applicable. Success — contact actions are visible and usable. Error / recovery — if a referenced contact asset is missing, the tidy fallback is shown and the contact actions remain reachable. Reduced motion — reveals become instant states.
Page 7 of 25

3. Functional Requirements

FR-01 — One-page portfolio delivery (explicit) As the Portfolio Owner, I should have a one-page portfolio website for Jassinta Roid Triniti (Social Media Specialist, Content Creator, Videographer, Graphic Designer) built as a web app ready to deploy to Vercel, so that my work is publicly presentable.

  • Trigger: the site is built and deployed.
  • Observable result: a single long page is served from the static dist/ output.
  • Failure/recovery: if a feature is hard to build, the best possible version is built with a clear // TODO: comment rather than silently removing it.
  • Continuation: the visitor can scroll the page and use the table of contents.

FR-02 — Single long page with no reloads (explicit) As the Portfolio Visitor, I should navigate between sections using smooth scroll plus a table of contents without any page reload, so that browsing feels continuous.

  • Trigger: I select a table-of-contents entry or scroll.
  • Observable result: the page scrolls smoothly to the target section; no reload occurs.
  • Failure/recovery: if smooth scrolling is unavailable, the section is still reachable.
  • Continuation: I continue reading the target section.

FR-03 — Locker item overlays (explicit) As the Portfolio Visitor, I should open locker "pop-up" items (Participation, Achievement, and similar) as full-screen overlays rather than new routes, so that I can inspect individual items without leaving the page.

  • Trigger: I select a locker item.
  • Observable result: a full-screen overlay opens with the item's content.
  • Failure/recovery: if the item's referenced asset is missing, the overlay still opens and shows the tidy fallback.
  • Continuation: I close the overlay and return to the locker.

FR-04 — Overlay close, Escape, and Back support (explicit) As the Portfolio Visitor, I should close an overlay with a close button, the Escape key, or the browser Back button, so that dismissal behaves the way I expect.

  • Trigger: I press the close button, press Escape, or press browser Back while an overlay is open.
  • Observable result: the overlay closes and the page returns to its prior scroll position.
  • Failure/recovery: if a hash is not recognized, the page remains on the current section without breaking.
  • Continuation: I continue browsing the page.

FR-05 — Hash-based overlay navigation (explicit) As the Portfolio Visitor, I should have overlay state reflected in the URL using hashes such as #/participation, so that browser history behaves correctly.

  • Trigger: I open or close a locker item.
  • Observable result: the hash updates to the item's identifier on open and clears on close.
  • Failure/recovery: an unknown hash does not open an overlay and does not break the page.
  • Continuation: I can use Back and Forward to move between overlay and page states.

FR-06 — Playful, girly, textured theme (explicit) As the Portfolio Visitor, I should experience a playful, girly, textured theme that is elegant yet cheerful and evokes a school locker, paper, stickers, magazines, and a scrapbook, so that the site feels like a person rather than a template.

  • Trigger: I view any section.
  • Observable result: the section uses its specified color ground, typography, and texture treatment.
  • Failure/recovery: if a texture asset is missing, the section still renders with its color ground.
  • Continuation: I continue through the page.

FR-07 — Required stack (explicit) As the Portfolio Owner, I should have the site built with React 18 + Vite + TypeScript + Tailwind CSS, so that the required technology is used.

  • Trigger: the project is built.
  • Observable result: the source uses React 18, Vite, TypeScript, and Tailwind CSS.
  • Failure/recovery: not applicable.
  • Continuation: the build produces the static output.

FR-08 — Animation approach (explicit) As the Portfolio Visitor, I should see animation implemented with Framer Motion (or GSAP + ScrollTrigger where better suited for scroll-driven work), choosing one consistent approach per need, so that motion is coherent.

  • Trigger: I scroll or interact.
  • Observable result: reveals, marquees, hover color flips, scale-ins, and the page-turn flipbook animate consistently.
  • Failure/recovery: if an animation cannot run, the content remains visible in its final state.
  • Continuation: I continue interacting.

FR-09 — Smooth/inertial scroll with disable (explicit) As the Portfolio Visitor, I should have smooth/inertial scrolling via Lenis (or equivalent) that can be disabled during the Opening scroll-lock and while an overlay is open, so that locked states do not fight the scroll.

  • Trigger: the Opening lock engages or an overlay opens.
  • Observable result: inertial scrolling is disabled for the duration of the lock or overlay and restored afterward.
  • Failure/recovery: if Lenis is unavailable, native scrolling still works.
  • Continuation: scrolling resumes normally after the lock or overlay closes.

FR-10 — PDF flipbook (explicit) As the Portfolio Visitor, I should flip through documents in a flipbook built with page-flip (StPageFlip) or react-pageflip, rendering PDFs with pdfjs-dist, so that documents feel like physical pages.

  • Trigger: I drag a page in the flipbook.
  • Observable result: the page turns realistically and the next page is shown.
  • Failure/recovery: if a referenced PDF is missing, the section shows the tidy fallback rather than a broken frame.
  • Continuation: I continue flipping or move on to another section.

FR-11 — CSS 3D locker, not Three.js (explicit) As the Portfolio Visitor, I should see the 3D locker built with CSS 3D transforms (perspective, transform-style: preserve-3d) and not Three.js, so that it stays light on phones.

  • Trigger: I view the Opening section.
  • Observable result: the locker bank renders in CSS 3D and opens on interaction.
  • Failure/recovery: if 3D transforms are unsupported, the locker still presents its content.
  • Continuation: I open the locker or continue scrolling.

FR-12 — Fonts (explicit) As the Portfolio Visitor, I should see Sentient loaded from Fontshare and the remaining typefaces loaded from Google Fonts, so that the specified typography is used.

  • Trigger: the page loads.
  • Observable result: Sentient and the Google Fonts families render with their specified fallbacks.
  • Failure/recovery: if a font fails to load, the fallback stack renders without a large layout shift.
  • Continuation: I continue reading.

FR-13 — Static build for Vercel (explicit) As the Portfolio Owner, I should have the build produce a static dist/ folder deployable to Vercel without a server, so that hosting is simple and serverless.

  • Trigger: the build runs.
  • Observable result: dist/ contains the static site.
  • Failure/recovery: not applicable.
  • Continuation: the site is deployed.

FR-14 — Quality principles (explicit) As the Portfolio Visitor, I should experience 60fps on a mid-range laptop, no unintended horizontal scrollbar, no elements escaping their container, and no large layout shifts, so that the site feels polished.

  • Trigger: I scroll and interact on a mid-range laptop.
  • Observable result: motion stays smooth and layout stays stable.
  • Failure/recovery: if a heavy effect cannot hold the target, the best possible version is built with a clear // TODO: comment.
  • Continuation: I continue browsing.

FR-15 — Full color palette as tokens (explicit) As the Portfolio Owner, I should have the full color palette defined as CSS variables in :root and as custom Tailwind colors using the token names from the specification tables, so that the palette is consistent across the site.

  • Trigger: the styles are authored.
  • Observable result: every specified token exists with its exact hex value.
  • Failure/recovery: not applicable.
  • Continuation: sections consume the tokens.

FR-16 — Named gradients (explicit) As the Portfolio Owner, I should have the named gradients --grad-plum-night, --grad-cotton-candy, --grad-bubblegum, and --grad-lilac-mint defined with their exact stops, so that gradient grounds are consistent.

  • Trigger: a section uses a gradient ground.
  • Observable result: the gradient renders with its specified stops and angle.
  • Failure/recovery: not applicable.
  • Continuation: the section renders on its gradient ground.

FR-17 — Per-section color map (explicit) As the Portfolio Visitor, I should see each section use its specified background, text, and accent mapping — Opening closed and open, Personal Brand, Writing Portfolio hero, Cassette disc, Content Marketing, Example Strategy hero, Example Strategy video reveal, Project Campus, Podcast, Archive, and Contact — so that the page reads as color-blocked rather than neutral.

  • Trigger: I view a section.
  • Observable result: the section's ground, text, and accent match the specification.
  • Failure/recovery: not applicable.
  • Continuation: I continue to the next section.

FR-18 — Typography roles (explicit) As the Portfolio Visitor, I should see Sentient for display/headline serif with Fraunces/Georgia fallback; Poppins italic for narration (max 24.9px) and Poppins 400/500/600 for UI; Anton for the giant sans in Personal Brand; Caveat for handwriting letters; Pinyon Script for the magazine "Fashion" script; Bodoni Moda 700–900 (or Playfair Display) for VOGUE elegance; Bebas Neue for OOTD; DM Mono / Special Elite for labels/typewriter; and Permanent Marker or Caveat for polaroid captions, so that each typographic role is distinct.

  • Trigger: a role is used in a section.
  • Observable result: the correct family renders for that role.
  • Failure/recovery: each role falls back to its specified fallback stack.
  • Continuation: I continue reading.

FR-19 — Sentient loading discipline (explicit) As the Portfolio Visitor, I should have Sentient loaded via Fontshare with font-display: swap, preconnect, and fallbacks, so that there is no layout shift while the font loads.

  • Trigger: the page loads.
  • Observable result: the fallback renders first and Sentient swaps in without a large layout shift.
  • Failure/recovery: if Fontshare is unreachable, the fallback stack renders.
  • Continuation: I continue reading.

FR-20 — Fluid sizing rules (explicit) As the Portfolio Visitor, I should see the headline at 66px via clamp(2.1rem, 1.2rem + 3.6vw, 4.125rem) with line-height: 1.02, letter-spacing: -0.01em, and text-wrap: balance; the narration at 24.9px via clamp(1rem, 0.85rem + 0.7vw, 1.556rem) in Poppins italic with line-height: 1.5, text-wrap: pretty, and a max width of about 58ch; and --headline-narration-gap: 1.5rem, so that type scales fluidly from desktop to mobile.

  • Trigger: the viewport changes.
  • Observable result: headline and narration sizes scale within their clamp bounds and the gap between them is 1.5rem.
  • Failure/recovery: not applicable.
  • Continuation: I continue reading at any viewport.

FR-21 — Language rules (explicit) As the Portfolio Owner, I should have all website-facing text in full English and all code, variable names, component names, and code comments in English, with Indonesian work/article titles displayed as-is, so that the site reads consistently while original titles stay authentic.

  • Trigger: content or code is authored.
  • Observable result: visible text is English except Indonesian work/article titles, which appear verbatim.
  • Failure/recovery: not applicable.
  • Continuation: the site is reviewed.

FR-22 — Modular structure with separated data (explicit) As the Portfolio Owner, I should have the site built modularly with one component per section and content data separated in src/data/*.ts, with no content data inside components, so that I can update content by editing data files.

  • Trigger: content is updated.
  • Observable result: editing a src/data/*.ts file changes the rendered content without touching component code.
  • Failure/recovery: not applicable.
  • Continuation: the site is rebuilt.

FR-23 — Asset paths and tidy fallbacks (explicit) As the Portfolio Visitor, I should have assets (images/videos/PDFs) referenced via /assets/... paths, and when a file is missing I should see a tidy fallback rather than a broken icon or error text, per each section's rules.

  • Trigger: a section references an asset.
  • Observable result: the asset renders when present; a tidy fallback renders when absent.
  • Failure/recovery: the fallback itself is the recovery.
  • Continuation: the section remains usable.

FR-24 — No client-side API keys, no API (explicit) As the Portfolio Owner, I should have no API keys on the client side and no API requirement, so that the site is safe and self-contained.

  • Trigger: the site is inspected.
  • Observable result: no API keys are present and no API calls are made.
  • Failure/recovery: not applicable.
  • Continuation: the site is deployed.

FR-25 — Literal, complete specification adherence (explicit) As the Portfolio Owner, I should have the specification followed literally and completely, without summarizing, shortening, or dropping features, and with a clear // TODO: comment plus the best possible version when a feature is hard, so that nothing is silently lost.

  • Trigger: a feature is implemented.
  • Observable result: the feature is present; if incomplete, a // TODO: comment explains what remains.
  • Failure/recovery: the // TODO: comment is the recovery path.
  • Continuation: the remaining work is visible.

FR-26 — Ambiguity resolution and DECISIONS.md (explicit) As the Portfolio Owner, I should have ambiguous points resolved by the specification when written, and otherwise by the option closest to the girly, playful, textured theme, recorded in DECISIONS.md, so that decisions are traceable.

  • Trigger: an ambiguity is encountered.
  • Observable result: the chosen option is implemented and recorded in DECISIONS.md.
  • Failure/recovery: not applicable.
  • Continuation: implementation proceeds.

FR-27 — Staged work discipline (explicit) As the Portfolio Owner, I should have work done in stages when asked ("Stage N"), and while working on one stage, other section files should not be modified except for minimal integration, so that stages stay isolated.

  • Trigger: a stage is requested.
  • Observable result: only the stage's files change, plus minimal integration edits.
  • Failure/recovery: not applicable.
  • Continuation: the next stage begins.

FR-28 — Stage summaries (explicit) As the Portfolio Owner, I should receive a short summary after each stage covering what was built, what is still TODO, and how to test it, so that I can verify progress.

  • Trigger: a stage completes.
  • Observable result: a summary is written.
  • Failure/recovery: not applicable.
  • Continuation: the next stage begins.

FR-29 — Anonymous root entry (required_inference) As the Portfolio Visitor, I should reach the page anonymously from the root as the explanatory Opening entry, so that I can begin browsing without any account.

  • Trigger: I open the site root.
  • Observable result: the Opening section renders with no login or account prompt.
  • Failure/recovery: if the root cannot render, no protected state is exposed.
  • Continuation: I open the locker or scroll onward.

FR-30 — Section continuity without reloads (required_inference) As the Portfolio Visitor, I should have the one-page navigation, smooth scrolling, and table of contents preserve section continuity without route reloads, so that my reading position is never lost.

  • Trigger: I navigate between sections.
  • Observable result: the page scrolls to the target section without a reload.
  • Failure/recovery: if a target is missing, the page stays on the current section.
  • Continuation: I continue reading.

FR-31 — Overlay coordination (required_inference) As the Portfolio Visitor, I should have locker overlays coordinate hash history, close controls, Escape handling, and scroll locking, so that overlay state is predictable.

  • Trigger: I open or close an overlay.
  • Observable result: the hash, close controls, Escape handling, and scroll lock stay in sync.
  • Failure/recovery: if the hash is unknown, no overlay opens and the page remains stable.
  • Continuation: I continue browsing.

FR-32 — Flipbook asset loading and fallback (required_inference) As the Portfolio Visitor, I should have the Writing Portfolio flipbook load PDF assets when available and use a tidy fallback when referenced assets are missing, so that the section never shows a broken frame.

  • Trigger: the flipbook initializes.
  • Observable result: available PDFs render as pages; missing PDFs show the tidy fallback.
  • Failure/recovery: the fallback itself is the recovery.
  • Continuation: I continue flipping or move on.

FR-33 — Contact reachability (required_inference) As the Portfolio Visitor, I should have contact actions remain reachable from the Contact section, so that I can get in touch.

  • Trigger: I reach the Contact section.
  • Observable result: the contact actions are visible and usable.
  • Failure/recovery: if a referenced contact asset is missing, the tidy fallback is shown and the actions remain reachable.
  • Continuation: I make contact.
Page 8 of 25

4. User Personas

Portfolio Visitor

The Portfolio Visitor is a recruiter, prospective client, or collaborator who lands on the one-page portfolio to evaluate Jassinta Roid Triniti's work as a Social Media Specialist, Content Creator, Videographer, and Graphic Designer. They arrive anonymously with no account and no prior context beyond the link they followed.

Their primary goal is to understand the range and quality of her work and to have a clear way to make contact. Their distinct responsibilities in the product are to scroll through the sections via smooth scroll and the table of contents, open the full-screen locker overlays (Participation, Achievement, and similar) to inspect individual items, flip through the PDF flipbook, and reach the Contact section to get in touch. Their relevant inputs and decisions are which sections to read, which locker items to open, which documents to flip through, and whether to make contact.

They interact with the Portfolio Owner only indirectly: the Owner's authored content, assets, and contact details are what the Visitor consumes. Their observable success is understanding her range of work and having a clear way to make contact. What makes this role distinct is that they are a pure consumer of authored content with no authoring, editing, or ownership responsibility anywhere in the product.

Page 9 of 25

Portfolio Owner (Jassinta Roid Triniti)

The Portfolio Owner is the creative professional whose personal brand the site presents. She is a Social Media Specialist, Content Creator, Videographer, and Graphic Designer, and she owns the content shown across every section — writing portfolio, content marketing, example strategy, campus projects, podcast, and archive — and supplies the assets (images, videos, PDFs) referenced under /assets/....

Her primary goal is a deployable, on-brand one-page site that represents her work accurately and can be updated by editing the separated data files in src/data/*.ts. Her distinct responsibilities are authoring the content data, supplying and naming the assets, and keeping the site's content current through those data files. Her relevant inputs and decisions are what work to include in each section, which assets to reference, and how each piece is titled — including Indonesian work/article titles, which are displayed as-is.

She does not interact with the Portfolio Visitor directly inside the product; the Visitor consumes what she authors. Her observable success is a static build that deploys to Vercel and presents her work correctly, with content changes achievable through src/data/*.ts alone. What makes this role distinct is that she is the sole author and asset owner, with no in-product editing surface — her work happens in the data files and asset paths, not in a running UI.

5. Core User Flows

Page 10 of 25

Flow 1 — Portfolio Visitor: arrive and open the locker

  1. The Portfolio Visitor opens the site root and lands anonymously on the Opening section. No account or login is requested.
  2. They see the school corridor: a pearl-to-warm-grey wall behind a steel-lilac locker bank filling the viewport, with JASSINTA ROID TRINITI in Anton spanning the full width, each word on its own flat color block (hot-pink, butter, pastel-mint, lavender).
  3. A DM Mono strip of rotating role labels (Social Media Specialist / Videographer / Graphic Designer) marquees along the bottom edge, and a hot-pink pill button "Open the locker" is pinned bottom-left.
  4. They select "Open the locker". The CSS-3D locker door opens to reveal the interior: locker --candy-pink, interior --berry, rack --blush. Smooth/inertial scrolling is disabled for the duration of this scroll-lock.
  5. Observable result: the locker is open and its interior rack is visible with the locker items on it.
  6. Continuation: they either select a locker item (Flow 2) or close the locker and scroll onward via the table of contents (Flow 3).

Flow 2 — Portfolio Visitor: inspect a locker item overlay

  1. From the open locker, the Portfolio Visitor selects a locker item such as Participation or Achievement.
  2. A full-screen overlay opens — not a new route — with the item's content, an oversized Anton title, a mono metadata block, and a corner "close\x20\xe2\x9c\x95" control that flips color on hover. The URL hash updates to the item's identifier, for example #/participation. Scrolling remains locked while the overlay is open.
  3. Observable result: the item's content is fully readable in the overlay.
  4. Failure/recovery: if the item's referenced asset is missing, the overlay still opens and shows the tidy fallback rather than a broken icon or error text.
  5. They dismiss the overlay using the close button, the Escape key, or the browser Back button. The hash clears, the scroll lock releases, and the page returns to its prior position.
  6. Continuation: they open another locker item or continue scrolling the page.

Flow 3 — Portfolio Visitor: navigate the page via the table of contents

  1. The Portfolio Visitor uses the table of contents — a sticky rail on desktop, a pill chip bar on mobile — to move between sections.
  2. They select a section entry. The page smooth-scrolls to that section with no reload.
  3. Observable result: the target section is in view and the page has not reloaded.
  4. Failure/recovery: if a target is unavailable, the page stays on the current section without breaking.
  5. Continuation: they read the section and continue to the next one.
Page 11 of 25

Flow 4 — Portfolio Visitor: read the Personal Brand canvas

  1. The Portfolio Visitor scrolls into the Personal Brand section on its mandatory pure-white ground.
  2. They read the personal brand statement, with the name set in Anton ultra-condensed all-caps at viewport-spanning scale, alongside white document paper elements and cherry-red accents.
  3. Observable result: the statement and wordmark render fully inside the viewport at 375px, 768px, and 1280px.
  4. Failure/recovery: if a referenced document image is missing, a tidy paper fallback is shown.
  5. Continuation: they scroll onward to the Writing Portfolio.

Flow 5 — Portfolio Visitor: flip through the Writing Portfolio

  1. The Portfolio Visitor reaches the Writing Portfolio hero on --powder-pink with grain, then the cassette disc composition on a --blush→--lilac ground with grain.
  2. They drag a page in the PDF flipbook. The page turns realistically, with visible paper edges and grain, and the next page is shown.
  3. Observable result: they can move forward and back through the document.
  4. Failure/recovery: if a referenced PDF is missing, the section shows the tidy fallback rather than a broken frame, and the rest of the section remains usable.
  5. Continuation: they continue flipping, or leave the section and return to the flipbook later in the same visit — the flipbook is independently revisitable.

Flow 6 — Portfolio Visitor: read Content Marketing

  1. The Portfolio Visitor scrolls into Content Marketing on the --grad-plum-night ground with film grain, milk-white text, and a hot-pink glow accent.
  2. They read the content marketing work and its supporting media.
  3. Observable result: the content renders legibly on the dark ground.
  4. Failure/recovery: missing media shows the tidy fallback.
  5. Continuation: they scroll onward to Example Strategy.

Flow 7 — Portfolio Visitor: read Example Strategy and watch the video reveal

  1. The Portfolio Visitor reaches the Example Strategy hero on --lilac with grain.
  2. They read the example strategy, then trigger the video reveal on the --grad-plum-night ground with the pink-checker floor.
  3. Observable result: the video plays within the reveal composition.
  4. Failure/recovery: if the video asset is missing or fails to load, the reveal area shows the tidy fallback and the section remains readable.
  5. Continuation: they scroll onward to Project Campus.
Page 12 of 25

Flow 8 — Portfolio Visitor: browse Project Campus

  1. The Portfolio Visitor scrolls into Project Campus on the --vanilla ground with the --walnut wood rack, cherry-red accents, and the cherry-red Sentient italic "The Campus" headline.
  2. They browse the campus project items on the wood rack and read project details.
  3. Observable result: items render on the rack and are readable.
  4. Failure/recovery: missing project media shows the tidy fallback.
  5. Continuation: they scroll onward to Podcast.

Flow 9 — Portfolio Visitor: read the Podcast section

  1. The Portfolio Visitor scrolls into Podcast on the --blush ground with cherry-red accents and the cherry-red Sentient italic "The Microphone" headline.
  2. They read the podcast work and review episode or series details.
  3. Observable result: podcast content renders legibly.
  4. Failure/recovery: missing media shows the tidy fallback.
  5. Continuation: they scroll onward to Archive.

Flow 10 — Portfolio Visitor: browse the Archive

  1. The Portfolio Visitor scrolls into Archive on the --grad-plum-night ground with milk-white text, hot-pink accents, and DM Mono uppercase labels with wide letterspacing.
  2. They browse archived work and assets and read the archive labels and credits.
  3. Observable result: archive items render with readable labels.
  4. Failure/recovery: if the archive has no items, a tidy empty state is shown; if an archive asset is missing, the tidy fallback is shown per section rules.
  5. Continuation: they scroll onward to Contact.

Flow 11 — Portfolio Visitor: reach contact

  1. The Portfolio Visitor scrolls into Contact on the --grad-plum-night ground with glow, milk-white text, and bubblegum accents.
  2. They review the contact details and use the contact actions to get in touch.
  3. Observable result: the contact actions are visible and usable, and the Visitor has a clear way to make contact.
  4. Failure/recovery: if a referenced contact asset is missing, the tidy fallback is shown and the contact actions remain reachable.
  5. Continuation: the Visitor leaves the site having understood her range of work and having a clear way to make contact.
Page 13 of 25

Flow 12 — Portfolio Owner: update content and deploy

  1. The Portfolio Owner opens the project and edits the relevant src/data/*.ts file to change content for a section — for example adding a writing portfolio entry or a campus project item.
  2. She places or replaces the corresponding asset under /assets/... using the path referenced by the data.
  3. She runs the build, which produces the static dist/ folder.
  4. Observable result: the updated content renders on the site, and any asset she has not yet supplied shows the tidy fallback rather than a broken icon or error text.
  5. Failure/recovery: if a feature could not be completed as specified, a clear // TODO: comment marks it rather than the feature being silently removed.
  6. Continuation: she deploys dist/ to Vercel without a server.

6. Visuals Colors and Theme

Muse: Jessica Walsh. Headline: Playful maximalism — a locker-room scrapbook that refuses to be quiet. The direction is colour-first, never white-first: saturated colour fields, oversized chunky display type, sticker and prop compositions, and humour in every frame. The generic indigo/blue-on-white SaaS template is forbidden for this project.

Page 14 of 25

Colour tokens (light mode)

RoleTokenHex
Background (dominant ground)--blush#FFD6E8
Surface (paper)--vanilla#FFF8EE
Text--ink#1B1017
Primary--hot-pink#FF2E93
Accent--cherry-red#E5173F
Muted--dusty-rose#E8A5B8

Blush #FFD6E8 and powder-pink #FDE4EC are the dominant grounds; vanilla #FFF8EE and milk-white #FFFDF9 are paper surfaces for scrapbook cards; hot-pink #FF2E93 is the single hot accent (buttons, glow, marquee); cherry-red #E5173F is the editorial italic headline and staple/pin colour. Lavender #BFA8E5, candy-pink #FFB3D9, pastel-mint #A8E6CF, butter #FFF1A8, and baby-blue #BFE3F5 appear as flat sticker/colour-block fields, one per block, never blended. Dark sections (Content Marketing, Archive, Contact) invert to the plum-night gradient with milk-white #FFFDF9 text and hot-pink glow.

Page 15 of 25

Full palette (CSS variables in :root and custom Tailwind colors)

Pink: --hot-pink #FF2E93 (primary buttons, glow reveal, strong accents); --barbie-pink #E91E8C (button hover, accent text, stickers); --raspberry #D81B72 (accent lines, icons); --bubblegum #FF8DC7 (highlight blocks, badges); --candy-pink #FFB3D9 (open locker body, stickers); --blush #FFD6E8 (soft section grounds, highlight blocks); --rose-quartz #F7CAD0 (cards, paper); --powder-pink #FDE4EC (bright section grounds); --dusty-rose #E8A5B8 (coloured shadows, details); --cherry-red #E5173F (italic headline colour for The Campus, The Story, The Microphone; staples, pins); --lipstick-red #C8102E (magazine elements — lips, ribbons); --coral-pop #FF6F6F (playful accents); --peach-fizz #FFB38A (highlight blocks, labels); --apricot #FFD3B0 (soft highlights).

Purple / Lavender: --lavender #BFA8E5 (envelopes, cards, locker); --lilac #D4C1F5 (section grounds, highlight blocks); --wisteria #A98BDA (secondary accents); --orchid #DA9AF2 (glow, gradients); --grape-soda #7B4FB8 (text on pastels); --berry #7A2E5C (open locker interior, warm dark panel); --aubergine #4B1D4F (dark gradients); --plum-night #2A0F2E (main dark ground, "plum night gradient").

Mint / Green / Pastel Blue: --mint-cream #D4F2E4 (soft grounds); --pastel-mint #A8E6CF (highlight blocks, camera, cards); --matcha #B7D9A8 (plant details/accents); --sage #A9C4A0 (neutral accents); --baby-blue #BFE3F5 (highlight blocks, icons); --sky-pastel #A7D8F5 (accents); --periwinkle #B8C4F2 (accents); --notebook-blue #8FB8E8 (ruled paper lines); --steel-lilac #B9B8CC (closed locker, grey-lavender metal).

Yellow / Cream / Paper: --butter #FFF1A8 (highlight blocks, sticky notes); --lemon-chiffon #FFF6C9 (soft highlights); --vanilla #FFF8EE (warm cream ground); --aged-paper #F3E3B8 (yellowed paper, photo pin board); --honey #F6D76B (accents); --milk-white #FFFDF9 (white paper, text on dark); --pure-white #FFFFFF (Personal Brand canvas — mandatory pure white).

Neutrals & Metal: --ink #1B1017 (primary text); --espresso #2B1B17 (text on paper); --cocoa #5A3A2E (wood/brown details); --walnut #7A4A32 (umbrella handle, wood rack); --pearl #F4EFF1 (light neutral); --warm-grey #D9D3D6 (lines, shadows); --chrome #C9CCD5 (metal — handles, locks, vents); --gold #D4A64A (frames, trophies); --champagne #EBD08C (gold highlights); --staple-red #D7263D (staples/pins on paper).

Page 16 of 25

Named gradients

  • --grad-plum-night: linear-gradient(160deg, #2A0F2E 0%, #4B1D4F 55%, #7A2E5C 100%)
  • --grad-cotton-candy: linear-gradient(135deg, #FFD6E8 0%, #E3D4FA 50%, #CDEBF8 100%)
  • --grad-bubblegum: linear-gradient(135deg, #FF8DC7 0%, #FF2E93 100%)
  • --grad-lilac-mint: linear-gradient(135deg, #D4C1F5 0%, #D4F2E4 100%)

Per-section colour map

SectionBackgroundTextAccent
Opening (closed)Wall --pearl→--warm-grey; locker --steel-lilac--inkMulti-colour word blocks, --hot-pink button
Opening (open)Locker --candy-pink; interior --berry; rack --blush--ink / --milk-white--hot-pink
Personal Brand--pure-white--ink--cherry-red, white document paper
Writing Portfolio hero--powder-pink + grain--ink--hot-pink
Cassette disc--blush→--lilac + grain--ink--hot-pink
Content Marketing--grad-plum-night + film grain--milk-whiteGlow --hot-pink
Example Strategy hero--lilac + grain--ink--hot-pink
Example Strategy video reveal--grad-plum-night, pink-checker floor--milk-white--hot-pink
Project Campus--vanilla + wood rack --walnut--ink--cherry-red
Podcast--blush--ink--cherry-red
Archive--grad-plum-night--milk-white--hot-pink
Contact--grad-plum-night + glow--milk-white--bubblegum
Page 17 of 25

Typography

RoleFontFallback
Display / headline serifSentient (Fontshare) — Regular, Italic, Bold, Bold Italic'Fraunces', Georgia, serif
Body / narrationPoppins italic for narration (max 24.9px), Poppins regular 400/500/600 for UIsystem-ui, sans-serif
Giant sans (Personal Brand)Anton (ultra-bold condensed)'Archivo Black', Impact, sans-serif
Handwriting (letters)Caveat (clearly legible)'Patrick Hand', cursive
Script "Fashion" (magazine)Pinyon Script'Great Vibes', cursive
VOGUE elegantBodoni Moda 700–900 (or Playfair Display)serif
OOTD boldBebas NeueOswald, Impact, sans-serif
Label / typewriter (archive cards, tags, credits)DM Mono / Special Elitemonospace
Polaroid captionPermanent Marker or Caveatcursive

Sentient is loaded from Fontshare at https://api.fontshare.com/v2/css?f[]=sentient@300,301,400,401,500,501,700,701&display=swap with font-display: swap, preconnect, and fallbacks. Variant numbers are verified on the Sentient page at fontshare.com; odd numbers are italic: 300 Light, 301 Light Italic, 400 Regular, 401 Italic, 500 Medium, 501 Medium Italic, 700 Bold, 701 Bold Italic.

Type scale: 1.333 modular with a poster jump — 128 / 96 / 66 / 40 / 25 / 18 / 16. Display 66px desktop to 33.6px mobile via clamp(2.1rem, 1.2rem + 3.6vw, 4.125rem); narrative 24.9px max via clamp(1rem, 0.85rem + 0.7vw, 1.556rem) in Poppins italic, line-height: 1.5, max-width: 58ch, gap from headline 1.5rem; labels 12–14px DM Mono; captions 18–22px Permanent Marker.

Fluid sizing rules: headline font-size: clamp(2.1rem, 1.2rem + 3.6vw, 4.125rem); line-height: 1.02; letter-spacing: -0.01em; text-wrap: balance. Narration font-size: clamp(1rem, 0.85rem + 0.7vw, 1.556rem); Poppins italic; line-height: 1.5; text-wrap: pretty; max-width: ~58ch. --headline-narration-gap: 1.5rem.

Page 18 of 25

Shape language

Hard-edged colour fields and sticker-cut silhouettes rather than soft glass: bold rectangles, capsule and blob stickers with 1–2px ink outlines, rotated tags and tape strips, halftone and grain textures, oversized circles for the cassette and locker dials. Radii are either fully round (pills, stickers) or zero (colour blocks, magazine rules) — nothing in between, and no glassmorphism.

Layout

Colour-blocked vertical scroll: each section owns one saturated ground and collides with the next at a hard edge or diagonal band. Asymmetric editorial grids with type bled to the viewport edge, overlapping sticker layers, and a sticky table-of-contents rail on desktop that collapses to a pill chip bar on mobile. The locker opening is a full-viewport CSS-3D composition; overlay pages are full-screen colour fields with a mono close control.

Imagery

Typography and flat colour are the image; photography is high-contrast art-directed cutouts of Jassinta (portrait, camera, mic, locker props) treated as duotone pink/cherry or full-bleed with hard crops. Surreal 3D props (cassette, lipstick, polaroid, trophy) rendered flat-glossy on colour grounds; halftone and film-grain overlays on every section; no stock people, no gradient blobs.

Page 19 of 25

Readable-text and control integrity

Headlines, wordmarks, labels, numbers, cards' text, and controls stay entirely inside the viewport and their container at 375px, 768px, and 1280px, wrapping or scaling (for example font-size: clamp(...) with its mobile size) to fit, and no other element covers any part of them. Imagery, decoration, and motion may be cropped, bled off an edge, rotated, overlapped, or cut as the direction asks, as long as they cover no readable text or control. Moving and scrollable content (marquees, tickers, carousels, horizontally scrollable rows) may cross the viewport or container edge by design; every item becomes fully readable as it passes. With prefers-reduced-motion, moving content stops and shows whole items, wrapping into rows or sitting in a horizontally scrollable row (overflow-x: auto).

Page 20 of 25

7. Signature Design Concept

The Corridor Locker Bank. The public entry is a full-viewport school corridor rendered entirely in CSS 3D. A pearl-to-warm-grey wall recedes behind one steel-lilac locker bank that fills the viewport, its doors, handles, vents, and dials built from flat colour fields, 1–2px ink outlines, and grain rather than glass or gradient. Above the bank, JASSINTA ROID TRINITI is set in Anton at clamp(3rem, 12vw, 9rem) spanning the full width, each word sitting on its own flat colour block — hot-pink, butter, pastel-mint, lavender — so the name reads as four stickers slapped across the wall. A hot-pink pill button "Open the locker" is pinned bottom-left, deliberately off-axis. Along the bottom edge, a DM Mono strip of rotating role labels — Social Media Specialist / Videographer / Graphic Designer — marquees as a taped ticker. Grain sits over the whole frame.

The signature move is the opening itself: the locker door swings on a CSS 3D hinge (perspective on the corridor, transform-style: preserve-3d on the bank), revealing a candy-pink body, a berry interior, and a blush rack holding the locker items. Each item is a sticker-cut object with an ink outline; selecting one launches its full-screen colour-field overlay with an oversized Anton title, a mono metadata block, and a corner "close\x20\xe2\x9c\x95" control that flips colour on hover. The composition recomposes only accepted content and controls — the name, the role labels, the open control, the locker items, and their overlays — and introduces no new behaviour, page, or destination.

8. Interaction Model & Motion Direction

Interaction Model: Animated Motion Tempo: expressive Hero Dimensionality: layered_2d

Page 21 of 25

Landing Hero Motion Brief

  • Focal subject: the steel-lilac locker bank on the corridor wall, with the Anton name spanning the viewport above it, each word on its own flat colour block.
  • Input → transformation → outcome thesis: as the visitor arrives and scrolls or interacts, the corridor settles into place — the name's colour blocks stagger in word by word, the DM Mono role strip begins its marquee, and the hot-pink "Open the locker" pill pulses once — so that the first frame reads as a poster that is about to move. Selecting "Open the locker" transforms the composition: the door swings on its CSS 3D hinge, the interior is revealed, and the scroll lock engages; closing the door reverses the transformation and releases the lock.
  • Motion vocabulary: staggered word and sticker reveals on scroll, marquee ticker strips, hover colour flips, scale-ins with spring easing, and the page-turn flipbook on drag. Lenis handles inertial scroll and is disabled during the Opening lock and any overlay.
  • Composed first frame: off-axis and poster-like — the locker bank filling the viewport, the Anton name above it on four flat colour blocks, the hot-pink pill bottom-left, the DM Mono role strip along the bottom edge, grain over the whole frame. Nothing is centred.
  • Reduced-motion state: prefers-reduced-motion stops the marquees (items wrap or sit in an overflow-x: auto row) and replaces reveals with instant states; the locker still opens and closes, but without the animated swing.
Page 22 of 25

9. Non-Functional Requirements

NFR-01 — Performance target (explicit) The site should hold 60fps on a mid-range laptop. Rationale: the specification states this as a quality principle, and the CSS-3D locker is explicitly chosen over Three.js to stay light on phones.

NFR-02 — No unintended horizontal scrollbar (explicit) No unintended horizontal scrollbar may appear. Rationale: stated quality principle; marquees and horizontally scrollable rows are the only intentional horizontal movement.

NFR-03 — No container overflow (explicit) No element may escape its container. Rationale: stated quality principle; readable text and controls must stay whole at 375px, 768px, and 1280px.

NFR-04 — No large layout shift (explicit) No large layout shift may occur. Rationale: stated quality principle; Sentient is loaded with font-display: swap, preconnect, and fallbacks specifically to avoid shift.

NFR-05 — Static, serverless deployment (explicit) The build must produce a static dist/ folder deployable to Vercel without a server. Rationale: explicit deployment constraint.

NFR-06 — No client-side API keys, no API dependency (explicit) There must be no API keys on the client side and the website must require no API. Rationale: explicit security and scope constraint.

NFR-07 — Evergreen browser support (explicit) The site targets evergreen desktop and mobile browsers; legacy browsers outside evergreen desktop/mobile are out of scope. Rationale: stated non-goal.

NFR-08 — English-only content except source titles (explicit) All website-facing text must be in full English, except Indonesian work/article titles, which are displayed as-is. Rationale: explicit language constraint and stated non-goal of providing content in Bahasa Indonesia except where source titles require.

NFR-09 — Modularity and data separation (explicit) Content data must not live inside components; it belongs in src/data/*.ts, with one component per section. Rationale: explicit structural constraint that keeps content updatable without touching component code.

NFR-10 — Feature preservation with explicit TODOs (explicit) Features must not be summarized, shortened, or silently removed; a hard feature gets the best possible version plus a clear // TODO: comment. Rationale: explicit working rule.

NFR-11 — Stage isolation (explicit) While working on one stage, other section files must not be modified except for minimal integration. Rationale: explicit working rule.

NFR-12 — Decision traceability (explicit) Ambiguities must be resolved by the specification when written, and otherwise by the option closest to the girly, playful, textured theme, recorded in DECISIONS.md. Rationale: explicit working rule.

NFR-13 — Stage reporting (explicit) After each stage, a short summary must state what was built, what is still TODO, and how to test it. Rationale: explicit working rule.

NFR-14 — Reduced-motion compliance (required_inference) Under prefers-reduced-motion, marquees must stop and reveals must become instant states, with moving content wrapping into rows or sitting in an overflow-x: auto row. Rationale: required to keep the expressive motion direction usable without decorative motion running under reduced-motion preferences.

NFR-15 — Tidy missing-asset fallbacks (explicit) When a referenced asset under /assets/... is missing, each section must show a tidy fallback — not a broken icon, not error text. Rationale: explicit asset-handling rule.

Page 23 of 25

10. Tech Stack

  • React 18 — required UI framework. (explicit)
  • Vite — required build tool; produces the static dist/ output. (explicit)
  • TypeScript — required language. (explicit)
  • Tailwind CSS — required styling layer, with the full palette defined as custom colors and typography tokens. (explicit)
  • Framer Motion — primary animation toolkit; GSAP + ScrollTrigger only where better suited for scroll-driven work, choosing one consistent approach per need. (explicit)
  • Lenis (or equivalent) — smooth/inertial scrolling, disableable during the Opening scroll-lock and while an overlay is open. (explicit)
  • page-flip (StPageFlip) or react-pageflip — flipbook with realistic page turns. (explicit)
  • pdfjs-dist — PDF rendering for the flipbook. (explicit)
  • CSS 3D transforms (perspective, transform-style: preserve-3d) — the 3D locker; Three.js is explicitly not used, to stay light on phones. (explicit)
  • Fontshare (Sentient) — display/headline serif, loaded with font-display: swap, preconnect, and fallbacks. (explicit, brand_source)
  • Google Fonts — Poppins, Anton, Caveat, Pinyon Script, Bodoni Moda, Bebas Neue, DM Mono / Special Elite, Permanent Marker. (explicit)
  • Vercel static hosting — deployment target for the static dist/ folder, no server. (explicit)

No storage, database, backend framework, container, or orchestration layer is required by the authoritative requirements; the product is a static front-end with no API.

Page 24 of 25

11. Assumptions and Constraints

Assumptions

  • A-01 (required_inference) — The page remains anonymously reachable from the root as the explanatory Opening entry; no account, login, or identity is required anywhere in the product.
  • A-02 (required_inference) — The one-page navigation, smooth scrolling, and table of contents preserve section continuity without route reloads.
  • A-03 (required_inference) — Locker overlays coordinate hash history, close controls, Escape handling, and scroll locking.
  • A-04 (required_inference) — The Writing Portfolio flipbook loads PDF assets when available and uses a tidy fallback when referenced assets are missing.
  • A-05 (required_inference) — Contact actions remain reachable from the Contact section.
  • A-06 (required_inference) — The Portfolio Visitor and the Portfolio Owner are the only active human personas; the Portfolio Owner authors content through src/data/*.ts and supplies assets under /assets/... rather than through any in-product editing surface.
  • A-07 (required_inference) — Where the specification does not name a specific locker item beyond Participation and Achievement, additional locker items follow the same overlay pattern and are authored as data.

Constraints

  • C-01 (explicit) — One-page website only: a single long page with no page reload and no new routes; locker items are full-screen overlays.
  • C-02 (explicit) — The 3D locker must use CSS 3D transforms, not Three.js.
  • C-03 (explicit) — No API keys on the client side; the website requires no API.
  • C-04 (explicit) — Smooth/inertial scroll must be disableable during the Opening scroll-lock and while an overlay is open.
  • C-05 (explicit) — The build must produce a static dist/ folder deployable to Vercel without a server.
  • C-06 (explicit) — All website-facing text must be in full English; all code, variable names, component names, and code comments must be in English (Indonesian work/article titles displayed as-is).
  • C-07 (explicit) — Content data must not live inside components; it belongs in src/data/*.ts.
  • C-08 (explicit) — Do not summarize, shorten, or silently remove features; hard features get the best possible version plus a clear // TODO: comment.
  • C-09 (explicit) — When working on one stage, do not modify other section files except for minimal integration.
  • C-10 (explicit) — The Personal Brand canvas must be pure white (--pure-white).
  • C-11 (explicit) — No unintended horizontal scrollbar, no elements escaping their container, no large layout shifts; target 60fps on a mid-range laptop.
  • C-12 (explicit) — Assets are referenced via /assets/... paths; missing files show a tidy fallback, not a broken icon or error text.
  • C-13 (explicit) — The full color palette is defined as CSS variables in :root and as custom Tailwind colors using the specification's token names.
  • C-14 (explicit) — The named gradients --grad-plum-night, --grad-cotton-candy, --grad-bubblegum, and --grad-lilac-mint are defined with their exact stops.
  • C-15 (explicit) — Each section uses its specified background, text, and accent mapping.
  • C-16 (explicit) — Typography roles and fluid sizing rules follow the specification exactly, including --headline-narration-gap: 1.5rem.
  • C-17 (explicit) — Sentient is loaded via Fontshare with font-display: swap, preconnect, and fallbacks to avoid layout shift.
  • C-18 (explicit) — Legacy browsers outside evergreen desktop/mobile are not supported.
  • C-19 (explicit) — Content is not provided in Bahasa Indonesia except where source titles require it.
Page 25 of 25

12. Glossary

  • Locker — The CSS-3D school locker bank in the Opening section; it opens to reveal an interior rack holding locker items.
  • Locker item — An object on the locker's interior rack (for example Participation, Achievement) that opens as a full-screen overlay.
  • Overlay — A full-screen in-page state opened by a locker item; not a new route, with a close button, Escape support, and hash-based Back-button support.
  • Hash route — The URL fragment identifying an open overlay, for example #/participation.
  • Flipbook — The draggable page-turn reader in the Writing Portfolio, built with page-flip (StPageFlip) or react-pageflip and rendering PDFs with pdfjs-dist.
  • Cassette disc — The physical-object cassette composition in the Writing Portfolio section.
  • Table of contents — The navigation control for the one-page site; a sticky rail on desktop that collapses to a pill chip bar on mobile.
  • Scroll lock — The state in which smooth/inertial scrolling is disabled, during the Opening lock and while an overlay is open.
  • Lenis — The smooth/inertial scrolling library (or equivalent) used for the page.
  • Sentient — The Fontshare display serif used for headlines, loaded with font-display: swap, preconnect, and fallbacks.
  • Token — A named CSS variable and matching custom Tailwind color, using the specification's names (for example --hot-pink).
  • Named gradient — One of --grad-plum-night, --grad-cotton-candy, --grad-bubblegum, --grad-lilac-mint.
  • Tidy fallback — The graceful placeholder shown when a referenced asset under /assets/... is missing; never a broken icon or error text.
  • DECISIONS.md — The file recording decisions made when the specification is ambiguous.
  • src/data/*.ts — The separated content data files; no content data lives inside components.
  • dist/ — The static build output deployable to Vercel without a server.
  • Portfolio Visitor — The recruiter, prospective client, or collaborator who browses the site anonymously.
  • Portfolio Owner — Jassinta Roid Triniti, the creative professional whose work the site presents and who authors its content data and assets.

No completed page designs yet.

Completed design pages will appear here when they are ready to preview.

Opening: Review published locker presentation
Personal Brand: Edit brand data file
Personal Brand: Verify statement and fallback
Writing Portfolio: Add writing portfolio entry
Writing Portfolio: Supply referenced PDF asset
Content Marketing: Update content marketing entries
Example Strategy: Update strategy and video asset
Project Campus: Add campus project item
Podcast: Update podcast episode data
Archive: Update archive credits
Contact: Confirm contact details
Opening: Build static deployment output

No completed page designs yet.

Completed design pages will appear here when they are ready to preview.

Opening: Review published locker presentation
Personal Brand: Edit brand data file
Personal Brand: Verify statement and fallback
Writing Portfolio: Add writing portfolio entry
Writing Portfolio: Supply referenced PDF asset
Content Marketing: Update content marketing entries
Example Strategy: Update strategy and video asset
Project Campus: Add campus project item
Podcast: Update podcast episode data
Archive: Update archive credits
Contact: Confirm contact details
Opening: Build static deployment output