@cyberskill/design 1.0.0 → 1.1.0
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/DESIGN.md +10 -9
- package/README.md +31 -28
- package/SKILL.md +13 -9
- package/VERSION +1 -1
- package/_ds_bundle.js +660 -202
- package/_ds_manifest.json +1 -1
- package/_esm/cs.mjs +14 -8
- package/_esm/react.d.ts +216 -0
- package/_esm/react.mjs +114 -0
- package/base/collections.css +31 -0
- package/base/components.css +3 -0
- package/base/data.css +33 -0
- package/base/forms.css +8 -0
- package/base/interaction.css +1 -0
- package/base/typography.css +6 -0
- package/components/_i18n/strings.js +8 -4
- package/components/ai/ai-conversation.card.html +2 -2
- package/components/ai/ai-lumi.card.html +2 -2
- package/components/ai/ai.card.html +2 -2
- package/components/brand/brand.card.html +2 -2
- package/components/button/buttons.card.html +2 -2
- package/components/data/AspectRatio.d.ts +16 -0
- package/components/data/AspectRatio.figma.tsx +12 -0
- package/components/data/AspectRatio.jsx +16 -0
- package/components/data/AspectRatio.prompt.md +7 -0
- package/components/data/Collapsible.d.ts +21 -0
- package/components/data/Collapsible.figma.tsx +12 -0
- package/components/data/Collapsible.jsx +49 -0
- package/components/data/Collapsible.prompt.md +7 -0
- package/components/data/Image.d.ts +4 -0
- package/components/data/Image.prompt.md +2 -2
- package/components/data/Item.d.ts +26 -0
- package/components/data/Item.figma.tsx +12 -0
- package/components/data/Item.jsx +63 -0
- package/components/data/Item.prompt.md +10 -0
- package/components/data/ScrollArea.d.ts +16 -0
- package/components/data/ScrollArea.figma.tsx +12 -0
- package/components/data/ScrollArea.jsx +25 -0
- package/components/data/ScrollArea.prompt.md +7 -0
- package/components/data/collections.card.html +15 -4
- package/components/data/data.card.html +15 -4
- package/components/datatable/datatable.card.html +2 -2
- package/components/dialog/dialog.card.html +2 -2
- package/components/feedback/feedback-2.card.html +2 -2
- package/components/feedback/feedback.card.html +2 -2
- package/components/forms/Cascader.jsx +5 -3
- package/components/forms/Editor.prompt.md +1 -1
- package/components/forms/InputGroup.d.ts +4 -0
- package/components/forms/InputGroup.jsx +38 -8
- package/components/forms/InputGroup.prompt.md +3 -3
- package/components/forms/NativeSelect.d.ts +22 -0
- package/components/forms/NativeSelect.figma.tsx +12 -0
- package/components/forms/NativeSelect.jsx +56 -0
- package/components/forms/NativeSelect.prompt.md +10 -0
- package/components/forms/NumberField.d.ts +5 -0
- package/components/forms/NumberField.jsx +51 -7
- package/components/forms/NumberField.prompt.md +2 -2
- package/components/forms/SegmentedControl.jsx +1 -1
- package/components/forms/TagInput.d.ts +3 -0
- package/components/forms/TagInput.jsx +62 -20
- package/components/forms/TagInput.prompt.md +2 -2
- package/components/forms/forms-2.card.html +2 -2
- package/components/forms/forms.card.html +5 -4
- package/components/icon/Icon.prompt.md +1 -1
- package/components/icon/icon.card.html +2 -2
- package/components/logo/Logo.jsx +2 -1
- package/components/logo/logo.card.html +2 -2
- package/components/navigation/Menu.jsx +14 -1
- package/components/navigation/navigation.card.html +2 -2
- package/components/navigation/shell.card.html +2 -2
- package/components/overlays/AlertDialog.d.ts +29 -0
- package/components/overlays/AlertDialog.figma.tsx +12 -0
- package/components/overlays/AlertDialog.jsx +142 -0
- package/components/overlays/AlertDialog.prompt.md +12 -0
- package/components/overlays/Drawer.jsx +1 -1
- package/components/overlays/Popconfirm.jsx +14 -1
- package/components/overlays/Popover.jsx +14 -1
- package/components/overlays/alertdialog.card.html +42 -0
- package/components/overlays/overlays.card.html +2 -2
- package/components/textfield/textfield.card.html +2 -2
- package/docs/benchmark-rubric.md +46 -0
- package/docs/ci-cd.md +17 -11
- package/docs/consumer-grant.md +37 -0
- package/docs/consuming.md +45 -16
- package/docs/contrast-report.md +91 -103
- package/docs/conventions.md +12 -9
- package/docs/decisions.md +33 -10
- package/docs/deploy.md +1 -1
- package/docs/design-styles.md +26 -8
- package/docs/figma.md +3 -3
- package/docs/live-hub.md +5 -3
- package/docs/products.md +13 -11
- package/docs/quality-gates.md +35 -21
- package/docs/release-notes.md +13 -3
- package/docs/status/assets/favicon.svg +5 -0
- package/docs/status/assets/status-legacy.css +399 -0
- package/docs/status/assets/status-legacy.js +505 -0
- package/docs/status/assets/status.css +644 -0
- package/docs/status/assets/status.js +1308 -0
- package/docs/status/data/status-feed.json +1 -0
- package/docs/status/data/task/TASK-REL-001.js +1 -0
- package/docs/status/index.html +45 -0
- package/docs/status/roadmap.html +4 -0
- package/docs/status/status-legacy.html +121 -0
- package/docs/storybook.md +5 -4
- package/docs/sync.md +3 -2
- package/docs/tasks/BACKLOG.md +25 -0
- package/docs/tasks/release/TASK-REL-001-launch-1-1-0/spec.md +55 -0
- package/docs/template-schema-v2.md +15 -3
- package/docs/vi/benchmark-rubric.md +46 -0
- package/docs/vi/ci-cd.md +17 -11
- package/docs/vi/consumer-grant.md +37 -0
- package/docs/vi/consuming.md +45 -16
- package/docs/vi/contrast-report.md +94 -106
- package/docs/vi/conventions.md +12 -9
- package/docs/vi/decisions.md +33 -10
- package/docs/vi/deploy.md +1 -1
- package/docs/vi/design-styles.md +26 -8
- package/docs/vi/figma.md +3 -3
- package/docs/vi/live-hub.md +5 -3
- package/docs/vi/products.md +13 -11
- package/docs/vi/quality-gates.md +35 -21
- package/docs/vi/release-notes.md +18 -8
- package/docs/vi/storybook.md +5 -4
- package/docs/vi/sync.md +3 -2
- package/docs/vi/template-schema-v2.md +15 -3
- package/docs/viewer.html +2 -2
- package/fonts/spacegrotesk-var-latin-ext.woff2 +0 -0
- package/fonts/spacegrotesk-var-latin.woff2 +0 -0
- package/fonts/spacegrotesk-var-vietnamese.woff2 +0 -0
- package/guidelines/atomic-view.html +40 -27
- package/guidelines/elements-geometry.html +69 -0
- package/guidelines/elements-variants.html +17 -17
- package/guidelines/type-families.html +16 -10
- package/llms.txt +17 -11
- package/package.json +38 -16
- package/styles.css +1 -0
- package/templates/ai-cluster-demo.html +29 -14
- package/templates/app-shell/support.js +4 -4
- package/templates/article/content-schema.json +6 -0
- package/templates/article/support.js +4 -4
- package/templates/auth/support.js +4 -4
- package/templates/bod-deck/support.js +4 -4
- package/templates/bod-investor-update/support.js +4 -4
- package/templates/bod-memo/support.js +4 -4
- package/templates/bod-minutes/content-schema.json +12 -0
- package/templates/bod-minutes/support.js +4 -4
- package/templates/bod-report/support.js +4 -4
- package/templates/bod-resolution/support.js +4 -4
- package/templates/culture-event-invite/support.js +4 -4
- package/templates/dashboard/support.js +4 -4
- package/templates/delivery-change-note/support.js +4 -4
- package/templates/delivery-kickoff/support.js +4 -4
- package/templates/delivery-qbr-deck/support.js +4 -4
- package/templates/delivery-runbook/content-schema.json +6 -0
- package/templates/delivery-runbook/support.js +4 -4
- package/templates/delivery-status-email/support.js +4 -4
- package/templates/doc-style-guide/DocStyleGuide.dc.html +2 -2
- package/templates/doc-style-guide/support.js +4 -4
- package/templates/doc-suite-index/support.js +4 -4
- package/templates/doc-templates/DocTemplates.dc.html +1 -1
- package/templates/doc-templates/support.js +4 -4
- package/templates/email/support.js +4 -4
- package/templates/email-safe/README.md +17 -4
- package/templates/email-safe/email-launch.html +3 -3
- package/templates/email-safe/email-newsletter.html +1 -1
- package/templates/finance-dunning-email/support.js +4 -4
- package/templates/finance-expense-report/support.js +4 -4
- package/templates/finance-invoice/support.js +4 -4
- package/templates/finance-quote/support.js +4 -4
- package/templates/hr-announcement/support.js +4 -4
- package/templates/hr-interview-kit/content-schema.json +12 -0
- package/templates/hr-interview-kit/support.js +4 -4
- package/templates/hr-offboarding/content-schema.json +12 -0
- package/templates/hr-offboarding/support.js +4 -4
- package/templates/hr-performance-review/content-schema.json +12 -0
- package/templates/hr-performance-review/support.js +4 -4
- package/templates/hr-pip/content-schema.json +12 -0
- package/templates/hr-pip/support.js +4 -4
- package/templates/legal-msa/content-schema.json +16 -0
- package/templates/legal-msa/support.js +4 -4
- package/templates/legal-sow/support.js +4 -4
- package/templates/marketing-campaign-brief/support.js +4 -4
- package/templates/marketing-case-study/support.js +4 -4
- package/templates/marketing-launch/support.js +4 -4
- package/templates/marketing-newsletter/support.js +4 -4
- package/templates/marketing-page/content-schema.json +0 -1
- package/templates/marketing-page/support.js +4 -4
- package/templates/marketing-press-release/support.js +4 -4
- package/templates/marketing-social-kit/support.js +4 -4
- package/templates/playground.html +8 -4
- package/templates/sales-one-pager/support.js +4 -4
- package/templates/sales-proposal-deck/support.js +4 -4
- package/templates/settings/Settings.dc.html +26 -14
- package/templates/settings/content-schema.json +36 -0
- package/templates/settings/support.js +4 -4
- package/templates/slide-deck/support.js +4 -4
- package/templates/team-meeting-agenda/content-schema.json +16 -0
- package/templates/team-meeting-agenda/support.js +4 -4
- package/templates/tech-incident-report/support.js +4 -4
- package/templates/tech-release-notes/support.js +4 -4
- package/templates/tech-retro/content-schema.json +12 -0
- package/templates/tech-retro/support.js +4 -4
- package/templates/tech-rfc/content-schema.json +6 -0
- package/templates/tech-rfc/support.js +4 -4
- package/templates/vn-appointment-transfer/support.js +4 -4
- package/templates/vn-certificate-of-employment/support.js +4 -4
- package/templates/vn-code-of-conduct/support.js +4 -4
- package/templates/vn-compensation-regulation/support.js +4 -4
- package/templates/vn-contract-amendment/support.js +4 -4
- package/templates/vn-contractor-agreement/support.js +4 -4
- package/templates/vn-data-protection-policy/support.js +4 -4
- package/templates/vn-disciplinary-case-file/support.js +4 -4
- package/templates/vn-disciplinary-schedule/content-schema.json +15 -0
- package/templates/vn-disciplinary-schedule/support.js +4 -4
- package/templates/vn-employee-request/support.js +4 -4
- package/templates/vn-exit-handover/support.js +4 -4
- package/templates/vn-foreign-employee-pack/support.js +4 -4
- package/templates/vn-grassroots-democracy/support.js +4 -4
- package/templates/vn-infosec-policy/support.js +4 -4
- package/templates/vn-internal-labor-regulations/support.js +4 -4
- package/templates/vn-internship-agreement/support.js +4 -4
- package/templates/vn-job-description/support.js +4 -4
- package/templates/vn-labor-contract/support.js +4 -4
- package/templates/vn-labour-management-book/content-schema.json +15 -0
- package/templates/vn-labour-management-book/support.js +4 -4
- package/templates/vn-mutual-nda/support.js +4 -4
- package/templates/vn-ndnca-ip/support.js +4 -4
- package/templates/vn-offer-letter/support.js +4 -4
- package/templates/vn-onboarding-checklist/support.js +4 -4
- package/templates/vn-pdpl-consent/support.js +4 -4
- package/templates/vn-performance-evaluation-regulation/support.js +4 -4
- package/templates/vn-performance-review-form/support.js +4 -4
- package/templates/vn-phantom-stock/support.js +4 -4
- package/templates/vn-probation-contract/support.js +4 -4
- package/templates/vn-receipt-acknowledgement/content-schema.json +15 -0
- package/templates/vn-receipt-acknowledgement/support.js +4 -4
- package/templates/vn-remote-work-policy/support.js +4 -4
- package/templates/vn-resignation-letter/support.js +4 -4
- package/templates/vn-salary-scale/content-schema.json +15 -0
- package/templates/vn-salary-scale/support.js +4 -4
- package/templates/vn-sow-appendix/support.js +4 -4
- package/templates/vn-termination-decision/support.js +4 -4
- package/templates/vn-total-rewards-appendix/support.js +4 -4
- package/templates/vn-training-commitment/support.js +4 -4
- package/templates/vn-travel-expense-policy/support.js +4 -4
- package/tokens/element-seeds.json +112 -0
- package/tokens/elements.css +274 -187
- package/tokens/fonts.css +12 -3
- package/tokens/native/CSTokens.kt +84 -68
- package/tokens/native/CSTokens.swift +84 -68
- package/tokens/native/cs_tokens.dart +84 -68
- package/tokens/provenance.json +9 -9
- package/tokens/styles.css +15 -0
- package/tokens/tokens.dtcg.json +258 -233
- package/tokens/tokens.js +168 -167
- package/tokens/tokens.json +167 -166
- package/tokens/typography.css +9 -1
- package/ui_kits/status-hub/README.md +1 -2
- package/ui_kits/status-hub/index.html +2 -2
- package/ui_kits/status-hub/settings.html +6 -3
- package/ui_kits/website/chat.html +2 -2
- package/ui_kits/website/index.html +2 -2
- package/ui_kits/status-hub/identity-lab.html +0 -134
package/docs/quality-gates.md
CHANGED
|
@@ -4,41 +4,46 @@ Every deterministic quality gate in the system, what it asserts, its pass criter
|
|
|
4
4
|
|
|
5
5
|
**Where gates run.** *Fast board CI* = the `fast-gates` job in `.github/workflows/design-system-gates.yml`, which serves the repo and drives `_audit/run.html` headless via `_audit/ci/run-gates.mjs` (every push/PR + nightly + manual) — new board rows are picked up automatically. Two gates additionally run standalone as *merge blockers* (`docs-consistency-blocker` job, via `_audit/ci/run-single-gate.mjs`). *Whole-set CI* = the `whole-set-audits` job (every push/PR + nightly — owner decision B). *Unit test* = `npm run test:unit` in the `unit-tests` job (plain Node, no browser). *Node pre-checks* = the `node-prechecks` job (browser-free authorities: bundle freshness, DESIGN.md freshness) plus the `token-provenance` job. Every browser gate publishes a verdict global (`window.__*`) that the headless runners read.
|
|
6
6
|
|
|
7
|
-
## Fast board —
|
|
7
|
+
## Fast board — 34 gates in `_audit/run.html`
|
|
8
|
+
|
|
9
|
+
Benchmark principles (WCAG · APCA · OKLCH · DTCG · CDS doctrine + style expansion): [`docs/benchmark-rubric.md`](benchmark-rubric.md).
|
|
8
10
|
|
|
9
11
|
| Gate | File | What it asserts | Pass criterion | Type | Where it runs |
|
|
10
12
|
|---|---|---|---|---|---|
|
|
11
13
|
| Contrast guard | `_audit/contrast-guard.html` | No base rule paints umber on a themeable surface without a dark override; every semantic text×surface pair scores in light and dark | 0 unshielded rules and 0 failing pairs (`__contrastguard`) | Hard | Fast board CI |
|
|
12
|
-
|
|
|
14
|
+
| Axes guard | `_audit/axis-guard.html` | No live source reintroduces the retired Expression/Density product surface | 0 hits across manifest-indexed sources (`__axisguard`) | Hard | Fast board CI |
|
|
13
15
|
| Manifest CSS paths | `_audit/manifest-css-guard.html` | Every `_ds_manifest.json` `globalCssPaths` entry exists as raw CSS; every `styles.css` `@import` is listed | 0 missing / 0 unlisted (`__cssguard`) | Hard | Fast board CI |
|
|
14
|
-
| Docs consistency | `_audit/docs-consistency.html` | Every count claim in README/SKILL/llms.txt matches the compiler manifest; `VERSION` + `package.json` pinned 1.
|
|
16
|
+
| Docs consistency | `_audit/docs-consistency.html` | Every count claim in README/SKILL/llms.txt matches the compiler manifest; audit prose card-count claims (`_audit/index` / README / namespace-portability) match `manifest.cards`; `VERSION` + `package.json` pinned 1.1.0; no changelog-file reference; stale-phrase blacklist (the retired suite/pack counts the Jul 2026 audit removed) clean across README/SKILL/llms + `docs/*.md` (historical notes under `_audit/archive/` are not scanned); `DESIGN.md` exists with front-matter version = `VERSION`; agent routing honesty — Claude path cites `_esm/cs.mjs` + bundle prefix; Stitch path forbids `*.dc.html` as SoT; package name `@cyberskill/design` | 0 mismatched claims, 0 blacklist hits, pin + stamp + routing intact (`__docs`) | Hard | Fast board CI + merge blocker |
|
|
15
17
|
| Docs language parity | `_audit/docs-lang-parity.html` | Every operator-facing EN `docs/*.md` has a `docs/vi/` counterpart; VI is not an empty/TODO stub (≥40% EN length); stale-phrase blacklist clean on both EN and VI (historical notes under `_audit/archive/` are not tracked) | 0 missing pairs, 0 stubs, 0 blacklist hits (`__docslangparity`) | Hard | Fast board CI |
|
|
16
|
-
| DESIGN.md parity | `_audit/design-md-parity.html` | The root `DESIGN.md` (Stitch open-spec surface) byte-equals an in-browser regeneration from `tokens.dtcg.json` + `_ds_manifest.json` + `VERSION` via the shared `scripts/design-md-lib.mjs`; every
|
|
17
|
-
| Version stamp | `_audit/version-stamp.html` | `package.json`, `tokens.json`/`tokens.js` metas, DTCG `$extensions`, `provenance.json` release + dtcgStamp,
|
|
18
|
+
| DESIGN.md parity | `_audit/design-md-parity.html` | The root `DESIGN.md` (Stitch open-spec surface) byte-equals an in-browser regeneration from `tokens.dtcg.json` + `_ds_manifest.json` + `VERSION` via the shared `scripts/design-md-lib.mjs`; every token row re-checked individually (the count is printed with the verdict) | Byte-identical + 0 drifted rows (`__designmd`) | Hard | Fast board CI |
|
|
19
|
+
| Version stamp | `_audit/version-stamp.html` | `package.json`, `tokens.json`/`tokens.js` metas, DTCG `$extensions`, `provenance.json` release + dtcgStamp, `DESIGN.md` front matter, and `_esm/cs.mjs` `export const VERSION` all equal `VERSION` (1.1.0 pin) | All 9 stamps equal (`__versionstamp`) | Hard | Fast board CI |
|
|
18
20
|
| Namespace portability | `_audit/namespace-portability.html` | No manifest-indexed source hardcodes the compiler's project-id bundle suffix | 0 hardcoded suffixes (`__nsguard`) | Hard | Fast board CI |
|
|
19
21
|
| Token contract | `_audit/token-contract.html` | All 15 element×variant scopes resolve all 9 `--cs-accent-*` roles; core semantic tokens resolve | 0 missing roles, 0 missing core tokens (`__contract`) | Hard | Fast board CI |
|
|
20
22
|
| Token pipeline | `_audit/token-pipeline-test.html` | Every DTCG-derived constant appears verbatim in all three `tokens/native/` targets; provenance sha-256 matches the DTCG source | 0 drifted constants, hash match (`__tokenpipe`) | Hard | Fast board CI |
|
|
21
23
|
| Token format parity | `_audit/token-format-parity.html` | Every `--cs-*` declaration in `tokens/*.css` equals its mirror in `tokens.json`, `tokens.js` (live ESM deep-equal), and DTCG (ext-css string or typed transform) — base `:root` + dark/system themes + 15 element packs + 15 dark packs; the 4 `_ds_manifest.json` durations equal `motion.css` (guards the reduced-motion 0ms compiler bug) | 0 diffs across all scopes (`__tokenformat`) | Hard | Fast board CI |
|
|
22
24
|
| DTCG typing | `_audit/dtcg-typing.html` | Every DTCG `$value` leaf carries a W3C `$type`; every `{alias}` resolves (chains followed, no cycles); every shadow token is a structured object/array with full layer fields; byType counts equal `provenance.json` | 0 untyped / dangling / string shadows (`__dtcgtyping`) | Hard | Fast board CI |
|
|
23
|
-
|
|
|
25
|
+
| Font-face integrity | `_audit/font-face-integrity.html` | Every `@font-face` in `tokens/fonts.css` is self-hosted under `fonts/` (no CDN `src`), subset-split with `font-display: swap`, and points at a file whose bytes start with the `wOF2` magic; every family named first by a `--cs-font-family-*` token has faces here **including the Vietnamese subset** (`U+1EA0-1EF9`), and every self-hosted family is named by a token; `_ds_manifest.json` `fonts[]` matches the parsed faces entry-for-entry and `brandFonts[]` matches the token-named families; each family loads for real via `document.fonts`; `.cs-display-face` retargets `--cs-heading-family` to the display family without leaking onto body copy | 0 missing/remote files, 0 families without a VN subset, 0 manifest diffs (`__fontface`) | Hard | Fast board CI |
|
|
26
|
+
| Story coverage | `_audit/story-coverage.html` | Every primary bundle export has an Atomic View story; tweakable primaries in `PLAYGROUND_REQUIRED` must also ship `controls` + `renderC` playgrounds | 0 missing stories + 0 missing playgrounds (`__storycov`) | Hard | Fast board CI |
|
|
24
27
|
| Consumer smoke test | `_audit/consumer-smoke-test.html` | The external consumer path works: `styles.css` + `_ds_bundle.js` mount real components and brand tokens reach a rendered Button | Mount + token assertions all pass (`__smoke`) | Hard | Fast board CI |
|
|
25
28
|
| Bundle freshness | `_audit/bundle-freshness.html` | Every source recorded in the `_ds_bundle.js` header re-hashes to the header's sha-256 (browser replication of `ci/check-bundle-freshness.mjs`; the Node script stays the CI authority and additionally discovers new files); manifest component sources ⊆ header | 0 drifted / missing sources (`__bundlefresh`) | Hard | Fast board CI (+ Node authority in `node-prechecks`) |
|
|
26
|
-
| ESM smoke test | `_audit/esm-smoke-test.html` | `_esm/cs.mjs` imports without a build, re-exports every manifest component, and a mounted Button receives brand tokens | Export/manifest parity + token check (`__esm`) | Hard | Fast board CI |
|
|
27
|
-
| Package exports integrity | `_audit/package-exports-integrity.html` | Every `package.json` `files` entry and every `module`/`style`/`exports` target exists; every entry-point target is covered by `files` (pack-safe); `_esm/cs.mjs`
|
|
29
|
+
| ESM smoke test | `_audit/esm-smoke-test.html` | `_esm/cs.mjs` imports without a build, re-exports every manifest component, `VERSION` equals the root `VERSION` pin, and a mounted Button receives brand tokens | Export/manifest parity + VERSION pin + token check (`__esm`) | Hard | Fast board CI |
|
|
30
|
+
| Package exports integrity | `_audit/package-exports-integrity.html` | Every `package.json` `files` entry and every `module`/`types`/`style`/`exports` target exists; every entry-point target is covered by `files` (pack-safe); dual entries — `_esm/react.mjs` (default / `./react`, React peer) + `_esm/cs.mjs` (`./legacy`) — are ESM-shaped and their re-exports ⊆ the bundle header's exposed exports | 0 missing / uncovered / unknown (`__pkgexports`) | Hard | Fast board CI |
|
|
28
31
|
| Component children | `_audit/component-children-test.html` | Void-element components (Checkbox, Radio, Switch, SearchField, NumberField, Slider, Divider, TextField) mount with stray children without throwing React #137 | 0 throws (`__result.anyThrew === false`) | Hard | Fast board CI |
|
|
29
|
-
| Component behavior | `_audit/component-behavior-test.html` |
|
|
30
|
-
| A11y interactions | `_audit/a11y-gate.html` | Focus management (Dialog/Drawer trap + restore + Escape), roving tabindex, combobox `aria-activedescendant`, role/label contracts | All keyboard/ARIA assertions pass (`__a11y`) | Hard | Fast board CI |
|
|
32
|
+
| Component behavior | `_audit/component-behavior-test.html` | 78 real interaction assertions — every interactive public primary with a user-driven contract (overlays, forms, AI gates, shell chrome, media/copy); display-only primaries excluded by design | 78/78 assertions pass (`__behavior`) | Hard | Fast board CI |
|
|
33
|
+
| A11y interactions | `_audit/a11y-gate.html` | Focus management (Dialog/Drawer trap + restore + Escape), roving tabindex, combobox `aria-activedescendant`, role/label contracts, plus open-state Esc/focus for Cascader · TreeSelect · Tour · HoverCard · ContextMenu | All keyboard/ARIA assertions pass (`__a11y`) | Hard | Fast board CI |
|
|
31
34
|
| A11y CSSOM | `_audit/a11y-harness.html` | Every interactive `.cs-*` control meets its documented touch-target floor under coarse pointer; focus-ring, reduced-motion, and contrast rules proven in source CSS | 0 floor violations, all source proofs found (`__a11ycss`) | Hard | Fast board CI |
|
|
32
|
-
| Template schema v2 | `_audit/template-schema-test.html` | Every `content-schema.json` sidecar validates against the JSON Schema
|
|
35
|
+
| Template schema v2 | `_audit/template-schema-test.html` | Every `content-schema.json` sidecar validates against the JSON Schema, every declared slot id resolves to a real `{{ hole }}` in its template, and every template exposing an authorable **content** hole ships a sidecar (axis/control-flow and boolean tweak holes excluded — see `docs/template-schema-v2.md`) | 0 invalid sidecars, 0 dangling slot ids, 0 hole-driven templates without a sidecar (`__schemav2`) | Hard | Fast board CI |
|
|
33
36
|
| Support runtime identity | `_audit/support-runtime-identity.html` | All `templates/*/support.js` copies (one per template, 84) are byte-identical: sha-256 via SubtleCrypto, exactly one unique hash, copy count == manifest template count | 1 unique hash, count match (`__supportid`) | Hard | Fast board CI |
|
|
34
37
|
| Bilingual parity | `_audit/bilingual-parity.html` | Every component in `components/_i18n/strings.js` has en + vi tables with equal key sets and no empty values | 0 missing/extra keys, 0 empty values (`__bilingual`) | Hard | Fast board CI + merge blocker |
|
|
35
38
|
| Template language parity | `_audit/template-lang-parity.html` | Static source scan of all 84 `.dc.html`: en/vi hole-map key sets identical and non-empty (21 map templates); `sc-if` `isEN`/`isVN` branches paired (24 branch templates); every `language`-tweak template has a bilingual mechanism; EN-leak lexicon (Unsubscribe · View in browser · Preferences · All rights reserved · Manage subscription · Sent with) never appears outside `isEN` guards / the `en` map. VN-first stacked instruments (37 `vn-*` + 3 `doc-*`) are leak-exempt by design — both languages always render | 0 key drifts, 0 unpaired branches, 0 leaks (`__langparity`) | Hard | Fast board CI |
|
|
36
39
|
| APCA dark packs | `_audit/apca-dark-preview.html` | All 15 element×variant packs hold their APCA targets in dark (bright-as-text ≥ 75, accent UI ≥ 60, ink-on-accent ≥ 75, ink-on-tint ≥ 75) | 0 current failures (`__apcaPreview.currentFail === 0`) | Hard | Fast board CI |
|
|
40
|
+
| Element geometry | `_audit/element-geometry.html` | Soft/middle/deep intensity sync across five elements; variant distinctness; light↔dark hue identity; Thổ middle pins logo ochre; packs generated from seeds | `__elementgeometry.pass` | Hard | Fast board CI |
|
|
41
|
+
| Style contract | `_audit/style-contract.html` | Style axis allowlist: sole pack `liquid-glass` (absent ≡ default); `styles.css` imports `tokens/styles.css`; `--cs-style-pack` resolves; no unknown `data-cs-style` in scanned sources | `__stylecontract.pass` | Hard | Fast board CI |
|
|
37
42
|
| Visual baselines | `_audit/visual-diff.html` | Template baselines exist and are loadable for side-by-side / overlay comparison | Baselines present; drift judged by eye (`__visualdiff`) | Advisory | Fast board CI |
|
|
38
43
|
| Component baselines | `_audit/component-visual-diff.html` | 12 curated component crops anchor the atomic tiers for visual comparison | Crops render + baselines present (`__componentVisualDiff`) | Advisory | Fast board CI |
|
|
39
|
-
| Axe smoke | `_audit/axe-smoke.html` | axe-core 4.10.0 (vendored at `_audit/vendor/axe.min.js`) serious/critical rules on
|
|
44
|
+
| Axe smoke | `_audit/axe-smoke.html` + `_audit/lib/axe-fixtures.js` | axe-core 4.10.0 (vendored at `_audit/vendor/axe.min.js`) serious/critical WCAG 2 A/AA rules on every public primary (inventory-locked fixtures; bilingual EN·VI) — Dialog, AlertDialog, Drawer, Tour, CommandPalette, and Menu mount open, and Cascader / TreeSelect / Menubar / Combobox surfaces are expanded before the scan; gate-equivalent Storybook a11y enforcement (no separate test-runner) | 0 serious/critical findings (`__axesmoke`) | Hard | Fast board CI |
|
|
40
45
|
| Print smoke | `_audit/print-smoke.html` | Document templates declare the print-ownership meta and `@page` CSS hooks the export path relies on | 0 documents missing print hooks (`__printsmoke`) | Hard | Fast board CI |
|
|
41
|
-
| Pixel CI | `_audit/pixel-ci.html` + `_audit/ci/pixel-diff.mjs` |
|
|
46
|
+
| Pixel CI | `_audit/pixel-ci.html` + `_audit/ci/pixel-diff.mjs` | 15 curated baselines exist; Playwright capture script performs real % pixel compare; last report must be clean (`drifted[]` empty) | Contract + clean compare (`__pixelci.pass`); drift or missing report fails | Hard | Fast board CI (compare step feeds the row) + `pixel-diff` job |
|
|
42
47
|
|
|
43
48
|
## Whole-set audits — every template, every axis
|
|
44
49
|
|
|
@@ -56,35 +61,44 @@ Every deterministic quality gate in the system, what it asserts, its pass criter
|
|
|
56
61
|
| Bundle freshness (authority) | `_audit/ci/check-bundle-freshness.mjs` | The committed `_ds_bundle.js` was built from the component sources as they exist now — full source discovery (walks `components/`, `ui_kits/`, root sources), so new/deleted files are caught too, which the browser row cannot do | Exit 0, 0 drifted/new/deleted sources | Hard | CI `node-prechecks` job |
|
|
57
62
|
| DESIGN.md freshness | `scripts/generate-design-md.mjs --check` | The root `DESIGN.md` byte-equals a fresh regeneration from DTCG + manifest + `VERSION` | Exit 0 on byte match | Hard | CI `node-prechecks` job |
|
|
58
63
|
|
|
59
|
-
## Unit tests — `npm run test:unit` (
|
|
64
|
+
## Unit tests — `npm run test:unit` (11)
|
|
60
65
|
|
|
61
66
|
| Test | File | What it asserts | Pass criterion | Type | Where it runs |
|
|
62
67
|
|---|---|---|---|---|---|
|
|
63
68
|
| Nav model | `_audit/ci/test-nav-model.mjs` | The shipped `guidelines/nav-model.js` classify/group logic behaves (drives the real module) | All assertions pass (exit 0) | Hard | Unit test |
|
|
64
69
|
| Health/Tokens UI contract | `_audit/ci/test-health-tokens-contract.mjs` | Structural contracts of the Health + Tokens HTML entry points hold | All assertions pass (exit 0) | Hard | Unit test |
|
|
65
70
|
| Form paths | `_audit/ci/test-form-paths.mjs` | Form path helpers behave (drives the shipped `Form.jsx` via dynamic import) | All assertions pass (exit 0) | Hard | Unit test |
|
|
66
|
-
| Storybook contract | `_audit/ci/test-storybook-contract.mjs` | Live hub is Storybook only; SB10 ESM main + addon-docs/a11y; complete CSF for every public primary; Matrix/AllVariants + AllSizes when `argTypes.size`; States/Matrix cover disabled/loading/error/busy; every discrete size/variant enum mounted; FullMatrix required when ≥
|
|
71
|
+
| Storybook contract | `_audit/ci/test-storybook-contract.mjs` | Live hub is Storybook only; SB10 ESM main + addon-docs/a11y; complete CSF for every public primary; Matrix/AllVariants + AllSizes when `argTypes.size`; States/Matrix cover disabled/loading/error/busy; every discrete size/variant enum mounted; FullMatrix required when ≥1 of {size, variant, state} axes exist (≥28 qualifiers) | All assertions pass (exit 0) | Hard | Unit test |
|
|
72
|
+
| Axe coverage | `_audit/ci/test-axe-coverage.mjs` | Fixture `NAMES` ≡ `listPublicComponents()`; axe-smoke loads inventory-locked fixtures | All assertions pass (exit 0) | Hard | Unit test |
|
|
67
73
|
| Figma push helpers | `_audit/ci/test-figma-push-helpers.mjs` | Pure helpers in `push-figma-variables.mjs` behave (no network, no secrets) | All assertions pass (exit 0) | Hard | Unit test |
|
|
68
|
-
| Code Connect helpers | `_audit/ci/test-code-connect.mjs` |
|
|
74
|
+
| Code Connect helpers | `_audit/ci/test-code-connect.mjs` | 105 primaries, node-map/render helpers, soft-skip classifiers, committed `figma.config.json` + high-traffic `.figma.tsx` | All assertions pass (exit 0) | Hard | Unit test |
|
|
69
75
|
| Native samples | `_audit/ci/test-native-samples.mjs` | SwiftUI / Compose / Flutter sample apps each have ≥ 3 screens, reference generated token constants, and ship Fastlane store scaffolds (submit disabled) | All assertions pass (exit 0) | Hard | Unit test |
|
|
70
76
|
| Subtree consume | `_audit/ci/test-subtree-consume.mjs` | Portable copy of `styles.css` + `base/` + `tokens/` + `fonts/` + `_esm/` + `_ds_bundle.js` (no full clone) still resolves tokens/fonts and mounts a Button via ESM — Stitch/Claude subtree-copy path | All assertions pass (exit 0) | Hard | Unit test |
|
|
77
|
+
| React entry | `_audit/ci/test-react-entry.mjs` | Dual package exports (`.` / `./react` → `_esm/react.mjs`, `./legacy` → `_esm/cs.mjs`); VERSION pin 1.1.0; React peerDeps; react.mjs has no CDN/bundle bridge and re-exports match the bundle header; `generate-react-entry --check` green | All assertions pass (exit 0) | Hard | Unit test |
|
|
78
|
+
| Element packs | `_audit/ci/test-element-packs.mjs` | `tokens/elements.css` + JSON/JS/DTCG mirrors byte-equal regeneration from `tokens/element-seeds.json` | `generate-element-packs --check` exit 0 | Hard | Unit test |
|
|
71
79
|
|
|
72
80
|
The `test:unit` suite is wired into the CI workflow as part of the July 2026 hardening change (it previously only ran locally).
|
|
73
81
|
|
|
74
82
|
## Sync / distribution jobs (soft-skip)
|
|
75
83
|
|
|
76
|
-
Soft-skip means the job exits 0 with a report when secrets/plan/API cannot complete the real write — **not** that
|
|
84
|
+
Soft-skip means the job exits 0 with a report when secrets/plan/API cannot complete the real write — **not** that Code Connect or Figma Variables are live. npm CI publish uses Trusted Publishing; soft-skip covers auth/conflict honesty. Treat remaining maintainer tasks in `docs/decisions.md` as the open list (Code Connect deferred; consumer grant is in `docs/consumer-grant.md`). Storybook `FullMatrix` is required for every public primary with ≥1 of {size enums, variant enums, state keys} — shared helpers in `stories/lib/matrix.jsx`.
|
|
77
85
|
|
|
78
86
|
| Job | Script / workflow | What it asserts | Soft-skip when | Where it runs |
|
|
79
87
|
|---|---|---|---|---|
|
|
80
|
-
| Figma Variables | `_audit/ci/push-figma-variables.mjs` + `figma-variables-push` job | Secrets open the file; optional Variables write |
|
|
81
|
-
| Code Connect | `_audit/ci/code-connect-publish.mjs` + `code-connect` job | Config +
|
|
82
|
-
| npm publish | `_audit/ci/npm-publish.mjs` + `npm-publish.yml` | Pack-safe `files`/`exports`;
|
|
88
|
+
| Figma Variables | `_audit/ci/push-figma-variables.mjs` + `figma-variables-push` job | Secrets open the file; optional Variables write | Soft-skip when secrets missing (same honesty as Code Connect) or non-Enterprise / missing `file_variables:*` scopes / API **403** after secrets are present. Soft-skip ≠ live sync | `main` push + manual |
|
|
89
|
+
| Code Connect | `_audit/ci/code-connect-publish.mjs` + `code-connect` job | Config + 105 mappings; optional publish | Missing `FIGMA_TOKEN`/`FIGMA_FILE_KEY` or API 403/404/429 | PR + `main` + manual |
|
|
90
|
+
| npm publish | `_audit/ci/npm-publish.mjs` + `npm-publish.yml` | Pack-safe `files`/`exports`; `npm publish` via OIDC Trusted Publishing (tokens disallowed on package) | Auth / 403 / 404 / EOTP / version conflict | `workflow_dispatch` / `v*` tags |
|
|
83
91
|
| Native store | `_audit/ci/native-store-dry-run.mjs` + `native-store.yml` | Fastlane scaffolds + metadata; signed-release secrets check | Missing `ASC_*` / `PLAY_SERVICE_ACCOUNT_JSON` (submit always disabled) | PR + `main` (paths) + manual |
|
|
84
92
|
|
|
93
|
+
## Registry consumer smoke (hard)
|
|
94
|
+
|
|
95
|
+
| Job | Script / workflow | What it asserts | Pass criterion | Where it runs |
|
|
96
|
+
|---|---|---|---|---|
|
|
97
|
+
| npm-hello smoke | `examples/npm-hello` + `npm-hello-smoke` job | Public registry install of `@cyberskill/design@1.1.0` resolves package name + exports (`npm install` + `npm run smoke`; local pack proof if VERSION not on registry yet) | Exit 0 (**hard fail** once published; soft-skip pack proof if VERSION not on registry yet) | Path-filtered push/PR + nightly + manual |
|
|
98
|
+
|
|
85
99
|
## July 2026 hardening — delivered
|
|
86
100
|
|
|
87
|
-
The eight gates the audit planned (token-format-parity, version-stamp, support-runtime-identity, package-exports-integrity, template-lang-parity, dtcg-typing, bundle-freshness, design-md-parity) are now **implemented** — see their rows in the fast-board and Node-pre-check tables above. All are wired into `_audit/run.html`, `_audit/index.html`, the CI workflow (`fast-gates` picks the board rows up automatically; `node-prechecks` + `unit-tests` are new jobs)
|
|
101
|
+
The eight gates the audit planned (token-format-parity, version-stamp, support-runtime-identity, package-exports-integrity, template-lang-parity, dtcg-typing, bundle-freshness, design-md-parity) are now **implemented** — see their rows in the fast-board and Node-pre-check tables above. All are wired into `_audit/run.html`, `_audit/index.html`, and the CI workflow (`fast-gates` picks the board rows up automatically; `node-prechecks` + `unit-tests` are new jobs). Operators browse Health via Storybook **Status** (full-bleed `_audit/run.html`) and the audit index at `_audit/index.html` — `dashboard.html` is redirect-only and has no Health tab. The docs-consistency gate carries the stale-phrase blacklist (retired suite/pack counts) + `DESIGN.md` stamp extensions described in its row. The docs-lang-parity gate locks the `docs/vi/` mirror.
|
|
88
102
|
|
|
89
103
|
## Human-reviewed, never automated
|
|
90
104
|
|
package/docs/release-notes.md
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
|
-
Curated product highlights for operators. This is **not** a git log and **not** a `CHANGELOG.md` — the design system does not maintain a changelog file. Version
|
|
3
|
+
Curated product highlights for operators. This is **not** a git log and **not** a `CHANGELOG.md` — the design system does not maintain a changelog file. Version is **LAUNCHED at 1.1.0** (owner instruction Jul 2026); further bumps need an explicit owner instruction. Technical continuity is the repo tip; product-facing continuity is this page (mirrored in Storybook **Release Notes**).
|
|
4
|
+
|
|
5
|
+
## LAUNCH — `@cyberskill/design@1.1.0`
|
|
6
|
+
|
|
7
|
+
Owner **LAUNCH** cut. `VERSION` / `package.json` and every version stamp move from the pre-LAUNCH **1.0.0** pin to **1.1.0**. Publish via **npm Trusted Publishing (OIDC)** on tag `v1.1.0` (or `workflow_dispatch`). Package Publishing access on npmjs **disallows tokens**. Soft-skip on the npm-hello registry install is honest until **1.1.0** is live on the registry — soft-skip ≠ published.
|
|
8
|
+
|
|
9
|
+
Approved use for CyberSkill portfolio products remains in **`docs/consumer-grant.md`** (+ VI). The package remains **UNLICENSED**. First-consumer browser path: `examples/npm-hello/` (Lumi · Hỏa · plasma) — see `docs/consuming.md`.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @cyberskill/design@1.1.0
|
|
13
|
+
```
|
|
4
14
|
|
|
5
15
|
## Storybook at the domain root
|
|
6
16
|
|
|
7
17
|
`design.cyberskill.world/` is the full Storybook product site. Docs, Foundations, Components, Release Notes, and Status live in one sidebar. Legacy `/dashboard` and `/playground` paths redirect to `/`.
|
|
8
18
|
|
|
9
|
-
Portable consumers
|
|
19
|
+
Portable consumers: `styles.css`, `_ds_bundle.js`, bundler-native `_esm/react.mjs` (default `exports["."]`; React peer), and browser legacy `_esm/cs.mjs` (`@cyberskill/design/legacy`). Storybook is host-only tooling.
|
|
10
20
|
|
|
11
21
|
## Quality gates on Status
|
|
12
22
|
|
|
@@ -18,7 +28,7 @@ Public operator docs ship EN·VI pairs under `docs/` / `docs/vi/`. Templates rem
|
|
|
18
28
|
|
|
19
29
|
## Foundations and CSF library
|
|
20
30
|
|
|
21
|
-
Theme × Element × Language toolbar globals mirror production templates. Every public primary ships a Default story plus an honest control matrix. Foundations cover colors, typography, spacing, elevation, motion, and the 15 Ngũ Hành element packs.
|
|
31
|
+
Theme × Element × Language × Style toolbar globals mirror production templates (Theme includes **system** for OS `prefers-color-scheme`). Every public primary ships a Default story plus an honest control matrix; FullMatrix covers every ≥1-axis qualifier. Axe smoke scans all public primaries. Style’s sole pack is **liquid-glass**. Foundations cover colors, typography, spacing, elevation, motion, and the 15 Ngũ Hành element packs.
|
|
22
32
|
|
|
23
33
|
## Tokens and native mirrors
|
|
24
34
|
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
+
<rect width="64" height="64" rx="14" fill="#45210E"/>
|
|
3
|
+
<rect y="50" width="64" height="14" fill="#F4BA17"/>
|
|
4
|
+
<text x="32" y="42" font-family="Georgia, 'Times New Roman', serif" font-size="34" font-weight="700" fill="#ffffff" text-anchor="middle">D</text>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/* Generated by @cyberskill/tokens. Do not edit directly. */
|
|
2
|
+
:root {
|
|
3
|
+
/* Light is the default theme. Dark/system are opt-in via [data-theme] (see @cyberskill/react theme layer). */
|
|
4
|
+
color-scheme: light;
|
|
5
|
+
--cs-color-brand-umber: #45210E;
|
|
6
|
+
--cs-color-brand-ochre: #F4BA17;
|
|
7
|
+
--cs-color-surface-page: #FFFDF8;
|
|
8
|
+
--cs-color-surface-panel: #FFFFFF;
|
|
9
|
+
--cs-color-surface-raised: #FBF4E9;
|
|
10
|
+
--cs-color-text-primary: #45210E;
|
|
11
|
+
--cs-color-text-inverse: #FFFFFF;
|
|
12
|
+
--cs-color-text-accent: #6E3B0E;
|
|
13
|
+
--cs-color-text-muted: #6E5A4C;
|
|
14
|
+
--cs-color-semantic-success: #166534;
|
|
15
|
+
--cs-color-semantic-danger: #B42318;
|
|
16
|
+
--cs-color-semantic-warning: #92400E;
|
|
17
|
+
--cs-color-semantic-info: #1D4ED8;
|
|
18
|
+
--cs-color-accent-ochre: #F4BA17;
|
|
19
|
+
--cs-color-border-default: #E7D9C6;
|
|
20
|
+
--cs-space-0: 0px;
|
|
21
|
+
--cs-space-1: 4px;
|
|
22
|
+
--cs-space-2: 8px;
|
|
23
|
+
--cs-space-3: 12px;
|
|
24
|
+
--cs-space-4: 16px;
|
|
25
|
+
--cs-space-5: 20px;
|
|
26
|
+
--cs-space-6: 24px;
|
|
27
|
+
--cs-space-8: 32px;
|
|
28
|
+
--cs-space-10: 40px;
|
|
29
|
+
--cs-space-12: 48px;
|
|
30
|
+
--cs-space-16: 64px;
|
|
31
|
+
--cs-space-20: 80px;
|
|
32
|
+
--cs-space-24: 96px;
|
|
33
|
+
--cs-radius-sm: 4px;
|
|
34
|
+
--cs-radius-md: 8px;
|
|
35
|
+
--cs-radius-full: 999px;
|
|
36
|
+
--cs-font-family-ui: Be Vietnam Pro, ui-sans-serif, system-ui;
|
|
37
|
+
--cs-font-family-mono: JetBrains Mono, ui-monospace, SFMono-Regular, Menlo, Consolas;
|
|
38
|
+
--cs-font-lineHeight-body: 1.5;
|
|
39
|
+
--cs-font-lineHeight-heading: 1.35;
|
|
40
|
+
--cs-component-button-primary-bg: #45210E;
|
|
41
|
+
--cs-component-button-primary-fg: #FFFFFF;
|
|
42
|
+
--cs-component-button-gap: 8px;
|
|
43
|
+
--cs-component-button-radius: 8px;
|
|
44
|
+
--cs-component-button-sm-paddingY: 8px;
|
|
45
|
+
--cs-component-button-sm-paddingX: 14px;
|
|
46
|
+
--cs-component-button-sm-minHeight: 36px;
|
|
47
|
+
--cs-component-button-md-paddingY: 12px;
|
|
48
|
+
--cs-component-button-md-paddingX: 20px;
|
|
49
|
+
--cs-component-button-md-minHeight: 44px;
|
|
50
|
+
--cs-component-button-lg-paddingY: 16px;
|
|
51
|
+
--cs-component-button-lg-paddingX: 28px;
|
|
52
|
+
--cs-component-button-lg-minHeight: 52px;
|
|
53
|
+
--cs-component-textfield-border-default: #BFA58F;
|
|
54
|
+
--cs-component-textfield-paddingY: 10px;
|
|
55
|
+
--cs-component-textfield-paddingX: 12px;
|
|
56
|
+
--cs-component-textfield-minHeight: 44px;
|
|
57
|
+
--cs-breakpoint-xs: 0px;
|
|
58
|
+
--cs-breakpoint-sm: 640px;
|
|
59
|
+
--cs-breakpoint-md: 768px;
|
|
60
|
+
--cs-breakpoint-lg: 1024px;
|
|
61
|
+
--cs-breakpoint-xl: 1280px;
|
|
62
|
+
--cs-breakpoint-2xl: 1536px;
|
|
63
|
+
--cs-depth-bg: 0;
|
|
64
|
+
--cs-depth-section: 5;
|
|
65
|
+
--cs-depth-card: 10;
|
|
66
|
+
--cs-depth-nav: 50;
|
|
67
|
+
--cs-depth-modal: 100;
|
|
68
|
+
--cs-depth-toast: 200;
|
|
69
|
+
--cs-glass-whisper-blur: 8px;
|
|
70
|
+
--cs-glass-whisper-saturate: 110%;
|
|
71
|
+
--cs-glass-whisper-opacity: 60%;
|
|
72
|
+
--cs-glass-light-blur: 12px;
|
|
73
|
+
--cs-glass-light-saturate: 130%;
|
|
74
|
+
--cs-glass-light-opacity: 70%;
|
|
75
|
+
--cs-glass-standard-blur: 16px;
|
|
76
|
+
--cs-glass-standard-saturate: 150%;
|
|
77
|
+
--cs-glass-standard-opacity: 80%;
|
|
78
|
+
--cs-glass-heavy-blur: 24px;
|
|
79
|
+
--cs-glass-heavy-saturate: 180%;
|
|
80
|
+
--cs-glass-heavy-opacity: 90%;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* status.css - the stylesheet for status-hub@2 (one page, three lenses).
|
|
84
|
+
Built on @cyberskill/tokens; tokens.css is prepended at render time.
|
|
85
|
+
Contract: raw colour literals live ONLY in the two token blocks below. Every component
|
|
86
|
+
rule speaks in var(--cs-*). Dark is opt-in via [data-theme="dark"] on <html>, per CDS. */
|
|
87
|
+
|
|
88
|
+
:root {
|
|
89
|
+
/* page-local tokens: the CDS palette has no "text on a filled chip" role */
|
|
90
|
+
--cs-status-on-ochre: #45210E; /* text on ochre fills - dark in both themes */
|
|
91
|
+
--cs-status-on-fill: #FFFFFF; /* text on success / danger fills */
|
|
92
|
+
--cs-status-todo: #E7D9C6; /* the "draft" segment - readable in both themes */
|
|
93
|
+
--cs-status-header-bg: #45210E;
|
|
94
|
+
--cs-status-header-fg: #FFFFFF;
|
|
95
|
+
--cs-status-scrim: rgba(23, 17, 12, .45);
|
|
96
|
+
--cs-status-shadow: rgba(23, 17, 12, .22);
|
|
97
|
+
--cs-status-ghost-border: rgba(255, 255, 255, .25);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
[data-theme="dark"] {
|
|
101
|
+
color-scheme: dark;
|
|
102
|
+
--cs-color-brand-umber: #F0E3D4;
|
|
103
|
+
--cs-color-brand-ochre: #F4BA17;
|
|
104
|
+
--cs-color-surface-page: #17110C;
|
|
105
|
+
--cs-color-surface-panel: #211913;
|
|
106
|
+
--cs-color-surface-raised: #2C221A;
|
|
107
|
+
--cs-color-text-primary: #F3E9DC;
|
|
108
|
+
--cs-color-text-inverse: #17110C;
|
|
109
|
+
--cs-color-text-accent: #E9BE86;
|
|
110
|
+
--cs-color-text-muted: #A9917C;
|
|
111
|
+
--cs-color-semantic-success: #35A264;
|
|
112
|
+
--cs-color-semantic-danger: #E4756A;
|
|
113
|
+
--cs-color-semantic-warning: #D9A441;
|
|
114
|
+
--cs-color-semantic-info: #7BA6F5;
|
|
115
|
+
--cs-color-border-default: #3B2E24;
|
|
116
|
+
--cs-component-textfield-border-default: #55432F;
|
|
117
|
+
--cs-status-header-bg: #120D09;
|
|
118
|
+
--cs-status-header-fg: #F3E9DC;
|
|
119
|
+
--cs-status-on-fill: #17110C;
|
|
120
|
+
--cs-status-todo: #59452F;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* ---- base ---------------------------------------------------------------- */
|
|
124
|
+
* { box-sizing: border-box; }
|
|
125
|
+
html { scroll-behavior: smooth; }
|
|
126
|
+
body {
|
|
127
|
+
margin: 0;
|
|
128
|
+
background: var(--cs-color-surface-page);
|
|
129
|
+
color: var(--cs-color-text-primary);
|
|
130
|
+
font-family: var(--cs-font-family-ui);
|
|
131
|
+
font-size: 15px;
|
|
132
|
+
line-height: var(--cs-font-lineHeight-body);
|
|
133
|
+
-webkit-font-smoothing: antialiased;
|
|
134
|
+
}
|
|
135
|
+
a { color: var(--cs-color-text-accent); }
|
|
136
|
+
button { font: inherit; color: inherit; }
|
|
137
|
+
.wrap { max-width: 1320px; margin: 0 auto; padding: 0 var(--cs-space-6); }
|
|
138
|
+
.mono, .code { font-family: var(--cs-font-family-mono); }
|
|
139
|
+
.muted { color: var(--cs-color-text-muted); }
|
|
140
|
+
.skip { position: absolute; left: -9999px; }
|
|
141
|
+
.skip:focus { left: var(--cs-space-4); top: var(--cs-space-2); z-index: var(--cs-depth-toast);
|
|
142
|
+
background: var(--cs-color-brand-ochre); color: var(--cs-status-on-ochre);
|
|
143
|
+
padding: var(--cs-space-2) var(--cs-space-3); border-radius: var(--cs-radius-md); }
|
|
144
|
+
:focus-visible { outline: 2px solid var(--cs-color-brand-ochre); outline-offset: 2px; }
|
|
145
|
+
|
|
146
|
+
/* ---- header -------------------------------------------------------------- */
|
|
147
|
+
.hd { background: var(--cs-status-header-bg); color: var(--cs-status-header-fg);
|
|
148
|
+
border-bottom: 3px solid var(--cs-color-brand-ochre); }
|
|
149
|
+
.hd-in { display: flex; align-items: center; justify-content: space-between; gap: var(--cs-space-6);
|
|
150
|
+
padding: var(--cs-space-5) var(--cs-space-6); flex-wrap: wrap; }
|
|
151
|
+
.hd-id { display: flex; align-items: center; gap: var(--cs-space-4); }
|
|
152
|
+
.hd-mark { width: 42px; height: 42px; flex: none; display: grid; place-items: center;
|
|
153
|
+
border-radius: 12px; background: var(--cs-color-brand-ochre); color: var(--cs-status-on-ochre);
|
|
154
|
+
font-family: Georgia, "Times New Roman", serif; font-size: 22px; font-weight: 700; }
|
|
155
|
+
.hd h1 { margin: 0; font-size: 24px; letter-spacing: .2px; line-height: var(--cs-font-lineHeight-heading); }
|
|
156
|
+
.hd-sub { margin: 2px 0 0; font-size: 13.5px; opacity: .8; }
|
|
157
|
+
.hd-side { display: flex; align-items: center; gap: var(--cs-space-4); }
|
|
158
|
+
.hd-meta { margin: 0; font-size: 12.5px; opacity: .75; text-align: right; }
|
|
159
|
+
|
|
160
|
+
/* ---- buttons ------------------------------------------------------------- */
|
|
161
|
+
.btn { border: 1px solid var(--cs-color-border-default); background: var(--cs-color-surface-panel);
|
|
162
|
+
color: var(--cs-color-text-primary); border-radius: var(--cs-radius-md);
|
|
163
|
+
padding: 7px 12px; cursor: pointer; font-size: 13.5px; font-weight: 600; }
|
|
164
|
+
.btn:hover { border-color: var(--cs-color-brand-ochre); }
|
|
165
|
+
.btn.sm { padding: 5px 10px; font-size: 12.5px; }
|
|
166
|
+
.hd .btn.ghost { background: transparent; border-color: var(--cs-status-ghost-border);
|
|
167
|
+
color: var(--cs-status-header-fg); width: 36px; height: 36px; padding: 0; }
|
|
168
|
+
|
|
169
|
+
/* ---- deck ---------------------------------------------------------------- */
|
|
170
|
+
.deck { margin: var(--cs-space-6) 0 var(--cs-space-4); display: grid; gap: var(--cs-space-4);
|
|
171
|
+
grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); align-items: stretch; }
|
|
172
|
+
.panel { background: var(--cs-color-surface-panel); border: 1px solid var(--cs-color-border-default);
|
|
173
|
+
border-radius: 14px; padding: var(--cs-space-4) var(--cs-space-5); }
|
|
174
|
+
.panel > h2 { margin: 0 0 var(--cs-space-3); font-size: 12px; text-transform: uppercase;
|
|
175
|
+
letter-spacing: .09em; color: var(--cs-color-text-muted); }
|
|
176
|
+
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: var(--cs-space-3);
|
|
177
|
+
margin-bottom: var(--cs-space-4); }
|
|
178
|
+
.kpi { text-align: left; border: 0; background: transparent; padding: 0; border-radius: var(--cs-radius-md); }
|
|
179
|
+
button.kpi { cursor: pointer; }
|
|
180
|
+
.kpi b { display: block; font-size: 24px; line-height: 1.15; }
|
|
181
|
+
.kpi span { font-size: 12px; color: var(--cs-color-text-muted); }
|
|
182
|
+
.kpi[data-on="1"] b, button.kpi:hover b { color: var(--cs-color-text-accent); }
|
|
183
|
+
.bar-seg { height: 12px; border-radius: var(--cs-radius-full); background: var(--cs-color-surface-raised);
|
|
184
|
+
overflow: hidden; display: flex; }
|
|
185
|
+
.bar-seg i { display: block; height: 100%; }
|
|
186
|
+
.seg-done { background: var(--cs-color-semantic-success); }
|
|
187
|
+
.seg-active { background: var(--cs-color-brand-ochre); }
|
|
188
|
+
.seg-hold { background: var(--cs-color-semantic-danger); }
|
|
189
|
+
.seg-todo { background: var(--cs-status-todo); }
|
|
190
|
+
.legend { display: flex; gap: var(--cs-space-4); flex-wrap: wrap; margin-top: var(--cs-space-3);
|
|
191
|
+
font-size: 12.5px; color: var(--cs-color-text-muted); }
|
|
192
|
+
.legend span { display: inline-flex; align-items: center; gap: 6px; }
|
|
193
|
+
.dot { width: 10px; height: 10px; border-radius: 3px; display: inline-block; margin-right: 5px; }
|
|
194
|
+
.spark { display: flex; align-items: flex-end; gap: 6px; height: 78px; margin-top: var(--cs-space-2); }
|
|
195
|
+
.spark a { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; align-items: center;
|
|
196
|
+
gap: 4px; text-decoration: none; color: var(--cs-color-text-muted); font-size: 10.5px; }
|
|
197
|
+
.spark i { display: block; width: 100%; background: var(--cs-color-brand-ochre);
|
|
198
|
+
border-radius: 4px 4px 0 0; min-height: 3px; }
|
|
199
|
+
.spark a:hover i { background: var(--cs-color-text-accent); }
|
|
200
|
+
.spark b { font-size: 11px; color: var(--cs-color-text-primary); font-weight: 600; }
|
|
201
|
+
|
|
202
|
+
/* ---- now shipping -------------------------------------------------------- */
|
|
203
|
+
.now { background: var(--cs-color-surface-raised); border: 1px solid var(--cs-color-brand-ochre);
|
|
204
|
+
border-left: 4px solid var(--cs-color-brand-ochre); border-radius: 12px;
|
|
205
|
+
padding: var(--cs-space-4) var(--cs-space-5); margin-bottom: var(--cs-space-4); }
|
|
206
|
+
.now h2 { margin: 0 0 var(--cs-space-2); font-size: 13px; text-transform: uppercase; letter-spacing: .08em; }
|
|
207
|
+
|
|
208
|
+
/* ---- command bar --------------------------------------------------------- */
|
|
209
|
+
.bar { position: sticky; top: 0; z-index: var(--cs-depth-nav);
|
|
210
|
+
background: var(--cs-color-surface-page);
|
|
211
|
+
border: 1px solid var(--cs-color-border-default); border-radius: 14px;
|
|
212
|
+
padding: var(--cs-space-3) var(--cs-space-4); margin-bottom: var(--cs-space-4); }
|
|
213
|
+
.bar-top { display: flex; gap: var(--cs-space-3); align-items: center; flex-wrap: wrap; }
|
|
214
|
+
.bar-bot { display: flex; gap: var(--cs-space-2); align-items: center; flex-wrap: wrap;
|
|
215
|
+
margin-top: var(--cs-space-3); }
|
|
216
|
+
.srch { flex: 1 1 340px; display: flex; align-items: center; gap: var(--cs-space-2);
|
|
217
|
+
background: var(--cs-color-surface-panel); border: 1px solid var(--cs-component-textfield-border-default);
|
|
218
|
+
border-radius: var(--cs-radius-full); padding: 0 var(--cs-space-4); min-height: 42px; }
|
|
219
|
+
.srch:focus-within { border-color: var(--cs-color-brand-ochre); }
|
|
220
|
+
.srch .ic { color: var(--cs-color-text-muted); font-size: 17px; }
|
|
221
|
+
.srch input { flex: 1; border: 0; background: transparent; outline: 0; min-width: 0;
|
|
222
|
+
color: var(--cs-color-text-primary); font-size: 14px; }
|
|
223
|
+
.lenses { display: flex; gap: 4px; background: var(--cs-color-surface-raised);
|
|
224
|
+
border: 1px solid var(--cs-color-border-default); border-radius: var(--cs-radius-full); padding: 3px; }
|
|
225
|
+
.ln { border: 0; background: transparent; border-radius: var(--cs-radius-full);
|
|
226
|
+
padding: 7px 15px; font-size: 13.5px; font-weight: 600; cursor: pointer; color: var(--cs-color-text-accent); }
|
|
227
|
+
.ln[aria-selected="true"] { background: var(--cs-color-brand-umber); color: var(--cs-color-text-inverse); }
|
|
228
|
+
[data-theme="dark"] .ln[aria-selected="true"] { background: var(--cs-color-brand-ochre);
|
|
229
|
+
color: var(--cs-status-on-ochre); }
|
|
230
|
+
.facet { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--cs-color-text-muted); }
|
|
231
|
+
.facet select { background: var(--cs-color-surface-panel); color: var(--cs-color-text-primary);
|
|
232
|
+
border: 1px solid var(--cs-color-border-default); border-radius: var(--cs-radius-sm);
|
|
233
|
+
padding: 5px 8px; font-family: inherit; font-size: 13px; max-width: 190px; }
|
|
234
|
+
.cnt { margin-left: auto; font-size: 12.5px; color: var(--cs-color-text-muted); }
|
|
235
|
+
.chipbar { display: flex; gap: 6px; flex-wrap: wrap; margin-top: var(--cs-space-2); }
|
|
236
|
+
.fchip { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600;
|
|
237
|
+
background: var(--cs-color-surface-raised); border: 1px solid var(--cs-color-border-default);
|
|
238
|
+
border-radius: var(--cs-radius-full); padding: 3px 6px 3px 10px; }
|
|
239
|
+
.fchip button { border: 0; background: transparent; cursor: pointer; color: var(--cs-color-text-muted);
|
|
240
|
+
line-height: 1; padding: 2px 4px; border-radius: var(--cs-radius-full); }
|
|
241
|
+
.fchip button:hover { color: var(--cs-color-semantic-danger); }
|
|
242
|
+
|
|
243
|
+
/* ---- task chips and pills -------------------------------------------------- */
|
|
244
|
+
.task-chips { display: flex; flex-wrap: wrap; gap: 5px; }
|
|
245
|
+
.chip { font-family: var(--cs-font-family-mono); font-size: 11px; font-weight: 600;
|
|
246
|
+
padding: 3px 7px; border-radius: 6px; cursor: pointer; display: inline-block;
|
|
247
|
+
background: var(--cs-color-surface-raised); color: var(--cs-color-text-accent);
|
|
248
|
+
border: 1px solid var(--cs-color-border-default); }
|
|
249
|
+
.chip:hover { border-color: var(--cs-color-brand-ochre); }
|
|
250
|
+
.chip.done { background: var(--cs-color-semantic-success); color: var(--cs-status-on-fill);
|
|
251
|
+
border-color: transparent; }
|
|
252
|
+
.chip.active { background: var(--cs-color-brand-ochre); color: var(--cs-status-on-ochre);
|
|
253
|
+
border-color: transparent; }
|
|
254
|
+
.chip.hold { background: var(--cs-color-semantic-danger); color: var(--cs-status-on-fill);
|
|
255
|
+
border-color: transparent; }
|
|
256
|
+
.chip.ghost { opacity: .6; border-style: dashed; }
|
|
257
|
+
.pill { display: inline-block; font-size: 11px; font-weight: 700; padding: 2px 8px;
|
|
258
|
+
border-radius: var(--cs-radius-full); text-transform: uppercase; letter-spacing: .04em; }
|
|
259
|
+
.pill.done { background: var(--cs-color-semantic-success); color: var(--cs-status-on-fill); }
|
|
260
|
+
.pill.active { background: var(--cs-color-brand-ochre); color: var(--cs-status-on-ochre); }
|
|
261
|
+
.pill.hold { background: var(--cs-color-semantic-danger); color: var(--cs-status-on-fill); }
|
|
262
|
+
.pill.todo { background: var(--cs-color-border-default); color: var(--cs-color-text-accent); }
|
|
263
|
+
.pri { font-size: 11px; font-weight: 700; letter-spacing: .04em; }
|
|
264
|
+
/* task@1 FM-105 priority is p0..p3. The MoSCoW classes are kept so a repo that has
|
|
265
|
+
not run the 2026-07-14 schema migration still renders coloured priorities rather
|
|
266
|
+
than silently falling back to unstyled text. */
|
|
267
|
+
.pri.p0, .pri.MUST { color: var(--cs-color-semantic-danger); }
|
|
268
|
+
.pri.p1, .pri.SHOULD { color: var(--cs-color-semantic-warning); }
|
|
269
|
+
.pri.p2, .pri.p3, .pri.COULD, .pri.MAY { color: var(--cs-color-text-muted); }
|
|
270
|
+
|
|
271
|
+
/* ---- lens: board --------------------------------------------------------- */
|
|
272
|
+
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); gap: var(--cs-space-4); }
|
|
273
|
+
.card { background: var(--cs-color-surface-panel); border: 1px solid var(--cs-color-border-default);
|
|
274
|
+
border-radius: 14px; padding: var(--cs-space-4); }
|
|
275
|
+
.card.hot { border-color: var(--cs-color-brand-ochre); }
|
|
276
|
+
.card-h { display: flex; align-items: baseline; justify-content: space-between; gap: var(--cs-space-2); }
|
|
277
|
+
.card-h h3 { margin: 0; font-size: 15px; line-height: var(--cs-font-lineHeight-heading); }
|
|
278
|
+
.card-h h3 .k { color: var(--cs-color-brand-umber); font-weight: 700; }
|
|
279
|
+
.card-h .pct { font-size: 12.5px; color: var(--cs-color-text-muted); white-space: nowrap; }
|
|
280
|
+
.minibar { height: 6px; border-radius: var(--cs-radius-full); background: var(--cs-color-surface-raised);
|
|
281
|
+
overflow: hidden; display: flex; margin: var(--cs-space-2) 0 var(--cs-space-3); }
|
|
282
|
+
.minibar i { display: block; height: 100%; }
|
|
283
|
+
|
|
284
|
+
/* ---- lens: table --------------------------------------------------------- */
|
|
285
|
+
.tbl-wrap { border: 1px solid var(--cs-color-border-default); border-radius: 14px; overflow: hidden;
|
|
286
|
+
background: var(--cs-color-surface-panel); }
|
|
287
|
+
table { border-collapse: collapse; width: 100%; font-size: 13px; }
|
|
288
|
+
th, td { text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--cs-color-border-default);
|
|
289
|
+
vertical-align: top; }
|
|
290
|
+
thead th { position: sticky; top: 78px; z-index: 1; background: var(--cs-color-surface-raised);
|
|
291
|
+
font-size: 11.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--cs-color-text-muted);
|
|
292
|
+
cursor: pointer; white-space: nowrap; }
|
|
293
|
+
thead th[aria-sort="ascending"]::after { content: " \2191"; }
|
|
294
|
+
thead th[aria-sort="descending"]::after { content: " \2193"; }
|
|
295
|
+
tbody tr { cursor: pointer; }
|
|
296
|
+
tbody tr:hover { background: var(--cs-color-surface-raised); }
|
|
297
|
+
tbody tr:last-child td { border-bottom: 0; }
|
|
298
|
+
td.t { max-width: 520px; }
|
|
299
|
+
|
|
300
|
+
/* ---- lens: releases ------------------------------------------------------ */
|
|
301
|
+
.rels { display: grid; gap: var(--cs-space-3); }
|
|
302
|
+
.rel { background: var(--cs-color-surface-panel); border: 1px solid var(--cs-color-border-default);
|
|
303
|
+
border-radius: 14px; padding: var(--cs-space-4) var(--cs-space-5); display: grid;
|
|
304
|
+
grid-template-columns: 30px 1fr; gap: var(--cs-space-4); }
|
|
305
|
+
.rel.now { border-color: var(--cs-color-brand-ochre); }
|
|
306
|
+
.rel .tick { width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
|
|
307
|
+
font-size: 12px; font-weight: 700; color: var(--cs-status-on-fill);
|
|
308
|
+
background: var(--cs-color-semantic-success); }
|
|
309
|
+
.rel.now .tick { background: var(--cs-color-brand-ochre); color: var(--cs-status-on-ochre); }
|
|
310
|
+
.rel-h { display: flex; align-items: baseline; gap: var(--cs-space-3); flex-wrap: wrap; }
|
|
311
|
+
.rel-h b { font-size: 17px; font-family: var(--cs-font-family-mono); }
|
|
312
|
+
.rel-sec { margin-top: var(--cs-space-3); }
|
|
313
|
+
.rel-sec h4 { margin: 0 0 var(--cs-space-1); font-size: 11.5px; text-transform: uppercase;
|
|
314
|
+
letter-spacing: .07em; color: var(--cs-color-text-muted); }
|
|
315
|
+
.rel-sec ul { margin: 0; padding-left: 18px; font-size: 13.5px; }
|
|
316
|
+
.rel-sec li { margin: 3px 0; }
|
|
317
|
+
.rel details { margin-top: var(--cs-space-3); }
|
|
318
|
+
.rel summary { cursor: pointer; font-size: 12.5px; color: var(--cs-color-text-muted); }
|
|
319
|
+
.rel .task-chips { margin-top: var(--cs-space-2); }
|
|
320
|
+
.relnote { font-size: 12.5px; color: var(--cs-color-text-muted); margin: var(--cs-space-2) 0 0; }
|
|
321
|
+
|
|
322
|
+
/* ---- drawer -------------------------------------------------------------- */
|
|
323
|
+
.scrim { position: fixed; inset: 0; background: var(--cs-status-scrim); z-index: var(--cs-depth-modal); }
|
|
324
|
+
.drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(760px, 100%);
|
|
325
|
+
z-index: calc(var(--cs-depth-modal) + 1); background: var(--cs-color-surface-page);
|
|
326
|
+
border-left: 1px solid var(--cs-color-border-default);
|
|
327
|
+
box-shadow: -18px 0 48px var(--cs-status-shadow); display: flex; flex-direction: column; }
|
|
328
|
+
.dw-h { padding: var(--cs-space-4) var(--cs-space-5); border-bottom: 1px solid var(--cs-color-border-default);
|
|
329
|
+
background: var(--cs-color-surface-panel); }
|
|
330
|
+
.dw-h .row { display: flex; align-items: center; gap: var(--cs-space-2); flex-wrap: wrap; }
|
|
331
|
+
.dw-h h2 { margin: var(--cs-space-2) 0 0; font-size: 19px; line-height: var(--cs-font-lineHeight-heading); }
|
|
332
|
+
.dw-x { margin-left: auto; border: 0; background: transparent; cursor: pointer; font-size: 22px;
|
|
333
|
+
line-height: 1; color: var(--cs-color-text-muted); padding: 2px 6px; }
|
|
334
|
+
.dw-x:hover { color: var(--cs-color-semantic-danger); }
|
|
335
|
+
.dw-tabs { display: flex; gap: 4px; padding: 0 var(--cs-space-5); background: var(--cs-color-surface-panel);
|
|
336
|
+
border-bottom: 1px solid var(--cs-color-border-default); }
|
|
337
|
+
.dw-tab { border: 0; background: transparent; cursor: pointer; padding: 9px 12px; font-size: 13.5px;
|
|
338
|
+
font-weight: 600; color: var(--cs-color-text-muted); border-bottom: 2px solid transparent; }
|
|
339
|
+
.dw-tab[aria-selected="true"] { color: var(--cs-color-text-primary);
|
|
340
|
+
border-bottom-color: var(--cs-color-brand-ochre); }
|
|
341
|
+
.dw-b { overflow: auto; padding: var(--cs-space-5); flex: 1; }
|
|
342
|
+
.meta { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--cs-space-3);
|
|
343
|
+
margin: 0 0 var(--cs-space-4); }
|
|
344
|
+
.meta div { min-width: 0; }
|
|
345
|
+
.meta dt { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--cs-color-text-muted); }
|
|
346
|
+
.meta dd { margin: 2px 0 0; font-size: 13.5px; word-break: break-word; }
|
|
347
|
+
.sect { margin-top: var(--cs-space-5); }
|
|
348
|
+
.sect h3 { margin: 0 0 var(--cs-space-2); font-size: 12px; text-transform: uppercase;
|
|
349
|
+
letter-spacing: .08em; color: var(--cs-color-text-muted); }
|
|
350
|
+
.tasks { margin: 0; padding-left: 18px; font-size: 13.5px; }
|
|
351
|
+
.tasks li { margin: 3px 0; }
|
|
352
|
+
.risk { background: var(--cs-color-surface-raised); border-left: 3px solid var(--cs-color-semantic-danger);
|
|
353
|
+
border-radius: var(--cs-radius-md); padding: var(--cs-space-3) var(--cs-space-4); font-size: 13.5px; }
|
|
354
|
+
.rel-links { display: grid; gap: var(--cs-space-4); }
|
|
355
|
+
.rel-links h3 { margin: 0 0 var(--cs-space-2); font-size: 12px; text-transform: uppercase;
|
|
356
|
+
letter-spacing: .08em; color: var(--cs-color-text-muted); }
|
|
357
|
+
.load { color: var(--cs-color-text-muted); font-size: 13.5px; }
|
|
358
|
+
.toc { position: sticky; top: 0; background: var(--cs-color-surface-page); padding-bottom: var(--cs-space-2);
|
|
359
|
+
margin-bottom: var(--cs-space-3); border-bottom: 1px solid var(--cs-color-border-default);
|
|
360
|
+
display: flex; gap: 6px; flex-wrap: wrap; }
|
|
361
|
+
.toc a { font-size: 11.5px; text-decoration: none; border: 1px solid var(--cs-color-border-default);
|
|
362
|
+
border-radius: var(--cs-radius-full); padding: 3px 9px; color: var(--cs-color-text-accent); }
|
|
363
|
+
.toc a:hover { border-color: var(--cs-color-brand-ochre); }
|
|
364
|
+
|
|
365
|
+
/* ---- the task spec, rendered ----------------------------------------------- */
|
|
366
|
+
.spec { font-size: 14px; }
|
|
367
|
+
.spec h1, .spec h2 { font-size: 16px; margin: var(--cs-space-5) 0 var(--cs-space-2);
|
|
368
|
+
padding-bottom: 4px; border-bottom: 1px solid var(--cs-color-border-default); }
|
|
369
|
+
.spec h3 { font-size: 14px; margin: var(--cs-space-4) 0 var(--cs-space-1); }
|
|
370
|
+
.spec p, .spec li { line-height: 1.6; }
|
|
371
|
+
.spec pre { background: var(--cs-color-surface-raised); border: 1px solid var(--cs-color-border-default);
|
|
372
|
+
border-radius: var(--cs-radius-md); padding: var(--cs-space-3); overflow: auto; font-size: 12.5px; }
|
|
373
|
+
.spec code { font-family: var(--cs-font-family-mono); font-size: 12.5px;
|
|
374
|
+
background: var(--cs-color-surface-raised); padding: 1px 5px; border-radius: var(--cs-radius-sm); }
|
|
375
|
+
.spec pre code { background: transparent; padding: 0; }
|
|
376
|
+
.spec table { font-size: 12.5px; margin: var(--cs-space-3) 0; }
|
|
377
|
+
.spec th, .spec td { border: 1px solid var(--cs-color-border-default); }
|
|
378
|
+
.spec blockquote { margin: var(--cs-space-3) 0; padding-left: var(--cs-space-4);
|
|
379
|
+
border-left: 3px solid var(--cs-color-brand-ochre); color: var(--cs-color-text-muted); }
|
|
380
|
+
.spec img { max-width: 100%; }
|
|
381
|
+
|
|
382
|
+
/* ---- misc ---------------------------------------------------------------- */
|
|
383
|
+
.empty { text-align: center; color: var(--cs-color-text-muted); padding: var(--cs-space-16) 0; }
|
|
384
|
+
.groupq { margin: var(--cs-space-5) 0 var(--cs-space-3); font-size: 12px; text-transform: uppercase;
|
|
385
|
+
letter-spacing: .08em; color: var(--cs-color-text-muted); }
|
|
386
|
+
.nojs { background: var(--cs-color-surface-panel); border: 1px solid var(--cs-color-border-default);
|
|
387
|
+
border-radius: 14px; padding: var(--cs-space-4); }
|
|
388
|
+
.ft { margin: var(--cs-space-12) 0 var(--cs-space-16); text-align: center; font-size: 12px;
|
|
389
|
+
color: var(--cs-color-text-muted); }
|
|
390
|
+
[hidden] { display: none !important; }
|
|
391
|
+
|
|
392
|
+
@media (max-width: 900px) {
|
|
393
|
+
.deck { grid-template-columns: 1fr; }
|
|
394
|
+
.hd-meta { text-align: left; }
|
|
395
|
+
thead th { top: 0; }
|
|
396
|
+
}
|
|
397
|
+
@media print {
|
|
398
|
+
.bar, .drawer, .scrim, .hd-side { display: none !important; }
|
|
399
|
+
}
|