Uname:Linux server17213-10344.hostycare.online 5.14.0-687.38.1.el9_8.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Aug 12 17:19:12 EDT 2026 x86_64

403WebShell
403Webshell
Server IP : 103.243.232.44  /  Your IP : 216.73.216.237
Web Server : LiteSpeed
System : Linux server17213-10344.hostycare.online 5.14.0-687.38.1.el9_8.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Aug 12 17:19:12 EDT 2026 x86_64
User : iamakash ( 1400)
PHP Version : 8.1.34
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/iamakash/kautuki.co.in/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/iamakash/kautuki.co.in/AGENTS.md
# Kautuki marketing site — agent guide

## What this is

The **marketing website** for Kautuki (kautuki.co.in) — a live tutoring marketplace for Class 6–12
students in Tier 2–4 India. This repo is **not** the product: there is no booking, no auth, no class
player here. The only working feature is an early-access lead form.

The site is **pre-launch**. `partials/head.php` sets `<meta name="robots" content="noindex">` on every
PHP page, and the footer's registered-office address is still a visible `[TODO]` placeholder. Product
claims on these pages describe the intended launch product — treat them as copy to keep internally
consistent, not as a spec of what ships today.

## Stack — deliberately zero-build

Flat PHP on shared cPanel hosting. **No npm, no framework, no bundler, no preprocessor, no
dependencies of any kind.** PHP is used only for `include`-ing shared partials and for one lead
endpoint; there is no database, no composer, no router.

Do not introduce a build step, a package manager, a CSS framework, or a JS library. If a task seems to
need one, say so and ask before adding it.

```
index.php  classes.php  subjects.php  selfstudy.php  safety.php     <- the 15 "exam paper" pages
teach.php  schools.php  about.php     contact.php    gallery.php
faq.php    privacy.php  terms.php     refund.php     404.php
partials/head.php  form.php  foot.php                               <- included by all 15
assets/exam.css  exam.js                                            <- the ONLY live CSS/JS
assets/app.css   app.js                                             <- DEAD: no page uses these now
api/lead.php  api/mail.php  api/config.example.php                 <- the only endpoint + its SMTP sender
logo/  gallery/                                                     <- brand assets, photos, posters
index-old.html  v2/                                                 <- abandoned; excluded from deploy
```

### Page anatomy

Every content page is three lines of PHP wrapping plain HTML:

```php
<?php $PAGE = 'classes'; $TITLE = 'Classes & fees — Kautuki'; $DESC = '…'; include 'partials/head.php'; ?>
  <section class="q body-cell" id="classes"> … </section>
<?php include 'partials/form.php'; include 'partials/foot.php'; ?>
```

- `$PAGE` must be one of `home classes subjects selfstudy safety teach schools about gallery faq
  contact privacy terms refund` (and `''` on `404.php`) — it drives the nav's active state via the
  `on()` / `on_any()` helpers in `head.php`. The three legal pages are footer-only by design: they set
  `$PAGE` but have no nav entry, so nothing highlights. Don't "fix" that by adding them to the menu.
  `on()` emits a whole ` class="on"` attribute, so it only works on a link that has **no** `class` of
  its own. On a link that already carries one, use `on_any()` *inside* the attribute —
  `class="foo<?php on_any(array('about')); ?>"` — or you silently emit a duplicate `class` that the
  browser discards.
- `$TITLE` and `$DESC` are escaped with `htmlspecialchars` in the head, so write them as plain text
  with real `&` and `—`, not entities.
- **Adding a page** means: create `newpage.php`; add `$PAGE` to the list in `head.php`'s comment; add
  nav links in `head.php` — both the desktop `.menu`/`.drop` entry *and* an entry in the `.drawer`,
  since the phone menu is a separate off-canvas card; add a footer link in `foot.php`; add a `<url>` to `sitemap.xml`
  using the extensionless form (`/newpage`, per the `.htaccess` rewrite) — but check first that no
  directory of that name exists, or the pretty URL resolves to the directory instead of the page (this
  is exactly what has gone wrong with `/gallery`).

### CSS and JS

`assets/exam.css` (~940 lines) and `assets/exam.js` (~250 lines) are hand-authored and cover all eleven
pages. Both are plain, commented and organised by section — read the neighbouring block before adding
to either.

- All colour, spacing and layout constants live in `:root` at the top of `exam.css`. Use the tokens
  (`--ink`, `--paper`, `--red`, `--amber`, `--m`, `--gutter`, `--bleed-l/r`), never raw hex.
- Fluid type and spacing via `clamp()`. **No fixed pixel widths, no media-query-only layouts** — the
  site is mobile-first. Four breakpoint values, in two places. The main block sits together around
  line 645: `960px` (grids halve), `720px` (the phone layout: the red margin rule is dropped and
  `.marginal` Q-numbers become inline stamps), `620px` (the comparison table restacks, two-column
  indexes go to one) and `520px` (grids go to one column, and the `nowrap` escapes live here).
  A **second `720px` block at the very end** belongs to the multi-page nav — that is where the whole
  `.idx` row is hidden and the off-canvas `.drawer` takes over (a `520px` block follows it, trimming
  the header CTA so logo + CTA + burger fit one 320px row). Put nav rules there, page rules in the
  main block;
  and note `prefers-reduced-motion` has its own block around line 918.
- **There are two kinds of grid here, and they are responsive in different ways.**
  - *Fixed column counts*, which need a breakpoint for every step: `.trust-row` and `.arc` are
    `repeat(4, 1fr)`, `.kit` is `repeat(3, 1fr)`, `.gal` is `repeat(3, 1fr)`, `.circular` is
    `repeat(2, 1fr)`. All six are covered in the media queries — keep it that way if you add one.
  - *Self-responsive `auto-fit` grids*: `.formats`, `.fees`, `.syllabus`, `.board-grid`, `.pages`,
    `.stories`. Every one is written `repeat(auto-fit, minmax(min(NNNpx, 100%), 1fr))` and the
    **`min(NNNpx, 100%)` is not decoration** — a bare `minmax(280px, 1fr)` overflows the screen below
    280px. Copy the whole pattern or don't use it.
- Match your item count to the columns, or add a modifier. Four `.kit` cards strand one on its own row,
  which is what `.kit.four` exists for: it steps 4 → 2 → 1 and deliberately never 3. Prefer explicit
  counts over `auto-fit` when an orphan matters — `auto-fit` settles on whatever happens to fit, which
  can be the orphaning number. And note a modifier like `.kit.four` out-specifies the plain `.kit`
  rules inside the media queries, so it needs its own entry in each one.
- `.ticks` is a horizontal wrapping row, meant for short chips. Whole-sentence items need the stacked
  variant — `.fees .ticks` and `.abt-ticks .ticks` set `flex-direction: column` and make each `li` a
  flex row, so wrapped text hangs beside the tick instead of running back underneath it.
- A long unbreakable token (an email address) will overflow a narrow card, because there is nowhere to
  break it. Give it `overflow-wrap: anywhere` — see `.fmt .mail`.
- **`white-space: nowrap` needs an escape at 520px.** It is used deliberately — to keep `.marks` on the
  heading's line, a `.gate .tag` unbroken, a `.books .ext` domain intact — but a nowrap run cannot
  break, so on a 320px screen it just overruns. `.marks` gets `white-space: normal` and `.books a`
  gets `flex-wrap: wrap` in the 520px block for exactly this reason. Check any new nowrap the same way:
  longest string × font-size × ~0.53 against roughly 284px of content width at 320px.
- **`body` has `overflow-x: hidden`.** It stops the page scrolling sideways, but it does that by
  *hiding* overflow rather than preventing it — an element that runs off the edge is silently clipped
  instead of showing a scrollbar. Do not read "no horizontal scrollbar" as "the layout fits".
- **Working out how wide something actually is:** `.paper` is `max-width: 1160px`, centred — so the
  container stops growing there even though `--m` and `--gutter` keep scaling with `vw`. `.body-cell`
  is `padding-left: var(--m) + var(--gutter)` but `padding-right: clamp(16px, 4vw, 48px)` — the two
  sides are *not* symmetric. Above 1160px a `vw`-scaled font therefore keeps growing while its column
  does not, which is how a figure that fitted at 1000px overflowed at 1440px. Content width is
  `min(vw, 1160) − (m + gutter) − clamp(16,4vw,48)`, and below 720px simply `vw − 36`.
- **Banners.** The home hero and the six page banners (`classes`, `subjects`, `selfstudy`, `teach`,
  `schools`, `gallery`) are the *same* component — copy the markup from `index.php` rather than
  inventing a variant. A slide is: a `<div>` holding `h1`/`h2` + `.sub` + `.go`, then a sibling
  `.art`. Two things carry the theme and are easy to leave out —
  - **`.hl`** on part of the headline: the amber highlighter that sweeps 0 → 100% as the slide
    activates. It is the most recognisable move on the site. `.dim` (amber text) is a quieter partner,
    not a substitute.
  - **`.art`**: a line drawing on a 340×240 canvas in the palette (`#0F2557` strokes, `#C93B2E`
    accents, `#F5A623` fills, `#F6EFE2`, white) — or a photo from `gallery/`. Page banners open with a
    photo and use SVGs for the abstract slides.

  A banner that skips these reads as off-theme even when the geometry is right — that is exactly how
  a hand-made `.fig` card variant went wrong and had to be thrown away.
- `.band` is the quiet closing banner on the legal pages (`#help` anchor): a bordered panel with a
  heading, a line of copy and one `.stamp`. It lifts on hover and is registered `rv-t`. Service, not
  sales — the legal pages carry no lead form on purpose.
- **Check a new class name against the existing ones before you take it.** `.plain` was already the
  site's secondary-link style (`.q-cta .plain`, `.slide .go .plain`); a legal-page component briefly
  reused the name and put a red rule down the side of every secondary link on every page. It is
  `.gloss` now. `grep` the class in `exam.css` first.
- **Long-form documents** (privacy, terms, refund) use `.toc` + `.legal` / `.clause` / `.gloss`, not
  the marketing components. The legal text is never collapsed — burying terms a user is agreeing to
  behind an accordion is the wrong call, and it hurts Ctrl+F. What folds is the `.gloss` "in plain
  English" gloss beside each clause. These pages also skip the wry `.marks` asides: `[10 clauses]`
  is fine, `[3 marks — no partial credit]` is not, on a page someone is agreeing to.
- Legal wording is load-bearing. When restyling one of those pages, change only the chrome around the
  text — then diff the rendered prose against the old file sentence by sentence before deleting it.
- The nav dropdown sits 8px below its button, and that gap is bridged by an invisible
  `.idx .drop::after` strip. Without it the pointer crosses dead space on the way down, `:hover` goes
  false and the panel shuts before you reach it. The strip belongs to `.drop`, so hovering it still
  counts as hovering inside `.menu`. Don't delete it as an empty rule — and if you change the 8px
  offset, change the strip to match.
- **The phone menu is a separate component, not a reflow of the desktop one.** Below 720px `.idx-wrap`
  is hidden outright and `.burger` (in `.hdr-top`) opens `.drawer` — an index card that slides in from
  the right, carrying its own red margin rule, Caveat group labels, the same stamp links and one
  `.stamp` CTA. Open/shut is a single `nav-open` class on `<html>`: the CSS slides the card, fades
  `.nav-scrim` and locks page scroll. The card is hidden with `visibility`, not `display`, so it stays
  out of the tab order while shut and can still animate. A new page needs a link in **both** the
  desktop `.menu`/`.drop` and the `.drawer`.
- `exam.js` is nine small IIFEs: scroll reveals, sticky-header measurement, dropdown menus, the phone
  drawer, progress rule, role pre-select, form POST, gallery lightbox, banner sliders. ES5-ish, no
  build, no polyfills.
  The slider IIFE drives **every `.slider` on the page**, not just the home hero — each gets its own
  index, its own hold flag and its own 5s timer. Add a `.slider` containing a `.slides` track and a
  `.dots` box and it wires itself up; no IDs are involved.
- **New animated blocks must be registered** in the `groups` array at the top of `exam.js`, or they
  never reveal on scroll. Use `'rv'` normally, `'rv-t'` for anything that carries its own tilt or
  hover-lift transform, `'rv-m'` for red-margin annotations.
- Everything must degrade without JS: the `.js` class is added by the script and all reveal styles are
  scoped under it, so a no-JS visitor gets a fully readable page.

`assets/app.css` / `app.js` are the **legacy v1 design system** (Plus Jakarta Sans / Inter, blue
`#0F3F7A`). **No live page uses them any more** — the last five (`contact`, `privacy`, `terms`,
`refund`, `404`) were rebuilt on the exam-paper system and their `.html` files deleted. The two files
are kept only because `index-old.html` still references them. Don't build anything new on them.

When converting an `.html` page to `.php`, the rebuild and the delete have to happen together:
`.htaccess` resolves `.html` before `.php`, so a leftover `foo.html` silently shadows the new
`foo.php`. The pretty URLs (`/privacy`, `/contact`) did not change, but every explicit `foo.html`
link did — grep for the old filename across `*.php`, `*.xml` and `.htaccess`.

**Asset paths in the partials are absolute** (`/assets/exam.css`, `/logo/…`, and `form.php` posts to
`/api/lead.php`). That is required, not stylistic: `404.php` is served for *any* URL, so relative
paths would resolve against `/deep/path/` and the error page would render unstyled. Keep them
absolute — the site is served from the domain root.

`gallery/` holds seven AI-generated photographs — `photo-class`, `photo-doubt`, `photo-whiteboard`,
`photo-verify`, `poster-video`, `school-hall`, `teach-notice` — and `gallery/PROMPTS.md` records the
house style and the exact prompt behind each. That file also specifies four slots that were planned
and **never produced**: `hero-1/2/3.jpg` and `photo-teacher.jpg`. If a page needs an image that isn't
in the seven, generate it from the documented prompt rather than inventing a new style, and keep the
`PROMPTS.md` table in step. `PROMPTS.md` is excluded from deploy.

`index-old.html` (the original single-page v1) and `v2/` (an abandoned "cinematic" alternative) are
dead explorations kept for reference. **Never update them alongside a live page.**

## The design idiom — an exam paper

This is the strongest constraint in the repo. The whole site is staged as a school exam answer paper: a
cream sheet lying on a desk, one continuous red margin rule running the full height of the page,
sections numbered like questions, and red-pen annotations in a handwriting face.

New content has to arrive **as a question on that paper**:

```html
<section class="q body-cell" id="verify">
  <span class="marginal" style="top:clamp(56px,7vw,100px)">Q1.</span>   <!-- red-margin annotation -->
  <div class="q-head">
    <h2>The verification story.</h2>
    <span class="marks">[3 marks — no partial credit]</span>            <!-- always bracketed, wry -->
  </div>
  <p class="q-kicker">One or two sentences setting up the section.</p>
  …
</section>
```

- `.body-cell` goes on every top-level section — it supplies the left padding that clears the margin
  rule. A section without it sits under the red line.
- Three type faces, each with one job: **Fraunces** (headings), **Hanken Grotesk** (body), **Caveat**
  (`.redpen` / `.script` — the teacher's red pen: ✓ ticks, ✎ notes, the "Kautuki:" labels, "rough work"
  headings). Never mix these roles.
- Recurring furniture: `.stamp` (the rubber-stamp CTA button), `.ticks` (red-pen checklists), `.rough`
  (a "rough work" table showing worked rupee arithmetic), `.marks` (the bracketed aside), and
  "— end of paper —" above the footer.
- Use HTML entities the way the existing markup does: `&mdash; &ndash; &rsquo; &ldquo; &rdquo;
  &#8377; &#10003; &rarr;`. Files are **UTF-8 with CRLF line endings** — preserve both when editing.

## Voice and copy rules

The copy is deliberately anti-edtech, and this matters more here than any technical convention.

- **Never** write "AI-powered", "revolutionary", "world-class", "unlock your potential", countdown
  urgency, fake scarcity, or testimonials and statistics that aren't real.
- Write for a parent in a Tier-2 town deciding whether to spend ₹300. Concrete over abstract: rupee
  figures, "the night before a test", "the auto fare, twice a day, six days a week".
- Show the arithmetic. Every fee or earnings claim appears as a visible `.rough` table, footnoted as
  illustrative, with "rates are set by each teacher and shown on their profile before you book".
- Keep the five load-bearing promises consistent wherever they appear (`index.php#why`, `classes.php`,
  `faq.php`, the `classes.php#compare` table): first class ₹0 · pay per class, no package · teachers
  hand-verified by a person · 1:1 or batches of ≤12 · a free self-study library between classes.
  Changing a number in one place means grepping for it in the others.
- The comparison table argues against "the usual model" generically and says so in a footnote.
  **Do not name a competitor** anywhere on the site.

## Running it locally

Needs PHP on PATH — the pages use `include`, so opening a `.php` file from disk will not work.

```sh
php -S localhost:8000        # then http://localhost:8000/
php -l api/lead.php          # the lint CI runs
```

`.htaccess` rewrites only apply under Apache, so on `php -S` use the full `classes.php` form rather
than the extensionless `/classes`.

Under a local Apache (WampServer on Windows) point the vhost `DocumentRoot` at the repo and the
rewrites work, so the extensionless URLs can be tested too — worth doing, since a new page's pretty
URL can collide with a real directory. Two stock-WampServer defaults bite there and are worth knowing
before you debug the wrong thing:

- **`mod_expires` is off**, so the `.htaccess` caching rules do nothing at all — including the one that
  tells browsers never to cache HTML. The browser then caches by heuristic and you edit a page and keep
  seeing the old one. Fix it on the dev vhost with `Header always set Cache-Control "no-store"` rather
  than enabling `mod_expires`, which would also switch on the 7-day CSS/JS caching and hide your edits.
- **`mod_access_compat` is off**, which makes `Deny from all` in `leads/.htaccess` an unparseable
  directive, so `/leads/*` returns 500 rather than 403. Nothing leaks either way, but enable the module
  locally if you want to check that guard behaves.

## Deploy and data handling

`main` → GitHub Actions (`.github/workflows/deploy.yml`) → FTPS sync to Hostycare cPanel. The `check`
job lints `api/lead.php` and **fails the build if any lead CSV was committed**. `index-old.html`,
`gallery/PROMPTS.md` and `leads/` are excluded from the upload.

`api/lead.php` validates the form (Indian mobile regex, a honeypot field named `company`, an explicit
consent flag), appends to `leads/leads.csv` and emails the team. The email goes through Google
Workspace SMTP (`api/mail.php`, a dependency-free client) when `api/config.php` exists on the server;
that file holds an App Password, is gitignored, excluded from the deploy sync and web-blocked by
`api/.htaccess`, and is created by hand from `api/config.example.php` via cPanel File Manager. Without
it the script falls back to PHP `mail()`, which fails SPF/DKIM and lands in junk. SMTP failures are
appended to `leads/mail.log` (never the password). That CSV holds names and phone numbers of real
people:

- `leads/*.csv` and `leads/*.log` are gitignored, blocked by `leads/.htaccess`, and 403'd by a
  `RedirectMatch` in the root `.htaccess`. **Never commit one, never paste its contents anywhere,
  never weaken any of those three guards.**
- The privacy copy commits to the DPDP Act 2023 and data residency in Mumbai. Don't add a third-party
  script, pixel, font host or analytics tag without asking — today the only external requests are to
  Google Fonts.

## Before launch (open items)

1. Remove `<meta name="robots" content="noindex">` from `partials/head.php`.
2. Fill the `[Registered office address — add before launch]` placeholder. It now appears in **two**
   places: `partials/foot.php` and `contact.php` (Q3).
3. ~~Rebuild the legacy-design pages on the exam-paper system.~~ **Done** — all five (`contact`,
   `privacy`, `terms`, `refund`, `404`) are converted. `assets/app.css` / `app.js` are now dead
   weight, kept only for `index-old.html`; they can go whenever that file does.

Known bugs, none of them fixed:

4. **`/gallery` never reaches `gallery.php`.** The extensionless URL collides with the real `gallery/`
   photo directory, and `mod_dir` redirects to `/gallery/` before the `.htaccess` rewrite gets a look.
   The nav links straight to `gallery.php` so visitors are fine, but `sitemap.xml` lists `/gallery` and
   so points crawlers at a directory. Either rename the folder or use `/gallery.php` in the sitemap.
5. ~~The phone nav never highlights the current page.~~ **Fixed** — the `.mob` duplicate links that
   carried the duplicate-`class` bug are gone; below 720px the nav is the `.drawer`, whose links have
   no `class` of their own and so take `on()` correctly.

Youez - 2016 - github.com/yon3zu
LinuXploit