@sebastienrousseau/dotfiles 0.2.508 → 0.2.510
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.
- package/CHANGELOG.md +30 -0
- package/README.md +5 -5
- package/docs/COPYRIGHT +1 -1
- package/docs/GOVERNANCE.md +2 -2
- package/docs/adr/ADR-011-nushell-tier3-keep.md +2 -2
- package/docs/guides/INSTALL.md +3 -3
- package/docs/index.md +116 -27
- package/docs/interop/A2A.md +2 -2
- package/docs/interop/POWERSHELL.md +4 -4
- package/docs/manual/00-introduction.md +3 -3
- package/docs/manual/01-concepts/02-trust-model.md +3 -3
- package/docs/manual/01-concepts/04-fleet.md +1 -1
- package/docs/manual/02-tutorials/01-first-install.md +1 -1
- package/docs/manual/02-tutorials/05-deploy-fleet.md +2 -2
- package/docs/manual/03-reference/02-config-files.md +1 -1
- package/docs/manual/03-reference/04-templates.md +1 -1
- package/docs/manual/04-cookbook/01-recipes.md +1 -1
- package/docs/manual/04-cookbook/02-troubleshooting.md +1 -1
- package/docs/manual/05-appendices/B-security-checklist.md +1 -1
- package/docs/manual/command-index.md +76 -1
- package/docs/manual/index.md +1 -1
- package/docs/operations/ARCHITECTURE_ROADMAP.md +145 -0
- package/docs/operations/CI_CADENCE.md +2 -2
- package/docs/operations/COMPLETIONS.md +2 -2
- package/docs/operations/COVERAGE.md +4 -4
- package/docs/operations/DRIFT.md +1 -1
- package/docs/operations/MAINTENANCE.md +6 -6
- package/docs/operations/PERFORMANCE.md +6 -6
- package/docs/operations/RELIABILITY.md +1 -1
- package/docs/operations/ROADMAP_V0_2_503.md +1 -1
- package/docs/operations/TRACEABILITY.md +2 -0
- package/docs/operations/TRUSTED_AGENT_WORKSTATION.md +6 -6
- package/docs/operations/VERSION_SYNC.md +3 -3
- package/docs/reference/UTILS.md +82 -0
- package/docs/security/AUDIT_BYPASS.md +3 -3
- package/docs/security/AUTOMATION_SECRETS.md +1 -1
- package/docs/security/CI_PINNING.md +10 -10
- package/docs/security/COMMIT_SIGNING.md +10 -10
- package/docs/security/DEPS_DEV_EXCEPTIONS.md +4 -4
- package/docs/security/DISCLOSURE.md +3 -3
- package/docs/security/INCIDENT_RESPONSE.md +1 -1
- package/docs/security/INSTALL_VERIFICATION.md +2 -2
- package/docs/security/MCP_POLICY.md +4 -4
- package/docs/security/SCORECARD.md +7 -7
- package/docs/security/SECURITY_CHECKLIST.md +1 -1
- package/docs/security/SHELL_EXEMPTIONS.md +2 -2
- package/docs/security/SOUP_REGISTER.md +4 -4
- package/docs/stylesheets/extra.css +444 -0
- package/docs/themes/hero-shot.svg +1 -1
- package/install.sh +17 -6
- package/package.json +1 -1
- package/scripts/ci/check-copyright-headers.sh +1 -1
- package/scripts/ci/check-shell-preamble.sh +1 -1
- package/scripts/ci/guard-gitleaks-checkout.sh +1 -1
- package/scripts/dot/commands/agent.sh +7 -6
- package/scripts/dot/commands/ai.sh +8 -5
- package/scripts/dot/commands/appearance.sh +14 -1
- package/scripts/dot/commands/completion.sh +134 -0
- package/scripts/dot/commands/core.sh +8 -0
- package/scripts/dot/commands/diagnostics.sh +16 -0
- package/scripts/dot/commands/fleet.sh +7 -3
- package/scripts/dot/commands/lint.sh +55 -30
- package/scripts/dot/commands/secrets.sh +61 -7
- package/scripts/dot/commands/security.sh +8 -0
- package/scripts/dot/powershell/Dot.psm1 +1 -1
- package/scripts/git-hooks/pre-commit-audit.sh +1 -1
- package/scripts/ops/heal-tools.sh +28 -0
- package/scripts/ops/teleport.sh +2 -2
- package/scripts/qa/examples-coverage.sh +94 -0
- package/scripts/version-sync.sh +29 -2
- package/docs/_config.yml +0 -59
|
@@ -7,7 +7,7 @@ render_with_liquid: false
|
|
|
7
7
|
The CI workflow `.github/workflows/deps-dev-validation.yml` scans
|
|
8
8
|
direct dependencies (npm + PyPI + GitHub Actions) against the
|
|
9
9
|
[deps.dev Insights API](https://docs.deps.dev/) on every PR, every
|
|
10
|
-
push to `
|
|
10
|
+
push to `main`, and every Tuesday at 04:00 UTC. When an advisory
|
|
11
11
|
is reported at or above the threshold (default `HIGH`), the workflow
|
|
12
12
|
fails.
|
|
13
13
|
|
|
@@ -79,8 +79,8 @@ auto-fail the gate even when they're still listed here.
|
|
|
79
79
|
|
|
80
80
|
## References
|
|
81
81
|
|
|
82
|
-
- [`tools/ci/check-deps-dev.sh`](
|
|
83
|
-
- [`.github/workflows/deps-dev-validation.yml`](
|
|
84
|
-
- [`tests/unit/security/test_check_deps_dev.sh`](
|
|
82
|
+
- [`tools/ci/check-deps-dev.sh`](https://github.com/sebastienrousseau/dotfiles/blob/main/tools/ci/check-deps-dev.sh) — the scanner.
|
|
83
|
+
- [`.github/workflows/deps-dev-validation.yml`](https://github.com/sebastienrousseau/dotfiles/blob/main/.github/workflows/deps-dev-validation.yml) — CI wiring.
|
|
84
|
+
- [`tests/unit/security/test_check_deps_dev.sh`](https://github.com/sebastienrousseau/dotfiles/blob/main/tests/unit/security/test_check_deps_dev.sh) — contract test against canned fixtures.
|
|
85
85
|
- [deps.dev API reference](https://docs.deps.dev/api/v3/).
|
|
86
86
|
- Issue [#877](https://github.com/sebastienrousseau/dotfiles/issues/877).
|
|
@@ -34,7 +34,7 @@ gpg --fingerprint security@sebastienrousseau.com
|
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
The fingerprint must match the one published in
|
|
37
|
-
[`.github/SECURITY.md`](
|
|
37
|
+
[`.github/SECURITY.md`](https://github.com/sebastienrousseau/dotfiles/blob/main/.github/SECURITY.md). Cross-verify
|
|
38
38
|
against the SSH signing key in `dot_config/git/allowed_signers.tmpl`
|
|
39
39
|
— the maintainer signs commits with the same identity, so both
|
|
40
40
|
fingerprints derive from the same identity claim.
|
|
@@ -75,7 +75,7 @@ subjects in plain text).
|
|
|
75
75
|
## 5. Acknowledgement
|
|
76
76
|
|
|
77
77
|
You should receive an acknowledgement within the SLA in
|
|
78
|
-
[`.github/SECURITY.md`](
|
|
78
|
+
[`.github/SECURITY.md`](https://github.com/sebastienrousseau/dotfiles/blob/main/.github/SECURITY.md):
|
|
79
79
|
|
|
80
80
|
| Severity | Initial response |
|
|
81
81
|
|---|---|
|
|
@@ -122,7 +122,7 @@ The maintainer commits to:
|
|
|
122
122
|
|
|
123
123
|
## See also
|
|
124
124
|
|
|
125
|
-
- [`.github/SECURITY.md`](
|
|
125
|
+
- [`.github/SECURITY.md`](https://github.com/sebastienrousseau/dotfiles/blob/main/.github/SECURITY.md) — policy
|
|
126
126
|
overview + fingerprint.
|
|
127
127
|
- [`docs/security/KEY_ROTATION.md`](KEY_ROTATION.md) — schedule for
|
|
128
128
|
when the disclosure key is rotated.
|
|
@@ -113,7 +113,7 @@ lock-configs
|
|
|
113
113
|
gh workflow disable <workflow-name>
|
|
114
114
|
|
|
115
115
|
# Force-protect the main branch
|
|
116
|
-
gh api repos/{owner}/{repo}/branches/
|
|
116
|
+
gh api repos/{owner}/{repo}/branches/main/protection \
|
|
117
117
|
--method PUT \
|
|
118
118
|
--field required_status_checks='{"strict":true,"contexts":["ci"]}' \
|
|
119
119
|
--field enforce_admins=true
|
|
@@ -56,7 +56,7 @@ These are weaker than a SHA256 check, but they catch the obvious
|
|
|
56
56
|
After chezmoi is installed, `install.sh` clones the dotfiles repo
|
|
57
57
|
itself. This isn't currently cryptographically verified beyond Git's
|
|
58
58
|
own object integrity, but commits in the repo are SSH-signed and
|
|
59
|
-
branch protection on `
|
|
59
|
+
branch protection on `main` requires signed commits (see #853).
|
|
60
60
|
|
|
61
61
|
## How to obtain per-release hashes
|
|
62
62
|
|
|
@@ -64,7 +64,7 @@ The verified-install snippet uses the SHA256 of the `install.sh`
|
|
|
64
64
|
file *as it exists at the release tag*. To regenerate after a release:
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
|
-
git switch
|
|
67
|
+
git switch main
|
|
68
68
|
git pull
|
|
69
69
|
NEW_TAG="v0.2.502" # adjust
|
|
70
70
|
git tag -s "$NEW_TAG" -m "..."
|
|
@@ -21,9 +21,9 @@ Properties:
|
|
|
21
21
|
|
|
22
22
|
## Policy artifact
|
|
23
23
|
|
|
24
|
-
The source of truth lives in [mcp-policy.json](
|
|
25
|
-
Approved package pins live in [mcp-lock.json](
|
|
26
|
-
Tracked server registry entries live in [mcp-registry.json](
|
|
24
|
+
The source of truth lives in [mcp-policy.json](https://github.com/sebastienrousseau/dotfiles/blob/main/defaults/dot_config/dotfiles/mcp-policy.json).
|
|
25
|
+
Approved package pins live in [mcp-lock.json](https://github.com/sebastienrousseau/dotfiles/blob/main/defaults/dot_config/dotfiles/mcp-lock.json).
|
|
26
|
+
Tracked server registry entries live in [mcp-registry.json](https://github.com/sebastienrousseau/dotfiles/blob/main/defaults/dot_config/dotfiles/mcp-registry.json).
|
|
27
27
|
|
|
28
28
|
Current defaults:
|
|
29
29
|
|
|
@@ -75,4 +75,4 @@ Current approved refs:
|
|
|
75
75
|
- active servers match the tracked registry entries
|
|
76
76
|
- remote HTTP transports are HTTPS and OAuth-backed
|
|
77
77
|
|
|
78
|
-
Policy bundle baselines live in [policy-bundles.json](
|
|
78
|
+
Policy bundle baselines live in [policy-bundles.json](https://github.com/sebastienrousseau/dotfiles/blob/main/defaults/dot_config/dotfiles/policy-bundles.json).
|
|
@@ -41,7 +41,7 @@ Aggregate score **7.6 / 10** at 2026-05-17T08:11:51Z.
|
|
|
41
41
|
[](https://scorecard.dev/viewer/?uri=github.com/sebastienrousseau/dotfiles)
|
|
42
42
|
|
|
43
43
|
The badge above is regenerated every Monday at 06:00 UTC and on every
|
|
44
|
-
push to `
|
|
44
|
+
push to `main` by `.github/workflows/scorecard.yml`. The SARIF
|
|
45
45
|
result is uploaded to GitHub Code Scanning (Security tab) and
|
|
46
46
|
retained as a 30-day workflow artifact.
|
|
47
47
|
|
|
@@ -57,7 +57,7 @@ Regressions are triaged within one Monday cycle: identify the check
|
|
|
57
57
|
that dropped, either remediate or file an exception entry below with
|
|
58
58
|
a rationale and an expiry date.
|
|
59
59
|
|
|
60
|
-
## Per-check posture (snapshot,
|
|
60
|
+
## Per-check posture (snapshot, main HEAD)
|
|
61
61
|
|
|
62
62
|
The checks below come from OpenSSF Scorecard's published rubric. Tick
|
|
63
63
|
marks reflect this repo's posture at the time of writing — the
|
|
@@ -65,19 +65,19 @@ marks reflect this repo's posture at the time of writing — the
|
|
|
65
65
|
|
|
66
66
|
| Check | Status | Notes |
|
|
67
67
|
|---|---|---|
|
|
68
|
-
| Branch-Protection | ⚠ | `
|
|
68
|
+
| Branch-Protection | ⚠ | `main` requires signed commits, linear history, required checks (`.github/rulesets/main.json`). Scorecard can't read classic protection rules without a fine-grained PAT, so this check reports as `-1` ("internal error"). |
|
|
69
69
|
| Code-Review | ⚠ | Single-maintainer repo; PRs are self-merged after CI. Scorecard scores 0/30 here by design — see `Open findings` below. |
|
|
70
70
|
| Signed-Commits | ✓ | Enforced by pre-push hook (`scripts/git-hooks/pre-push`) and at-push by branch protection (#853 + #857). |
|
|
71
71
|
| Dependency-Update-Tool | ✓ | Dependabot configured for github-actions / npm / docker / devcontainers / uv. |
|
|
72
72
|
| Fuzzing | ⚠ | `install.sh` fuzz harness lives under `tests/fuzz/` (closes #881), but it's shell-based and Scorecard's heuristic only recognizes OSS-Fuzz / ClusterFuzzLite / native Go fuzz / libFuzzer / Atheris. None support shell. Property tests under `tests/unit/functions/test_property_*.sh` cover the closest equivalent surface. |
|
|
73
73
|
| License | ✓ | MIT at repo root (`LICENSE`). |
|
|
74
|
-
| Maintained | ✓ | Active commit cadence; the [README](
|
|
74
|
+
| Maintained | ✓ | Active commit cadence; the [README](https://github.com/sebastienrousseau/dotfiles/blob/main/README.md) lists the current `dotfiles_version`. |
|
|
75
75
|
| Pinned-Dependencies | ⚠ | Closed 8 of 14 findings this cycle (every Dockerfile base + every workflow action + 2 `curl \| sh` installers + the `npm install -g npm` upgrade step). 5 residual findings stay open by design — see `Open findings`. |
|
|
76
76
|
| SAST | ✓ | CodeQL (`.github/workflows/codeql.yml`) + Checkov + Grype. |
|
|
77
77
|
| SBOM | ✓ | Generated per PR by `sbom-diff.yml` and per release by `security-release.yml`. |
|
|
78
78
|
| Security-Policy | ✓ | `.github/SECURITY.md` + this page + `docs/security/THREAT_MODEL.md`. |
|
|
79
79
|
| Token-Permissions | ✓ | Top-level `permissions:` blocks restricted to `contents: read`. `write` scopes scoped to the jobs that need them (#886). |
|
|
80
|
-
| Vulnerabilities | ✓ | Grype gate hard-fails on `high` / `critical` on `
|
|
80
|
+
| Vulnerabilities | ✓ | Grype gate hard-fails on `high` / `critical` on `main` (#852). |
|
|
81
81
|
| Webhooks | n/a | No external webhooks configured. |
|
|
82
82
|
| CI-Tests | ✓ | Linux + macOS Intel + Apple Silicon matrix; optional Windows. |
|
|
83
83
|
| CII-Best-Practices | ☐ | Not applied yet — see `Open work` below. |
|
|
@@ -138,7 +138,7 @@ false positives in Scorecard's regex.
|
|
|
138
138
|
- **Re-trigger Scorecard after SLSA backfill propagates** — expected `Signed-Releases` 3 → 10.
|
|
139
139
|
- **`harden-runner` block-mode adoption (#878)** — should tighten the `Token-Permissions` check further.
|
|
140
140
|
- **Investigate `License` 9/10 false-positive** — repo is MIT (SPDX-compliant), Scorecard's penalty should not apply.
|
|
141
|
-
- **Investigate `Branch-Protection` `-1`** — scanner internal error; manually verify with `gh api repos/:owner/:repo/branches/
|
|
141
|
+
- **Investigate `Branch-Protection` `-1`** — scanner internal error; manually verify with `gh api repos/:owner/:repo/branches/main/protection` and document.
|
|
142
142
|
|
|
143
143
|
### Enabling Branch-Protection + Webhooks checks (one-time PAT setup)
|
|
144
144
|
|
|
@@ -180,7 +180,7 @@ gh api 'repos/sebastienrousseau/dotfiles/code-scanning/alerts?state=open&per_pag
|
|
|
180
180
|
--jq '[.[].rule.id] | group_by(.) | map({rule: .[0], count: length})'
|
|
181
181
|
|
|
182
182
|
# Trigger Scorecard manually:
|
|
183
|
-
gh workflow run scorecard.yml --ref
|
|
183
|
+
gh workflow run scorecard.yml --ref main
|
|
184
184
|
```
|
|
185
185
|
|
|
186
186
|
If a new category appears, add a row to the matching bucket. If a
|
|
@@ -45,7 +45,7 @@ Run `dot mcp --strict --json` to validate all MCP server configurations and capt
|
|
|
45
45
|
- [ ] **SBOM Generation**: Verify `dotfiles-sbom.spdx.json` is generated in release workflow.
|
|
46
46
|
- [ ] **Attestation Signing**: Confirm `actions/attest-build-provenance` signs the release artifacts.
|
|
47
47
|
- [ ] **Attestation Verification**: Verify with `gh attestation verify <artifact> --repo sebastienrousseau/dotfiles`.
|
|
48
|
-
- [ ] **Branch Protection**: Ensure `security-attestation` is a required status check on
|
|
48
|
+
- [ ] **Branch Protection**: Ensure `security-attestation` is a required status check on main.
|
|
49
49
|
- [ ] **Automation Keying**: Confirm `ACTIONS_BOT_SIGNING_KEY` exists and matches the signer in `dot_config/git/allowed_signers`.
|
|
50
50
|
|
|
51
51
|
## 7. Final Verification
|
|
@@ -7,10 +7,10 @@ render_with_liquid: false
|
|
|
7
7
|
Every bash script in this repo must include `set -euo pipefail` (or
|
|
8
8
|
`set -eu` for POSIX `sh`) within its first 50 lines. The rule is
|
|
9
9
|
enforced by
|
|
10
|
-
[`tools/ci/check-shell-preamble.sh`](
|
|
10
|
+
[`tools/ci/check-shell-preamble.sh`](https://github.com/sebastienrousseau/dotfiles/blob/main/tools/ci/check-shell-preamble.sh),
|
|
11
11
|
wired into `pre-commit` and the `reusable-shell-lint.yml` CI job.
|
|
12
12
|
Tests pin the contract under
|
|
13
|
-
[`tests/unit/security/test_shell_preamble_lint.sh`](
|
|
13
|
+
[`tests/unit/security/test_shell_preamble_lint.sh`](https://github.com/sebastienrousseau/dotfiles/blob/main/tests/unit/security/test_shell_preamble_lint.sh).
|
|
14
14
|
|
|
15
15
|
## Why the preamble is mandatory
|
|
16
16
|
|
|
@@ -12,13 +12,13 @@ Controlled inventory for software of unknown pedigree used by the dotfiles platf
|
|
|
12
12
|
|
|
13
13
|
| Component | Source | Version control | Verification path | Owner | Status |
|
|
14
14
|
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
15
|
-
| Homebrew installer | `raw.githubusercontent.com/Homebrew/install` | Moving upstream script, gated by `HOMEBREW_INSTALLER_SHA256` | SHA-256 in [package_managers.sh](
|
|
15
|
+
| Homebrew installer | `raw.githubusercontent.com/Homebrew/install` | Moving upstream script, gated by `HOMEBREW_INSTALLER_SHA256` | SHA-256 in [package_managers.sh](https://github.com/sebastienrousseau/dotfiles/blob/main/install/lib/package_managers.sh) | Repo maintainer | Conditional |
|
|
16
16
|
| Chezmoi installer | `get.chezmoi.io` | Pinned by `CHEZMOI_INSTALLER_SHA256` when used | SHA-256 in `install/lib/chezmoi.sh` | Repo maintainer | Controlled |
|
|
17
17
|
| GitHub Actions marketplace actions | GitHub Marketplace | Full commit SHA pinning | Workflow `uses:` pins | Repo maintainer | Controlled |
|
|
18
|
-
| Grype container | `anchore/grype` | Pinned tag in workflow | Container tag in [security-enhanced.yml](
|
|
19
|
-
| Trivy container | `aquasec/trivy` | Pinned tag in workflow | Container tag in [security-enhanced.yml](
|
|
18
|
+
| Grype container | `anchore/grype` | Pinned tag in workflow | Container tag in [security-enhanced.yml](https://github.com/sebastienrousseau/dotfiles/blob/main/.github/workflows/security-enhanced.yml) | Repo maintainer | Controlled |
|
|
19
|
+
| Trivy container | `aquasec/trivy` | Pinned tag in workflow | Container tag in [security-enhanced.yml](https://github.com/sebastienrousseau/dotfiles/blob/main/.github/workflows/security-enhanced.yml) | Repo maintainer | Controlled |
|
|
20
20
|
| Checkov action | GitHub Marketplace | Full commit SHA pinning | Workflow `uses:` pin | Repo maintainer | Controlled |
|
|
21
|
-
| Nix inputs | GitHub flakes | Locked in [flake.lock](
|
|
21
|
+
| Nix inputs | GitHub flakes | Locked in [flake.lock](https://github.com/sebastienrousseau/dotfiles/blob/main/flake.lock) | `narHash` and revision lock | Repo maintainer | Controlled |
|
|
22
22
|
| GitHub release metadata queries | GitHub API | Discovery only, not release validation | `update-deps.yml` query path | Repo maintainer | Monitored |
|
|
23
23
|
|
|
24
24
|
## Validation record
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
/* ──────────────────────────────────────────────────────────────────────────
|
|
2
|
+
* doc.dotfiles.io — custom theme
|
|
3
|
+
* Dark + terminal-green palette on MkDocs Material.
|
|
4
|
+
* Inspired by the polish of docs.n8n.io / GitHub docs dark, adapted to
|
|
5
|
+
* Material's structure.
|
|
6
|
+
* ────────────────────────────────────────────────────────────────────── */
|
|
7
|
+
|
|
8
|
+
/* -- font stack ------------------------------------------------------------ */
|
|
9
|
+
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap");
|
|
10
|
+
|
|
11
|
+
:root {
|
|
12
|
+
--dot-font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
|
|
13
|
+
"Helvetica Neue", Arial, sans-serif;
|
|
14
|
+
--dot-font-code: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono",
|
|
15
|
+
Menlo, Consolas, monospace;
|
|
16
|
+
|
|
17
|
+
--dot-green: #7ee787; /* terminal green */
|
|
18
|
+
--dot-green-bright: #b0f5b7; /* hover / focused */
|
|
19
|
+
--dot-green-dim: #4a9153; /* muted / secondary */
|
|
20
|
+
--dot-green-rgb: 126, 231, 135;
|
|
21
|
+
|
|
22
|
+
--dot-bg: #0b0e14; /* base */
|
|
23
|
+
--dot-bg-elev: #111621; /* elevated card */
|
|
24
|
+
--dot-bg-elev-2: #161b26; /* higher elevation */
|
|
25
|
+
--dot-border: #1f2937;
|
|
26
|
+
--dot-border-strong: #2b3646;
|
|
27
|
+
|
|
28
|
+
--dot-fg: #e4e7ec;
|
|
29
|
+
--dot-fg-muted: #94a3b8;
|
|
30
|
+
--dot-fg-subtle: #64748b;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* -- global typography ----------------------------------------------------- */
|
|
34
|
+
body,
|
|
35
|
+
.md-typeset {
|
|
36
|
+
font-family: var(--dot-font-body);
|
|
37
|
+
font-feature-settings: "ss01", "cv11";
|
|
38
|
+
-webkit-font-smoothing: antialiased;
|
|
39
|
+
-moz-osx-font-smoothing: grayscale;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.md-typeset code,
|
|
43
|
+
.md-typeset kbd,
|
|
44
|
+
.md-typeset pre,
|
|
45
|
+
code {
|
|
46
|
+
font-family: var(--dot-font-code);
|
|
47
|
+
font-feature-settings: "calt", "ss20";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* -- dark palette override (slate) ---------------------------------------- */
|
|
51
|
+
[data-md-color-scheme="slate"] {
|
|
52
|
+
--md-hue: 210;
|
|
53
|
+
--md-default-bg-color: var(--dot-bg);
|
|
54
|
+
--md-default-fg-color: var(--dot-fg);
|
|
55
|
+
--md-default-fg-color--light: var(--dot-fg-muted);
|
|
56
|
+
--md-default-fg-color--lighter: var(--dot-fg-subtle);
|
|
57
|
+
--md-default-fg-color--lightest: hsla(210, 20%, 40%, 0.3);
|
|
58
|
+
|
|
59
|
+
--md-primary-fg-color: var(--dot-green);
|
|
60
|
+
--md-primary-fg-color--light: var(--dot-green-bright);
|
|
61
|
+
--md-primary-fg-color--dark: var(--dot-green-dim);
|
|
62
|
+
--md-primary-bg-color: var(--dot-bg);
|
|
63
|
+
--md-primary-bg-color--light: var(--dot-bg-elev);
|
|
64
|
+
|
|
65
|
+
--md-accent-fg-color: var(--dot-green-bright);
|
|
66
|
+
--md-accent-fg-color--transparent: rgba(126, 231, 135, 0.1);
|
|
67
|
+
--md-accent-bg-color: var(--dot-bg);
|
|
68
|
+
--md-accent-bg-color--light: var(--dot-bg-elev);
|
|
69
|
+
|
|
70
|
+
--md-typeset-a-color: var(--dot-green);
|
|
71
|
+
|
|
72
|
+
--md-code-bg-color: var(--dot-bg-elev-2);
|
|
73
|
+
--md-code-fg-color: var(--dot-fg);
|
|
74
|
+
--md-code-hl-color: rgba(126, 231, 135, 0.12);
|
|
75
|
+
--md-code-hl-color--light: rgba(126, 231, 135, 0.08);
|
|
76
|
+
|
|
77
|
+
/* Admonitions */
|
|
78
|
+
--md-admonition-bg-color: var(--dot-bg-elev);
|
|
79
|
+
--md-admonition-fg-color: var(--dot-fg);
|
|
80
|
+
|
|
81
|
+
/* Footer */
|
|
82
|
+
--md-footer-bg-color: #050710;
|
|
83
|
+
--md-footer-bg-color--dark: #030509;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* -- header --------------------------------------------------------------- */
|
|
87
|
+
.md-header {
|
|
88
|
+
background-color: rgba(11, 14, 20, 0.92);
|
|
89
|
+
backdrop-filter: saturate(180%) blur(12px);
|
|
90
|
+
-webkit-backdrop-filter: saturate(180%) blur(12px);
|
|
91
|
+
border-bottom: 1px solid var(--dot-border);
|
|
92
|
+
box-shadow: none;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.md-header[data-md-state="shadow"] {
|
|
96
|
+
box-shadow: 0 1px 0 var(--dot-border);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.md-header__title {
|
|
100
|
+
font-weight: 600;
|
|
101
|
+
letter-spacing: -0.01em;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.md-header__button.md-logo :is(img, svg) {
|
|
105
|
+
color: var(--dot-green);
|
|
106
|
+
fill: var(--dot-green);
|
|
107
|
+
height: 1.6rem;
|
|
108
|
+
width: 1.6rem;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* -- tabs --------------------------------------------------------------- */
|
|
112
|
+
.md-tabs {
|
|
113
|
+
background-color: rgba(11, 14, 20, 0.85);
|
|
114
|
+
border-bottom: 1px solid var(--dot-border);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.md-tabs__link {
|
|
118
|
+
color: var(--dot-fg-muted);
|
|
119
|
+
opacity: 1;
|
|
120
|
+
font-size: 0.75rem;
|
|
121
|
+
font-weight: 500;
|
|
122
|
+
transition: color 120ms ease;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.md-tabs__link:hover,
|
|
126
|
+
.md-tabs__link--active {
|
|
127
|
+
color: var(--dot-green-bright);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.md-tabs__link--active {
|
|
131
|
+
position: relative;
|
|
132
|
+
}
|
|
133
|
+
.md-tabs__link--active::after {
|
|
134
|
+
content: "";
|
|
135
|
+
position: absolute;
|
|
136
|
+
left: 0;
|
|
137
|
+
right: 0;
|
|
138
|
+
bottom: -2px;
|
|
139
|
+
height: 2px;
|
|
140
|
+
background: linear-gradient(90deg, transparent, var(--dot-green), transparent);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* -- sidebar (left nav) --------------------------------------------------- */
|
|
144
|
+
.md-nav__title {
|
|
145
|
+
font-size: 0.68rem;
|
|
146
|
+
font-weight: 700;
|
|
147
|
+
text-transform: uppercase;
|
|
148
|
+
letter-spacing: 0.05em;
|
|
149
|
+
color: var(--dot-fg-subtle);
|
|
150
|
+
padding-top: 1.2rem;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.md-nav__link {
|
|
154
|
+
color: var(--dot-fg-muted);
|
|
155
|
+
transition: color 120ms ease, background-color 120ms ease;
|
|
156
|
+
border-radius: 6px;
|
|
157
|
+
padding: 4px 8px;
|
|
158
|
+
margin: 1px 0;
|
|
159
|
+
}
|
|
160
|
+
.md-nav__link:hover {
|
|
161
|
+
color: var(--dot-fg);
|
|
162
|
+
background: rgba(126, 231, 135, 0.06);
|
|
163
|
+
}
|
|
164
|
+
.md-nav__link--active,
|
|
165
|
+
.md-nav__link.md-nav__link--active {
|
|
166
|
+
color: var(--dot-green-bright);
|
|
167
|
+
background: rgba(126, 231, 135, 0.1);
|
|
168
|
+
font-weight: 500;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* -- right TOC ------------------------------------------------------------ */
|
|
172
|
+
.md-nav--secondary .md-nav__title {
|
|
173
|
+
border-left: 2px solid var(--dot-border);
|
|
174
|
+
background: transparent;
|
|
175
|
+
}
|
|
176
|
+
.md-nav--secondary .md-nav__link--active {
|
|
177
|
+
border-left: 2px solid var(--dot-green);
|
|
178
|
+
color: var(--dot-green-bright);
|
|
179
|
+
background: transparent;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* -- content -------------------------------------------------------------- */
|
|
183
|
+
.md-typeset h1,
|
|
184
|
+
.md-typeset h2,
|
|
185
|
+
.md-typeset h3,
|
|
186
|
+
.md-typeset h4 {
|
|
187
|
+
font-family: var(--dot-font-body);
|
|
188
|
+
letter-spacing: -0.02em;
|
|
189
|
+
color: var(--dot-fg);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.md-typeset h1 {
|
|
193
|
+
font-weight: 700;
|
|
194
|
+
font-size: 2.2rem;
|
|
195
|
+
line-height: 1.15;
|
|
196
|
+
margin-bottom: 0.6em;
|
|
197
|
+
background: linear-gradient(180deg, #ffffff 0%, #cbd5e1 100%);
|
|
198
|
+
-webkit-background-clip: text;
|
|
199
|
+
background-clip: text;
|
|
200
|
+
color: transparent;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.md-typeset h2 {
|
|
204
|
+
font-weight: 600;
|
|
205
|
+
font-size: 1.6rem;
|
|
206
|
+
margin-top: 2.4em;
|
|
207
|
+
padding-top: 0.4em;
|
|
208
|
+
border-top: 1px solid var(--dot-border);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.md-typeset h3 {
|
|
212
|
+
font-weight: 600;
|
|
213
|
+
font-size: 1.2rem;
|
|
214
|
+
color: var(--dot-green-bright);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.md-typeset a {
|
|
218
|
+
text-decoration: none;
|
|
219
|
+
border-bottom: 1px solid transparent;
|
|
220
|
+
transition: border-color 120ms ease, color 120ms ease;
|
|
221
|
+
}
|
|
222
|
+
.md-typeset a:hover {
|
|
223
|
+
border-bottom-color: var(--dot-green-bright);
|
|
224
|
+
color: var(--dot-green-bright);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* -- code blocks ---------------------------------------------------------- */
|
|
228
|
+
.md-typeset pre > code,
|
|
229
|
+
.md-typeset .highlight pre {
|
|
230
|
+
background-color: var(--dot-bg-elev-2);
|
|
231
|
+
border: 1px solid var(--dot-border);
|
|
232
|
+
border-radius: 8px;
|
|
233
|
+
}
|
|
234
|
+
.md-typeset code {
|
|
235
|
+
background-color: rgba(126, 231, 135, 0.08);
|
|
236
|
+
border: 1px solid rgba(126, 231, 135, 0.15);
|
|
237
|
+
color: var(--dot-green-bright);
|
|
238
|
+
border-radius: 4px;
|
|
239
|
+
padding: 0.1em 0.35em;
|
|
240
|
+
font-size: 0.88em;
|
|
241
|
+
}
|
|
242
|
+
.md-typeset pre > code {
|
|
243
|
+
background: transparent;
|
|
244
|
+
border: none;
|
|
245
|
+
color: var(--dot-fg);
|
|
246
|
+
padding: 0;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* -- tables --------------------------------------------------------------- */
|
|
250
|
+
.md-typeset table:not([class]) {
|
|
251
|
+
border: 1px solid var(--dot-border);
|
|
252
|
+
border-radius: 8px;
|
|
253
|
+
overflow: hidden;
|
|
254
|
+
font-size: 0.8rem;
|
|
255
|
+
}
|
|
256
|
+
.md-typeset table:not([class]) th {
|
|
257
|
+
background: var(--dot-bg-elev);
|
|
258
|
+
color: var(--dot-fg);
|
|
259
|
+
font-weight: 600;
|
|
260
|
+
border-bottom: 1px solid var(--dot-border-strong);
|
|
261
|
+
}
|
|
262
|
+
.md-typeset table:not([class]) tr:hover {
|
|
263
|
+
background: rgba(126, 231, 135, 0.03);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* -- admonitions ---------------------------------------------------------- */
|
|
267
|
+
.md-typeset .admonition,
|
|
268
|
+
.md-typeset details {
|
|
269
|
+
background: var(--dot-bg-elev);
|
|
270
|
+
border: 1px solid var(--dot-border);
|
|
271
|
+
border-left: 3px solid var(--dot-green);
|
|
272
|
+
border-radius: 8px;
|
|
273
|
+
box-shadow: none;
|
|
274
|
+
}
|
|
275
|
+
.md-typeset .admonition-title,
|
|
276
|
+
.md-typeset summary {
|
|
277
|
+
background: transparent;
|
|
278
|
+
border-bottom: 1px solid var(--dot-border);
|
|
279
|
+
font-weight: 600;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/* -- grid cards ----------------------------------------------------------- */
|
|
283
|
+
.md-typeset .grid.cards > :is(ul, ol) > li,
|
|
284
|
+
.md-typeset .grid.cards > .card {
|
|
285
|
+
background: var(--dot-bg-elev);
|
|
286
|
+
border: 1px solid var(--dot-border);
|
|
287
|
+
border-radius: 12px;
|
|
288
|
+
padding: 1.2rem;
|
|
289
|
+
transition: transform 180ms ease, border-color 180ms ease,
|
|
290
|
+
box-shadow 180ms ease, background 180ms ease;
|
|
291
|
+
position: relative;
|
|
292
|
+
overflow: hidden;
|
|
293
|
+
}
|
|
294
|
+
.md-typeset .grid.cards > :is(ul, ol) > li::before {
|
|
295
|
+
content: "";
|
|
296
|
+
position: absolute;
|
|
297
|
+
inset: 0;
|
|
298
|
+
background: radial-gradient(
|
|
299
|
+
circle at top left,
|
|
300
|
+
rgba(126, 231, 135, 0.06),
|
|
301
|
+
transparent 60%
|
|
302
|
+
);
|
|
303
|
+
opacity: 0;
|
|
304
|
+
transition: opacity 220ms ease;
|
|
305
|
+
pointer-events: none;
|
|
306
|
+
}
|
|
307
|
+
.md-typeset .grid.cards > :is(ul, ol) > li:hover {
|
|
308
|
+
transform: translateY(-2px);
|
|
309
|
+
border-color: rgba(126, 231, 135, 0.35);
|
|
310
|
+
background: var(--dot-bg-elev-2);
|
|
311
|
+
box-shadow: 0 8px 24px -8px rgba(0, 0, 0, 0.5),
|
|
312
|
+
0 0 0 1px rgba(126, 231, 135, 0.08) inset;
|
|
313
|
+
}
|
|
314
|
+
.md-typeset .grid.cards > :is(ul, ol) > li:hover::before {
|
|
315
|
+
opacity: 1;
|
|
316
|
+
}
|
|
317
|
+
.md-typeset .grid.cards > :is(ul, ol) > li > :first-child {
|
|
318
|
+
margin-top: 0;
|
|
319
|
+
}
|
|
320
|
+
.md-typeset .grid.cards > :is(ul, ol) > li strong {
|
|
321
|
+
color: var(--dot-green-bright);
|
|
322
|
+
font-weight: 600;
|
|
323
|
+
font-size: 1rem;
|
|
324
|
+
display: block;
|
|
325
|
+
margin-bottom: 0.4rem;
|
|
326
|
+
}
|
|
327
|
+
.md-typeset .grid.cards > :is(ul, ol) > li .twemoji,
|
|
328
|
+
.md-typeset .grid.cards > :is(ul, ol) > li svg {
|
|
329
|
+
color: var(--dot-green);
|
|
330
|
+
fill: var(--dot-green);
|
|
331
|
+
height: 1.4rem;
|
|
332
|
+
width: 1.4rem;
|
|
333
|
+
margin-bottom: 0.6rem;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/* -- hero banner (used by landing page) ----------------------------------- */
|
|
337
|
+
.dot-hero {
|
|
338
|
+
padding: 3rem 0 2.4rem;
|
|
339
|
+
margin: -1.6rem -0.8rem 2.4rem;
|
|
340
|
+
text-align: center;
|
|
341
|
+
border-bottom: 1px solid var(--dot-border);
|
|
342
|
+
position: relative;
|
|
343
|
+
background: radial-gradient(
|
|
344
|
+
ellipse 60% 100% at 50% 0%,
|
|
345
|
+
rgba(126, 231, 135, 0.08),
|
|
346
|
+
transparent 70%
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
.dot-hero h1 {
|
|
350
|
+
font-size: 3rem;
|
|
351
|
+
line-height: 1.05;
|
|
352
|
+
margin-bottom: 0.4em;
|
|
353
|
+
padding: 0;
|
|
354
|
+
border: none;
|
|
355
|
+
}
|
|
356
|
+
.dot-hero .tagline {
|
|
357
|
+
font-size: 1.1rem;
|
|
358
|
+
color: var(--dot-fg-muted);
|
|
359
|
+
max-width: 40rem;
|
|
360
|
+
margin: 0 auto 1.4rem;
|
|
361
|
+
}
|
|
362
|
+
.dot-hero .buttons {
|
|
363
|
+
display: flex;
|
|
364
|
+
gap: 0.6rem;
|
|
365
|
+
justify-content: center;
|
|
366
|
+
flex-wrap: wrap;
|
|
367
|
+
}
|
|
368
|
+
.dot-hero .buttons a {
|
|
369
|
+
display: inline-flex;
|
|
370
|
+
align-items: center;
|
|
371
|
+
gap: 0.4rem;
|
|
372
|
+
padding: 0.6rem 1.1rem;
|
|
373
|
+
border-radius: 8px;
|
|
374
|
+
font-weight: 500;
|
|
375
|
+
font-size: 0.9rem;
|
|
376
|
+
text-decoration: none;
|
|
377
|
+
border: 1px solid var(--dot-border-strong);
|
|
378
|
+
color: var(--dot-fg);
|
|
379
|
+
transition: all 160ms ease;
|
|
380
|
+
}
|
|
381
|
+
.dot-hero .buttons a.primary {
|
|
382
|
+
background: var(--dot-green);
|
|
383
|
+
color: var(--dot-bg);
|
|
384
|
+
border-color: var(--dot-green);
|
|
385
|
+
font-weight: 600;
|
|
386
|
+
}
|
|
387
|
+
.dot-hero .buttons a.primary:hover {
|
|
388
|
+
background: var(--dot-green-bright);
|
|
389
|
+
border-color: var(--dot-green-bright);
|
|
390
|
+
transform: translateY(-1px);
|
|
391
|
+
}
|
|
392
|
+
.dot-hero .buttons a:not(.primary):hover {
|
|
393
|
+
border-color: var(--dot-green);
|
|
394
|
+
color: var(--dot-green-bright);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/* -- search --------------------------------------------------------------- */
|
|
398
|
+
.md-search__form {
|
|
399
|
+
background: var(--dot-bg-elev);
|
|
400
|
+
border: 1px solid var(--dot-border);
|
|
401
|
+
border-radius: 8px;
|
|
402
|
+
}
|
|
403
|
+
.md-search__form:hover,
|
|
404
|
+
.md-search__input:focus + .md-search__icon,
|
|
405
|
+
.md-search__form:focus-within {
|
|
406
|
+
border-color: var(--dot-green);
|
|
407
|
+
background: var(--dot-bg-elev-2);
|
|
408
|
+
}
|
|
409
|
+
.md-search__input {
|
|
410
|
+
color: var(--dot-fg);
|
|
411
|
+
}
|
|
412
|
+
.md-search__input::placeholder {
|
|
413
|
+
color: var(--dot-fg-subtle);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/* -- footer --------------------------------------------------------------- */
|
|
417
|
+
.md-footer {
|
|
418
|
+
border-top: 1px solid var(--dot-border);
|
|
419
|
+
}
|
|
420
|
+
.md-footer-meta {
|
|
421
|
+
background: var(--dot-bg);
|
|
422
|
+
border-top: 1px solid var(--dot-border);
|
|
423
|
+
}
|
|
424
|
+
.md-copyright {
|
|
425
|
+
color: var(--dot-fg-subtle);
|
|
426
|
+
font-size: 0.72rem;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/* -- scrollbar (webkit) --------------------------------------------------- */
|
|
430
|
+
::-webkit-scrollbar {
|
|
431
|
+
width: 10px;
|
|
432
|
+
height: 10px;
|
|
433
|
+
}
|
|
434
|
+
::-webkit-scrollbar-track {
|
|
435
|
+
background: transparent;
|
|
436
|
+
}
|
|
437
|
+
::-webkit-scrollbar-thumb {
|
|
438
|
+
background: var(--dot-border-strong);
|
|
439
|
+
border-radius: 8px;
|
|
440
|
+
border: 2px solid var(--dot-bg);
|
|
441
|
+
}
|
|
442
|
+
::-webkit-scrollbar-thumb:hover {
|
|
443
|
+
background: var(--dot-green-dim);
|
|
444
|
+
}
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
<!-- New prompt -->
|
|
71
71
|
<text x="40" y="405" fill="#a6e3a1">➤</text>
|
|
72
72
|
<text x="60" y="405" fill="#cdd6f4">~/.dotfiles</text>
|
|
73
|
-
<text x="170" y="405" fill="#f5c2e7">on
|
|
73
|
+
<text x="170" y="405" fill="#f5c2e7">on main</text>
|
|
74
74
|
<rect x="275" y="393" width="8" height="16" fill="#cdd6f4">
|
|
75
75
|
<animate attributeName="opacity" values="1;0;1" dur="1s" repeatCount="indefinite" />
|
|
76
76
|
</rect>
|