@ifi/oh-pi-skills 0.4.4 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: devenv
3
+ description: Use devenv as the task runner and development environment when devenv.nix is present in the
4
+ project. Run scripts via `devenv test` to enter the shell, or `devenv shell <command>` when
5
+ commands aren't available outside the shell. Prefer devenv scripts over ad-hoc commands. Use when
6
+ devenv.nix exists, or when the user asks about devenv setup, scripts, processes, or Nix-based
7
+ dev environments.
8
+ ---
9
+
10
+ # devenv Skill
11
+
12
+ ## Activation
13
+
14
+ Load this skill when `devenv.nix` exists in the project root, or when the user mentions devenv,
15
+ Nix shells, or project task runners.
16
+
17
+ ## Quick start
18
+
19
+ ```bash
20
+ # Enter the development shell (sets up PATH, env, git hooks)
21
+ devenv test
22
+
23
+ # Run a one-off command inside the shell
24
+ devenv shell <command>
25
+
26
+ # Run a named script
27
+ devenv shell <script-name>
28
+ # Example: devenv shell lint:all
29
+ ```
30
+
31
+ ## Core rules
32
+
33
+ 1. **Prefer devenv scripts over raw commands.** When a `scripts` block exists in `devenv.nix`,
34
+ always use the script name instead of the underlying command.
35
+
36
+ ```bash
37
+ # ✅ Preferred
38
+ devenv shell lint:all
39
+ devenv shell test:all
40
+
41
+ # ❌ Avoid
42
+ cargo clippy --workspace --all-features -- -D warnings
43
+ pnpm test
44
+ ```
45
+
46
+ 2. **Use `devenv shell <command>` when direct commands fail.** If `pnpm`, `cargo`, or other
47
+ project tools are not on PATH, prefix with `devenv shell`:
48
+
49
+ ```bash
50
+ devenv shell pnpm install
51
+ devenv shell cargo build --workspace
52
+ ```
53
+
54
+ 3. **Use `devenv test` to enter the shell** for interactive work or to verify the environment
55
+ is correctly set up.
56
+
57
+ 4. **Check `devenv.nix` scripts before inventing commands.** Always read the `scripts` block to
58
+ find existing task names before running raw commands.
59
+
60
+ ## Common patterns
61
+
62
+ ### Running project tasks
63
+
64
+ ```bash
65
+ devenv shell build:all # Build everything
66
+ devenv shell test:all # Run all tests
67
+ devenv shell lint:all # Run all lints
68
+ devenv shell fix:all # Fix all autofixable problems
69
+ devenv shell docs:check # Check documentation
70
+ devenv shell docs:update # Update shared docs
71
+ ```
72
+
73
+ ### Managing the environment
74
+
75
+ ```bash
76
+ devenv test # Enter the shell (sets up env + hooks)
77
+ devenv update # Update flake inputs
78
+ devenv gc # Garbage collect old generations
79
+ ```
80
+
81
+ ### Running processes
82
+
83
+ ```bash
84
+ devenv up # Start all processes (postgres, redis, etc.)
85
+ devenv processes status # Check running processes
86
+ ```
87
+
88
+ ## When scripts aren't on PATH
89
+
90
+ Some devenv configurations set `enterShell` to add scripts to PATH via:
91
+
92
+ ```nix
93
+ enterShell = ''
94
+ export PATH="$DEVENV_ROOT/scripts:$PATH"
95
+ '';
96
+ ```
97
+
98
+ In those cases, scripts may be available directly inside `devenv test`. Outside the shell, always
99
+ use `devenv shell <script-name>`.
100
+
101
+ ## Script naming conventions
102
+
103
+ The user's preferred `devenv.nix` layout uses colon-separated namespaced scripts:
104
+
105
+ - `build:*` — build tasks
106
+ - `test:*` — test tasks
107
+ - `lint:*` — lint and check tasks
108
+ - `fix:*` — autofix tasks
109
+ - `install:*` — dependency installation tasks
110
+ - `update:*` — update tasks
111
+ - `docs:*` — documentation tasks
112
+ - `coverage:*` — coverage tasks
113
+ - `snapshot:*` — snapshot update/review tasks
114
+ - `setup:*` — editor/tool setup tasks
115
+ - `clean:*` — cleanup tasks
116
+ - `deny:check` — security/license checks
117
+ - `publish:check` — publication dry-run checks
118
+
119
+ ## See also
120
+
121
+ For the recommended `devenv.nix` layout, script structure, and git-hooks configuration, see
122
+ [REFERENCE.md](REFERENCE.md).
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: flutter-serverpod-mvp
3
- description:
4
- Scaffold and evolve full-stack Flutter + Serverpod MVPs using devenv, Riverpod + Hooks,
3
+ description: Scaffold and evolve full-stack Flutter + Serverpod MVPs using devenv, Riverpod + Hooks,
5
4
  strict i18n, and GoRouter shell routing patterns inspired by OpenBudget.
6
5
  ---
7
6
 
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: git-workflow
3
- description:
4
- Git workflow assistant for branching, commits, PRs, and conflict resolution. Use when user asks
3
+ description: Git workflow assistant for branching, commits, PRs, and conflict resolution. Use when user asks
5
4
  about git strategy, branch management, or PR workflow.
6
5
  ---
7
6
 
@@ -9,6 +8,83 @@ description:
9
8
 
10
9
  Help with Git operations and workflow best practices.
11
10
 
11
+ ## Core Principles
12
+
13
+ ### 1. Commit early and often
14
+
15
+ **Make small, frequent commits rather than accumulating large batches of changes.**
16
+
17
+ - Commit after every logical unit of work — even if it's just "wip: explore approach" or "wip: add failing test"
18
+ - A commit is cheap; losing work is expensive
19
+ - Small commits make reviews easier, bisection faster, and rollbacks safer
20
+ - Don't wait until everything is "perfect" — a messy commit history can be cleaned later with interactive rebase
21
+ - Prefer `git commit -m "wip: <description>"` over leaving work uncommitted for long stretches
22
+
23
+ ### 2. Use `git stash` instead of discarding
24
+
25
+ **When you need to clear or reset uncommitted work, never just delete it — stash it with an explanation.**
26
+
27
+ - Use `git stash push -m "<reason>: <description>"` to preserve work and record _why_ it was stashed
28
+ - The stash remains in Git history and can be recovered via `git stash list` or `git reflog`
29
+ - This protects against mistakes, dead ends that turn out to be useful later, or context lost during interruptions
30
+ - If you later decide the stashed work is truly worthless — only then drop it explicitly with `git stash drop <stash>`
31
+ - Explaining the stash in the message also helps future-you (or the next agent) understand what was happening
32
+
33
+ Example:
34
+
35
+ ```bash
36
+ # Bad: work is just gone
37
+ rm -rf changed-files/
38
+ git checkout -- .
39
+
40
+ # Good: work is preserved with context
41
+ git stash push -m "pivot: abandoning approach A for approach B after benchmark regression"
42
+ git stash push -m "interrupted: switching to urgent bugfix PR #123"
43
+ ```
44
+
45
+ ### 3. Use worktrees for new work
46
+
47
+ **Start new work in a fresh worktree rather than working directly on `main` or the current branch.**
48
+
49
+ - Create a worktree for every distinct task or feature: `git worktree add -b feat/description ../worktrees/feat-description`
50
+ - Keeps `main` clean and available for quick reference, hotfixes, or parallel reviews
51
+ - Eliminates risk of accidentally committing work-in-progress to the trunk
52
+ - Makes it safe to run tests, builds, and linting in isolation without polluting the main checkout
53
+ - When done, remove the worktree: `git worktree remove <path>` — the branch remains for PR/merge
54
+ - If the repo has the oh-pi worktree extension, prefer `/worktree create --purpose "..."`
55
+
56
+ ### 4. Clean up history before sharing
57
+
58
+ **Never merge or push to `origin` while `wip:` commits remain in the stack, unless the user explicitly says otherwise.**
59
+
60
+ - WIP commits are for _local_ iteration only — they are checkpoints, not publication-ready units
61
+ - Before pushing or opening a PR, restructure history so every commit is a logical, self-contained unit of work
62
+ - Each commit should tell a clear story: what changed, why it changed, and ideally be independently buildable/testable
63
+ - Squash related `wip:` commits using interactive rebase: `git rebase -i main`
64
+ - Rename `wip:` commits to proper Conventional Commit messages that describe the final intent
65
+ - If a commit cannot stand on its own (e.g. "wip: broken test"), squash it into the commit that makes it pass
66
+ - Only ever push `wip:` commits to `origin` if the user explicitly requests it (e.g. "just push what I have")
67
+
68
+ Example — cleaning up before a PR:
69
+
70
+ ```bash
71
+ # Check what's in the stack
72
+ git log --oneline main..HEAD
73
+
74
+ # If there are wip: commits, restructure
75
+ git rebase -i main
76
+ # pick feat(widget): add new rendering pipeline
77
+ # squash wip: failing test for edge case
78
+ # squash wip: fix off-by-one in renderer
79
+ # pick perf(widget): cache computed layout
80
+ # drop wip: try alternative approach (abandoned)
81
+
82
+ # Push the cleaned branch
83
+ git push origin feat/widget-rendering
84
+ ```
85
+
86
+ See also [Core Principle #1: Commit early and often](#1-commit-early-and-often) — commit freely with `wip:` during development, but clean up before sharing.
87
+
12
88
  ## Capabilities
13
89
 
14
90
  ### Branch Strategy
@@ -26,9 +102,44 @@ Recommend branching strategy based on project:
26
102
  - **Team**: main + develop + feature/fix branches
27
103
  - **Release**: GitFlow (main/develop/release/hotfix)
28
104
 
105
+ ### Worktree-aware workflow
106
+
107
+ When the repository uses git worktrees, do not assume the current checkout is the main repo root.
108
+ First establish:
109
+
110
+ ```bash
111
+ git rev-parse --show-toplevel
112
+ git rev-parse --git-common-dir
113
+ git worktree list --porcelain
114
+ ```
115
+
116
+ **Prefer worktrees for all new work.** See [Core Principle #3: Use worktrees for new work](#3-use-worktrees-for-new-work).
117
+
118
+ If the oh-pi worktree extension is available, prefer:
119
+
120
+ - `/worktree status` — show the current worktree, canonical repo root, and pi ownership metadata
121
+ - `/worktree list` — show all repo worktrees and which ones are pi-owned vs external/manual
122
+
123
+ For pi-owned worktrees:
124
+
125
+ - always record a human-readable purpose when creating one
126
+ - preserve the owner/session metadata so cleanup decisions stay explainable
127
+ - only clean up pi-owned worktrees by default
128
+ - do **not** clean external/manual worktrees unless the user explicitly asks
129
+
130
+ When finishing work in a worktree:
131
+
132
+ 1. Push the branch: `git push origin <branch>`
133
+ 2. Open a PR from the worktree branch
134
+ 3. Remove the worktree after merge: `git worktree remove <path>`
135
+
29
136
  ### Commit Messages
30
137
 
31
- Follow Conventional Commits:
138
+ Follow Conventional Commits
139
+
140
+ Small commits are better than perfect commits. See [Core Principle #1: Commit early and often](#1-commit-early-and-often).
141
+
142
+ Use these prefixes:
32
143
 
33
144
  ```
34
145
  feat(scope): add new feature
@@ -39,6 +150,22 @@ test(scope): add/update tests
39
150
  chore(scope): maintenance tasks
40
151
  ```
41
152
 
153
+ For work-in-progress commits (which are encouraged!), use `wip:` prefix or `chore(wip):`:
154
+
155
+ ```bash
156
+ git commit -am "wip: explore trie-based approach for tokenization"
157
+ git commit -am "wip: failing test for edge case in parser"
158
+ git commit -am "wip: checkpoint before attempting refactor"
159
+ ```
160
+
161
+ Clean up before opening a PR:
162
+
163
+ ```bash
164
+ git rebase -i main # squash related wip commits
165
+ ```
166
+
167
+ But **never leave work uncommitted for long** — stash or commit, don't let it sit dirty.
168
+
42
169
  ### PR Workflow
43
170
 
44
171
  1. `git diff main --stat` — Review changes
@@ -47,10 +174,10 @@ chore(scope): maintenance tasks
47
174
 
48
175
  ### PR link in summaries
49
176
 
50
- When a PR has been opened, **always include the full GitHub PR URL** in any summary or status
51
- update you provide. This makes it easy for the user to click through to the PR directly.
177
+ When a PR has been opened, **always include the full GitHub PR URL** in any summary or status update you provide. This makes it easy for the user to click through to the PR directly.
52
178
 
53
179
  Example summary format:
180
+
54
181
  ```
55
182
  PR: https://github.com/owner/repo/pull/42
56
183
  ```
@@ -61,13 +188,17 @@ Use `gh pr view --json url --jq .url` to retrieve the URL if you do not already
61
188
 
62
189
  When **the agent** runs `git` or `gh`, avoid opening an interactive editor or prompt.
63
190
 
64
- - For `git rebase --continue`, do **not** rely on `--no-edit` `git rebase --continue` does not support it.
65
- Use one of these instead:
66
- ```bash
67
- GIT_EDITOR=true git rebase --continue
68
- # or
69
- git -c core.editor=true rebase --continue
70
- ```
191
+ A lot of Git entrypoints use different editor config keys, so avoid surprises by disabling both:
192
+
193
+ - `core.editor` / `GIT_EDITOR` (commit, merge, tag message editing)
194
+ - `sequence.editor` / `GIT_SEQUENCE_EDITOR` (interactive rebase todo-list editing)
195
+
196
+ Use this pattern for non-interactive flows:
197
+
198
+ ```bash
199
+ GIT_EDITOR=true GIT_SEQUENCE_EDITOR=true git -c core.editor=true -c sequence.editor=true rebase --continue
200
+ ```
201
+
71
202
  - For commits, always pass the message on the command line:
72
203
  ```bash
73
204
  git commit -m "fix(scope): message"
@@ -76,7 +207,7 @@ When **the agent** runs `git` or `gh`, avoid opening an interactive editor or pr
76
207
  ```bash
77
208
  git merge --no-edit
78
209
  ```
79
- - For any other git command that could open an editor, set `GIT_EDITOR=true` for that invocation.
210
+ - For any other git command that could open an editor, set `GIT_EDITOR=true` and `GIT_SEQUENCE_EDITOR=true` (plus `-c core.editor=true -c sequence.editor=true`) for that invocation.
80
211
  - For GitHub CLI commands, disable terminal prompts and provide all required fields explicitly:
81
212
  ```bash
82
213
  GH_PROMPT_DISABLED=1 gh pr create --title "..." --body "..."
@@ -98,5 +229,5 @@ Guide through `git rebase -i` for cleaning up history before PR.
98
229
  If the agent is resolving conflicts during a rebase, continue with a non-interactive command such as:
99
230
 
100
231
  ```bash
101
- GIT_EDITOR=true git rebase --continue
232
+ GIT_EDITOR=true GIT_SEQUENCE_EDITOR=true git -c core.editor=true -c sequence.editor=true rebase --continue
102
233
  ```
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: glassmorphism
3
- description:
4
- Glassmorphism design system skill. Use when building frosted-glass UI components with blur,
3
+ description: Glassmorphism design system skill. Use when building frosted-glass UI components with blur,
5
4
  transparency, and layered depth effects.
6
5
  version: 1.0.0
7
6
  tags: [design, css, ui, glassmorphism]
@@ -26,12 +25,12 @@ Use CSS custom properties from `tokens.css` for consistent theming:
26
25
  @import "references/tokens.css";
27
26
 
28
27
  .glass-card {
29
- background: var(--glass-bg);
30
- backdrop-filter: var(--glass-blur);
31
- -webkit-backdrop-filter: var(--glass-blur);
32
- border: var(--glass-border);
33
- border-radius: var(--glass-radius);
34
- box-shadow: var(--glass-shadow);
28
+ background: var(--glass-bg);
29
+ backdrop-filter: var(--glass-blur);
30
+ -webkit-backdrop-filter: var(--glass-blur);
31
+ border: var(--glass-border);
32
+ border-radius: var(--glass-radius);
33
+ box-shadow: var(--glass-shadow);
35
34
  }
36
35
  ```
37
36
 
@@ -41,13 +40,13 @@ Use CSS custom properties from `tokens.css` for consistent theming:
41
40
 
42
41
  ```css
43
42
  .glass-card {
44
- background: var(--glass-bg);
45
- backdrop-filter: var(--glass-blur);
46
- -webkit-backdrop-filter: var(--glass-blur);
47
- border: var(--glass-border);
48
- border-radius: var(--glass-radius);
49
- box-shadow: var(--glass-shadow);
50
- padding: 1.5rem;
43
+ background: var(--glass-bg);
44
+ backdrop-filter: var(--glass-blur);
45
+ -webkit-backdrop-filter: var(--glass-blur);
46
+ border: var(--glass-border);
47
+ border-radius: var(--glass-radius);
48
+ box-shadow: var(--glass-shadow);
49
+ padding: 1.5rem;
51
50
  }
52
51
  ```
53
52
 
@@ -55,14 +54,14 @@ Use CSS custom properties from `tokens.css` for consistent theming:
55
54
 
56
55
  ```css
57
56
  .glass-nav {
58
- background: var(--glass-bg-heavy);
59
- backdrop-filter: var(--glass-blur-strong);
60
- -webkit-backdrop-filter: var(--glass-blur-strong);
61
- border-bottom: var(--glass-border);
62
- box-shadow: var(--glass-shadow);
63
- position: sticky;
64
- top: 0;
65
- z-index: 100;
57
+ background: var(--glass-bg-heavy);
58
+ backdrop-filter: var(--glass-blur-strong);
59
+ -webkit-backdrop-filter: var(--glass-blur-strong);
60
+ border-bottom: var(--glass-border);
61
+ box-shadow: var(--glass-shadow);
62
+ position: sticky;
63
+ top: 0;
64
+ z-index: 100;
66
65
  }
67
66
  ```
68
67
 
@@ -70,16 +69,16 @@ Use CSS custom properties from `tokens.css` for consistent theming:
70
69
 
71
70
  ```css
72
71
  .glass-modal-backdrop {
73
- background: rgba(0, 0, 0, 0.4);
74
- backdrop-filter: blur(4px);
72
+ background: rgba(0, 0, 0, 0.4);
73
+ backdrop-filter: blur(4px);
75
74
  }
76
75
  .glass-modal {
77
- background: var(--glass-bg-heavy);
78
- backdrop-filter: var(--glass-blur-strong);
79
- -webkit-backdrop-filter: var(--glass-blur-strong);
80
- border: var(--glass-border);
81
- border-radius: var(--glass-radius-lg);
82
- box-shadow: var(--glass-shadow-elevated);
76
+ background: var(--glass-bg-heavy);
77
+ backdrop-filter: var(--glass-blur-strong);
78
+ -webkit-backdrop-filter: var(--glass-blur-strong);
79
+ border: var(--glass-border);
80
+ border-radius: var(--glass-radius-lg);
81
+ box-shadow: var(--glass-shadow-elevated);
83
82
  }
84
83
  ```
85
84
 
@@ -87,15 +86,15 @@ Use CSS custom properties from `tokens.css` for consistent theming:
87
86
 
88
87
  ```css
89
88
  .glass-btn {
90
- background: var(--glass-bg-light);
91
- backdrop-filter: var(--glass-blur-light);
92
- -webkit-backdrop-filter: var(--glass-blur-light);
93
- border: var(--glass-border);
94
- border-radius: var(--glass-radius);
95
- transition: background 0.2s;
89
+ background: var(--glass-bg-light);
90
+ backdrop-filter: var(--glass-blur-light);
91
+ -webkit-backdrop-filter: var(--glass-blur-light);
92
+ border: var(--glass-border);
93
+ border-radius: var(--glass-radius);
94
+ transition: background 0.2s;
96
95
  }
97
96
  .glass-btn:hover {
98
- background: var(--glass-bg);
97
+ background: var(--glass-bg);
99
98
  }
100
99
  ```
101
100
 
@@ -112,13 +111,13 @@ Use CSS custom properties from `tokens.css` for consistent theming:
112
111
 
113
112
  ```css
114
113
  .glass-card {
115
- background: rgba(255, 255, 255, 0.85); /* fallback */
114
+ background: rgba(255, 255, 255, 0.85); /* fallback */
116
115
  }
117
116
  @supports (backdrop-filter: blur(1px)) {
118
- .glass-card {
119
- background: var(--glass-bg);
120
- backdrop-filter: var(--glass-blur);
121
- }
117
+ .glass-card {
118
+ background: var(--glass-bg);
119
+ backdrop-filter: var(--glass-blur);
120
+ }
122
121
  }
123
122
  ```
124
123
 
@@ -133,15 +132,15 @@ Use CSS custom properties from `tokens.css` for consistent theming:
133
132
 
134
133
  ```css
135
134
  @media (prefers-reduced-transparency: reduce) {
136
- .glass-card {
137
- background: rgba(255, 255, 255, 0.92);
138
- backdrop-filter: none;
139
- }
135
+ .glass-card {
136
+ background: rgba(255, 255, 255, 0.92);
137
+ backdrop-filter: none;
138
+ }
140
139
  }
141
140
  @media (prefers-contrast: more) {
142
- .glass-card {
143
- background: rgba(255, 255, 255, 0.85);
144
- border: 1px solid rgba(0, 0, 0, 0.3);
145
- }
141
+ .glass-card {
142
+ background: rgba(255, 255, 255, 0.85);
143
+ border: 1px solid rgba(0, 0, 0, 0.3);
144
+ }
146
145
  }
147
146
  ```
@@ -1,32 +1,32 @@
1
1
  :root {
2
- /* Backgrounds */
3
- --glass-bg-light: rgba(255, 255, 255, 0.08);
4
- --glass-bg: rgba(255, 255, 255, 0.15);
5
- --glass-bg-heavy: rgba(255, 255, 255, 0.25);
2
+ /* Backgrounds */
3
+ --glass-bg-light: rgba(255, 255, 255, 0.08);
4
+ --glass-bg: rgba(255, 255, 255, 0.15);
5
+ --glass-bg-heavy: rgba(255, 255, 255, 0.25);
6
6
 
7
- /* Blur */
8
- --glass-blur-light: blur(8px);
9
- --glass-blur: blur(16px);
10
- --glass-blur-strong: blur(32px);
7
+ /* Blur */
8
+ --glass-blur-light: blur(8px);
9
+ --glass-blur: blur(16px);
10
+ --glass-blur-strong: blur(32px);
11
11
 
12
- /* Border */
13
- --glass-border: 1px solid rgba(255, 255, 255, 0.18);
12
+ /* Border */
13
+ --glass-border: 1px solid rgba(255, 255, 255, 0.18);
14
14
 
15
- /* Radius */
16
- --glass-radius: 12px;
17
- --glass-radius-lg: 20px;
15
+ /* Radius */
16
+ --glass-radius: 12px;
17
+ --glass-radius-lg: 20px;
18
18
 
19
- /* Shadow */
20
- --glass-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
21
- --glass-shadow-elevated: 0 8px 40px rgba(0, 0, 0, 0.15);
19
+ /* Shadow */
20
+ --glass-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
21
+ --glass-shadow-elevated: 0 8px 40px rgba(0, 0, 0, 0.15);
22
22
  }
23
23
 
24
24
  /* Dark theme overrides */
25
25
  [data-theme="dark"] {
26
- --glass-bg-light: rgba(255, 255, 255, 0.04);
27
- --glass-bg: rgba(255, 255, 255, 0.08);
28
- --glass-bg-heavy: rgba(255, 255, 255, 0.14);
29
- --glass-border: 1px solid rgba(255, 255, 255, 0.12);
30
- --glass-shadow: 0 4px 30px rgba(0, 0, 0, 0.3);
31
- --glass-shadow-elevated: 0 8px 40px rgba(0, 0, 0, 0.4);
26
+ --glass-bg-light: rgba(255, 255, 255, 0.04);
27
+ --glass-bg: rgba(255, 255, 255, 0.08);
28
+ --glass-bg-heavy: rgba(255, 255, 255, 0.14);
29
+ --glass-border: 1px solid rgba(255, 255, 255, 0.12);
30
+ --glass-shadow: 0 4px 30px rgba(0, 0, 0, 0.3);
31
+ --glass-shadow-elevated: 0 8px 40px rgba(0, 0, 0, 0.4);
32
32
  }