|
1 | 1 | # Tiger Studio Manager — Claude reference |
2 | 2 |
|
| 3 | +## ⚡ Token efficiency — read this first |
| 4 | + |
| 5 | +Every file read and grep costs tokens. Follow these rules on every task to keep context lean: |
| 6 | + |
| 7 | +| Do | Don't | |
| 8 | +|----|-------| |
| 9 | +| Read `CODEMAP.md` → jump to the exact line range | Read `inventory.js` from the top | |
| 10 | +| `grep -n "anchorFn"` → read only that range (`offset`/`limit`) | Read an entire 1000-line file to find one function | |
| 11 | +| Re-use content already in context this session | Re-read a file you read 2 messages ago | |
| 12 | +| `Read` with `offset`+`limit` to fetch the exact slice | `Read` without limits on files > 200 lines | |
| 13 | +| `Edit` with the minimal `old_string` that is unique | Rewrite whole sections when only 3 lines change | |
| 14 | +| Run `grep` + `Read` in parallel when targets are independent | Sequential read-then-grep round-trips | |
| 15 | +| Check `CODEMAP.md` line ranges before any `inventory.js` read | Blind grep across the 15 000-line file | |
| 16 | + |
| 17 | +**Workflow for any `inventory.js` change:** |
| 18 | +1. `CODEMAP.md` → find section + anchor function name |
| 19 | +2. `grep -n "anchorFn"` → get exact line number |
| 20 | +3. `Read offset=N limit=40` → confirm context, draft edit |
| 21 | +4. `Edit` minimal diff |
| 22 | + |
| 23 | +**Workflow for any CSS change:** |
| 24 | +1. Identify the right file from the file map (00-base → 70-detail-misc) |
| 25 | +2. `grep -n "selector"` in that file → get line |
| 26 | +3. `Read offset=N limit=20` → confirm, then `Edit` |
| 27 | + |
| 28 | +> Warn the user when context is getting large (> ~60 k tokens used) so they can start a new session before quality degrades. |
| 29 | +
|
| 30 | +**Model fit — signal proactively, don't wait to be asked:** |
| 31 | +- **Tâche simple** (CSS tweak, i18n key, valeur à changer, question courte) → suggérer de passer sur **claude-haiku** ou **claude-sonnet** pour économiser. Formulation : *"Cette tâche est simple — tu peux la faire sur Sonnet/Haiku pour économiser des tokens."* |
| 32 | +- **Tâche complexe** (refacto multi-fichiers, nouveau système, débogage multi-couches, architecture) → si tu sens que le raisonnement manque de profondeur ou que tu te trompes, demander de passer sur **claude-opus**. Formulation : *"Cette tâche est complexe — passer sur Opus donnera un meilleur résultat."* |
| 33 | +- Ne pas attendre que l'utilisateur remarque un problème : signaler dès que le mismatch est évident. |
| 34 | + |
3 | 35 | ## Stack |
4 | 36 | Electron (no bundler) + vanilla HTML/CSS/JS. Entry: `main.js`. Renderer: `renderer/inventory.html` + modular CSS in `renderer/css/` + `renderer/inventory.js`. Preload bridge: `preload.js`. |
5 | 37 |
|
@@ -525,3 +557,36 @@ Source: `scripts/check-i18n-consistency.mjs` + `.githooks/pre-commit`. |
525 | 557 | - **CSS**: split across `renderer/css/00-base.css … 70-detail-misc.css` (loaded in numeric order). Add new rules in the section file that matches the feature — e.g. Snapmaker tweaks go in `50-snapmaker.css`, modal tweaks in `60-modals.css`. Asset URLs use `url('../../assets/svg/icons/…')` (two `..` because we're in `renderer/css/`). Scoped IDs (`#editAccountModalOverlay`, `#addAccountModalOverlay`, etc.) still apply where needed. |
526 | 558 | - **displayName**: always read from Firestore `users/{uid}.displayName` (pseudo). Never use Firebase Auth `user.displayName` for UI display — it contains the Google real name. |
527 | 559 | - **Admin fields**: `roles` and `Debug` in `users/{uid}` must only be written via Firebase Admin SDK / Cloud Function. The client toggle is a UX convenience for admins already authenticated. |
| 560 | +
|
| 561 | +## CSS coding standards |
| 562 | +
|
| 563 | +### SVG icons via `-webkit-mask-image` |
| 564 | +Always constrain **one dimension only** and derive the other from the SVG's intrinsic `viewBox` ratio using `aspect-ratio`. Never hard-code both `width` and `height` — doing so silently distorts the icon if the SVG is ever edited. |
| 565 | +
|
| 566 | +```css |
| 567 | +/* ✅ correct — only height forced, width auto-derived */ |
| 568 | +.my-icon { |
| 569 | + height: 18px; |
| 570 | + aspect-ratio: 52 / 22; /* viewBox="0 0 52 22" */ |
| 571 | + background-color: var(--muted); |
| 572 | + -webkit-mask-image: url('../../assets/svg/icons/icon_foo.svg'); |
| 573 | + -webkit-mask-size: contain; |
| 574 | + -webkit-mask-repeat: no-repeat; |
| 575 | + -webkit-mask-position: center; |
| 576 | +} |
| 577 | +
|
| 578 | +/* ❌ wrong — both dimensions hard-coded, ratio broken if SVG changes */ |
| 579 | +.my-icon { width: 40px; height: 18px; … } |
| 580 | +``` |
| 581 | +
|
| 582 | +To find the ratio: `head -1 assets/svg/icons/icon_foo.svg` → read `viewBox="0 0 W H"` → use `aspect-ratio: W / H`. |
| 583 | +
|
| 584 | +### CSS specificity |
| 585 | +When a global rule (e.g. `input[type="text"]` — specificity 0,1,1) overrides a class rule (0,1,0), **double the class selector** to reach 0,2,0 rather than adding `!important`: |
| 586 | +```css |
| 587 | +/* beats input[type="text"] without !important */ |
| 588 | +.my-sheet .my-input { background: transparent; } |
| 589 | +``` |
| 590 | +
|
| 591 | +### Hold-to-confirm buttons |
| 592 | +Use `setupHoldToConfirm(el, durationMs, callback)`. The element must contain a `<span class="hold-progress"></span>` child. Duration guideline: 1200 ms for reversible actions, 1500 ms for hard-destructive (delete/unlink). |
0 commit comments