@shortlink-org/portolan 0.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/LICENSE +21 -0
- package/README.md +387 -0
- package/catalog/enum_test.go +46 -0
- package/catalog/model.go +932 -0
- package/catalog/roundtrip_test.go +185 -0
- package/catalog/via_test.go +38 -0
- package/cli/portolan.mjs +368 -0
- package/go.mod +14 -0
- package/go.sum +14 -0
- package/index.html +13 -0
- package/internal/commands/cargo.go +154 -0
- package/internal/commands/commands.go +143 -0
- package/internal/commands/commands_test.go +323 -0
- package/internal/commands/gradle.go +77 -0
- package/internal/commands/justfile.go +82 -0
- package/internal/commands/makefile.go +106 -0
- package/internal/commands/maven.go +93 -0
- package/internal/commands/packagejson.go +159 -0
- package/internal/commands/pyproject.go +169 -0
- package/internal/commands/taskfile.go +101 -0
- package/internal/commands/testdata/estate/.cargo/config.toml +7 -0
- package/internal/commands/testdata/estate/Makefile +33 -0
- package/internal/commands/testdata/estate/Taskfile.yml +21 -0
- package/internal/commands/testdata/estate/build.gradle.kts +21 -0
- package/internal/commands/testdata/estate/justfile +20 -0
- package/internal/commands/testdata/estate/package.json +13 -0
- package/internal/commands/testdata/estate/pom.xml +29 -0
- package/internal/commands/testdata/estate/pyproject.toml +27 -0
- package/internal/commands/testdata/estate/xtask/src/main.rs +27 -0
- package/internal/commands/testdata/golden/commands.json +305 -0
- package/internal/gohttp/analyze.go +2500 -0
- package/internal/gohttp/endpoints.go +1067 -0
- package/internal/gohttp/roots.go +320 -0
- package/internal/gohttp/typed.go +143 -0
- package/internal/goscan/constants.go +85 -0
- package/internal/goscan/goscan_test.go +227 -0
- package/internal/goscan/names.go +52 -0
- package/internal/goscan/parse_test.go +11 -0
- package/internal/goscan/source.go +36 -0
- package/internal/goscan/tree.go +155 -0
- package/internal/goscan/types.go +99 -0
- package/internal/wsdl/ids.go +127 -0
- package/internal/wsdl/ids_test.go +21 -0
- package/internal/wsdl/model.go +62 -0
- package/internal/wsdl/parse.go +920 -0
- package/internal/wsdl/parse_test.go +133 -0
- package/package.json +117 -0
- package/plugin/describe.go +107 -0
- package/plugin/describe_test.go +114 -0
- package/plugin/protocol.go +117 -0
- package/plugin/schematest/schematest.go +126 -0
- package/plugins/README.md +1160 -0
- package/plugins/extract-adr/describe.go +19 -0
- package/plugins/extract-adr/describe_test.go +11 -0
- package/plugins/extract-adr/extract.go +153 -0
- package/plugins/extract-adr/extract_test.go +350 -0
- package/plugins/extract-adr/history.go +99 -0
- package/plugins/extract-adr/main.go +65 -0
- package/plugins/extract-adr/options.schema.json +26 -0
- package/plugins/extract-adr/parse.go +642 -0
- package/plugins/extract-adr/parse_test.go +405 -0
- package/plugins/extract-asyncapi/describe.go +19 -0
- package/plugins/extract-asyncapi/describe_test.go +11 -0
- package/plugins/extract-asyncapi/extract.go +315 -0
- package/plugins/extract-asyncapi/extract_test.go +197 -0
- package/plugins/extract-asyncapi/main.go +48 -0
- package/plugins/extract-asyncapi/options.schema.json +26 -0
- package/plugins/extract-asyncapi/spec.go +151 -0
- package/plugins/extract-celery/README.md +169 -0
- package/plugins/extract-celery/extract.py +346 -0
- package/plugins/extract-celery/extract_test.py +192 -0
- package/plugins/extract-celery/main.py +66 -0
- package/plugins/extract-celery/options.py +31 -0
- package/plugins/extract-celery/options.schema.json +31 -0
- package/plugins/extract-celery/producers.py +156 -0
- package/plugins/extract-celery/routes_test.py +106 -0
- package/plugins/extract-commands/describe.go +19 -0
- package/plugins/extract-commands/describe_test.go +11 -0
- package/plugins/extract-commands/extract.go +79 -0
- package/plugins/extract-commands/extract_test.go +92 -0
- package/plugins/extract-commands/main.go +55 -0
- package/plugins/extract-commands/options.schema.json +20 -0
- package/plugins/extract-csr/avro.go +258 -0
- package/plugins/extract-csr/describe.go +19 -0
- package/plugins/extract-csr/describe_test.go +11 -0
- package/plugins/extract-csr/extract.go +338 -0
- package/plugins/extract-csr/extract_test.go +374 -0
- package/plugins/extract-csr/jsonschema.go +343 -0
- package/plugins/extract-csr/lock.go +25 -0
- package/plugins/extract-csr/main.go +84 -0
- package/plugins/extract-csr/options.schema.json +43 -0
- package/plugins/extract-csr/subject.go +102 -0
- package/plugins/extract-django/README.md +386 -0
- package/plugins/extract-django/apps.py +100 -0
- package/plugins/extract-django/auth.py +302 -0
- package/plugins/extract-django/auth_test.py +188 -0
- package/plugins/extract-django/clients.py +121 -0
- package/plugins/extract-django/contracts.py +458 -0
- package/plugins/extract-django/database.py +119 -0
- package/plugins/extract-django/domain.py +318 -0
- package/plugins/extract-django/events.py +86 -0
- package/plugins/extract-django/extract.py +601 -0
- package/plugins/extract-django/extract_test.py +397 -0
- package/plugins/extract-django/flows.py +1278 -0
- package/plugins/extract-django/flows_test.py +338 -0
- package/plugins/extract-django/ids.py +42 -0
- package/plugins/extract-django/ids_test.py +30 -0
- package/plugins/extract-django/lifecycle.py +222 -0
- package/plugins/extract-django/lifecycle_test.py +76 -0
- package/plugins/extract-django/main.py +66 -0
- package/plugins/extract-django/openapi.py +229 -0
- package/plugins/extract-django/openapi_test.py +60 -0
- package/plugins/extract-django/operations.py +96 -0
- package/plugins/extract-django/options.py +61 -0
- package/plugins/extract-django/options.schema.json +126 -0
- package/plugins/extract-django/routing.py +214 -0
- package/plugins/extract-django/routing_test.py +198 -0
- package/plugins/extract-django/serializers.py +558 -0
- package/plugins/extract-django/store.py +434 -0
- package/plugins/extract-django/transport.py +242 -0
- package/plugins/extract-flows/describe.go +19 -0
- package/plugins/extract-flows/describe_test.go +11 -0
- package/plugins/extract-flows/extract.go +91 -0
- package/plugins/extract-flows/main.go +45 -0
- package/plugins/extract-flows/options.schema.json +16 -0
- package/plugins/extract-flows/parse.go +593 -0
- package/plugins/extract-flows/parse_test.go +204 -0
- package/plugins/extract-glossary/describe.go +19 -0
- package/plugins/extract-glossary/describe_test.go +11 -0
- package/plugins/extract-glossary/extract.go +115 -0
- package/plugins/extract-glossary/extract_test.go +220 -0
- package/plugins/extract-glossary/main.go +59 -0
- package/plugins/extract-glossary/options.schema.json +21 -0
- package/plugins/extract-glossary/parse.go +214 -0
- package/plugins/extract-glossary/parse_test.go +203 -0
- package/plugins/extract-go/aggregate.go +214 -0
- package/plugins/extract-go/client.go +409 -0
- package/plugins/extract-go/client_test.go +266 -0
- package/plugins/extract-go/describe.go +19 -0
- package/plugins/extract-go/describe_test.go +11 -0
- package/plugins/extract-go/enum.go +195 -0
- package/plugins/extract-go/enum_test.go +82 -0
- package/plugins/extract-go/event.go +99 -0
- package/plugins/extract-go/extract.go +191 -0
- package/plugins/extract-go/extract_test.go +261 -0
- package/plugins/extract-go/flow.go +1441 -0
- package/plugins/extract-go/flow_test.go +609 -0
- package/plugins/extract-go/httpclient.go +174 -0
- package/plugins/extract-go/httpclient_test.go +296 -0
- package/plugins/extract-go/ids.go +92 -0
- package/plugins/extract-go/layout.go +225 -0
- package/plugins/extract-go/layout_test.go +125 -0
- package/plugins/extract-go/lifecycle.go +324 -0
- package/plugins/extract-go/lifecycle_test.go +108 -0
- package/plugins/extract-go/main.go +79 -0
- package/plugins/extract-go/operation.go +157 -0
- package/plugins/extract-go/options.schema.json +66 -0
- package/plugins/extract-go/source.go +316 -0
- package/plugins/extract-go/transport.go +321 -0
- package/plugins/extract-go/transport_test.go +145 -0
- package/plugins/extract-go/wiring.go +434 -0
- package/plugins/extract-go-nats/describe.go +19 -0
- package/plugins/extract-go-nats/describe_test.go +11 -0
- package/plugins/extract-go-nats/extract.go +177 -0
- package/plugins/extract-go-nats/extract_test.go +389 -0
- package/plugins/extract-go-nats/index.go +379 -0
- package/plugins/extract-go-nats/main.go +42 -0
- package/plugins/extract-go-nats/options.schema.json +21 -0
- package/plugins/extract-go-nats/resolve.go +161 -0
- package/plugins/extract-go-nats/sites.go +224 -0
- package/plugins/extract-graphql/describe.go +19 -0
- package/plugins/extract-graphql/describe_test.go +11 -0
- package/plugins/extract-graphql/extract.go +433 -0
- package/plugins/extract-graphql/extract_test.go +256 -0
- package/plugins/extract-graphql/ids.go +49 -0
- package/plugins/extract-graphql/lex.go +237 -0
- package/plugins/extract-graphql/main.go +51 -0
- package/plugins/extract-graphql/options.schema.json +31 -0
- package/plugins/extract-graphql/parse.go +621 -0
- package/plugins/extract-graphql/parse_test.go +122 -0
- package/plugins/extract-http-clients/describe.go +19 -0
- package/plugins/extract-http-clients/describe_test.go +11 -0
- package/plugins/extract-http-clients/extract.go +705 -0
- package/plugins/extract-http-clients/extract_test.go +1263 -0
- package/plugins/extract-http-clients/main.go +42 -0
- package/plugins/extract-http-clients/options.schema.json +33 -0
- package/plugins/extract-java/README.md +190 -0
- package/plugins/extract-java/build/org/portolan/extract/Catalog.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients$1.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients$2.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients$Call.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients$Client.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients$Route.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Domain$Aggregate.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Domain.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Events$Found.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Events.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Extract.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows$1.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows$Binding.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows$Draft.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows$Frame.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows$Options.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Ids.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Json$Reader.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Json.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Lifecycle$1.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Lifecycle$Move.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Lifecycle.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Main.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/OpenApi$Operation.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/OpenApi$Spec.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/OpenApi.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Operations$1.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Operations$UseCase.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Operations.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Proto$Rpc.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Proto$Service.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Proto.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Protocol$Builder.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Protocol$Input.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Protocol$Options.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Protocol.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Source$Project.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Source$Unit.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Source.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Transport$Endpoint.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Transport.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Yaml$Line.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Yaml$Reader.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Yaml.class +0 -0
- package/plugins/extract-java/options.schema.json +70 -0
- package/plugins/extract-openapi/describe.go +19 -0
- package/plugins/extract-openapi/describe_test.go +11 -0
- package/plugins/extract-openapi/discover.go +243 -0
- package/plugins/extract-openapi/extract.go +526 -0
- package/plugins/extract-openapi/extract_test.go +545 -0
- package/plugins/extract-openapi/main.go +75 -0
- package/plugins/extract-openapi/options.schema.json +62 -0
- package/plugins/extract-openapi/spec.go +350 -0
- package/plugins/extract-project/README.md +22 -0
- package/plugins/extract-project/describe.go +19 -0
- package/plugins/extract-project/describe_test.go +11 -0
- package/plugins/extract-project/extract.go +221 -0
- package/plugins/extract-project/extract_test.go +109 -0
- package/plugins/extract-project/main.go +41 -0
- package/plugins/extract-project/options.schema.json +48 -0
- package/plugins/extract-proto/ast.go +125 -0
- package/plugins/extract-proto/consumes.go +77 -0
- package/plugins/extract-proto/describe.go +19 -0
- package/plugins/extract-proto/extract.go +293 -0
- package/plugins/extract-proto/extract_test.go +459 -0
- package/plugins/extract-proto/ids.go +89 -0
- package/plugins/extract-proto/ids_test.go +57 -0
- package/plugins/extract-proto/lex.go +285 -0
- package/plugins/extract-proto/main.go +100 -0
- package/plugins/extract-proto/module.go +120 -0
- package/plugins/extract-proto/options.schema.json +51 -0
- package/plugins/extract-proto/parse.go +720 -0
- package/plugins/extract-proto/parse_test.go +307 -0
- package/plugins/extract-proto/provides.go +236 -0
- package/plugins/extract-proto/resolve.go +222 -0
- package/plugins/extract-proto/resolve_test.go +119 -0
- package/plugins/extract-python-kafka/README.md +36 -0
- package/plugins/extract-python-kafka/extract.py +211 -0
- package/plugins/extract-python-kafka/extract_test.py +68 -0
- package/plugins/extract-python-kafka/main.py +59 -0
- package/plugins/extract-python-kafka/options.py +29 -0
- package/plugins/extract-python-kafka/options.schema.json +31 -0
- package/plugins/extract-redis/README.md +11 -0
- package/plugins/extract-redis/describe.go +19 -0
- package/plugins/extract-redis/describe_test.go +11 -0
- package/plugins/extract-redis/extract.go +183 -0
- package/plugins/extract-redis/extract_test.go +168 -0
- package/plugins/extract-redis/keyspaces.go +469 -0
- package/plugins/extract-redis/main.go +44 -0
- package/plugins/extract-redis/options.schema.json +30 -0
- package/plugins/extract-river/describe.go +19 -0
- package/plugins/extract-river/describe_test.go +11 -0
- package/plugins/extract-river/extract.go +507 -0
- package/plugins/extract-river/extract_test.go +132 -0
- package/plugins/extract-river/main.go +42 -0
- package/plugins/extract-river/options.schema.json +21 -0
- package/plugins/extract-rust/Cargo.lock +133 -0
- package/plugins/extract-rust/Cargo.toml +23 -0
- package/plugins/extract-rust/README.md +204 -0
- package/plugins/extract-rust/options.schema.json +65 -0
- package/plugins/extract-rust/rustfmt.toml +1 -0
- package/plugins/extract-sql/ddl.go +893 -0
- package/plugins/extract-sql/ddl_test.go +401 -0
- package/plugins/extract-sql/describe.go +19 -0
- package/plugins/extract-sql/describe_test.go +11 -0
- package/plugins/extract-sql/layout.go +221 -0
- package/plugins/extract-sql/layout_test.go +55 -0
- package/plugins/extract-sql/lineage.go +107 -0
- package/plugins/extract-sql/main.go +141 -0
- package/plugins/extract-sql/maps.go +564 -0
- package/plugins/extract-sql/maps_java.go +117 -0
- package/plugins/extract-sql/maps_rust.go +333 -0
- package/plugins/extract-sql/maps_rust_test.go +70 -0
- package/plugins/extract-sql/maps_test.go +204 -0
- package/plugins/extract-sql/maps_ts.go +398 -0
- package/plugins/extract-sql/maps_ts_test.go +136 -0
- package/plugins/extract-sql/options.schema.json +53 -0
- package/plugins/extract-sql/projection.go +70 -0
- package/plugins/extract-sql/projection_test.go +50 -0
- package/plugins/extract-sql/store.go +420 -0
- package/plugins/extract-sql/store_test.go +233 -0
- package/plugins/extract-sql/view.go +295 -0
- package/plugins/extract-ts/README.md +306 -0
- package/plugins/extract-ts/ast.test.ts +178 -0
- package/plugins/extract-ts/ast.ts +648 -0
- package/plugins/extract-ts/clients.ts +185 -0
- package/plugins/extract-ts/domain.ts +164 -0
- package/plugins/extract-ts/extract.test.ts +208 -0
- package/plugins/extract-ts/extract.ts +200 -0
- package/plugins/extract-ts/flows.ts +783 -0
- package/plugins/extract-ts/graphql.test.ts +73 -0
- package/plugins/extract-ts/graphql.ts +181 -0
- package/plugins/extract-ts/ids.test.ts +21 -0
- package/plugins/extract-ts/ids.ts +52 -0
- package/plugins/extract-ts/lifecycle.ts +138 -0
- package/plugins/extract-ts/main.ts +48 -0
- package/plugins/extract-ts/openapi.test.ts +64 -0
- package/plugins/extract-ts/openapi.ts +99 -0
- package/plugins/extract-ts/operations.ts +93 -0
- package/plugins/extract-ts/options.schema.json +96 -0
- package/plugins/extract-ts/source.test.ts +174 -0
- package/plugins/extract-ts/source.ts +465 -0
- package/plugins/extract-ts/transport.ts +147 -0
- package/plugins/extract-ts/tsconfig.json +13 -0
- package/plugins/extract-ts/wiring.ts +190 -0
- package/plugins/extract-watermill/describe.go +19 -0
- package/plugins/extract-watermill/describe_test.go +11 -0
- package/plugins/extract-watermill/extract.go +1228 -0
- package/plugins/extract-watermill/extract_test.go +234 -0
- package/plugins/extract-watermill/main.go +41 -0
- package/plugins/extract-watermill/options.schema.json +21 -0
- package/plugins/extract-wsdl/describe.go +19 -0
- package/plugins/extract-wsdl/describe_test.go +11 -0
- package/plugins/extract-wsdl/extract.go +148 -0
- package/plugins/extract-wsdl/extract_test.go +45 -0
- package/plugins/extract-wsdl/main.go +53 -0
- package/plugins/extract-wsdl/options.schema.json +59 -0
- package/plugins/fetch-bsr/auth.go +114 -0
- package/plugins/fetch-bsr/bsr.go +240 -0
- package/plugins/fetch-bsr/cache.go +66 -0
- package/plugins/fetch-bsr/describe.go +19 -0
- package/plugins/fetch-bsr/fetch.go +192 -0
- package/plugins/fetch-bsr/fetch_test.go +465 -0
- package/plugins/fetch-bsr/lock.go +71 -0
- package/plugins/fetch-bsr/main.go +117 -0
- package/plugins/fetch-bsr/options.schema.json +42 -0
- package/plugins/fetch-csr/auth.go +95 -0
- package/plugins/fetch-csr/cache.go +69 -0
- package/plugins/fetch-csr/describe.go +19 -0
- package/plugins/fetch-csr/describe_test.go +11 -0
- package/plugins/fetch-csr/fetch.go +254 -0
- package/plugins/fetch-csr/fetch_test.go +494 -0
- package/plugins/fetch-csr/lock.go +95 -0
- package/plugins/fetch-csr/main.go +122 -0
- package/plugins/fetch-csr/options.schema.json +42 -0
- package/plugins/fetch-csr/registry.go +209 -0
- package/plugins/fetch-git/cache.go +65 -0
- package/plugins/fetch-git/describe.go +19 -0
- package/plugins/fetch-git/describe_test.go +11 -0
- package/plugins/fetch-git/fetch.go +181 -0
- package/plugins/fetch-git/fetch_test.go +332 -0
- package/plugins/fetch-git/git.go +169 -0
- package/plugins/fetch-git/lock.go +72 -0
- package/plugins/fetch-git/main.go +127 -0
- package/plugins/fetch-git/offline.go +39 -0
- package/plugins/fetch-git/options.schema.json +42 -0
- package/plugins/fetch-git/pin.go +90 -0
- package/plugins/fetch-git/pin_test.go +74 -0
- package/plugins/gen-backstage/describe.go +17 -0
- package/plugins/gen-backstage/main.go +22 -0
- package/plugins/gen-backstage/options.schema.json +30 -0
- package/plugins/gen-backstage/plugin.go +473 -0
- package/plugins/gen-backstage/plugin_test.go +145 -0
- package/plugins/gen-backstage.wasm +0 -0
- package/plugins/gen-markdown/adr.go +162 -0
- package/plugins/gen-markdown/aggregate.go +362 -0
- package/plugins/gen-markdown/canonical.go +93 -0
- package/plugins/gen-markdown/context.go +90 -0
- package/plugins/gen-markdown/coverage_test.go +89 -0
- package/plugins/gen-markdown/describe.go +19 -0
- package/plugins/gen-markdown/describe_test.go +11 -0
- package/plugins/gen-markdown/external.go +71 -0
- package/plugins/gen-markdown/flow.go +277 -0
- package/plugins/gen-markdown/glossary.go +76 -0
- package/plugins/gen-markdown/glossary_test.go +148 -0
- package/plugins/gen-markdown/llms.go +302 -0
- package/plugins/gen-markdown/main.go +22 -0
- package/plugins/gen-markdown/markdown.go +254 -0
- package/plugins/gen-markdown/markdown_test.go +100 -0
- package/plugins/gen-markdown/module.go +107 -0
- package/plugins/gen-markdown/options.schema.json +16 -0
- package/plugins/gen-markdown/plugin.go +39 -0
- package/plugins/gen-markdown/quality_test.go +176 -0
- package/plugins/gen-markdown/redis_test.go +38 -0
- package/plugins/gen-markdown/render.go +344 -0
- package/plugins/gen-markdown/render_test.go +186 -0
- package/plugins/gen-markdown/service.go +456 -0
- package/plugins/gen-markdown/source.go +177 -0
- package/plugins/gen-markdown/store.go +201 -0
- package/plugins/gen-markdown.wasm +0 -0
- package/plugins/gen-mermaid/describe.go +17 -0
- package/plugins/gen-mermaid/main.go +22 -0
- package/plugins/gen-mermaid/options.schema.json +10 -0
- package/plugins/gen-mermaid/plugin.go +104 -0
- package/plugins/gen-mermaid/plugin_test.go +33 -0
- package/plugins/gen-mermaid.wasm +0 -0
- package/plugins/openapi/ids.go +261 -0
- package/plugins/openapi/ids_test.go +98 -0
- package/plugins/pyplugin/catalog.py +209 -0
- package/plugins/pyplugin/celery_conf.py +436 -0
- package/plugins/pyplugin/celery_tasks.py +76 -0
- package/plugins/pyplugin/kafka.py +570 -0
- package/plugins/pyplugin/names.py +38 -0
- package/plugins/pyplugin/protocol.py +79 -0
- package/plugins/pyplugin/source.py +285 -0
- package/plugins/verify-codeowners/describe.go +19 -0
- package/plugins/verify-codeowners/describe_test.go +11 -0
- package/plugins/verify-codeowners/main.go +75 -0
- package/plugins/verify-codeowners/match.go +85 -0
- package/plugins/verify-codeowners/match_test.go +47 -0
- package/plugins/verify-codeowners/options.schema.json +15 -0
- package/plugins/verify-codeowners/owners.go +164 -0
- package/plugins/verify-codeowners/owners_test.go +225 -0
- package/plugins/verify-codeowners/parse.go +90 -0
- package/plugins/verify-codeowners/parse_test.go +62 -0
- package/plugins/verify-otel/describe.go +19 -0
- package/plugins/verify-otel/describe_test.go +11 -0
- package/plugins/verify-otel/main.go +53 -0
- package/plugins/verify-otel/match.go +336 -0
- package/plugins/verify-otel/options.schema.json +30 -0
- package/plugins/verify-otel/otlp.go +200 -0
- package/plugins/verify-otel/verify.go +734 -0
- package/plugins/verify-otel/verify_test.go +460 -0
- package/portolan.json +1073 -0
- package/public/favicon.svg +12 -0
- package/schema/portolan.schema.json +2558 -0
- package/scripts/README.md +53 -0
- package/scripts/build-report.mjs +60 -0
- package/scripts/build-report.test.mjs +44 -0
- package/scripts/builtin-plugins.mjs +49 -0
- package/scripts/catalog-sources.mjs +67 -0
- package/scripts/diff.mjs +315 -0
- package/scripts/diff.test.mjs +151 -0
- package/scripts/forge-comment.mjs +144 -0
- package/scripts/forge-comment.test.mjs +151 -0
- package/scripts/forge-release.mjs +138 -0
- package/scripts/forge-release.test.mjs +106 -0
- package/scripts/forge.mjs +61 -0
- package/scripts/gen-likec4.mjs +854 -0
- package/scripts/gen-likec4.test.mjs +258 -0
- package/scripts/gen.mjs +603 -0
- package/scripts/generated-docs.test.mjs +66 -0
- package/scripts/local-api.mjs +1192 -0
- package/scripts/local-api.test.mjs +387 -0
- package/scripts/manifest.mjs +214 -0
- package/scripts/manifest.test.mjs +148 -0
- package/scripts/output-path.mjs +79 -0
- package/scripts/output-path.test.mjs +45 -0
- package/scripts/package-smoke.mjs +37 -0
- package/scripts/plugin-host.mjs +419 -0
- package/scripts/plugin-host.test.mjs +109 -0
- package/scripts/plugin-wasm-worker.mjs +34 -0
- package/scripts/run-builtin.mjs +81 -0
- package/scripts/schema.mjs +357 -0
- package/scripts/site-docs.mjs +295 -0
- package/scripts/site-docs.test.mjs +181 -0
- package/scripts/vendor-lock.mjs +58 -0
- package/scripts/vendor-lock.test.mjs +69 -0
- package/src/README.md +38 -0
- package/src/app/App.tsx +448 -0
- package/src/app/BranchPicker.test.ts +46 -0
- package/src/app/BranchPicker.tsx +153 -0
- package/src/app/Breadcrumbs.test.ts +38 -0
- package/src/app/Breadcrumbs.tsx +223 -0
- package/src/app/BuildStamp.tsx +146 -0
- package/src/app/CommandPalette.tsx +292 -0
- package/src/app/HashScroll.tsx +45 -0
- package/src/app/Sidebar.tsx +1742 -0
- package/src/app/TopBar.tsx +393 -0
- package/src/app/density.tsx +64 -0
- package/src/app/forge-access.test.ts +27 -0
- package/src/app/forge-access.tsx +80 -0
- package/src/app/panels.tsx +141 -0
- package/src/app/pins.tsx +242 -0
- package/src/app/query-client.ts +24 -0
- package/src/app/responsive.ts +55 -0
- package/src/app/shortcuts.test.ts +39 -0
- package/src/app/shortcuts.tsx +282 -0
- package/src/app/theme.tsx +51 -0
- package/src/app/title.test.ts +14 -0
- package/src/app/title.ts +30 -0
- package/src/app/toast.tsx +59 -0
- package/src/app/tree-keys.test.ts +80 -0
- package/src/app/tree-keys.ts +87 -0
- package/src/app/ui-store.ts +52 -0
- package/src/catalog-error.test.ts +105 -0
- package/src/catalog-profile.test.ts +59 -0
- package/src/catalog-profile.ts +101 -0
- package/src/catalog-stores.test.ts +431 -0
- package/src/catalog.test.ts +1215 -0
- package/src/catalog.ts +3125 -0
- package/src/chat/Cards.tsx +408 -0
- package/src/chat/ChatPanel.tsx +79 -0
- package/src/chat/ChatSettings.tsx +219 -0
- package/src/chat/Composer.tsx +99 -0
- package/src/chat/Conversation.tsx +281 -0
- package/src/chat/Header.tsx +46 -0
- package/src/chat/Message.tsx +49 -0
- package/src/chat/Notice.tsx +195 -0
- package/src/chat/Starter.tsx +67 -0
- package/src/chat/Steps.tsx +45 -0
- package/src/chat/Waiting.tsx +87 -0
- package/src/chat/flags.test.ts +59 -0
- package/src/chat/flags.ts +155 -0
- package/src/chat/linkify.test.ts +30 -0
- package/src/chat/linkify.ts +45 -0
- package/src/chat/prefs.ts +56 -0
- package/src/chat/prompt.test.ts +43 -0
- package/src/chat/prompt.ts +157 -0
- package/src/chat/store.ts +35 -0
- package/src/chat/tools.ts +58 -0
- package/src/chat/transport.ts +70 -0
- package/src/components/AdrRow.tsx +29 -0
- package/src/components/AnchorLink.tsx +67 -0
- package/src/components/ApiReference.tsx +134 -0
- package/src/components/AsyncApiReference.tsx +120 -0
- package/src/components/CatalogStamp.tsx +155 -0
- package/src/components/ChannelRows.tsx +132 -0
- package/src/components/CommandRows.tsx +139 -0
- package/src/components/DiagramSkeleton.tsx +71 -0
- package/src/components/EditorLink.tsx +85 -0
- package/src/components/FieldTree.tsx +305 -0
- package/src/components/FlowTrigger.tsx +34 -0
- package/src/components/Ident.tsx +89 -0
- package/src/components/Integrations.tsx +243 -0
- package/src/components/LifecycleDiagram.tsx +110 -0
- package/src/components/MachineDocs.tsx +42 -0
- package/src/components/Markdown.tsx +173 -0
- package/src/components/MarkdownTable.tsx +206 -0
- package/src/components/Mermaid.tsx +211 -0
- package/src/components/MethodRows.tsx +309 -0
- package/src/components/Overlay.tsx +125 -0
- package/src/components/PageHeader.tsx +189 -0
- package/src/components/RowActions.tsx +97 -0
- package/src/components/SchemaDocument.tsx +89 -0
- package/src/components/Select.tsx +126 -0
- package/src/components/ShapeRows.tsx +118 -0
- package/src/components/SourceDoc.tsx +82 -0
- package/src/components/SourcePreview.tsx +441 -0
- package/src/components/TabRow.tsx +182 -0
- package/src/components/TechIcon.tsx +34 -0
- package/src/components/Toc.tsx +132 -0
- package/src/components/WhatLinksHere.tsx +273 -0
- package/src/components/WsdlReference.tsx +84 -0
- package/src/components/ddd-icons.tsx +107 -0
- package/src/components/kind.tsx +157 -0
- package/src/components/logo.tsx +61 -0
- package/src/components/primitives.tsx +264 -0
- package/src/data.test.ts +18 -0
- package/src/data.ts +202 -0
- package/src/enrich.test.ts +1150 -0
- package/src/enrich.ts +672 -0
- package/src/er/ErCanvas.tsx +533 -0
- package/src/er/RedisSchema.tsx +74 -0
- package/src/er/RelationCard.tsx +267 -0
- package/src/er/StoreHeader.tsx +155 -0
- package/src/er/TableNode.tsx +84 -0
- package/src/er/ViewNode.tsx +83 -0
- package/src/er/layout.test.ts +115 -0
- package/src/er/layout.ts +77 -0
- package/src/er/lineage.test.ts +140 -0
- package/src/er/lineage.ts +107 -0
- package/src/er/markers.tsx +79 -0
- package/src/er/spec.test.ts +344 -0
- package/src/er/spec.ts +426 -0
- package/src/flow/ChainList.tsx +162 -0
- package/src/flow/FlowTable.tsx +123 -0
- package/src/flow/FlowToolbar.tsx +372 -0
- package/src/flow/StepDetail.tsx +380 -0
- package/src/flow/StepRail.tsx +428 -0
- package/src/flow/answers.test.ts +50 -0
- package/src/flow/answers.ts +58 -0
- package/src/flow/chain.test.ts +383 -0
- package/src/flow/chain.ts +353 -0
- package/src/flow/chapters.test.ts +185 -0
- package/src/flow/chapters.ts +225 -0
- package/src/flow/continues.test.ts +102 -0
- package/src/flow/continues.ts +65 -0
- package/src/flow/cross-context.test.ts +97 -0
- package/src/flow/cross-context.ts +35 -0
- package/src/flow/mermaid.test.ts +22 -0
- package/src/flow/mermaid.ts +141 -0
- package/src/flow/outline.test.ts +212 -0
- package/src/flow/outline.ts +170 -0
- package/src/flow/paths.test.ts +129 -0
- package/src/flow/paths.ts +147 -0
- package/src/flow/prefs.test.ts +80 -0
- package/src/flow/prefs.ts +104 -0
- package/src/graph/DependencyGraph.tsx +283 -0
- package/src/graph/DependencyNodes.tsx +162 -0
- package/src/graph/EdgeLabel.tsx +61 -0
- package/src/graph/FocusedEventGraph.tsx +211 -0
- package/src/graph/GraphToolbar.tsx +187 -0
- package/src/graph/RoutedEdge.tsx +80 -0
- package/src/graph/dependency-layout.test.ts +360 -0
- package/src/graph/dependency-layout.ts +444 -0
- package/src/graph/elk.test.ts +70 -0
- package/src/graph/elk.ts +287 -0
- package/src/graph/nodes.tsx +97 -0
- package/src/graph/theme.ts +81 -0
- package/src/graph/useElkFlow.ts +125 -0
- package/src/index.css +1547 -0
- package/src/language/InLanguage.tsx +40 -0
- package/src/language/TermCard.tsx +132 -0
- package/src/language/cards.test.ts +114 -0
- package/src/language/cards.ts +111 -0
- package/src/lib/admonition.test.ts +49 -0
- package/src/lib/admonition.ts +48 -0
- package/src/lib/adr.test.ts +131 -0
- package/src/lib/adr.ts +68 -0
- package/src/lib/api.test.ts +122 -0
- package/src/lib/api.ts +135 -0
- package/src/lib/backlinks.test.ts +330 -0
- package/src/lib/backlinks.ts +567 -0
- package/src/lib/branch-compare.ts +16 -0
- package/src/lib/build-info.test.ts +76 -0
- package/src/lib/build-info.ts +80 -0
- package/src/lib/catalog-diff.test.ts +275 -0
- package/src/lib/catalog-diff.ts +655 -0
- package/src/lib/clipboard.ts +43 -0
- package/src/lib/comparison-memory.test.ts +40 -0
- package/src/lib/comparison-memory.ts +39 -0
- package/src/lib/context-color.ts +27 -0
- package/src/lib/context-map.test.ts +148 -0
- package/src/lib/context-map.ts +399 -0
- package/src/lib/data-model.test.ts +245 -0
- package/src/lib/data-model.ts +399 -0
- package/src/lib/data-problems.test.ts +178 -0
- package/src/lib/data-problems.ts +314 -0
- package/src/lib/derive.test.ts +251 -0
- package/src/lib/derive.ts +515 -0
- package/src/lib/editor-link.test.ts +125 -0
- package/src/lib/editor-link.ts +96 -0
- package/src/lib/editor-prefs.ts +27 -0
- package/src/lib/event-graph.test.ts +237 -0
- package/src/lib/event-graph.ts +327 -0
- package/src/lib/export-canvas.ts +37 -0
- package/src/lib/export-file.test.ts +30 -0
- package/src/lib/export-file.ts +20 -0
- package/src/lib/flow-tree.test.ts +177 -0
- package/src/lib/flow-tree.ts +160 -0
- package/src/lib/forge-refs.test.ts +50 -0
- package/src/lib/forge-refs.ts +60 -0
- package/src/lib/format.test.ts +35 -0
- package/src/lib/format.ts +64 -0
- package/src/lib/github-catalog.test.ts +301 -0
- package/src/lib/github-catalog.ts +610 -0
- package/src/lib/integrations.test.ts +119 -0
- package/src/lib/integrations.ts +133 -0
- package/src/lib/kinds.test.ts +91 -0
- package/src/lib/kinds.ts +204 -0
- package/src/lib/lifecycle.test.ts +93 -0
- package/src/lib/lifecycle.ts +165 -0
- package/src/lib/local-api.ts +194 -0
- package/src/lib/motion-features.ts +11 -0
- package/src/lib/motion.test.ts +120 -0
- package/src/lib/motion.tsx +269 -0
- package/src/lib/palette-recent.test.ts +80 -0
- package/src/lib/palette-recent.ts +90 -0
- package/src/lib/palette.test.ts +365 -0
- package/src/lib/palette.ts +593 -0
- package/src/lib/pins.test.ts +139 -0
- package/src/lib/pins.ts +130 -0
- package/src/lib/problems.test.ts +112 -0
- package/src/lib/project-preview.ts +5 -0
- package/src/lib/proto-problems.test.ts +121 -0
- package/src/lib/proto-problems.ts +65 -0
- package/src/lib/queries.test.ts +113 -0
- package/src/lib/queries.ts +131 -0
- package/src/lib/registry.test.ts +219 -0
- package/src/lib/registry.ts +208 -0
- package/src/lib/scenarios.ts +547 -0
- package/src/lib/setup-info.test.ts +199 -0
- package/src/lib/setup-info.ts +415 -0
- package/src/lib/shape.test.ts +289 -0
- package/src/lib/shape.ts +454 -0
- package/src/lib/sidebar-prefs.test.ts +32 -0
- package/src/lib/sidebar-prefs.ts +75 -0
- package/src/lib/source-code.test.ts +159 -0
- package/src/lib/source-code.ts +286 -0
- package/src/lib/source-doc.test.ts +131 -0
- package/src/lib/source-doc.ts +103 -0
- package/src/lib/source-highlight.test.ts +29 -0
- package/src/lib/source-highlight.ts +24 -0
- package/src/lib/source-link.test.ts +153 -0
- package/src/lib/source-link.ts +201 -0
- package/src/lib/spec-files.test.ts +24 -0
- package/src/lib/spec-files.ts +23 -0
- package/src/lib/table-directive.test.ts +139 -0
- package/src/lib/table-directive.ts +106 -0
- package/src/lib/tech.test.ts +120 -0
- package/src/lib/tech.ts +421 -0
- package/src/lib/terms.test.ts +67 -0
- package/src/lib/terms.ts +179 -0
- package/src/lib/wire-problems.test.ts +263 -0
- package/src/lib/wire-problems.ts +281 -0
- package/src/likec4/C4View.tsx +55 -0
- package/src/likec4/CanvasBridge.tsx +187 -0
- package/src/likec4/FlowView.tsx +235 -0
- package/src/likec4/InteractiveView.tsx +144 -0
- package/src/likec4/canvas-viewport.test.ts +149 -0
- package/src/likec4/canvas-viewport.ts +135 -0
- package/src/likec4/flow-edges.test.ts +51 -0
- package/src/likec4/flow-edges.ts +89 -0
- package/src/likec4/frame-theme.test.ts +76 -0
- package/src/likec4/frame-theme.ts +101 -0
- package/src/likec4/highlight-css.test.ts +49 -0
- package/src/likec4/highlight-css.ts +52 -0
- package/src/likec4/ids.test.ts +151 -0
- package/src/likec4/ids.ts +115 -0
- package/src/likec4/levels.tsx +70 -0
- package/src/likec4/mapping.test.ts +66 -0
- package/src/likec4/mapping.ts +54 -0
- package/src/likec4/reserved.json +141 -0
- package/src/likec4/view-index.ts +78 -0
- package/src/main.tsx +13 -0
- package/src/map/ContextMapGraph.tsx +274 -0
- package/src/map/ContextNode.tsx +70 -0
- package/src/map/FloatingEdge.tsx +86 -0
- package/src/merge.test.ts +1038 -0
- package/src/merge.ts +1004 -0
- package/src/pages/AdrDetail.tsx +242 -0
- package/src/pages/AdrIndex.tsx +114 -0
- package/src/pages/AggregatePage.tsx +727 -0
- package/src/pages/BlockPage.tsx +478 -0
- package/src/pages/CatalogFailure.tsx +111 -0
- package/src/pages/Changes.tsx +313 -0
- package/src/pages/ContextMap.tsx +534 -0
- package/src/pages/ContextPage.tsx +346 -0
- package/src/pages/EnumPage.tsx +282 -0
- package/src/pages/EventPage.tsx +686 -0
- package/src/pages/ExternalPage.tsx +204 -0
- package/src/pages/FlowDetail.tsx +663 -0
- package/src/pages/FlowIndex.tsx +303 -0
- package/src/pages/GraphPage.tsx +217 -0
- package/src/pages/Language.tsx +257 -0
- package/src/pages/ModulePage.tsx +366 -0
- package/src/pages/NotFound.tsx +54 -0
- package/src/pages/Overview.tsx +344 -0
- package/src/pages/Problems.tsx +360 -0
- package/src/pages/RegistryIndex.tsx +118 -0
- package/src/pages/ServicePage.tsx +746 -0
- package/src/pages/Settings.tsx +975 -0
- package/src/pages/StorePage.tsx +114 -0
- package/src/peek/PeekCard.test.ts +35 -0
- package/src/peek/PeekCard.tsx +118 -0
- package/src/peek/PeekLayer.tsx +147 -0
- package/src/peek/model.test.ts +156 -0
- package/src/peek/model.ts +253 -0
- package/src/routes.test.ts +222 -0
- package/src/routes.ts +449 -0
- package/src/selection/DetailPanel.tsx +1407 -0
- package/src/selection/hash.test.ts +73 -0
- package/src/selection/hash.ts +58 -0
- package/src/selection/model.test.ts +199 -0
- package/src/selection/model.ts +473 -0
- package/src/selection/pages.test.ts +115 -0
- package/src/selection/pages.ts +268 -0
- package/src/selection/store.test.ts +62 -0
- package/src/selection/store.ts +46 -0
- package/src/selection/sync.tsx +99 -0
- package/src/table/ColumnsMenu.tsx +72 -0
- package/src/table/DataTable.tsx +780 -0
- package/src/table/Facets.tsx +54 -0
- package/src/table/GroupMenu.tsx +69 -0
- package/src/table/Toolbar.tsx +190 -0
- package/src/table/cells.tsx +117 -0
- package/src/table/compare.test.ts +117 -0
- package/src/table/compare.ts +196 -0
- package/src/table/export.test.ts +88 -0
- package/src/table/export.ts +66 -0
- package/src/table/facet-groups.test.ts +74 -0
- package/src/table/facet-groups.ts +56 -0
- package/src/table/grouping.test.ts +84 -0
- package/src/table/grouping.ts +82 -0
- package/src/table/infer.test.ts +57 -0
- package/src/table/infer.ts +50 -0
- package/src/table/persist.test.ts +76 -0
- package/src/table/persist.ts +112 -0
- package/src/table/sort-url.test.ts +75 -0
- package/src/table/sort-url.ts +52 -0
- package/src/table/types.ts +80 -0
- package/src/table/useTableState.ts +220 -0
- package/src/test-catalog.ts +7 -0
- package/src/testing/estate/data__catalog.json +2847 -0
- package/src/testing/estate/data__flows.json +1724 -0
- package/src/testing/estate/examples__auth__portolan__api.json +212 -0
- package/src/testing/estate/examples__auth__portolan__domain.json +1204 -0
- package/src/testing/estate/examples__auth__portolan__glossary.json +226 -0
- package/src/testing/estate/examples__auth__portolan__observed.json +757 -0
- package/src/testing/estate/examples__auth__portolan__stores.json +195 -0
- package/src/testing/estate/examples__shop__cart__portolan__api.json +234 -0
- package/src/testing/estate/examples__shop__cart__portolan__commands.json +86 -0
- package/src/testing/estate/examples__shop__cart__portolan__domain.json +966 -0
- package/src/testing/estate/examples__shop__cart__portolan__observed.json +498 -0
- package/src/testing/estate/examples__shop__cart__portolan__stores.json +208 -0
- package/src/testing/estate/examples__shop__oms__portolan__glossary.json +98 -0
- package/src/testing/estate/examples__shop__oms__portolan__proto.json +186 -0
- package/src/testing/estate.ts +49 -0
- package/src/trail/Trail.tsx +81 -0
- package/src/trail/model.test.ts +157 -0
- package/src/trail/model.ts +189 -0
- package/src/trail/record.tsx +32 -0
- package/src/trail/store.test.ts +66 -0
- package/src/trail/store.ts +102 -0
- package/tsconfig.json +35 -0
- package/vite.config.ts +171 -0
package/src/index.css
ADDED
|
@@ -0,0 +1,1547 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
|
|
3
|
+
/* Theme is driven by a class on <html> so the toggle is instant and SSR-free. */
|
|
4
|
+
@custom-variant dark (&:where(.dark, .dark *));
|
|
5
|
+
|
|
6
|
+
/* ---------------------------------------------------------------------------
|
|
7
|
+
Tokens. Defined once, here. Nothing else in the app hard-codes a colour,
|
|
8
|
+
a radius, a duration or a step of the spacing rhythm.
|
|
9
|
+
|
|
10
|
+
The rhythm is 4px. Every literal below is a multiple of it: page gutter 24,
|
|
11
|
+
card padding 20, section gap 32, grid gap 20, card gap 16.
|
|
12
|
+
--------------------------------------------------------------------------- */
|
|
13
|
+
:root,
|
|
14
|
+
/* The sheet a foreign document is drawn on takes the light palette whatever
|
|
15
|
+
the site's theme is - see the rule further down that says why. Listed here
|
|
16
|
+
rather than repeating the values: one palette, declared once. */
|
|
17
|
+
.spec-sheet {
|
|
18
|
+
--bg: #ffffff;
|
|
19
|
+
--surface: #f7f8f9;
|
|
20
|
+
--surface-2: #eef0f2;
|
|
21
|
+
--border: #d9dde1;
|
|
22
|
+
--border-strong: #b9c0c7;
|
|
23
|
+
--fg: #14181c;
|
|
24
|
+
--fg-muted: #61707d;
|
|
25
|
+
/* A step below muted, and the last grey that is still text. Section counts
|
|
26
|
+
live here: a count annotates the header it sits on, and at --fg-muted it
|
|
27
|
+
competes with the header for the same glance. */
|
|
28
|
+
--fg-faint: #96a1ac;
|
|
29
|
+
--accent: #1f6feb;
|
|
30
|
+
/* The two stops of the one sanctioned accent gradient. Derived from --accent
|
|
31
|
+
rather than named, so a theme swap carries the gradient with it. */
|
|
32
|
+
--accent-lo: #1a5ec9;
|
|
33
|
+
--accent-hi: #3d86f5;
|
|
34
|
+
|
|
35
|
+
/* Source preview syntax. These are semantic roles rather than one imported
|
|
36
|
+
editor theme, so code follows Portolan's light and dark palettes. */
|
|
37
|
+
--syntax-comment: #6a737d;
|
|
38
|
+
--syntax-keyword: #7a3fa8;
|
|
39
|
+
--syntax-string: #0f7a6c;
|
|
40
|
+
--syntax-number: #a8552b;
|
|
41
|
+
--syntax-title: #2563a8;
|
|
42
|
+
--syntax-attribute: #8c4a6b;
|
|
43
|
+
|
|
44
|
+
--status-verified: #157f4a;
|
|
45
|
+
--status-declared: #8a6d1f;
|
|
46
|
+
--status-unresolved: #c02a29;
|
|
47
|
+
|
|
48
|
+
/* Domain events are the loudest leaf in the tree. Amber, but a step darker
|
|
49
|
+
than amber-600 so 12px mono still clears contrast on white. */
|
|
50
|
+
--kind-event: #b45309;
|
|
51
|
+
|
|
52
|
+
/* GitHub paints `[!IMPORTANT]` purple. Purple already exists in the context
|
|
53
|
+
ramp, where it means "this context"; the alert gets a name of its own so
|
|
54
|
+
the two can never drift into each other. The other four alerts reuse the
|
|
55
|
+
status ramp, which already carries their meaning. */
|
|
56
|
+
--alert-important: #7a3fa8;
|
|
57
|
+
|
|
58
|
+
--ctx-0: #2563a8;
|
|
59
|
+
--ctx-1: #7a3fa8;
|
|
60
|
+
--ctx-2: #0f7a6c;
|
|
61
|
+
--ctx-3: #a8552b;
|
|
62
|
+
--ctx-4: #4a5b8c;
|
|
63
|
+
--ctx-5: #8c4a6b;
|
|
64
|
+
|
|
65
|
+
/* Scrollbar thumbs are their own pair: they must read on --surface, not on
|
|
66
|
+
--bg, or the thin ones vanish inside a raised pane. */
|
|
67
|
+
--scroll-thumb: #cbd2d8;
|
|
68
|
+
--scroll-thumb-hover: #aeb7bf;
|
|
69
|
+
|
|
70
|
+
/* One shadow scale. xs sits under cards at rest, md under overlays only. */
|
|
71
|
+
--shadow-xs: 0 1px 2px rgb(16 24 32 / 0.06), 0 0 0 1px rgb(16 24 32 / 0.03);
|
|
72
|
+
--shadow-md:
|
|
73
|
+
0 8px 24px -6px rgb(16 24 32 / 0.18), 0 2px 6px -2px rgb(16 24 32 / 0.08);
|
|
74
|
+
|
|
75
|
+
/* A card on a diagram canvas. Three passes, the way Stripe draws a card: a
|
|
76
|
+
hairline ring that stands in for a border, a soft ambient pass, and a
|
|
77
|
+
crisp one-pixel contact line. The border is gone because a canvas of
|
|
78
|
+
forty outlined boxes is a wireframe; the ring reads as an edge without
|
|
79
|
+
being one. Lifted on hover, and the ring is what selection paints. */
|
|
80
|
+
--shadow-card:
|
|
81
|
+
0 0 0 1px rgb(60 66 87 / 0.08), 0 2px 5px rgb(60 66 87 / 0.08),
|
|
82
|
+
0 1px 1px rgb(0 0 0 / 0.06);
|
|
83
|
+
--shadow-card-hover:
|
|
84
|
+
0 0 0 1px rgb(60 66 87 / 0.1), 0 3px 9px rgb(60 66 87 / 0.12),
|
|
85
|
+
0 2px 2px rgb(0 0 0 / 0.06);
|
|
86
|
+
--ring:
|
|
87
|
+
0 0 0 1px var(--accent),
|
|
88
|
+
0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent);
|
|
89
|
+
--radius-node: 8px;
|
|
90
|
+
|
|
91
|
+
/* The canvas is a shade cooler than the page and the cards on it are the
|
|
92
|
+
page's white, so a card is lighter than what it sits on - that contrast,
|
|
93
|
+
not a border, is what makes it a card. The dots are the faintest grey
|
|
94
|
+
that still registers as a grid. */
|
|
95
|
+
--flow-pane: #f6f9fc;
|
|
96
|
+
--flow-card: #ffffff;
|
|
97
|
+
--flow-dot: #d9dfe6;
|
|
98
|
+
|
|
99
|
+
--font-sans:
|
|
100
|
+
ui-sans-serif, -apple-system, "Segoe UI", Roboto, Helvetica, Arial,
|
|
101
|
+
sans-serif;
|
|
102
|
+
--font-mono:
|
|
103
|
+
ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
|
|
104
|
+
|
|
105
|
+
/* Space. Named so a page cannot invent a seventh value for a gutter. */
|
|
106
|
+
--gutter: 24px;
|
|
107
|
+
--pad-card: 20px;
|
|
108
|
+
--gap-section: 32px;
|
|
109
|
+
--gap-grid: 20px;
|
|
110
|
+
--gap-card: 16px;
|
|
111
|
+
--w-prose: 900px;
|
|
112
|
+
--w-table: 1200px;
|
|
113
|
+
|
|
114
|
+
/* Density. Two settings, four tokens, set on <html data-density>. The
|
|
115
|
+
comfortable row is 40px because that is a row you read; the compact one is
|
|
116
|
+
30px because that is a row you scan. Nothing else changes: no font swap,
|
|
117
|
+
no border loss, no second layout. The header sits a step below its rows:
|
|
118
|
+
it is a label for the column, not another row of it. */
|
|
119
|
+
--row-h: 40px;
|
|
120
|
+
--row-h-head: 36px;
|
|
121
|
+
--row-h-tree: 32px;
|
|
122
|
+
--text-meta: 13px;
|
|
123
|
+
|
|
124
|
+
/* Motion. Three durations, two easings, nothing else. */
|
|
125
|
+
--dur-micro: 150ms;
|
|
126
|
+
--dur-panel: 250ms;
|
|
127
|
+
--dur-page: 250ms;
|
|
128
|
+
--dur-narrative: 400ms;
|
|
129
|
+
--ease-out: cubic-bezier(0.2, 0, 0, 1);
|
|
130
|
+
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
[data-density="compact"] {
|
|
134
|
+
--row-h: 30px;
|
|
135
|
+
--row-h-head: 28px;
|
|
136
|
+
--row-h-tree: 26px;
|
|
137
|
+
--text-meta: 12px;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.dark {
|
|
141
|
+
--bg: #0c0e11;
|
|
142
|
+
--surface: #14181d;
|
|
143
|
+
--surface-2: #1b2027;
|
|
144
|
+
--border: #262c34;
|
|
145
|
+
--border-strong: #3a424c;
|
|
146
|
+
--fg: #e3e8ee;
|
|
147
|
+
--fg-muted: #8b97a4;
|
|
148
|
+
--fg-faint: #626e7b;
|
|
149
|
+
--accent: #5b9dff;
|
|
150
|
+
--accent-lo: #3d7fe0;
|
|
151
|
+
--accent-hi: #7ab2ff;
|
|
152
|
+
|
|
153
|
+
--syntax-comment: #8b97a4;
|
|
154
|
+
--syntax-keyword: #c6a0f6;
|
|
155
|
+
--syntax-string: #72d5c4;
|
|
156
|
+
--syntax-number: #efa66a;
|
|
157
|
+
--syntax-title: #82b4f4;
|
|
158
|
+
--syntax-attribute: #e19abb;
|
|
159
|
+
|
|
160
|
+
--status-verified: #3fbf7f;
|
|
161
|
+
--status-declared: #d6a844;
|
|
162
|
+
--status-unresolved: #ff6b63;
|
|
163
|
+
|
|
164
|
+
--kind-event: #e8a33d;
|
|
165
|
+
|
|
166
|
+
--alert-important: #b98cf0;
|
|
167
|
+
|
|
168
|
+
--ctx-0: #6aa5f0;
|
|
169
|
+
--ctx-1: #b98cf0;
|
|
170
|
+
--ctx-2: #46bfae;
|
|
171
|
+
--ctx-3: #e0925f;
|
|
172
|
+
--ctx-4: #8e9fd8;
|
|
173
|
+
--ctx-5: #d98bab;
|
|
174
|
+
|
|
175
|
+
--scroll-thumb: #333b45;
|
|
176
|
+
--scroll-thumb-hover: #47515e;
|
|
177
|
+
|
|
178
|
+
/* Dark surfaces get no lift from a soft grey shadow, so the ambient pass is
|
|
179
|
+
near-black and the hairline that reads as elevation is carried by the ring. */
|
|
180
|
+
--shadow-xs: 0 1px 2px rgb(0 0 0 / 0.4), 0 0 0 1px rgb(255 255 255 / 0.04);
|
|
181
|
+
--shadow-md:
|
|
182
|
+
0 12px 32px -8px rgb(0 0 0 / 0.7), 0 2px 8px -2px rgb(0 0 0 / 0.5);
|
|
183
|
+
|
|
184
|
+
/* Same three passes, but the ring goes light and does the lifting: a dark
|
|
185
|
+
card on a dark canvas has no shadow to cast, only an edge to catch. */
|
|
186
|
+
--shadow-card:
|
|
187
|
+
0 0 0 1px rgb(255 255 255 / 0.07), 0 2px 5px rgb(0 0 0 / 0.4),
|
|
188
|
+
0 1px 1px rgb(0 0 0 / 0.5);
|
|
189
|
+
--shadow-card-hover:
|
|
190
|
+
0 0 0 1px rgb(255 255 255 / 0.12), 0 3px 9px rgb(0 0 0 / 0.5),
|
|
191
|
+
0 2px 2px rgb(0 0 0 / 0.5);
|
|
192
|
+
|
|
193
|
+
/* Inverted: the canvas is the page's black and the cards are a step up. */
|
|
194
|
+
--flow-pane: #0c0e11;
|
|
195
|
+
--flow-card: #161b21;
|
|
196
|
+
--flow-dot: #262c34;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@theme inline {
|
|
200
|
+
/* Roles, not raw names: `bg-canvas`, `text-muted`, `border-line`. The raw
|
|
201
|
+
custom properties above stay the single source of truth, so a theme swap
|
|
202
|
+
needs no rebuild and SVG/canvas code can still read them directly. */
|
|
203
|
+
--color-canvas: var(--bg);
|
|
204
|
+
--color-surface: var(--surface);
|
|
205
|
+
--color-raised: var(--surface-2);
|
|
206
|
+
--color-line: var(--border);
|
|
207
|
+
--color-line-strong: var(--border-strong);
|
|
208
|
+
--color-ink: var(--fg);
|
|
209
|
+
--color-muted: var(--fg-muted);
|
|
210
|
+
--color-faint: var(--fg-faint);
|
|
211
|
+
--color-accent: var(--accent);
|
|
212
|
+
--color-verified: var(--status-verified);
|
|
213
|
+
--color-declared: var(--status-declared);
|
|
214
|
+
--color-unresolved: var(--status-unresolved);
|
|
215
|
+
--color-event: var(--kind-event);
|
|
216
|
+
|
|
217
|
+
--font-sans: var(--font-sans);
|
|
218
|
+
--font-mono: var(--font-mono);
|
|
219
|
+
|
|
220
|
+
/* 12 / 13 / 14 / 16 / 20 / 28. Prose leads at 1.5, headings at 1.2. */
|
|
221
|
+
--text-xs: 12px;
|
|
222
|
+
--text-xs--line-height: 1.5;
|
|
223
|
+
--text-sm: 13px;
|
|
224
|
+
--text-sm--line-height: 1.5;
|
|
225
|
+
--text-base: 14px;
|
|
226
|
+
--text-base--line-height: 1.5;
|
|
227
|
+
--text-md: 16px;
|
|
228
|
+
--text-md--line-height: 1.5;
|
|
229
|
+
--text-lg: 20px;
|
|
230
|
+
--text-lg--line-height: 1.2;
|
|
231
|
+
--text-lg--letter-spacing: -0.01em;
|
|
232
|
+
--text-xl: 28px;
|
|
233
|
+
--text-xl--line-height: 1.2;
|
|
234
|
+
--text-xl--letter-spacing: -0.01em;
|
|
235
|
+
|
|
236
|
+
/* 6 controls, 10 cards, 14 modals and the palette. */
|
|
237
|
+
--radius-control: 6px;
|
|
238
|
+
--radius-card: 10px;
|
|
239
|
+
--radius-modal: 14px;
|
|
240
|
+
--radius-node: var(--radius-node);
|
|
241
|
+
|
|
242
|
+
--shadow-xs: var(--shadow-xs);
|
|
243
|
+
--shadow-md: var(--shadow-md);
|
|
244
|
+
--shadow-card: var(--shadow-card);
|
|
245
|
+
|
|
246
|
+
--spacing-gutter: var(--gutter);
|
|
247
|
+
--spacing-card: var(--pad-card);
|
|
248
|
+
--spacing-section: var(--gap-section);
|
|
249
|
+
--spacing-grid: var(--gap-grid);
|
|
250
|
+
|
|
251
|
+
--container-prose: var(--w-prose);
|
|
252
|
+
--container-table: var(--w-table);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* ---------------------------------------------------------------------------
|
|
256
|
+
Utilities
|
|
257
|
+
--------------------------------------------------------------------------- */
|
|
258
|
+
|
|
259
|
+
/* Identifiers are always monospace; prose never is. Counts, versions and
|
|
260
|
+
coverage all pass through here, so they are tabular by construction. */
|
|
261
|
+
@utility mono {
|
|
262
|
+
font-family: var(--font-mono);
|
|
263
|
+
font-size: var(--text-xs);
|
|
264
|
+
letter-spacing: -0.01em;
|
|
265
|
+
font-variant-numeric: tabular-nums;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* For the digits that are *not* monospace - card stats, tab counts. */
|
|
269
|
+
@utility tnum {
|
|
270
|
+
font-variant-numeric: tabular-nums;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* Paints from a --ctx custom property set on the element, so one class covers
|
|
274
|
+
every context colour without generating a utility per context. */
|
|
275
|
+
@utility ctx {
|
|
276
|
+
color: var(--ctx);
|
|
277
|
+
border-color: var(--ctx);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* Sanctioned gradient 1 - the page hero strip. A 120px wash of the entity's
|
|
281
|
+
own context colour behind the header; the content below it stays on solid
|
|
282
|
+
background, so nothing is ever read off a gradient. */
|
|
283
|
+
@utility hero {
|
|
284
|
+
position: relative;
|
|
285
|
+
isolation: isolate;
|
|
286
|
+
}
|
|
287
|
+
@utility hero-wash {
|
|
288
|
+
position: absolute;
|
|
289
|
+
inset: 0 0 auto 0;
|
|
290
|
+
height: 120px;
|
|
291
|
+
z-index: -1;
|
|
292
|
+
pointer-events: none;
|
|
293
|
+
background: linear-gradient(
|
|
294
|
+
to bottom,
|
|
295
|
+
color-mix(in srgb, var(--ctx, var(--accent)) 6%, transparent),
|
|
296
|
+
transparent
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* Sanctioned gradient 3 - a soft accent glow behind an empty-state
|
|
301
|
+
illustration or the palette input. 4%, centred, never on a border. */
|
|
302
|
+
@utility glow {
|
|
303
|
+
background-image: radial-gradient(
|
|
304
|
+
60% 120% at 50% 0%,
|
|
305
|
+
color-mix(in srgb, var(--accent) 4%, transparent),
|
|
306
|
+
transparent 70%
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/* Custom scrollbars on inner panes only: the shell itself never scrolls. */
|
|
311
|
+
@utility pane {
|
|
312
|
+
scrollbar-width: thin;
|
|
313
|
+
scrollbar-color: var(--scroll-thumb) transparent;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/* Names that can overflow truncate, and carry the full string in `title`. */
|
|
317
|
+
@utility trunc {
|
|
318
|
+
overflow: hidden;
|
|
319
|
+
text-overflow: ellipsis;
|
|
320
|
+
white-space: nowrap;
|
|
321
|
+
min-width: 0;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/* The same, cut from the other end. A dotted id reads right to left: the head
|
|
325
|
+
is the context, which every rail already says in colour, and the tail is the
|
|
326
|
+
only part that tells two participants apart. `shop.oms` and `shop.pricing`
|
|
327
|
+
truncated from the right are both `sho…`; from the left they are `…oms` and
|
|
328
|
+
`…pricing`, which is the whole question the line was asked.
|
|
329
|
+
The box is rtl so the ellipsis lands at the start; the text inside must be
|
|
330
|
+
wrapped in <bdi> so it is isolated and still reads left to right. */
|
|
331
|
+
@utility trunc-tail {
|
|
332
|
+
overflow: hidden;
|
|
333
|
+
text-overflow: ellipsis;
|
|
334
|
+
white-space: nowrap;
|
|
335
|
+
min-width: 0;
|
|
336
|
+
direction: rtl;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
@layer components {
|
|
340
|
+
.source-code .hljs-comment,
|
|
341
|
+
.source-code .hljs-quote {
|
|
342
|
+
color: var(--syntax-comment);
|
|
343
|
+
font-style: italic;
|
|
344
|
+
}
|
|
345
|
+
.source-code .hljs-keyword,
|
|
346
|
+
.source-code .hljs-selector-tag,
|
|
347
|
+
.source-code .hljs-meta,
|
|
348
|
+
.source-code .hljs-doctag {
|
|
349
|
+
color: var(--syntax-keyword);
|
|
350
|
+
}
|
|
351
|
+
.source-code .hljs-string,
|
|
352
|
+
.source-code .hljs-regexp,
|
|
353
|
+
.source-code .hljs-template-tag,
|
|
354
|
+
.source-code .hljs-template-variable,
|
|
355
|
+
.source-code .hljs-addition {
|
|
356
|
+
color: var(--syntax-string);
|
|
357
|
+
}
|
|
358
|
+
.source-code .hljs-number,
|
|
359
|
+
.source-code .hljs-literal,
|
|
360
|
+
.source-code .hljs-symbol,
|
|
361
|
+
.source-code .hljs-bullet,
|
|
362
|
+
.source-code .hljs-deletion {
|
|
363
|
+
color: var(--syntax-number);
|
|
364
|
+
}
|
|
365
|
+
.source-code .hljs-title,
|
|
366
|
+
.source-code .hljs-section,
|
|
367
|
+
.source-code .hljs-built_in,
|
|
368
|
+
.source-code .hljs-type {
|
|
369
|
+
color: var(--syntax-title);
|
|
370
|
+
}
|
|
371
|
+
.source-code .hljs-attr,
|
|
372
|
+
.source-code .hljs-attribute,
|
|
373
|
+
.source-code .hljs-variable,
|
|
374
|
+
.source-code .hljs-params,
|
|
375
|
+
.source-code .hljs-property {
|
|
376
|
+
color: var(--syntax-attribute);
|
|
377
|
+
}
|
|
378
|
+
.source-code .hljs-emphasis {
|
|
379
|
+
font-style: italic;
|
|
380
|
+
}
|
|
381
|
+
.source-code .hljs-strong {
|
|
382
|
+
font-weight: 600;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/* Floating UI publishes the whole available viewport as an inline maximum.
|
|
386
|
+
A branch list may contain a hundred refs; cap it to a readable picker and
|
|
387
|
+
let the list scroll instead of turning the picker into a page-sized veil. */
|
|
388
|
+
.branch-options {
|
|
389
|
+
max-height: min(28rem, calc(100vh - 64px)) !important;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/* The bordered monospace token used for status, contexts and classes. */
|
|
393
|
+
.chip {
|
|
394
|
+
@apply mono inline-flex items-center gap-1 rounded-control border px-1.5 py-px leading-4;
|
|
395
|
+
}
|
|
396
|
+
.chip-lg {
|
|
397
|
+
@apply mono inline-flex items-center gap-1.5 rounded-control border px-2 py-0.5 leading-4;
|
|
398
|
+
}
|
|
399
|
+
/* Square marker that inherits the chip's colour. */
|
|
400
|
+
.dot {
|
|
401
|
+
@apply inline-block size-1.5 shrink-0 rounded-[1px] bg-current;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.status-verified {
|
|
405
|
+
color: var(--status-verified);
|
|
406
|
+
border-color: var(--status-verified);
|
|
407
|
+
}
|
|
408
|
+
.status-declared {
|
|
409
|
+
color: var(--status-declared);
|
|
410
|
+
border-color: var(--status-declared);
|
|
411
|
+
}
|
|
412
|
+
.status-unresolved {
|
|
413
|
+
color: var(--status-unresolved);
|
|
414
|
+
border-color: var(--status-unresolved);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/* Section label above a block of content. */
|
|
418
|
+
.label {
|
|
419
|
+
@apply mono uppercase text-muted;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/* The heading of a page section, and whatever the section puts opposite it.
|
|
423
|
+
|
|
424
|
+
They were both `.label`: the same 12px muted grey, so "Consumers" and
|
|
425
|
+
"published by auth.auth" carried the same weight and the eye had no
|
|
426
|
+
reason to read one before the other. The title keeps the mono eyebrow -
|
|
427
|
+
it is this app's signature - but takes a step up into ink, and the aside
|
|
428
|
+
takes a step down into faint, which is what the token was defined for.
|
|
429
|
+
|
|
430
|
+
The aside is sans, because most of them are sentences rather than counts:
|
|
431
|
+
"identity matters - these are tracked over time" is prose, and prose set
|
|
432
|
+
in 12px monospace reads as a log line. Digits are tabular anyway, so a
|
|
433
|
+
count loses nothing; an identifier in there still asks for `.mono`. */
|
|
434
|
+
.section-title {
|
|
435
|
+
@apply mono uppercase text-ink;
|
|
436
|
+
font-size: var(--text-sm);
|
|
437
|
+
font-weight: 500;
|
|
438
|
+
}
|
|
439
|
+
.section-aside {
|
|
440
|
+
@apply text-faint;
|
|
441
|
+
font-size: var(--text-meta);
|
|
442
|
+
font-variant-numeric: tabular-nums;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/* A bordered, hoverable block that is also a link. Padding is the card
|
|
446
|
+
token; the shadow is the only elevation a card ever gets - a card does not
|
|
447
|
+
rise on hover, because md is the overlay tier and a grid of twelve cards
|
|
448
|
+
that all want to be overlays is a grid nobody can read. What changes on
|
|
449
|
+
hover is the border, from the hairline to the strong one: the card firms
|
|
450
|
+
up rather than lifts. */
|
|
451
|
+
.card {
|
|
452
|
+
@apply relative block rounded-card border border-line p-card shadow-xs;
|
|
453
|
+
transition:
|
|
454
|
+
background-color var(--dur-micro) var(--ease-out),
|
|
455
|
+
border-color var(--dur-micro) var(--ease-out);
|
|
456
|
+
}
|
|
457
|
+
.card:hover {
|
|
458
|
+
@apply bg-surface;
|
|
459
|
+
border-color: var(--border-strong);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/* A card that HOLDS destinations rather than being one. It must not light
|
|
463
|
+
up under the pointer: a surface that reacts to hover and answers no click
|
|
464
|
+
is the fastest way to teach a reader that hover means nothing here. */
|
|
465
|
+
.card-static:hover {
|
|
466
|
+
background: transparent;
|
|
467
|
+
border-color: var(--border);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/* The context stripe, as a class rather than three inline style longhands
|
|
471
|
+
on every card that wants one. It stays its context's colour while the
|
|
472
|
+
other three edges firm up, so hovering never costs the card its tag. */
|
|
473
|
+
.card-tagged {
|
|
474
|
+
border-left-width: 3px;
|
|
475
|
+
border-left-color: var(--ctx, var(--accent));
|
|
476
|
+
}
|
|
477
|
+
.card-tagged:hover {
|
|
478
|
+
border-left-color: var(--ctx, var(--accent));
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/*
|
|
482
|
+
* A card whose title is a link, made clickable everywhere.
|
|
483
|
+
*
|
|
484
|
+
* A 300px card with one 90px link in the corner of it is a target the reader
|
|
485
|
+
* has to aim at, and every card in this app is a card about ONE thing. The
|
|
486
|
+
* title's ::after covers the whole card, so a click anywhere follows it;
|
|
487
|
+
* every other control inside is lifted above that sheet so the counts, the
|
|
488
|
+
* chips and the row actions keep their own clicks. Links cannot nest, which
|
|
489
|
+
* is why this is a pseudo-element and not a wrapper.
|
|
490
|
+
*/
|
|
491
|
+
.card-link::after {
|
|
492
|
+
content: "";
|
|
493
|
+
position: absolute;
|
|
494
|
+
inset: 0;
|
|
495
|
+
border-radius: inherit;
|
|
496
|
+
}
|
|
497
|
+
.card :is(a, button):not(.card-link) {
|
|
498
|
+
position: relative;
|
|
499
|
+
z-index: 1;
|
|
500
|
+
}
|
|
501
|
+
.card:hover .card-link {
|
|
502
|
+
text-decoration: underline;
|
|
503
|
+
}
|
|
504
|
+
/* The ring belongs to the card, not to the eight characters of its name:
|
|
505
|
+
j and k move focus to the title, and what the reader needs to see is
|
|
506
|
+
which card they are standing on. */
|
|
507
|
+
.card:has(.card-link:focus-visible) {
|
|
508
|
+
outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent);
|
|
509
|
+
outline-offset: 2px;
|
|
510
|
+
}
|
|
511
|
+
.card .card-link:focus-visible {
|
|
512
|
+
outline: none;
|
|
513
|
+
}
|
|
514
|
+
.row {
|
|
515
|
+
@apply flex items-center gap-3 rounded-control border border-line px-3 py-2;
|
|
516
|
+
min-height: var(--row-h);
|
|
517
|
+
transition: background-color var(--dur-micro) var(--ease-out);
|
|
518
|
+
}
|
|
519
|
+
.row:hover {
|
|
520
|
+
@apply bg-surface;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/* A list whose rows line up. The list owns the columns and each row is a
|
|
524
|
+
subgrid of them, so the same field starts at the same x on every line and
|
|
525
|
+
the eye reads down a column instead of hunting along each row. Rows keep
|
|
526
|
+
their own border and hover, which is why this is a subgrid rather than one
|
|
527
|
+
flat grid with the row chrome painted over it.
|
|
528
|
+
|
|
529
|
+
The list says what the columns are - `rows grid-cols-[auto_1fr_auto]` -
|
|
530
|
+
and every row emits one cell per column, empty ones included: a skipped
|
|
531
|
+
cell shifts everything after it one column to the left. */
|
|
532
|
+
.rows {
|
|
533
|
+
@apply grid gap-1;
|
|
534
|
+
}
|
|
535
|
+
.rows > * {
|
|
536
|
+
@apply col-span-full grid grid-cols-subgrid;
|
|
537
|
+
}
|
|
538
|
+
/* A chip is a badge, not a cell. It keeps the width of what it says rather
|
|
539
|
+
than stretching to the column the alignment handed it. */
|
|
540
|
+
.rows > * > .chip {
|
|
541
|
+
@apply justify-self-start;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/* Toolbar and filter buttons. Border colour is the only thing that changes
|
|
545
|
+
on hover or press, so nothing reflows underneath. */
|
|
546
|
+
.tbtn {
|
|
547
|
+
@apply mono flex items-center gap-1.5 rounded-control border border-line px-2 py-1 text-muted;
|
|
548
|
+
transition:
|
|
549
|
+
background-color var(--dur-micro) var(--ease-out),
|
|
550
|
+
border-color var(--dur-micro) var(--ease-out),
|
|
551
|
+
color var(--dur-micro) var(--ease-out);
|
|
552
|
+
}
|
|
553
|
+
.tbtn:hover {
|
|
554
|
+
@apply bg-surface;
|
|
555
|
+
}
|
|
556
|
+
.tbtn-on {
|
|
557
|
+
border-color: var(--accent);
|
|
558
|
+
color: var(--accent);
|
|
559
|
+
background: color-mix(in srgb, var(--accent) 10%, transparent);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/* Sanctioned gradient 2 - the accent surface. Reserved for a primary button;
|
|
563
|
+
white on --accent-lo clears 4.5:1 in both themes. */
|
|
564
|
+
.btn-accent {
|
|
565
|
+
@apply mono flex items-center gap-1.5 rounded-control px-3 py-1.5;
|
|
566
|
+
color: #fff;
|
|
567
|
+
background-image: linear-gradient(
|
|
568
|
+
to bottom,
|
|
569
|
+
var(--accent-hi),
|
|
570
|
+
var(--accent-lo)
|
|
571
|
+
);
|
|
572
|
+
transition: filter var(--dur-micro) var(--ease-out);
|
|
573
|
+
}
|
|
574
|
+
.btn-accent:hover {
|
|
575
|
+
filter: brightness(1.06);
|
|
576
|
+
}
|
|
577
|
+
.btn-accent:disabled,
|
|
578
|
+
.tbtn:disabled {
|
|
579
|
+
cursor: not-allowed;
|
|
580
|
+
opacity: 0.55;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/* A group of related controls reads as one object: a single border around
|
|
584
|
+
the set, hairlines only between its members. */
|
|
585
|
+
.seg {
|
|
586
|
+
@apply flex items-center overflow-hidden rounded-control border border-line;
|
|
587
|
+
}
|
|
588
|
+
.seg > * + * {
|
|
589
|
+
border-left: 1px solid var(--border);
|
|
590
|
+
}
|
|
591
|
+
.seg > button,
|
|
592
|
+
.seg > a {
|
|
593
|
+
@apply mono px-2 py-1 text-muted;
|
|
594
|
+
transition:
|
|
595
|
+
background-color var(--dur-micro) var(--ease-out),
|
|
596
|
+
color var(--dur-micro) var(--ease-out);
|
|
597
|
+
}
|
|
598
|
+
.seg > button:hover,
|
|
599
|
+
.seg > a:hover {
|
|
600
|
+
@apply bg-surface;
|
|
601
|
+
}
|
|
602
|
+
.seg > .is-on {
|
|
603
|
+
color: var(--accent);
|
|
604
|
+
background: color-mix(in srgb, var(--accent) 10%, transparent);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/* Rows of switches under one border. The box belongs to the stack, the
|
|
608
|
+
hairlines to what is inside it: the rows are the same object seen twice,
|
|
609
|
+
not two objects stacked. */
|
|
610
|
+
.seg-stack {
|
|
611
|
+
@apply overflow-hidden rounded-control border border-line;
|
|
612
|
+
}
|
|
613
|
+
.seg-stack > .seg {
|
|
614
|
+
@apply rounded-none border-0;
|
|
615
|
+
}
|
|
616
|
+
.seg-stack > .seg + .seg {
|
|
617
|
+
border-top: 1px solid var(--border);
|
|
618
|
+
}
|
|
619
|
+
/* A segment floating over a canvas. It is a card, so it wears the card's
|
|
620
|
+
shadow in place of its border; the hairlines between members stay. */
|
|
621
|
+
.seg-float {
|
|
622
|
+
@apply shadow-card;
|
|
623
|
+
background: var(--flow-card);
|
|
624
|
+
border-color: transparent;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/* ---------------------------------------------------------------------
|
|
628
|
+
A node on a React Flow canvas. The class carries what every kind of node
|
|
629
|
+
shares - the card surface, the radius, the shadow and its lift - so a
|
|
630
|
+
component is left with only what makes it a service, an event or a
|
|
631
|
+
table. A ghost is not a card: it is a name someone wrote down, and it is
|
|
632
|
+
drawn as an outline of one.
|
|
633
|
+
--------------------------------------------------------------------- */
|
|
634
|
+
.flow-card {
|
|
635
|
+
background: var(--flow-card);
|
|
636
|
+
border-radius: var(--radius-node);
|
|
637
|
+
box-shadow: var(--shadow-card);
|
|
638
|
+
transition: box-shadow var(--dur-micro) var(--ease-out);
|
|
639
|
+
}
|
|
640
|
+
.flow-card:hover {
|
|
641
|
+
box-shadow: var(--shadow-card-hover);
|
|
642
|
+
}
|
|
643
|
+
.flow-card-ghost {
|
|
644
|
+
background: transparent;
|
|
645
|
+
border-radius: var(--radius-node);
|
|
646
|
+
border: 1px dashed currentColor;
|
|
647
|
+
}
|
|
648
|
+
/* The small tinted square an icon sits in, which is where a card keeps
|
|
649
|
+
the colour of the context that owns it. */
|
|
650
|
+
.flow-tile {
|
|
651
|
+
@apply flex shrink-0 items-center justify-center rounded-control;
|
|
652
|
+
width: 22px;
|
|
653
|
+
height: 22px;
|
|
654
|
+
background: color-mix(in srgb, currentColor 12%, transparent);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/* Non-navigable header for a group of leaves inside an aggregate. */
|
|
658
|
+
.group-row {
|
|
659
|
+
@apply mono flex w-full items-center gap-1.5 py-[3px] pr-2 text-left text-muted hover:bg-surface;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/* ---------------------------------------------------------------------
|
|
663
|
+
The table of contents dock. 24px of the page, whatever the section names
|
|
664
|
+
are - the panel inside is absolute and anchored to the dock's right edge,
|
|
665
|
+
so opening it costs the layout nothing and closing it costs no reflow.
|
|
666
|
+
--------------------------------------------------------------------- */
|
|
667
|
+
.toc-dock {
|
|
668
|
+
width: 24px;
|
|
669
|
+
/* Pinned just under the page's name row, which is pinned too. */
|
|
670
|
+
top: var(--page-header-h, 0px);
|
|
671
|
+
}
|
|
672
|
+
/* In flow, so the dock has a height to be hovered at all - what overlays is
|
|
673
|
+
the WIDTH. The panel grows to 216px while its left margin goes equally
|
|
674
|
+
negative, so its right edge never moves and the extra 192px are taken out
|
|
675
|
+
of the page rather than added to it. */
|
|
676
|
+
.toc-panel {
|
|
677
|
+
position: relative;
|
|
678
|
+
z-index: 20;
|
|
679
|
+
width: 24px;
|
|
680
|
+
overflow: hidden;
|
|
681
|
+
padding-bottom: 4px;
|
|
682
|
+
border: 1px solid transparent;
|
|
683
|
+
border-radius: var(--radius-card);
|
|
684
|
+
transition:
|
|
685
|
+
width var(--dur-micro) var(--ease-out),
|
|
686
|
+
margin-left var(--dur-micro) var(--ease-out),
|
|
687
|
+
background-color var(--dur-micro) var(--ease-out),
|
|
688
|
+
border-color var(--dur-micro) var(--ease-out),
|
|
689
|
+
box-shadow var(--dur-micro) var(--ease-out);
|
|
690
|
+
}
|
|
691
|
+
.toc-dock:hover .toc-panel,
|
|
692
|
+
.toc-panel:focus-within {
|
|
693
|
+
width: 216px;
|
|
694
|
+
margin-left: -192px;
|
|
695
|
+
border-color: var(--border-strong);
|
|
696
|
+
background: var(--bg);
|
|
697
|
+
box-shadow: var(--shadow-md);
|
|
698
|
+
}
|
|
699
|
+
/* The tick is the marker and the hairline at once: 2px, always drawn, so
|
|
700
|
+
nothing shifts as the spy moves down the page. */
|
|
701
|
+
.toc-item {
|
|
702
|
+
@apply block truncate py-0.5 pr-2 pl-2.5;
|
|
703
|
+
border-left-width: 2px;
|
|
704
|
+
border-left-style: solid;
|
|
705
|
+
transition:
|
|
706
|
+
color var(--dur-micro) var(--ease-out),
|
|
707
|
+
border-color var(--dur-micro) var(--ease-out);
|
|
708
|
+
}
|
|
709
|
+
.toc-item:hover {
|
|
710
|
+
text-decoration: underline;
|
|
711
|
+
}
|
|
712
|
+
/* Names are what you want once you have decided to leave, not while you are
|
|
713
|
+
reading. They are clipped rather than removed, so the panel can measure
|
|
714
|
+
them the moment it opens and a screen reader can always read them. */
|
|
715
|
+
.toc-name {
|
|
716
|
+
@apply block truncate opacity-0;
|
|
717
|
+
transition: opacity var(--dur-micro) var(--ease-out);
|
|
718
|
+
}
|
|
719
|
+
.toc-dock:hover .toc-name,
|
|
720
|
+
.toc-panel:focus-within .toc-name {
|
|
721
|
+
@apply opacity-100;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/* Anything that pins itself over scrolling content is translucent, not
|
|
725
|
+
opaque: the reader can see that there is more underneath. */
|
|
726
|
+
.sticky-bar {
|
|
727
|
+
background: color-mix(in srgb, var(--bg) 80%, transparent);
|
|
728
|
+
backdrop-filter: blur(8px);
|
|
729
|
+
-webkit-backdrop-filter: blur(8px);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/* The name row of an entity page stays at the top of the page while the
|
|
733
|
+
page scrolls under it. Transparent in place, so the hero wash shows
|
|
734
|
+
through as it always did; opaque once pinned, so the row is read off
|
|
735
|
+
solid ground and not off whatever is passing beneath. The rule under it
|
|
736
|
+
is a shadow rather than a border: a border would be a pixel of height
|
|
737
|
+
that appears on pinning, and the page would jump by it. Above a table's
|
|
738
|
+
sticky head (z-20) and a readme heading (z-10), below the overlays (z-40). */
|
|
739
|
+
.page-bar {
|
|
740
|
+
@apply sticky top-0 z-30;
|
|
741
|
+
transition: background-color var(--dur-micro) var(--ease-out);
|
|
742
|
+
}
|
|
743
|
+
.page-bar[data-stuck] {
|
|
744
|
+
background: var(--bg);
|
|
745
|
+
box-shadow: 0 1px 0 var(--border);
|
|
746
|
+
}
|
|
747
|
+
/* The row measures itself into --page-header-h on the box it scrolls in,
|
|
748
|
+
and that box treats the covered strip as not-visible: an anchor scrolled
|
|
749
|
+
to lands under the row's bottom edge rather than behind it. */
|
|
750
|
+
:has(> .page-bar) {
|
|
751
|
+
scroll-padding-top: var(--page-header-h, 0px);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/* A section's heading stays at the top of its section while the section
|
|
755
|
+
scrolls under it, just below the pinned name row - the same footing a
|
|
756
|
+
readme's h2 has. Sticky within the section, so it leaves when the section
|
|
757
|
+
does; opaque, so where two share a parent the later one simply covers the
|
|
758
|
+
first. The padding is what keeps the text off the row's rule when pinned,
|
|
759
|
+
and the negative margin gives it back, so nothing moves in place.
|
|
760
|
+
|
|
761
|
+
It pins a gutter higher than it reads, because sticky measures from the
|
|
762
|
+
scrollport's padding box: at `top: 0` a page with no header of its own
|
|
763
|
+
leaves the box's own gutter uncovered, and the rows scrolling through that
|
|
764
|
+
strip are the one thing a pinned heading exists to stop. Padding puts the
|
|
765
|
+
text back where it was, so a page that does have a header - which covers
|
|
766
|
+
the strip anyway, being the higher layer - is unchanged. */
|
|
767
|
+
.section-head {
|
|
768
|
+
position: sticky;
|
|
769
|
+
top: calc(var(--page-header-h, 0px) - var(--gutter));
|
|
770
|
+
z-index: 10;
|
|
771
|
+
padding-top: calc(var(--gutter) + 4px);
|
|
772
|
+
margin-top: calc(-1 * (var(--gutter) + 4px));
|
|
773
|
+
background: var(--bg);
|
|
774
|
+
/* The rule a readme's h2 has had all along, which is the footing this
|
|
775
|
+
heading was written to share. Unpinned it divides the page; pinned it is
|
|
776
|
+
the edge the section passes under, without which the content slides
|
|
777
|
+
against the words. A shadow rather than a border, for the reason the
|
|
778
|
+
page bar gives: a border is a pixel of height, and the section would
|
|
779
|
+
move by it. */
|
|
780
|
+
box-shadow: 0 1px 0 var(--border);
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
/* The flow page's one bar. Wraps rather than scrolls: a control that has
|
|
784
|
+
gone off the right-hand edge of a toolbar is a control nobody finds. */
|
|
785
|
+
.flow-toolbar {
|
|
786
|
+
@apply mt-2 flex flex-wrap items-center gap-2;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
/* A chapter header on the step rail. Sticky, because a chapter is how the
|
|
790
|
+
reader knows where they are in a forty-step sequence, and a heading that
|
|
791
|
+
scrolls away stops answering that at exactly the point it is asked. */
|
|
792
|
+
.chapter-row {
|
|
793
|
+
@apply sticky top-0 z-10 flex w-full items-center gap-1.5 border-y px-2 py-1 text-left border-line;
|
|
794
|
+
background: color-mix(in srgb, var(--surface) 92%, transparent);
|
|
795
|
+
backdrop-filter: blur(8px);
|
|
796
|
+
-webkit-backdrop-filter: blur(8px);
|
|
797
|
+
}
|
|
798
|
+
.chapter-row:hover {
|
|
799
|
+
background: var(--surface-2);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/* The matching-steps pill rides above the rail and must survive the rail
|
|
803
|
+
scrolling itself to a match, or it scrolls out of sight the moment it
|
|
804
|
+
becomes useful. */
|
|
805
|
+
.pill-rail {
|
|
806
|
+
@apply mono sticky top-0 z-10 flex items-center gap-1.5 border-b px-2 py-1.5 border-line;
|
|
807
|
+
background: color-mix(in srgb, var(--bg) 80%, transparent);
|
|
808
|
+
backdrop-filter: blur(8px);
|
|
809
|
+
-webkit-backdrop-filter: blur(8px);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/* One line with a bit of character, never an illustration block. The dashed
|
|
813
|
+
border and the 4% glow are the whole of the decoration.
|
|
814
|
+
|
|
815
|
+
It is a sentence, so it is set like one: sans, ranged left, at the size of
|
|
816
|
+
the rows it stands in for. Centred monospace made the best lines in the
|
|
817
|
+
app - "nobody is listening - this event falls silent" - read as debug
|
|
818
|
+
output, which is the opposite of what they are for. */
|
|
819
|
+
.empty {
|
|
820
|
+
@apply glow rounded-card border border-dashed border-line-strong px-4 py-3 text-muted;
|
|
821
|
+
font-size: var(--text-meta);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
/* ---------------------------------------------------------------------
|
|
825
|
+
Identifiers. Every id, path and type name in the app is an <Ident>, and
|
|
826
|
+
every <Ident> is this button: it looks like text until the pointer is on
|
|
827
|
+
it, then it looks like something you can take.
|
|
828
|
+
--------------------------------------------------------------------- */
|
|
829
|
+
.ident {
|
|
830
|
+
@apply trunc cursor-copy rounded-[4px] text-left align-baseline;
|
|
831
|
+
transition:
|
|
832
|
+
background-color var(--dur-micro) var(--ease-out),
|
|
833
|
+
color var(--dur-micro) var(--ease-out);
|
|
834
|
+
}
|
|
835
|
+
.ident:hover {
|
|
836
|
+
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
|
837
|
+
color: var(--accent);
|
|
838
|
+
}
|
|
839
|
+
/* Above and centred so it never covers the id it is confirming. */
|
|
840
|
+
.ident-tip {
|
|
841
|
+
@apply mono pointer-events-none absolute bottom-full left-1/2 z-30 mb-1 rounded-[4px] border px-1.5 py-px whitespace-nowrap;
|
|
842
|
+
transform: translateX(-50%);
|
|
843
|
+
border-color: var(--accent);
|
|
844
|
+
color: var(--accent);
|
|
845
|
+
background: var(--bg);
|
|
846
|
+
box-shadow: var(--shadow-xs);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/* ---------------------------------------------------------------------
|
|
850
|
+
Tables. Density lives in --row-h; the sticky pair keeps the header and
|
|
851
|
+
the first column on screen while a wide table scrolls under them.
|
|
852
|
+
--------------------------------------------------------------------- */
|
|
853
|
+
.tbl {
|
|
854
|
+
@apply w-full;
|
|
855
|
+
border-collapse: separate;
|
|
856
|
+
border-spacing: 0;
|
|
857
|
+
}
|
|
858
|
+
.tbl td {
|
|
859
|
+
height: var(--row-h);
|
|
860
|
+
}
|
|
861
|
+
.tbl th {
|
|
862
|
+
height: var(--row-h-head);
|
|
863
|
+
}
|
|
864
|
+
/* The row rule is drawn on the cells, not on the row: `border-collapse:
|
|
865
|
+
separate` is what makes a sticky column possible, and a separated table
|
|
866
|
+
never paints a border set on <tr>. */
|
|
867
|
+
.tbl thead th,
|
|
868
|
+
.tbl tbody td {
|
|
869
|
+
border-bottom: 1px solid var(--border);
|
|
870
|
+
}
|
|
871
|
+
.tbl tbody tr:last-child td {
|
|
872
|
+
border-bottom: 0;
|
|
873
|
+
}
|
|
874
|
+
.tbl tbody tr {
|
|
875
|
+
transition: background-color var(--dur-micro) var(--ease-out);
|
|
876
|
+
}
|
|
877
|
+
.tbl tbody tr:hover {
|
|
878
|
+
background: var(--surface);
|
|
879
|
+
}
|
|
880
|
+
/* The header is translucent over its own rows, and opaque where a sticky
|
|
881
|
+
first column passes under it - two translucent layers stack into a smear. */
|
|
882
|
+
.tbl-sticky thead th {
|
|
883
|
+
@apply sticky top-0 z-20;
|
|
884
|
+
background: color-mix(in srgb, var(--bg) 80%, transparent);
|
|
885
|
+
backdrop-filter: blur(8px);
|
|
886
|
+
-webkit-backdrop-filter: blur(8px);
|
|
887
|
+
}
|
|
888
|
+
.tbl-sticky tbody td:first-child,
|
|
889
|
+
.tbl-sticky thead th:first-child {
|
|
890
|
+
@apply sticky left-0 z-10;
|
|
891
|
+
background: var(--bg);
|
|
892
|
+
}
|
|
893
|
+
.tbl-sticky thead th:first-child {
|
|
894
|
+
z-index: 30;
|
|
895
|
+
}
|
|
896
|
+
.tbl-sticky tbody tr:hover td:first-child {
|
|
897
|
+
background: var(--surface);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/* Striping is off by default and a toolbar toggle away, because a table of
|
|
901
|
+
six rows does not need help being read and a table of six hundred does.
|
|
902
|
+
The stripe is painted on the cells for the same reason the row rule is:
|
|
903
|
+
a separated table never paints a background set on <tr> under a sticky
|
|
904
|
+
column. Parity comes from the row's display position rather than from
|
|
905
|
+
nth-child, so a virtualized body's spacer rows cannot invert it. */
|
|
906
|
+
.tbl-zebra tbody tr[data-even="false"] td {
|
|
907
|
+
background: var(--surface-2);
|
|
908
|
+
}
|
|
909
|
+
.tbl-zebra tbody tr:hover td {
|
|
910
|
+
background: var(--surface);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/* A group's heading row, tinted apart from the leaves under it. Painted on
|
|
914
|
+
the cell, and after the sticky-column rule, for the same reason the
|
|
915
|
+
stripe is: under a pinned first column a <tr> background never shows. */
|
|
916
|
+
.tbl tbody tr.tbl-group td,
|
|
917
|
+
.tbl-sticky tbody tr.tbl-group td:first-child {
|
|
918
|
+
background: var(--surface-2);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
/* A column edge you can take hold of. Four pixels wide and invisible until
|
|
922
|
+
the pointer is on the header, so the header is not a row of handles. */
|
|
923
|
+
.col-resize {
|
|
924
|
+
@apply absolute top-0 right-0 z-10 h-full w-1 cursor-col-resize touch-none opacity-0 select-none;
|
|
925
|
+
background: var(--accent);
|
|
926
|
+
transition: opacity var(--dur-micro) var(--ease-out);
|
|
927
|
+
}
|
|
928
|
+
th:hover > .col-resize,
|
|
929
|
+
.col-resize-on {
|
|
930
|
+
@apply opacity-100;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/* The header's own button. The chevron is in the DOM at every width and
|
|
934
|
+
shown only where it means something - the column under the pointer, or
|
|
935
|
+
the column the table is actually sorted by - so a header row is a row of
|
|
936
|
+
words rather than a row of arrows. */
|
|
937
|
+
.th-sort {
|
|
938
|
+
@apply mono flex w-full items-center gap-1 rounded-[4px] text-left uppercase text-muted;
|
|
939
|
+
transition: color var(--dur-micro) var(--ease-out);
|
|
940
|
+
}
|
|
941
|
+
.th-sort:hover {
|
|
942
|
+
color: var(--fg);
|
|
943
|
+
}
|
|
944
|
+
.th-sort > .sort-mark {
|
|
945
|
+
@apply shrink-0 opacity-0;
|
|
946
|
+
transition: opacity var(--dur-micro) var(--ease-out);
|
|
947
|
+
}
|
|
948
|
+
.th-sort:hover > .sort-mark,
|
|
949
|
+
.th-sort:focus-visible > .sort-mark,
|
|
950
|
+
.th-sort[data-sorted="true"] > .sort-mark {
|
|
951
|
+
@apply opacity-100;
|
|
952
|
+
}
|
|
953
|
+
.th-sort[data-sorted="true"] {
|
|
954
|
+
color: var(--accent);
|
|
955
|
+
}
|
|
956
|
+
/* The rank of a secondary sort key. Only ever drawn when there are two. */
|
|
957
|
+
.sort-rank {
|
|
958
|
+
@apply tnum shrink-0 text-[9px] leading-none;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
/* Cell content is a box of its own so a resized column clips its contents
|
|
962
|
+
rather than refusing to narrow, and so auto-fit has something whose
|
|
963
|
+
natural width it can measure. */
|
|
964
|
+
.cell-body {
|
|
965
|
+
@apply block min-w-0 overflow-hidden;
|
|
966
|
+
}
|
|
967
|
+
.cell-body-nowrap {
|
|
968
|
+
@apply truncate;
|
|
969
|
+
}
|
|
970
|
+
/* Set while a column is being measured for auto-fit: every cell in it is
|
|
971
|
+
briefly allowed its natural width, and read back in the same frame. */
|
|
972
|
+
.cell-measure .cell-body {
|
|
973
|
+
width: max-content;
|
|
974
|
+
max-width: none;
|
|
975
|
+
overflow: visible;
|
|
976
|
+
white-space: nowrap;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
/* A row's actions: present in the DOM, invisible until the row is under the
|
|
980
|
+
pointer or something inside it has focus, so a table of forty rows is not
|
|
981
|
+
also a table of eighty buttons. */
|
|
982
|
+
.row-actions {
|
|
983
|
+
@apply flex items-center gap-1 opacity-0;
|
|
984
|
+
transition: opacity var(--dur-micro) var(--ease-out);
|
|
985
|
+
}
|
|
986
|
+
tr:hover .row-actions,
|
|
987
|
+
.row:hover .row-actions,
|
|
988
|
+
.card:hover .row-actions,
|
|
989
|
+
.row-actions:focus-within {
|
|
990
|
+
@apply opacity-100;
|
|
991
|
+
}
|
|
992
|
+
.row-action {
|
|
993
|
+
@apply mono flex items-center gap-1 rounded-control border px-1.5 py-px border-line text-muted;
|
|
994
|
+
transition:
|
|
995
|
+
background-color var(--dur-micro) var(--ease-out),
|
|
996
|
+
color var(--dur-micro) var(--ease-out);
|
|
997
|
+
}
|
|
998
|
+
.row-action:hover {
|
|
999
|
+
@apply bg-surface text-ink;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/* A heading you can link to. `.anchored` is a trigger and nothing else - it
|
|
1003
|
+
sets no layout, so it can be dropped onto a row that already has one, or
|
|
1004
|
+
onto a markdown <h2> that must keep its own rule underneath. The chain is
|
|
1005
|
+
in the DOM at rest, invisible, so keyboard focus can still reach it: a
|
|
1006
|
+
page with nine sections must not be a page with nine chain icons. */
|
|
1007
|
+
.anchor-link {
|
|
1008
|
+
@apply inline-flex shrink-0 items-center rounded-[4px] p-0.5 opacity-0 text-muted;
|
|
1009
|
+
transition:
|
|
1010
|
+
opacity var(--dur-micro) var(--ease-out),
|
|
1011
|
+
background-color var(--dur-micro) var(--ease-out),
|
|
1012
|
+
color var(--dur-micro) var(--ease-out);
|
|
1013
|
+
}
|
|
1014
|
+
.anchored:hover .anchor-link,
|
|
1015
|
+
.anchor-link:focus-visible {
|
|
1016
|
+
@apply opacity-100;
|
|
1017
|
+
}
|
|
1018
|
+
.anchor-link:hover {
|
|
1019
|
+
color: var(--accent);
|
|
1020
|
+
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/* The sidebar tree obeys the same density switch as the tables. */
|
|
1024
|
+
.tree-row {
|
|
1025
|
+
min-height: var(--row-h-tree);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
/* ---------------------------------------------------------------------
|
|
1029
|
+
The sidebar's own furniture. The tree is ONE list: sections are told
|
|
1030
|
+
apart by 12px of air and a label, never by a border or a card. Anything
|
|
1031
|
+
here that looks like a box would make the reader count boxes instead of
|
|
1032
|
+
reading names.
|
|
1033
|
+
--------------------------------------------------------------------- */
|
|
1034
|
+
|
|
1035
|
+
/* A section header. It is a button because every section folds, and it keeps
|
|
1036
|
+
its count when folded - a closed section that also hid its size would be
|
|
1037
|
+
indistinguishable from an empty one. */
|
|
1038
|
+
.sb-section {
|
|
1039
|
+
@apply mono sticky top-0 z-10 flex w-full items-center gap-1.5 px-3 py-1.5 text-left uppercase text-muted;
|
|
1040
|
+
background: color-mix(in srgb, var(--bg) 80%, transparent);
|
|
1041
|
+
backdrop-filter: blur(8px);
|
|
1042
|
+
-webkit-backdrop-filter: blur(8px);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
/* The count that rides at the end of a header or a group row. Faint and
|
|
1046
|
+
tabular: it annotates the name, it is not another word in it. */
|
|
1047
|
+
.sb-count {
|
|
1048
|
+
@apply mono tnum ml-auto shrink-0;
|
|
1049
|
+
color: var(--fg-faint);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
/* A context this flow reaches, in that context's own colour. Square, like
|
|
1053
|
+
every other context marker in the app. */
|
|
1054
|
+
.sb-reach {
|
|
1055
|
+
@apply inline-block size-1.5 shrink-0 rounded-[1px];
|
|
1056
|
+
background: var(--ctx);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/* How far a flow has been made good on. Round, so it can never be read as a
|
|
1060
|
+
seventh context beside the square reach marks. */
|
|
1061
|
+
.sb-health {
|
|
1062
|
+
@apply inline-block size-2 shrink-0 rounded-full;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/* How a bounded context is rated, at the end of its row. Ten pixels, no
|
|
1066
|
+
border, no background: at this size the badge is a footnote on the name,
|
|
1067
|
+
and a bordered chip here reads as a control the reader can press. */
|
|
1068
|
+
.sb-class {
|
|
1069
|
+
@apply shrink-0 lowercase;
|
|
1070
|
+
font-size: 10px;
|
|
1071
|
+
line-height: 14px;
|
|
1072
|
+
color: var(--fg-muted);
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
/* Secondary text inside a row: 13px comfortable, 12px compact. */
|
|
1076
|
+
.meta {
|
|
1077
|
+
color: var(--fg-muted);
|
|
1078
|
+
font-size: var(--text-meta);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/* ---- Field tree: a shape opened under a schema row -----------------------
|
|
1082
|
+
|
|
1083
|
+
One shape per level, each a step in from the last, with a guide line
|
|
1084
|
+
down its left edge so a reader four levels deep can see where each
|
|
1085
|
+
level began. The header names the shape; the rows under it are its
|
|
1086
|
+
fields, drawn like the table rows above but without the table - they
|
|
1087
|
+
are an aside to a row, not a table of their own. */
|
|
1088
|
+
.shape {
|
|
1089
|
+
@apply mt-1 mb-0.5 ml-[5px] border-l border-line-strong pl-3;
|
|
1090
|
+
}
|
|
1091
|
+
.shape-root {
|
|
1092
|
+
width: 0;
|
|
1093
|
+
min-width: 100%;
|
|
1094
|
+
}
|
|
1095
|
+
/* One line of the shape's doc, cut where the row ends; the whole of it is
|
|
1096
|
+
on the shape's own page, one click away. */
|
|
1097
|
+
.shape-doc {
|
|
1098
|
+
@apply mb-1 truncate pl-5;
|
|
1099
|
+
}
|
|
1100
|
+
.shape-head {
|
|
1101
|
+
@apply mono flex min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5 py-0.5;
|
|
1102
|
+
font-size: var(--text-sm);
|
|
1103
|
+
}
|
|
1104
|
+
.field-tree {
|
|
1105
|
+
@apply flex flex-col;
|
|
1106
|
+
}
|
|
1107
|
+
.field-row {
|
|
1108
|
+
@apply flex min-w-0 items-center gap-x-3 rounded-control py-0.5 pr-2;
|
|
1109
|
+
font-size: var(--text-sm);
|
|
1110
|
+
min-height: 24px;
|
|
1111
|
+
}
|
|
1112
|
+
.field-row:hover {
|
|
1113
|
+
background: color-mix(in srgb, var(--accent) 5%, transparent);
|
|
1114
|
+
}
|
|
1115
|
+
.field-row[data-open] > .mono:first-of-type {
|
|
1116
|
+
color: var(--fg);
|
|
1117
|
+
}
|
|
1118
|
+
/* The chevron, or the room for one: rows with and without a shape to open
|
|
1119
|
+
keep their names on one line. */
|
|
1120
|
+
.field-toggle {
|
|
1121
|
+
@apply inline-flex size-4 shrink-0 items-center justify-center rounded-control text-muted;
|
|
1122
|
+
}
|
|
1123
|
+
button.field-toggle:hover {
|
|
1124
|
+
color: var(--fg);
|
|
1125
|
+
background: var(--surface-2);
|
|
1126
|
+
}
|
|
1127
|
+
/* A word beside a type - "list of", "optional" - in the tone of a footnote,
|
|
1128
|
+
not a chip: it qualifies the type, it is not a status of its own. */
|
|
1129
|
+
.type-mark {
|
|
1130
|
+
@apply mono shrink-0 rounded-[4px] px-1 leading-4;
|
|
1131
|
+
font-size: 11px;
|
|
1132
|
+
color: var(--fg-faint);
|
|
1133
|
+
background: var(--surface-2);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
/* ---------------------------------------------------------------------------
|
|
1138
|
+
Motion. One system: 150 micro, 250 panel and page, 400 narrative.
|
|
1139
|
+
--------------------------------------------------------------------------- */
|
|
1140
|
+
|
|
1141
|
+
@keyframes panel-in {
|
|
1142
|
+
from {
|
|
1143
|
+
opacity: 0;
|
|
1144
|
+
transform: translateX(16px);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
@keyframes palette-in {
|
|
1148
|
+
from {
|
|
1149
|
+
opacity: 0;
|
|
1150
|
+
transform: scale(0.98);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
@keyframes fade-in {
|
|
1154
|
+
from {
|
|
1155
|
+
opacity: 0;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
@keyframes row-in {
|
|
1159
|
+
from {
|
|
1160
|
+
opacity: 0;
|
|
1161
|
+
transform: translateY(4px);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
@keyframes bar-fill {
|
|
1165
|
+
from {
|
|
1166
|
+
transform: scaleX(0);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
/* Anything that also LEAVES or moves - a route, the palette, the drawer, the
|
|
1170
|
+
sheet, the toast, the light under a tab - is not here: that is Motion, in
|
|
1171
|
+
lib/motion.tsx, on the same tokens. */
|
|
1172
|
+
@utility panel-in {
|
|
1173
|
+
animation: panel-in var(--dur-panel) var(--ease-out) both;
|
|
1174
|
+
}
|
|
1175
|
+
@utility palette-in {
|
|
1176
|
+
animation: palette-in var(--dur-panel) var(--ease-out) both;
|
|
1177
|
+
}
|
|
1178
|
+
@utility overlay-in {
|
|
1179
|
+
animation: fade-in var(--dur-panel) var(--ease-out) both;
|
|
1180
|
+
}
|
|
1181
|
+
/* 20ms per row, capped at ten rows by the --i the row sets. */
|
|
1182
|
+
@utility stagger-in {
|
|
1183
|
+
animation: row-in var(--dur-panel) var(--ease-out) both;
|
|
1184
|
+
animation-delay: calc(var(--i, 0) * 20ms);
|
|
1185
|
+
}
|
|
1186
|
+
@utility bar-fill {
|
|
1187
|
+
transform-origin: left center;
|
|
1188
|
+
animation: bar-fill var(--dur-narrative) var(--ease-in-out) both;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
/* Everything that moves, moves for 150ms unless it says otherwise. */
|
|
1192
|
+
@utility t-micro {
|
|
1193
|
+
transition-duration: var(--dur-micro);
|
|
1194
|
+
transition-timing-function: var(--ease-out);
|
|
1195
|
+
}
|
|
1196
|
+
/* Flow playback dims and undims the steps it is not on. */
|
|
1197
|
+
@utility t-narrative {
|
|
1198
|
+
transition:
|
|
1199
|
+
opacity var(--dur-narrative) var(--ease-in-out),
|
|
1200
|
+
background-color var(--dur-narrative) var(--ease-in-out);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1204
|
+
/* Opacity may still cross-fade; nothing is allowed to travel, scale, or
|
|
1205
|
+
repeat. Anything mid-flight lands on its final frame immediately. */
|
|
1206
|
+
*,
|
|
1207
|
+
*::before,
|
|
1208
|
+
*::after {
|
|
1209
|
+
animation-duration: 1ms !important;
|
|
1210
|
+
animation-delay: 0ms !important;
|
|
1211
|
+
animation-iteration-count: 1 !important;
|
|
1212
|
+
transition-property:
|
|
1213
|
+
opacity, background-color, border-color, color, fill, stroke !important;
|
|
1214
|
+
transition-duration: 1ms !important;
|
|
1215
|
+
scroll-behavior: auto !important;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
/* ---------------------------------------------------------------------------
|
|
1220
|
+
Base
|
|
1221
|
+
--------------------------------------------------------------------------- */
|
|
1222
|
+
|
|
1223
|
+
html,
|
|
1224
|
+
body,
|
|
1225
|
+
#root {
|
|
1226
|
+
height: 100%;
|
|
1227
|
+
overflow: hidden;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
/* Keep the app shell anchored to the viewport. A long page owns its scroll in
|
|
1231
|
+
its pane; its descendants must not enlarge the document scrollport. */
|
|
1232
|
+
#root {
|
|
1233
|
+
position: fixed;
|
|
1234
|
+
inset: 0;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
body {
|
|
1238
|
+
background: var(--bg);
|
|
1239
|
+
color: var(--fg);
|
|
1240
|
+
font-family: var(--font-sans);
|
|
1241
|
+
font-size: var(--text-base);
|
|
1242
|
+
line-height: 1.5;
|
|
1243
|
+
-webkit-font-smoothing: antialiased;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
h1,
|
|
1247
|
+
h2,
|
|
1248
|
+
h3 {
|
|
1249
|
+
line-height: 1.2;
|
|
1250
|
+
letter-spacing: -0.01em;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
::selection {
|
|
1254
|
+
background: color-mix(in srgb, var(--accent) 20%, transparent);
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
/* Keyboard focus is a ring, not an outline hugging the glyphs, and it is
|
|
1258
|
+
drawn on top of neighbouring rows rather than clipped by them. */
|
|
1259
|
+
:focus-visible {
|
|
1260
|
+
outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent);
|
|
1261
|
+
outline-offset: 2px;
|
|
1262
|
+
border-radius: var(--radius-control);
|
|
1263
|
+
position: relative;
|
|
1264
|
+
z-index: 1;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
/* Inner panes only - `html` and `body` never scroll in this shell. */
|
|
1268
|
+
.pane::-webkit-scrollbar,
|
|
1269
|
+
[class*="overflow-y-auto"]::-webkit-scrollbar,
|
|
1270
|
+
[class*="overflow-x-auto"]::-webkit-scrollbar,
|
|
1271
|
+
[class*="overflow-auto"]::-webkit-scrollbar {
|
|
1272
|
+
width: 8px;
|
|
1273
|
+
height: 8px;
|
|
1274
|
+
}
|
|
1275
|
+
.pane::-webkit-scrollbar-thumb,
|
|
1276
|
+
[class*="overflow-y-auto"]::-webkit-scrollbar-thumb,
|
|
1277
|
+
[class*="overflow-x-auto"]::-webkit-scrollbar-thumb,
|
|
1278
|
+
[class*="overflow-auto"]::-webkit-scrollbar-thumb {
|
|
1279
|
+
background: var(--scroll-thumb);
|
|
1280
|
+
border-radius: 999px;
|
|
1281
|
+
}
|
|
1282
|
+
.pane::-webkit-scrollbar-thumb:hover,
|
|
1283
|
+
[class*="overflow-y-auto"]::-webkit-scrollbar-thumb:hover,
|
|
1284
|
+
[class*="overflow-x-auto"]::-webkit-scrollbar-thumb:hover,
|
|
1285
|
+
[class*="overflow-auto"]::-webkit-scrollbar-thumb:hover {
|
|
1286
|
+
background: var(--scroll-thumb-hover);
|
|
1287
|
+
}
|
|
1288
|
+
.pane::-webkit-scrollbar-track,
|
|
1289
|
+
[class*="overflow-y-auto"]::-webkit-scrollbar-track,
|
|
1290
|
+
[class*="overflow-x-auto"]::-webkit-scrollbar-track,
|
|
1291
|
+
[class*="overflow-auto"]::-webkit-scrollbar-track {
|
|
1292
|
+
background: transparent;
|
|
1293
|
+
}
|
|
1294
|
+
[class*="overflow-y-auto"],
|
|
1295
|
+
[class*="overflow-x-auto"],
|
|
1296
|
+
[class*="overflow-auto"] {
|
|
1297
|
+
scrollbar-width: thin;
|
|
1298
|
+
scrollbar-color: var(--scroll-thumb) transparent;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
/* One exception, and it sits after the rule it overrides rather than inside
|
|
1302
|
+
the components layer, which an unlayered rule would outrank: the strip a tab
|
|
1303
|
+
list scrolls inside has no scrollbar at all. The fade and the chevron at its
|
|
1304
|
+
edge already say the row continues, and an 8px bar under eight tabs said it
|
|
1305
|
+
a second time in the space the tabs were short of. */
|
|
1306
|
+
.tab-scroll,
|
|
1307
|
+
.tab-scroll[class*="overflow-x-auto"] {
|
|
1308
|
+
scrollbar-width: none;
|
|
1309
|
+
}
|
|
1310
|
+
.tab-scroll::-webkit-scrollbar {
|
|
1311
|
+
height: 0;
|
|
1312
|
+
width: 0;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
/* ---------------------------------------------------------------------------
|
|
1316
|
+
A document drawn by somebody else's component - the AsyncAPI reference.
|
|
1317
|
+
|
|
1318
|
+
It brings its own stylesheet, and that stylesheet has no dark mode at all:
|
|
1319
|
+
not a variant this site could set, none. So the sheet it is drawn on is
|
|
1320
|
+
always light, and `color-scheme` says so too, or the browser paints the form
|
|
1321
|
+
controls inside it for the other theme.
|
|
1322
|
+
|
|
1323
|
+
The tokens are re-declared rather than merely painted over because the two
|
|
1324
|
+
stylesheets share a class name: `.prose` is Tailwind Typography's, which the
|
|
1325
|
+
component's markup uses, and it is also this site's own. Its rules reach into
|
|
1326
|
+
the document and colour it with whatever `--fg` currently means - which, in
|
|
1327
|
+
the dark theme, is near-white text on a white sheet.
|
|
1328
|
+
--------------------------------------------------------------------------- */
|
|
1329
|
+
.spec-sheet {
|
|
1330
|
+
color-scheme: light;
|
|
1331
|
+
background: var(--bg);
|
|
1332
|
+
color: var(--fg);
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
/* ---------------------------------------------------------------------------
|
|
1336
|
+
Markdown prose. Capped at the prose width; tables and canvases are not.
|
|
1337
|
+
--------------------------------------------------------------------------- */
|
|
1338
|
+
.prose {
|
|
1339
|
+
max-width: var(--w-prose);
|
|
1340
|
+
color: var(--fg);
|
|
1341
|
+
font-size: var(--text-base);
|
|
1342
|
+
line-height: 1.5;
|
|
1343
|
+
}
|
|
1344
|
+
.prose h1 {
|
|
1345
|
+
font-size: var(--text-lg);
|
|
1346
|
+
font-weight: 600;
|
|
1347
|
+
margin: 20px 0 8px;
|
|
1348
|
+
}
|
|
1349
|
+
/* A readme's section heading stays at the top of the readme while its
|
|
1350
|
+
section scrolls under it, just below the page's pinned name row. Sticky
|
|
1351
|
+
within the readme, so every heading pins at the same edge and the next one
|
|
1352
|
+
simply covers the last - which is why it is opaque. */
|
|
1353
|
+
/* Pinned a gutter higher than it reads, for the reason `.section-head` is:
|
|
1354
|
+
sticky measures from the scrollport's padding box, so at `top: 0` the box's
|
|
1355
|
+
own gutter is left uncovered and prose scrolls visibly through the strip
|
|
1356
|
+
above the heading. The padding puts the text back where it was. */
|
|
1357
|
+
.prose h2 {
|
|
1358
|
+
position: sticky;
|
|
1359
|
+
top: calc(var(--page-header-h, 0px) - var(--gutter));
|
|
1360
|
+
z-index: 10;
|
|
1361
|
+
background: var(--bg);
|
|
1362
|
+
font-size: var(--text-md);
|
|
1363
|
+
font-weight: 600;
|
|
1364
|
+
margin: calc(24px - var(--gutter)) 0 8px;
|
|
1365
|
+
padding-top: var(--gutter);
|
|
1366
|
+
padding-bottom: 4px;
|
|
1367
|
+
border-bottom: 1px solid var(--border);
|
|
1368
|
+
}
|
|
1369
|
+
.prose h3 {
|
|
1370
|
+
font-size: var(--text-base);
|
|
1371
|
+
font-weight: 600;
|
|
1372
|
+
margin: 16px 0 4px;
|
|
1373
|
+
}
|
|
1374
|
+
/* A readme heading keeps its own block layout and its own rule; the chain
|
|
1375
|
+
simply rides at the end of the line. */
|
|
1376
|
+
.prose .anchor-link {
|
|
1377
|
+
margin-left: 6px;
|
|
1378
|
+
vertical-align: middle;
|
|
1379
|
+
}
|
|
1380
|
+
.prose p {
|
|
1381
|
+
margin: 8px 0;
|
|
1382
|
+
color: var(--fg);
|
|
1383
|
+
}
|
|
1384
|
+
.prose ul,
|
|
1385
|
+
.prose ol {
|
|
1386
|
+
margin: 8px 0;
|
|
1387
|
+
padding-left: 20px;
|
|
1388
|
+
list-style: disc;
|
|
1389
|
+
}
|
|
1390
|
+
.prose ol {
|
|
1391
|
+
list-style: decimal;
|
|
1392
|
+
}
|
|
1393
|
+
.prose li {
|
|
1394
|
+
margin: 4px 0;
|
|
1395
|
+
}
|
|
1396
|
+
.prose a {
|
|
1397
|
+
color: var(--accent);
|
|
1398
|
+
text-decoration: underline;
|
|
1399
|
+
text-underline-offset: 2px;
|
|
1400
|
+
}
|
|
1401
|
+
.prose code {
|
|
1402
|
+
font-family: var(--font-mono);
|
|
1403
|
+
font-size: var(--text-xs);
|
|
1404
|
+
background: var(--surface-2);
|
|
1405
|
+
border: 1px solid var(--border);
|
|
1406
|
+
border-radius: 4px;
|
|
1407
|
+
padding: 0 4px;
|
|
1408
|
+
}
|
|
1409
|
+
.prose pre {
|
|
1410
|
+
font-family: var(--font-mono);
|
|
1411
|
+
font-size: var(--text-xs);
|
|
1412
|
+
background: var(--surface);
|
|
1413
|
+
border: 1px solid var(--border);
|
|
1414
|
+
border-radius: var(--radius-control);
|
|
1415
|
+
padding: 12px;
|
|
1416
|
+
overflow-x: auto;
|
|
1417
|
+
margin: 12px 0;
|
|
1418
|
+
}
|
|
1419
|
+
.prose pre code {
|
|
1420
|
+
background: none;
|
|
1421
|
+
border: none;
|
|
1422
|
+
padding: 0;
|
|
1423
|
+
}
|
|
1424
|
+
/* A markdown table that stayed a markdown table - three rows or fewer, or an
|
|
1425
|
+
author who asked for it. The `:not(.tbl)` is what keeps these element-level
|
|
1426
|
+
rules off the enhanced ones: an element selector outranks a utility class,
|
|
1427
|
+
so without it a README's table would quietly repaint the app's. */
|
|
1428
|
+
.prose table:not(.tbl) {
|
|
1429
|
+
border-collapse: separate;
|
|
1430
|
+
border-spacing: 0;
|
|
1431
|
+
margin: 12px 0;
|
|
1432
|
+
font-size: var(--text-xs);
|
|
1433
|
+
width: 100%;
|
|
1434
|
+
border: 1px solid var(--border);
|
|
1435
|
+
border-radius: var(--radius-control);
|
|
1436
|
+
overflow: hidden;
|
|
1437
|
+
}
|
|
1438
|
+
.prose table:not(.tbl) th,
|
|
1439
|
+
.prose table:not(.tbl) td {
|
|
1440
|
+
border-bottom: 1px solid var(--border);
|
|
1441
|
+
padding: 6px 8px;
|
|
1442
|
+
text-align: left;
|
|
1443
|
+
}
|
|
1444
|
+
.prose table:not(.tbl) tr:last-child td {
|
|
1445
|
+
border-bottom: 0;
|
|
1446
|
+
}
|
|
1447
|
+
.prose table:not(.tbl) th {
|
|
1448
|
+
background: var(--surface);
|
|
1449
|
+
font-weight: 600;
|
|
1450
|
+
}
|
|
1451
|
+
.prose blockquote {
|
|
1452
|
+
border-left: 2px solid var(--border-strong);
|
|
1453
|
+
padding-left: 12px;
|
|
1454
|
+
color: var(--fg-muted);
|
|
1455
|
+
margin: 12px 0;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
/* GitHub admonitions. `> [!NOTE]` and its four siblings arrive in any README
|
|
1459
|
+
written on GitHub; left as a blockquote they read as a quotation, which is
|
|
1460
|
+
the opposite of what the author meant. One box, tinted from the --callout
|
|
1461
|
+
colour the component sets, so five kinds need one rule. */
|
|
1462
|
+
.prose .callout {
|
|
1463
|
+
margin: 12px 0;
|
|
1464
|
+
padding: 12px;
|
|
1465
|
+
border: 1px solid color-mix(in srgb, var(--callout) 28%, var(--border));
|
|
1466
|
+
border-left: 3px solid var(--callout);
|
|
1467
|
+
border-radius: var(--radius-control);
|
|
1468
|
+
background: color-mix(in srgb, var(--callout) 5%, transparent);
|
|
1469
|
+
}
|
|
1470
|
+
.prose .callout-title {
|
|
1471
|
+
display: flex;
|
|
1472
|
+
align-items: center;
|
|
1473
|
+
gap: 8px;
|
|
1474
|
+
margin: 0 0 4px;
|
|
1475
|
+
color: var(--callout);
|
|
1476
|
+
font-weight: 600;
|
|
1477
|
+
font-size: var(--text-sm);
|
|
1478
|
+
}
|
|
1479
|
+
.prose .callout > :last-child {
|
|
1480
|
+
margin-bottom: 0;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
/* ---------------------------------------------------------------------------
|
|
1484
|
+
A mermaid diagram, drawn into the page by the library rather than by this
|
|
1485
|
+
app. Mermaid names a node's text `.label`, and so does this app - where it
|
|
1486
|
+
means a mono uppercase eyebrow over a section. The utility wins by
|
|
1487
|
+
cascade order and shouts every state name in a diagram, so the transform
|
|
1488
|
+
is undone inside the figure and nowhere else.
|
|
1489
|
+
--------------------------------------------------------------------------- */
|
|
1490
|
+
.mermaid-figure :is(.label, .labelBkg, .nodeLabel, .edgeLabel) {
|
|
1491
|
+
text-transform: none;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
/* ---------------------------------------------------------------------------
|
|
1495
|
+
React Flow. It ships its chrome - pane, dot grid, minimap, rubber-band
|
|
1496
|
+
selection - painted from --xy-* custom properties, so the canvases are
|
|
1497
|
+
themed here, once, from the app's own tokens: the .dark block above swaps
|
|
1498
|
+
the tokens and every --xy-* follows without a second declaration. Nodes and
|
|
1499
|
+
edges are this app's components and carry their own paint; what this block
|
|
1500
|
+
owns is the chrome, and the one thing React Flow will not do for a custom
|
|
1501
|
+
node, which is draw its selected state.
|
|
1502
|
+
--------------------------------------------------------------------------- */
|
|
1503
|
+
.react-flow {
|
|
1504
|
+
--xy-background-color: var(--flow-pane);
|
|
1505
|
+
--xy-background-pattern-color: var(--flow-dot);
|
|
1506
|
+
--xy-node-border-radius: var(--radius-node);
|
|
1507
|
+
--xy-edge-stroke: var(--border-strong);
|
|
1508
|
+
--xy-edge-stroke-selected: var(--accent);
|
|
1509
|
+
--xy-edge-label-background-color: var(--flow-card);
|
|
1510
|
+
--xy-edge-label-color: var(--fg-muted);
|
|
1511
|
+
--xy-minimap-background-color: var(--flow-card);
|
|
1512
|
+
--xy-minimap-mask-background-color: color-mix(
|
|
1513
|
+
in srgb,
|
|
1514
|
+
var(--flow-pane) 72%,
|
|
1515
|
+
transparent
|
|
1516
|
+
);
|
|
1517
|
+
--xy-minimap-mask-stroke-color: var(--border-strong);
|
|
1518
|
+
--xy-selection-background-color: color-mix(
|
|
1519
|
+
in srgb,
|
|
1520
|
+
var(--accent) 8%,
|
|
1521
|
+
transparent
|
|
1522
|
+
);
|
|
1523
|
+
--xy-selection-border: 1px solid
|
|
1524
|
+
color-mix(in srgb, var(--accent) 60%, transparent);
|
|
1525
|
+
font-family: var(--font-sans);
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
/* Selection is the ring, on the node's own box. The event pill is the one
|
|
1529
|
+
node that is not the shape of its box - it is a capsule, and at fit zooms
|
|
1530
|
+
it shrinks to an icon inside the box - so it draws the ring itself. */
|
|
1531
|
+
.react-flow__node.selected:not(.react-flow__node-event) {
|
|
1532
|
+
border-radius: var(--radius-node);
|
|
1533
|
+
box-shadow: var(--ring);
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
/* A routed edge turns corners; round joins keep them from growing spurs at
|
|
1537
|
+
the thicker lit width. Caps stay flat because the dashed status markers
|
|
1538
|
+
are measured for flat caps. */
|
|
1539
|
+
.react-flow__edge-path {
|
|
1540
|
+
stroke-linejoin: round;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
.react-flow__minimap {
|
|
1544
|
+
border-radius: var(--radius-node);
|
|
1545
|
+
box-shadow: var(--shadow-card);
|
|
1546
|
+
overflow: hidden;
|
|
1547
|
+
}
|