A Pen by Altaf Hussain on CodePen.
Created
August 29, 2026 03:58
-
-
Save TheLearnerDev19/6fdd0e23845e2606150ec21e1d0ad316 to your computer and use it in GitHub Desktop.
Altaf Hussain Literary Archive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Altaf Hussain — Literary Works & Introspection</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400;1,500&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"> | |
| <style> | |
| :root{ | |
| --bg: #F9F6F0; | |
| --bg-raised: #F4EFEA; | |
| --ink: #1C1B1A; | |
| --slate: #6E6B68; | |
| --rust: #A04A36; | |
| --sage: #4A6B5D; | |
| --rule: rgba(28,27,26,0.12); | |
| --rule-soft: rgba(28,27,26,0.06); | |
| --serif: 'Cormorant Garamond', Georgia, serif; | |
| --mono: 'JetBrains Mono', 'Space Mono', monospace; | |
| --measure: 66ch; | |
| } | |
| *{box-sizing:border-box;} | |
| html{scroll-behavior:smooth;} | |
| body{ | |
| margin:0; | |
| background:var(--bg); | |
| color:var(--ink); | |
| font-family:var(--serif); | |
| -webkit-font-smoothing:antialiased; | |
| position:relative; | |
| min-height:100vh; | |
| } | |
| /* paper grain */ | |
| body::before{ | |
| content:""; | |
| position:fixed; | |
| inset:0; | |
| pointer-events:none; | |
| z-index:1; | |
| opacity:0.35; | |
| mix-blend-mode:multiply; | |
| background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E"); | |
| } | |
| @media (prefers-reduced-motion: reduce){ | |
| *{animation-duration:0.001ms !important; animation-iteration-count:1 !important; transition-duration:0.001ms !important; scroll-behavior:auto !important;} | |
| } | |
| a{color:inherit;} | |
| button{font-family:inherit; cursor:pointer;} | |
| /* ===== Header ===== */ | |
| header{ | |
| position:sticky; top:0; z-index:40; | |
| background:rgba(249,246,240,0.88); | |
| backdrop-filter:blur(10px); | |
| border-bottom:1px solid var(--rule); | |
| } | |
| .header-inner{ | |
| max-width:1180px; margin:0 auto; | |
| padding:22px 32px 0 32px; | |
| } | |
| .brandrow{ | |
| display:flex; align-items:baseline; justify-content:space-between; | |
| flex-wrap:wrap; gap:10px 24px; | |
| padding-bottom:18px; | |
| } | |
| .brand{ | |
| font-family:var(--serif); | |
| font-size:1.5rem; | |
| font-weight:600; | |
| letter-spacing:0.01em; | |
| } | |
| .brand .sep{color:var(--rust); padding:0 10px; font-weight:400;} | |
| .brand .sub{ | |
| font-family:var(--mono); | |
| font-size:0.68rem; | |
| letter-spacing:0.14em; | |
| text-transform:uppercase; | |
| color:var(--slate); | |
| font-weight:500; | |
| } | |
| .tagline{ | |
| font-family:var(--mono); | |
| font-size:0.7rem; | |
| letter-spacing:0.08em; | |
| color:var(--slate); | |
| text-transform:uppercase; | |
| } | |
| .controls-row{ | |
| display:flex; align-items:center; justify-content:space-between; | |
| gap:20px; flex-wrap:wrap; | |
| padding-bottom:16px; | |
| } | |
| nav.filters{ | |
| display:flex; gap:2px; position:relative; | |
| font-family:var(--mono); | |
| border:1px solid var(--rule); | |
| border-radius:100px; | |
| padding:3px; | |
| background:var(--bg-raised); | |
| } | |
| nav.filters button{ | |
| position:relative; z-index:2; | |
| background:transparent; border:none; | |
| padding:7px 16px; | |
| font-family:var(--mono); | |
| font-size:0.72rem; | |
| letter-spacing:0.06em; | |
| text-transform:uppercase; | |
| color:var(--slate); | |
| border-radius:100px; | |
| transition:color 0.35s ease; | |
| white-space:nowrap; | |
| } | |
| nav.filters button.active{color:var(--bg);} | |
| .filter-pill{ | |
| position:absolute; z-index:1; top:3px; bottom:3px; left:3px; | |
| width:0; border-radius:100px; | |
| background:var(--ink); | |
| transition:transform 0.4s cubic-bezier(.65,0,.35,1), width 0.4s cubic-bezier(.65,0,.35,1); | |
| } | |
| .right-controls{ | |
| display:flex; align-items:center; gap:14px; | |
| flex-wrap:wrap; | |
| } | |
| .search-wrap{ | |
| position:relative; | |
| display:flex; align-items:center; | |
| } | |
| .search-wrap svg{ | |
| position:absolute; left:12px; width:13px; height:13px; | |
| stroke:var(--slate); | |
| } | |
| #searchInput{ | |
| font-family:var(--mono); | |
| font-size:0.78rem; | |
| background:var(--bg-raised); | |
| border:1px solid var(--rule); | |
| border-radius:100px; | |
| padding:8px 14px 8px 32px; | |
| width:200px; | |
| color:var(--ink); | |
| outline:none; | |
| transition:border-color 0.25s ease, width 0.3s ease; | |
| } | |
| #searchInput:focus{border-color:var(--rust); width:240px;} | |
| #searchInput::placeholder{color:var(--slate); opacity:0.8;} | |
| .view-toggle{ | |
| display:flex; border:1px solid var(--rule); border-radius:8px; overflow:hidden; | |
| } | |
| .view-toggle button{ | |
| background:var(--bg-raised); border:none; | |
| padding:8px 10px; | |
| display:flex; align-items:center; justify-content:center; | |
| color:var(--slate); | |
| transition:background 0.25s ease, color 0.25s ease; | |
| } | |
| .view-toggle button + button{border-left:1px solid var(--rule);} | |
| .view-toggle button.active{background:var(--ink); color:var(--bg);} | |
| .view-toggle svg{width:15px; height:15px;} | |
| /* ===== Main ===== */ | |
| main{max-width:1180px; margin:0 auto; padding:36px 32px 100px 32px; position:relative; z-index:2;} | |
| .count-line{ | |
| font-family:var(--mono); | |
| font-size:0.72rem; | |
| letter-spacing:0.06em; | |
| color:var(--slate); | |
| text-transform:uppercase; | |
| margin-bottom:20px; | |
| padding-bottom:14px; | |
| border-bottom:1px solid var(--rule-soft); | |
| } | |
| /* ---- Grid view ---- */ | |
| .grid-view{ | |
| display:grid; | |
| grid-template-columns:repeat(auto-fill, minmax(280px, 1fr)); | |
| gap:22px; | |
| } | |
| .card{ | |
| background:var(--bg-raised); | |
| border:1px solid var(--rule); | |
| border-radius:2px; | |
| padding:26px 24px 22px 24px; | |
| display:flex; flex-direction:column; | |
| cursor:pointer; | |
| transition:transform 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease; | |
| animation:cardIn 0.5s ease both; | |
| } | |
| .card:hover{ | |
| transform:translateY(-4px); | |
| border-color:rgba(28,27,26,0.28); | |
| box-shadow:0 14px 30px -18px rgba(28,27,26,0.35); | |
| } | |
| .card:focus-visible{outline:2px solid var(--rust); outline-offset:3px;} | |
| @keyframes cardIn{ | |
| from{opacity:0; transform:translateY(10px);} | |
| to{opacity:1; transform:translateY(0);} | |
| } | |
| .card.hide{display:none;} | |
| .badge-row{display:flex; align-items:center; justify-content:space-between; margin-bottom:14px;} | |
| .badge{ | |
| font-family:var(--mono); | |
| font-size:0.62rem; | |
| letter-spacing:0.1em; | |
| text-transform:uppercase; | |
| padding:3px 9px; | |
| border-radius:100px; | |
| border:1px solid currentColor; | |
| } | |
| .badge.poems{color:var(--sage);} | |
| .badge.micro-poetry{color:var(--rust);} | |
| .badge.essays{color:var(--slate);} | |
| .card-date{font-family:var(--mono); font-size:0.68rem; color:var(--slate);} | |
| .card-title{ | |
| font-size:1.5rem; | |
| font-weight:600; | |
| line-height:1.25; | |
| margin:0 0 10px 0; | |
| } | |
| .card-excerpt{ | |
| color:var(--slate); | |
| font-size:1.02rem; | |
| font-style:italic; | |
| line-height:1.55; | |
| margin:0 0 18px 0; | |
| flex-grow:1; | |
| } | |
| .card-footer{ | |
| display:flex; align-items:center; justify-content:space-between; | |
| padding-top:14px; border-top:1px solid var(--rule-soft); | |
| font-family:var(--mono); font-size:0.66rem; color:var(--slate); | |
| letter-spacing:0.04em; text-transform:uppercase; | |
| } | |
| .read-link{color:var(--rust); display:flex; align-items:center; gap:5px;} | |
| .read-link svg{width:11px; height:11px; transition:transform 0.25s ease;} | |
| .card:hover .read-link svg{transform:translateX(3px);} | |
| /* ---- List view ---- */ | |
| .list-view{display:none; flex-direction:column;} | |
| .list-view.active{display:flex;} | |
| .grid-view.hidden{display:none;} | |
| .list-row{ | |
| display:flex; align-items:baseline; gap:20px; | |
| padding:16px 4px; | |
| border-bottom:1px solid var(--rule-soft); | |
| cursor:pointer; | |
| transition:padding-left 0.25s ease, background 0.25s ease; | |
| } | |
| .list-row:hover{padding-left:10px; background:var(--rule-soft);} | |
| .list-row.hide{display:none;} | |
| .list-date{font-family:var(--mono); font-size:0.68rem; color:var(--slate); width:90px; flex-shrink:0;} | |
| .list-title{font-size:1.2rem; font-weight:600; flex-grow:1;} | |
| .list-badge{font-family:var(--mono); font-size:0.6rem; letter-spacing:0.08em; text-transform:uppercase; color:var(--slate); flex-shrink:0;} | |
| .empty-state{ | |
| text-align:center; padding:70px 20px; color:var(--slate); | |
| font-family:var(--mono); font-size:0.85rem; letter-spacing:0.04em; | |
| } | |
| .empty-state span{display:block; font-family:var(--serif); font-style:italic; font-size:1.3rem; color:var(--ink); margin-bottom:10px;} | |
| /* ===== Modal / Reading canvas ===== */ | |
| .overlay{ | |
| position:fixed; inset:0; z-index:100; | |
| background:rgba(28,27,26,0.35); | |
| backdrop-filter:blur(3px); | |
| opacity:0; pointer-events:none; | |
| transition:opacity 0.35s ease; | |
| } | |
| .overlay.open{opacity:1; pointer-events:auto;} | |
| .reading-canvas{ | |
| position:fixed; z-index:101; | |
| top:0; right:0; height:100%; | |
| width:min(720px, 100%); | |
| background:var(--bg); | |
| box-shadow:-30px 0 60px -20px rgba(0,0,0,0.25); | |
| transform:translateX(100%); | |
| transition:transform 0.45s cubic-bezier(.65,0,.35,1); | |
| display:flex; flex-direction:column; | |
| overflow:hidden; | |
| } | |
| .reading-canvas.open{transform:translateX(0);} | |
| .progress-track{height:2px; background:var(--rule-soft); flex-shrink:0;} | |
| .progress-fill{height:100%; width:0%; background:var(--rust); transition:width 0.1s linear;} | |
| .canvas-top{ | |
| display:flex; align-items:center; justify-content:space-between; | |
| padding:20px 40px; border-bottom:1px solid var(--rule); | |
| flex-shrink:0; | |
| } | |
| .orbit-indicator{width:34px; height:34px; flex-shrink:0;} | |
| .orbit-indicator circle.track{fill:none; stroke:var(--rule); stroke-width:1.5;} | |
| .orbit-indicator circle.body{fill:var(--rust);} | |
| .orbit-indicator circle.ellipse-path{fill:none; stroke:var(--rule); stroke-width:1;} | |
| .canvas-actions{display:flex; align-items:center; gap:10px;} | |
| .icon-btn{ | |
| background:var(--bg-raised); border:1px solid var(--rule); | |
| border-radius:8px; padding:8px 12px; | |
| display:flex; align-items:center; gap:7px; | |
| font-family:var(--mono); font-size:0.66rem; letter-spacing:0.06em; text-transform:uppercase; | |
| color:var(--ink); | |
| transition:background 0.2s ease, border-color 0.2s ease; | |
| } | |
| .icon-btn:hover{background:var(--ink); color:var(--bg); border-color:var(--ink);} | |
| .icon-btn svg{width:13px; height:13px;} | |
| .close-btn{ | |
| background:transparent; border:none; padding:6px; | |
| color:var(--ink); display:flex; | |
| } | |
| .close-btn svg{width:20px; height:20px;} | |
| .canvas-body{ | |
| flex-grow:1; overflow-y:auto; | |
| padding:48px 40px 80px 40px; | |
| } | |
| .canvas-meta{ | |
| font-family:var(--mono); font-size:0.68rem; color:var(--slate); | |
| letter-spacing:0.06em; text-transform:uppercase; | |
| display:flex; gap:16px; flex-wrap:wrap; | |
| margin-bottom:22px; | |
| } | |
| .canvas-title{ | |
| font-size:2.3rem; font-weight:600; line-height:1.15; | |
| margin:0 0 30px 0; max-width:var(--measure); | |
| } | |
| .canvas-content{ | |
| font-size:1.28rem; line-height:1.85; | |
| white-space:pre-wrap; | |
| max-width:var(--measure); | |
| color:var(--ink); | |
| } | |
| .canvas-content.poems, .canvas-content.micro-poetry{ | |
| font-style:italic; | |
| font-size:1.42rem; | |
| line-height:1.9; | |
| } | |
| ::-webkit-scrollbar{width:8px;} | |
| ::-webkit-scrollbar-thumb{background:var(--rule); border-radius:4px;} | |
| @media (max-width:640px){ | |
| .header-inner{padding:16px 18px 0 18px;} | |
| .brand{font-size:1.2rem;} | |
| main{padding:24px 18px 80px 18px;} | |
| .controls-row{flex-direction:column; align-items:stretch;} | |
| nav.filters{overflow-x:auto;} | |
| #searchInput{width:100%;} | |
| #searchInput:focus{width:100%;} | |
| .right-controls{width:100%; justify-content:space-between;} | |
| .reading-canvas{width:100%;} | |
| .canvas-top{padding:16px 20px;} | |
| .canvas-body{padding:32px 20px 60px 20px;} | |
| .canvas-title{font-size:1.7rem;} | |
| .canvas-content{font-size:1.1rem;} | |
| .canvas-content.poems, .canvas-content.micro-poetry{font-size:1.2rem;} | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <div class="header-inner"> | |
| <div class="brandrow"> | |
| <div class="brand">Altaf Hussain<span class="sep">·</span><span class="sub">Literary Works & Introspection</span></div> | |
| <div class="tagline">Verse / Prose / Enquiry</div> | |
| </div> | |
| <div class="controls-row"> | |
| <nav class="filters" id="filterNav"> | |
| <span class="filter-pill" id="filterPill"></span> | |
| <button data-filter="all" class="active">All Works</button> | |
| <button data-filter="poems">Poems</button> | |
| <button data-filter="micro-poetry">Micro-Poetry</button> | |
| <button data-filter="essays">Essays</button> | |
| </nav> | |
| <div class="right-controls"> | |
| <div class="search-wrap"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="7"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg> | |
| <input type="text" id="searchInput" placeholder="Search titles, words, lines…" autocomplete="off"> | |
| </div> | |
| <div class="view-toggle" role="group" aria-label="Layout view"> | |
| <button id="gridBtn" class="active" aria-label="Grid view"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect></svg> | |
| </button> | |
| <button id="listBtn" aria-label="List view"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="4" y1="6" x2="20" y2="6"></line><line x1="4" y1="12" x2="20" y2="12"></line><line x1="4" y1="18" x2="20" y2="18"></line></svg> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <main> | |
| <div class="count-line" id="countLine">Showing all works</div> | |
| <div class="grid-view" id="gridView"></div> | |
| <div class="list-view" id="listView"></div> | |
| <div class="empty-state" id="emptyState" style="display:none;"> | |
| <span>Nothing here yet.</span> | |
| No piece matches that search or filter. Try a different word or clear the filter. | |
| </div> | |
| </main> | |
| <div class="overlay" id="overlay"></div> | |
| <div class="reading-canvas" id="readingCanvas" role="dialog" aria-modal="true" aria-labelledby="canvasTitle"> | |
| <div class="progress-track"><div class="progress-fill" id="progressFill"></div></div> | |
| <div class="canvas-top"> | |
| <svg class="orbit-indicator" viewBox="0 0 40 40" aria-hidden="true"> | |
| <ellipse class="ellipse-path" cx="20" cy="20" rx="17" ry="9"></ellipse> | |
| <circle class="track" cx="20" cy="20" r="2"></circle> | |
| <circle class="body" id="orbitBody" cx="37" cy="20" r="3"></circle> | |
| </svg> | |
| <div class="canvas-actions"> | |
| <button class="icon-btn" id="copyBtn"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"></rect><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"></path></svg> | |
| Copy text | |
| </button> | |
| <button class="close-btn" id="closeBtn" aria-label="Close"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="canvas-body" id="canvasBody"> | |
| <div class="canvas-meta" id="canvasMeta"></div> | |
| <h1 class="canvas-title" id="canvasTitle"></h1> | |
| <div class="canvas-content" id="canvasContent"></div> | |
| </div> | |
| </div> | |
| <script> | |
| /* ========================================================= | |
| DATA | |
| To add your own writing, append objects to this array. | |
| Required fields: | |
| id - unique string, e.g. "work-7" | |
| title - string | |
| category - "poems" | "micro-poetry" | "essays" | |
| date - display string, e.g. "August 2026" | |
| readingTime - display string, e.g. "3 min read" (leave "" to auto-calculate from word count) | |
| excerpt - one or two lines shown on the card | |
| content - full text. Use \n for line breaks, \n\n for stanza/paragraph breaks. | |
| Whitespace and indentation are preserved exactly as written. | |
| ========================================================= */ | |
| const literaryArchive = [ | |
| { | |
| id: "work-1", | |
| title: "On the Geometry of Silence", | |
| category: "essays", | |
| date: "August 2026", | |
| readingTime: "", | |
| excerpt: "We often treat silence as the mere absence of sound, rather than an active spatial dimension.", | |
| content: `We often treat silence as the mere absence of sound, rather than an active spatial dimension. In examining the architecture of contemplative thought, stillness operates not as a void, but as the medium through which cognition recognizes its own boundaries. | |
| When we eliminate the ambient noise of external validation, internal structures collapse into their true equilibrium. What remains is not emptiness but resolution, the settling of a system into the state it was always tending toward, had we only stopped forcing it elsewhere.` | |
| }, | |
| { | |
| id: "work-2", | |
| title: "The Celestial Coordinate", | |
| category: "poems", | |
| date: "July 2026", | |
| readingTime: "", | |
| excerpt: "Between the aphelion of grief and the perihelion of dawn.", | |
| content: `Between the aphelion of grief | |
| and the perihelion of dawn, | |
| we trace an eccentric orbit | |
| calculating distance from what is gone. | |
| No gravity is lost to empty space; | |
| it merely bends the light | |
| until every forgotten equation | |
| finds its balance in the night.` | |
| }, | |
| { | |
| id: "work-3", | |
| title: "Fracture", | |
| category: "micro-poetry", | |
| date: "June 2026", | |
| readingTime: "", | |
| excerpt: "A single word spoken out of phase.", | |
| content: `A single word spoken out of phase | |
| can shatter an axis | |
| years in the making.` | |
| }, | |
| /* --------------------------------------------------------- | |
| PASTE YOUR FULL COLLECTION BELOW THIS LINE. | |
| Copy the object shape above, give each a unique id, | |
| and drop it in. The grid, list, filters, and search | |
| all read from this array automatically — no other | |
| code needs to change. | |
| --------------------------------------------------------- */ | |
| { | |
| id: "work-4", | |
| title: "Privilege of Silence", | |
| category: "poems", | |
| date: "2026", | |
| readingTime: "", | |
| excerpt: "What a privilege, to sit in the silence, to see the birds pass by.", | |
| content: `What a privilege | |
| To sit in the silence. | |
| To see the birds pass by | |
| To look at the sky | |
| Clouds sketching pictures high. | |
| What peace | |
| To be in quiet. | |
| Vacant thoughts, Empty hands | |
| No grudges, No wishes | |
| An uncluttered mind | |
| Denying desires | |
| That half of mankind | |
| Is eager to sign.` | |
| }, | |
| { | |
| id: "work-5", | |
| title: "The Window Across", | |
| category: "poems", | |
| date: "2026", | |
| readingTime: "", | |
| excerpt: "The fan is a sound that swirls. In my room, I can almost sleep.", | |
| content: `The fan is a sound that swirls. | |
| In my room, I can almost sleep. | |
| I sit on my bed. I am quiet. | |
| The door is maroon, | |
| left a little bit open. | |
| Through the gap, my neighbor's home. | |
| And there, the window. | |
| It is lighted. | |
| A yellow is there, | |
| coming from their room. | |
| The glass is like a skin, | |
| reflecting it back to me. | |
| They connect, the glass and the light, | |
| An imaginary relationship. | |
| The yellow says to the glass, | |
| a silent question: | |
| "Let me pass through you." | |
| And the window, the skin of glass, | |
| replies without a sound: | |
| "I shall always. | |
| After all, | |
| you are the one | |
| who makes me feel seen."` | |
| }, | |
| { | |
| id: "work-6", | |
| title: "Oh Darling", | |
| category: "poems", | |
| date: "2026", | |
| readingTime: "", | |
| excerpt: "Oh darling, how would I say how much I have loved you.", | |
| content: `Oh darling, how would I say | |
| How much I have loved you | |
| Still remember the date | |
| The madness of you | |
| When you were late. | |
| How amusing it is | |
| I remember all the things | |
| You had never notice | |
| Felt alive around you | |
| But just for a bliss | |
| I know we are apart | |
| But you will always be, | |
| In my heart.` | |
| }, | |
| { | |
| id: "work-7", | |
| title: "On Dying Into Life", | |
| category: "essays", | |
| date: "2026", | |
| readingTime: "", | |
| excerpt: "I wonder what it will feel like when I die. Is it the same as not having been born?", | |
| content: `I wonder what it will feel like when I die. Is it the same as not having been born? I worry that I will have only a few memories of the life I had. But what if nothing happens at all? This thought is really bothering me now... | |
| Isn't it a genuine concern? We talk about living, pursuing luxury, and desiring to travel all over the world, but we never wonder what it will feel like when we die. | |
| I think we're like rivers: when a river is attached to the mountains, it is the mountains. But then the mountains let it flow, roam the world to see, feel, and cherish life, and bring fertility to barren lands. It does all these things... and so do we! The river merges with the ocean and becomes vast and dense, but what do we become? | |
| We become Life in Itself! We have felt our existence so closely and consciously that we embody life itself. | |
| Just as the ocean may never know why it is vast and dense, so too will we never know what it feels like to experience life after having become Life itself, because there will be no end to life. It exists in every part of the universe.` | |
| }, | |
| { | |
| id: "work-8", | |
| title: "The Road We Are", | |
| category: "essays", | |
| date: "2026", | |
| readingTime: "", | |
| excerpt: "Life is a road, and we are all vehicles on it.", | |
| content: `Life is a road, and we are all vehicles on it. | |
| The road is the same for everyone, but the vehicles are different, unique in their design, speed, and journey. Just as accidents happen between two vehicles on the road, accidents also happen between two people in life. | |
| Some people die in road accidents, and in the accidents of life, people often die because of each other. After an accident, one driver blames the other, and both remember it for the rest of their lives as the accident. Similarly, when accidents happen in life, we remember the person involved, but only for that one incident, that one mistake which cannot be undone. Yet it can be forgiven, if only we choose to understand and communicate with kindness. | |
| Some people believe life runs on luck, others on hard work. But the truth is, luck is shaped by our actions. Everyone is working hard, the difference lies in how we face the traffic jams. Some get stuck and give up; others keep moving, no matter how slow the road becomes.` | |
| }, | |
| { | |
| id: "work-9", | |
| title: "The Fallen Leaf", | |
| category: "poems", | |
| date: "2026", | |
| readingTime: "", | |
| excerpt: "I am like that fallen leaf, I go wherever the cold winds blow.", | |
| content: `I am like that fallen leaf, I go | |
| Wherever the cold winds blow. | |
| No path is mine, no voice, no claim, | |
| Just drifting on, without a name. | |
| No one turns to look at me, | |
| I don't shine, I don't please. | |
| But still, I'd burn without a plea, | |
| Just to give you warmth, some peace. | |
| I don't know my destination, | |
| Just live beneath the tree's old charm. | |
| Rootless, weightless, without direction, | |
| Still aching to do no harm. | |
| They didn't notice me while I stayed | |
| A shadow beneath their busy day. | |
| But when I fell, they turned their eyes, | |
| As if my fall brought some sunrise. | |
| They watched me break, they heard me cry, | |
| They called it grace as I passed by. | |
| Torn apart, like waste, thrown down, | |
| Still I rose with winds unbound. | |
| The breeze became my borrowed wings, | |
| I danced alone through distant springs. | |
| I toured the world without delay, | |
| Didn't bend, didn't lose my way. | |
| And when they saw me soaring high, | |
| They screamed like crows who feared the sky. | |
| But I had left that weight below | |
| Now I go where the free winds go.` | |
| }, | |
| { | |
| id: "work-10", | |
| title: "Who I Become", | |
| category: "poems", | |
| date: "2026", | |
| readingTime: "", | |
| excerpt: "To some people, I'm intelligent. To some, I'm quiet.", | |
| content: `To some people, I'm intelligent. | |
| To some, I'm quiet. | |
| To some, I talk too much. | |
| To some, I'm kind, soft. | |
| And maybe, to some, I'm rude. | |
| Because I never talk to them. | |
| But to me... who am I? | |
| Do the eyes of people define me? | |
| Do their words, their stories, | |
| decide the shape of my soul? | |
| I guess, maybe not. | |
| Because to me, I am a watcher. | |
| An observer of everything around | |
| the sky, the silence, | |
| the beauty that hides in the smallest things. | |
| To me, I'm a poet. | |
| A man who can't sleep till midnight, | |
| because the thoughts in his mind | |
| are too heavy, too strange, | |
| too alive to let him rest. | |
| I stay awake, | |
| not because I want to, | |
| but because my mind refuses to stop dreaming. | |
| To me, I'm a catcher | |
| among people who run from questions, | |
| I stand still and face them. | |
| I dare to look, | |
| to break the mirror, | |
| to see the truth behind the blur. | |
| To me, I'm brave. | |
| Brave enough to see the reality within. | |
| Brave enough to question myself. | |
| Brave enough to stay. | |
| And maybe that's me. | |
| Not who they think I am, | |
| but who I become | |
| when no one's watching.` | |
| }, | |
| { | |
| id: "work-11", | |
| title: "Hospital Balcony", | |
| category: "poems", | |
| date: "2026", | |
| readingTime: "", | |
| excerpt: "I stand on the balcony of a hospital, watching the crowd move along the road below.", | |
| content: `I stand on the balcony of a hospital, | |
| watching the crowd move along the road below. | |
| People rush | |
| someone on a call, trying to reach a friend, | |
| someone tending a small stall by the pavement. | |
| A father urges his child to walk straight, | |
| a man leads his beloved by the hand | |
| through the restless flow of strangers. | |
| Someone waits for the traffic to clear, | |
| just to go home. | |
| The rest move on instinct | |
| some stand still, | |
| some drift nowhere. | |
| And then there's me, | |
| watching everything, | |
| noticing every small detail, | |
| thinking for no reason at all. | |
| Am I sick? | |
| Oh, yes. | |
| That's why I'm at the hospital.` | |
| }, | |
| { | |
| id: "work-12", | |
| title: "Borrowed Maturity", | |
| category: "poems", | |
| date: "2026", | |
| readingTime: "", | |
| excerpt: "I carry a burden on my back, the weight of wisdom, borrowed maturity.", | |
| content: `I carry a burden on my back, | |
| the weight of wisdom, borrowed maturity. | |
| i'm still a kid, fenced in by my vicinity, | |
| expected to endure, never falter, | |
| never ask for help. | |
| it feels uneven. | |
| i try to explain, but the words blur | |
| like a lens that's slipped out of focus. | |
| if you could adjust it, | |
| maybe you'd see what I'm trying to show. | |
| but I don't have much left to offer. | |
| this absurd life waits for meaning to pour, | |
| and I wait with it, hoping it arrives, | |
| hoping it shapes itself into something | |
| I can finally understand | |
| and maybe even adore.` | |
| }, | |
| { | |
| id: "work-13", | |
| title: "On Marriage and Readiness", | |
| category: "essays", | |
| date: "2026", | |
| readingTime: "", | |
| excerpt: "People often ask me, when will you get married? My answer is always the same.", | |
| content: `People often ask me, | |
| "When will you get married?" | |
| My answer is always the same: | |
| "When the right time comes." | |
| I believe marriage is a responsibility, | |
| and irresponsible people are not fit for marriage. | |
| When I look at many married people, I feel pity for their foolishness. | |
| Most of them never stopped to think, | |
| "Am I actually responsible enough for marriage?" | |
| "Responsible... responsible... what do I even mean by that?" | |
| Wait. I'll explain. | |
| By responsibility, I mean having clarity about yourself, | |
| understanding what is right and wrong, | |
| understanding the world, | |
| knowing when, where, what, and how things happen. | |
| It also means understanding human emotions | |
| why people behave the way they do, | |
| when they react, how they react, and for what reason. | |
| Today, people decide someone is "ready for marriage" | |
| just by looking at money, status, respect, and a house. | |
| But I believe this is completely wrong. | |
| Tell me this: | |
| Would you go to a doctor who has a degree | |
| but knows nothing about diseases or medicines? | |
| Would you study from a teacher who does not know how to teach? | |
| Your answer would be "No." | |
| Then marrying a person who is not truly capable of marriage | |
| is also wrong, isn't it?` | |
| }, | |
| ]; | |
| /* ========================================================= | |
| STATE | |
| ========================================================= */ | |
| let currentFilter = "all"; | |
| let currentQuery = ""; | |
| let currentView = "grid"; | |
| const gridView = document.getElementById("gridView"); | |
| const listView = document.getElementById("listView"); | |
| const emptyState = document.getElementById("emptyState"); | |
| const countLine = document.getElementById("countLine"); | |
| const filterNav = document.getElementById("filterNav"); | |
| const filterPill = document.getElementById("filterPill"); | |
| const searchInput = document.getElementById("searchInput"); | |
| const overlay = document.getElementById("overlay"); | |
| const readingCanvas = document.getElementById("readingCanvas"); | |
| const canvasBody = document.getElementById("canvasBody"); | |
| const progressFill = document.getElementById("progressFill"); | |
| const orbitBody = document.getElementById("orbitBody"); | |
| const CATEGORY_LABELS = { "poems": "Poem", "micro-poetry": "Micro-Poetry", "essays": "Essay" }; | |
| function wordCount(text){ | |
| return text.trim().split(/\s+/).filter(Boolean).length; | |
| } | |
| function autoReadingTime(text){ | |
| const words = wordCount(text); | |
| const mins = Math.max(1, Math.round(words / 180)); | |
| return mins + " min read"; | |
| } | |
| function getReadingTime(work){ | |
| return work.readingTime && work.readingTime.length ? work.readingTime : autoReadingTime(work.content); | |
| } | |
| /* ========================================================= | |
| RENDER: cards + list rows | |
| ========================================================= */ | |
| function matchesQuery(work, q){ | |
| if(!q) return true; | |
| const hay = (work.title + " " + work.excerpt + " " + work.content).toLowerCase(); | |
| return hay.includes(q.toLowerCase()); | |
| } | |
| function matchesFilter(work, f){ | |
| return f === "all" || work.category === f; | |
| } | |
| function renderGrid(list){ | |
| gridView.innerHTML = ""; | |
| list.forEach((work, i) => { | |
| const card = document.createElement("article"); | |
| card.className = "card"; | |
| card.tabIndex = 0; | |
| card.style.animationDelay = (i * 0.04) + "s"; | |
| card.setAttribute("role", "button"); | |
| card.setAttribute("aria-label", "Read " + work.title); | |
| card.innerHTML = ` | |
| <div class="badge-row"> | |
| <span class="badge ${work.category}">${CATEGORY_LABELS[work.category] || work.category}</span> | |
| <span class="card-date">${work.date}</span> | |
| </div> | |
| <h2 class="card-title">${work.title}</h2> | |
| <p class="card-excerpt">${work.excerpt}</p> | |
| <div class="card-footer"> | |
| <span>${getReadingTime(work)}</span> | |
| <span class="read-link">Read | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg> | |
| </span> | |
| </div> | |
| `; | |
| card.addEventListener("click", () => openWork(work)); | |
| card.addEventListener("keydown", (e) => { if(e.key === "Enter" || e.key === " "){ e.preventDefault(); openWork(work); } }); | |
| gridView.appendChild(card); | |
| }); | |
| } | |
| function renderList(list){ | |
| listView.innerHTML = ""; | |
| list.forEach((work) => { | |
| const row = document.createElement("div"); | |
| row.className = "list-row"; | |
| row.tabIndex = 0; | |
| row.setAttribute("role", "button"); | |
| row.setAttribute("aria-label", "Read " + work.title); | |
| row.innerHTML = ` | |
| <span class="list-date">${work.date}</span> | |
| <span class="list-title">${work.title}</span> | |
| <span class="list-badge">${CATEGORY_LABELS[work.category] || work.category}</span> | |
| `; | |
| row.addEventListener("click", () => openWork(work)); | |
| row.addEventListener("keydown", (e) => { if(e.key === "Enter" || e.key === " "){ e.preventDefault(); openWork(work); } }); | |
| listView.appendChild(row); | |
| }); | |
| } | |
| function applyFilters(){ | |
| const filtered = literaryArchive.filter(w => matchesFilter(w, currentFilter) && matchesQuery(w, currentQuery)); | |
| renderGrid(filtered); | |
| renderList(filtered); | |
| emptyState.style.display = filtered.length === 0 ? "block" : "none"; | |
| gridView.style.display = (currentView === "grid" && filtered.length) ? "grid" : "none"; | |
| listView.classList.toggle("active", currentView === "list" && filtered.length > 0); | |
| const total = literaryArchive.length; | |
| if(filtered.length === total){ | |
| countLine.textContent = `Showing all ${total} work${total === 1 ? "" : "s"}`; | |
| } else { | |
| countLine.textContent = `Showing ${filtered.length} of ${total} works`; | |
| } | |
| } | |
| /* ========================================================= | |
| FILTER PILL POSITIONING | |
| ========================================================= */ | |
| function movePill(btn){ | |
| filterPill.style.width = btn.offsetWidth + "px"; | |
| filterPill.style.transform = `translateX(${btn.offsetLeft - 3}px)`; | |
| } | |
| filterNav.addEventListener("click", (e) => { | |
| const btn = e.target.closest("button[data-filter]"); | |
| if(!btn) return; | |
| filterNav.querySelectorAll("button[data-filter]").forEach(b => b.classList.remove("active")); | |
| btn.classList.add("active"); | |
| movePill(btn); | |
| currentFilter = btn.dataset.filter; | |
| applyFilters(); | |
| }); | |
| /* ========================================================= | |
| SEARCH (debounced) | |
| ========================================================= */ | |
| let searchTimer = null; | |
| searchInput.addEventListener("input", (e) => { | |
| clearTimeout(searchTimer); | |
| const val = e.target.value; | |
| searchTimer = setTimeout(() => { | |
| currentQuery = val; | |
| applyFilters(); | |
| }, 220); | |
| }); | |
| /* ========================================================= | |
| VIEW TOGGLE | |
| ========================================================= */ | |
| document.getElementById("gridBtn").addEventListener("click", () => { | |
| currentView = "grid"; | |
| document.getElementById("gridBtn").classList.add("active"); | |
| document.getElementById("listBtn").classList.remove("active"); | |
| applyFilters(); | |
| }); | |
| document.getElementById("listBtn").addEventListener("click", () => { | |
| currentView = "list"; | |
| document.getElementById("listBtn").classList.add("active"); | |
| document.getElementById("gridBtn").classList.remove("active"); | |
| applyFilters(); | |
| }); | |
| /* ========================================================= | |
| READING CANVAS | |
| ========================================================= */ | |
| let lastFocusedElement = null; | |
| function openWork(work){ | |
| lastFocusedElement = document.activeElement; | |
| document.getElementById("canvasMeta").innerHTML = | |
| `<span>${work.date}</span><span>${getReadingTime(work)}</span><span>${wordCount(work.content)} words</span>`; | |
| document.getElementById("canvasTitle").textContent = work.title; | |
| const contentEl = document.getElementById("canvasContent"); | |
| contentEl.textContent = work.content; | |
| contentEl.className = "canvas-content " + work.category; | |
| overlay.classList.add("open"); | |
| readingCanvas.classList.add("open"); | |
| canvasBody.scrollTop = 0; | |
| updateProgress(); | |
| document.body.style.overflow = "hidden"; | |
| readingCanvas.focus(); | |
| } | |
| function closeWork(){ | |
| overlay.classList.remove("open"); | |
| readingCanvas.classList.remove("open"); | |
| document.body.style.overflow = ""; | |
| if(lastFocusedElement) lastFocusedElement.focus(); | |
| } | |
| document.getElementById("closeBtn").addEventListener("click", closeWork); | |
| overlay.addEventListener("click", closeWork); | |
| document.addEventListener("keydown", (e) => { | |
| if(e.key === "Escape" && readingCanvas.classList.contains("open")) closeWork(); | |
| }); | |
| function updateProgress(){ | |
| const scrollable = canvasBody.scrollHeight - canvasBody.clientHeight; | |
| const pct = scrollable > 0 ? (canvasBody.scrollTop / scrollable) * 100 : 0; | |
| progressFill.style.width = pct + "%"; | |
| const angle = (pct / 100) * Math.PI * 2 - Math.PI / 2; | |
| const rx = 17, ry = 9, cx = 20, cy = 20; | |
| const x = cx + rx * Math.cos(angle); | |
| const y = cy + ry * Math.sin(angle); | |
| orbitBody.setAttribute("cx", x.toFixed(2)); | |
| orbitBody.setAttribute("cy", y.toFixed(2)); | |
| } | |
| canvasBody.addEventListener("scroll", updateProgress); | |
| /* ========================================================= | |
| COPY TEXT | |
| ========================================================= */ | |
| document.getElementById("copyBtn").addEventListener("click", async () => { | |
| const title = document.getElementById("canvasTitle").textContent; | |
| const content = document.getElementById("canvasContent").textContent; | |
| const btn = document.getElementById("copyBtn"); | |
| const original = btn.innerHTML; | |
| try{ | |
| await navigator.clipboard.writeText(title + "\n\n" + content); | |
| btn.innerHTML = "Copied"; | |
| }catch(err){ | |
| btn.innerHTML = "Copy failed"; | |
| } | |
| setTimeout(() => { btn.innerHTML = original; }, 1600); | |
| }); | |
| /* ========================================================= | |
| INIT | |
| ========================================================= */ | |
| window.addEventListener("load", () => { | |
| movePill(filterNav.querySelector("button.active")); | |
| applyFilters(); | |
| }); | |
| window.addEventListener("resize", () => { | |
| movePill(filterNav.querySelector("button.active")); | |
| }); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment