# رصد · Rasad — product-studio website (Nuxt 3 + Vue 3 + Tailwind + Three.js + GSAP) ```bash npm install npm run dev # http://localhost:3000 npm run generate # static, SEO-complete build in .output/public ``` ## Concept The whole site is one engraved **astrolabe** (اسطرلاب), the Persian precision instrument, operated by scrolling. The plate is projected for Tehran (35.7°N). Its rete (عنکبوت) carries **15 star pointers = 15 products** in 4 constellations. Signature moments 1. **Engraving** – on load the instrument draws itself line by line (hero). 2. **The rete** – `#products` pins for 15 steps; each step turns the rete clockwise so the next star (waiting on the left, RTL "next") lands under the lapis rule. Swipe, arrow keys, the progress rule and the star labels all navigate. 3. **Anatomy** – the instrument tilts and separates into its four physical layers: shared infra / data model / products / team. ## Architecture | Path | Role | |---|---| | `lib/astrolabe.js` | Framework-agnostic Three.js scene. Damped targets (`set({cx, cy, size, tilt, explode, focus, active…})`), line draw-on, label projection, low-power mode (half density, DPR cap), reduced-motion (no spin, instant), pauses when tab hidden. | | `lib/story.js` | The camera path: scroll position + section metrics → scene target. One continuous interpolation, no section-by-section cuts. Separate desktop/mobile compositions of the *same* states. | | `components/AstrolabeStage.client.vue` | Client-only canvas. GSAP ticker drives frames; ScrollTrigger measures sections and refreshes on resize/fonts. | | `components/*Section.vue`, `ZijTable.vue` | Server-rendered content. Every product is real HTML in the Zij table + JSON-LD `ItemList` of `SoftwareApplication`. | | `data/products.js` | Single content source (15 products, 4 families, Persian digit helpers). | ## RTL notes - `` from `nuxt.config`, never mirrored after the fact. - Only logical utilities (`ms-/me-/ps-/pe-/start-/end-`, `text-start`). The physical `left` on star labels is intentional: they are placed in canvas pixel space. - Latin (product names, URLs, code, phone) is isolated with ``; numbers use Persian digits in Persian copy. - No letter-spacing on Persian (breaks joins). Directional motion is RTL-semantic: next enters from the left, ArrowLeft = next, rightward swipe = next. Content (company, figures, contact) is placeholder.