# Dr. E. Maruthi Prasad, Ph.D. — portfolio website

A static, build-free portfolio and publication library for **Dr. E. Maruthi Prasad**,
clinical biochemist and biomedical researcher (Department of Clinical Chemistry,
Apollo Diagnostics Global Reference Laboratory, Hyderabad).

Everything on the site is either verified against a public record or explicitly
labelled as unverified and awaiting the owner's confirmation. Nothing has been
invented: no fabricated publications, DOIs, metrics, awards or collaborations.

---

## 1. Run it

There is no build step, no package manager and no server-side code.

**Open directly**

```
index.html
```

The site works from `file://`, because all scripts are classic `<script>` tags
(not ES modules) and all data is loaded from local files.

**Or serve it locally** (recommended — `file://` blocks a few browser APIs and
makes relative requests behave differently)

```powershell
# from this folder
py -m http.server 8124 --bind 0.0.0.0
# then open http://localhost:8124/
```

Any static host works for deployment (GitHub Pages, Netlify, Cloudflare Pages,
S3 + CloudFront, nginx). Upload the folder as-is; there is nothing to compile.

---

## 2. File map

| Path | What it is |
| --- | --- |
| `index.html` | The whole page: header, hero, about, experience, research explorer, featured publication, publications library, laboratory expertise, impact, contact, footer. Also the SVG icon sprite, all metadata and the JSON-LD block. |
| `assets/css/styles.css` | Complete design system: colour tokens, light/dark themes, typography scale, components, responsive breakpoints, reduced-motion and print styles. |
| `assets/js/config.js` | **Owner-editable config**: canonical origin, person details, contact routing, public profiles, bibliometric snapshots. |
| `assets/js/data/publications.js` | The publication library (one object per paper) plus the theme list and the "pending owner review" list. |
| `assets/js/data/research.js` | The eight research domains, each with an integrity `status` label. |
| `assets/js/app.js` | All behaviour: theme toggle, sticky header, mobile menu, research explorer, publication search/filter/sort, metrics, contact form, reveal-on-scroll, origin rewrite. |
| `assets/img/portrait.svg` | Placeholder portrait (see `OWNER-REVIEW.md` — replace with a real photograph). |
| `assets/img/favicon.svg` | Favicon / apple-touch icon. |
| `assets/img/og-image.png` | Social sharing card, exactly 1200×630 px. |
| `site.webmanifest` | Web app manifest (name, colours, icon). |
| `robots.txt`, `sitemap.xml` | Crawler directives. Both contain the placeholder origin. |
| `tools/og-card.html` | The source markup of the social card. Kept for future regeneration. |
| `README.md`, `OWNER-REVIEW.md` | This file, and the owner checklist. |

---

## 3. Design system

- **Palette** — Midnight Navy `#102238`, Scientific White `#FFFFFF`, Soft Platinum
  `#F3F5F7`, Deep Teal `#167C80`, Muted Gold `#B89A61`.
- **Type** — Manrope (UI/body) and Newsreader (editorial serif headings), loaded
  from Google Fonts with `preconnect`. System font fallbacks are declared, so the
  page is fully readable if the CDN is unreachable.
- **Layout** — mobile-first, fluid `clamp()` scales, generous whitespace, hairline
  borders, restrained motion.
- **Themes** — light and dark. The choice is stored in `localStorage` and applied
  before first paint to avoid a flash.
- **Accessibility** — semantic landmarks, a single `h1`, no skipped heading levels,
  labelled form fields, visible focus rings, `prefers-reduced-motion` support,
  print stylesheet, and a skip link.

Any text colour used on a light surface resolves through a contrast-checked token
(`--gold-ink`, `--text-faint`, `--teal-300`) so the palette stays readable.

---

## 4. Editing content

### Add or change a publication

Open `assets/js/data/publications.js` and copy an existing object to the **top** of
`SITE_DATA.publications` (the list is newest-first). Minimum useful fields:

```js
{
  id: "unique-url-safe-id",
  title: "…",
  authors: ["E. Maruthi Prasad", "…"],
  role: "First author",              // or "Co-author", "Corresponding author"…
  journal: "…",
  publisher: "…",
  year: 2025,
  volume: "12", issue: "3", pages: "1–10",
  doi: "10.xxxx/yyyy",               // or null if no DOI is registered
  doiUrl: "https://doi.org/10.xxxx/yyyy",
  publisherUrl: "https://…",         // optional
  searchUrl: "https://scholar.google.com/scholar?q=…",  // optional fallback
  openAccess: true,
  themes: ["clinical-biochemistry"], // ids from SITE_DATA.themes
  summary: "Your own plain-language summary (not copied from the abstract).",
  abstractExcerpt: "“Short verbatim excerpt…”",          // optional, attributed
  verified: "How this record was verified, and against what."
}
```

Optional extras the renderer understands:

- `linkNote` — a small note under the links, e.g. when a publisher page is broken.
- `featured: true` — highlights the entry (used by the featured 2024 paper).

Then save. The library, the filter counts and the search index rebuild themselves;
no other file needs editing.

### Add or change a research domain

Edit `assets/js/data/research.js`. Keep the `status` field honest:

- `published` — backed by at least one paper listed in the library;
- `mixed` — some parts published, some from professional practice;
- `interest` — a stated interest with no indexed publication.

Never set `published` without adding a real citation id to that domain's `pubs`.

### Owner details, contact routing and metrics

Everything of that kind lives in `assets/js/config.js` (see `OWNER-REVIEW.md`).

---

## 5. Contact form behaviour

The form never fakes delivery. In order:

1. **Client-side validation** — inline errors per field, `aria-invalid` set, and an
   error summary that receives focus.
2. **Spam protection** — a hidden honeypot field, a minimum completion time of
   2.5 s, and a 60-second `localStorage` throttle.
3. **Delivery**, in this order of preference:
   - `contact.formEndpoint` set → the message is `POST`ed there (JSON) and a real
     success or failure state is shown;
   - else `contact.email` set → the visitor's own mail client is opened with the
     message pre-filled (the site states clearly that nothing is transmitted until
     they press send);
   - else → an honest "contact routing is not configured yet" message that tells the
     visitor nothing was sent or stored and offers the profile links instead.

**The site is not "finished" for a visitor until one of the two config values is
set.** See `OWNER-REVIEW.md`.

---

## 6. Search engine / social metadata

- `link[rel=canonical]`, Open Graph and Twitter card tags, plus `Person`,
  `ScholarlyArticle` and `WebSite` JSON-LD.
- All of these currently point at the **placeholder origin**
  `https://dr-maruthi-prasad.example` (a reserved, non-resolving TLD, so it can
  never accidentally point at a third party).
- Set `SITE_CONFIG.origin` in `assets/js/config.js` to the real domain and the page
  rewrites the canonical URL, the `og:*` / `twitter:*` images and every JSON-LD URL
  at runtime. Also update `robots.txt` and `sitemap.xml`, which contain the origin
  as literal text.

---

## 7. QA status (last pass)

- **Lighthouse** — Accessibility **100**, Best Practices **100**, SEO **100**, with
  zero reported failures.
- **axe-core** (light and dark themes, all reveal-animated sections forced visible)
  — zero violations.
- **Contrast** — every text node measured programmatically against its effective
  background in both themes: no failures.
- **Structure** — one `h1`, no skipped heading levels, every image has `alt`, every
  form control has a label, no duplicate `id`s, no unresolved in-page anchors.
- **Responsive** — checked at 1440 / 834 / 390 px: no horizontal page overflow. The
  research tab strip scrolls horizontally by design inside its own container.
- **Interactions** — research tabs (incl. keyboard arrows + hash sync), theme
  toggle (persisted), mobile menu (Escape closes, closes on link click, scroll
  lock, label updates), publication search (140 ms debounce), filter chips, sort,
  and every contact-form branch.
- **Console** — no warnings or errors.
- **Links** — every external link was crawled. 403/999 responses are bot blocking
  (MDPI, ScienceDirect, ResearchGate, LinkedIn) and work in a normal browser. One
  publisher page returns 404 (the 2015 docking paper); the DOI is kept as the
  scholarly identifier, a Google Scholar fallback is offered, and the card carries a
  visible note explaining it.

---

## 8. Before you publish

Work through `OWNER-REVIEW.md`. At minimum: set the real origin, set the contact
routing, replace the portrait, and confirm the items flagged **confirm** on the page.
