From e2768f74b103bd9f43f0cd4962a32154be61d92f Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Tue, 27 Oct 2026 23:35:42 -0300 Subject: [PATCH 01/56] =?UTF-8?q?docs:=20renomeia=20para=20RetroX,=20aceit?= =?UTF-8?q?a=20ADRs=20e=20registra=20decis=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PRD 0.2 com a seção de revisão do plano técnico. - ADRs 0001-0009 aceitos, com emendas onde o plano pediu. - Novos ADR-0010 (build SwiftPM-first) e ADR-0012 (detecção de sistema). - docs/DECISOES.md com decisões D1-D3, suposições e pendências. - Prompts originais movidos para docs/origem/. Co-Authored-By: Claude Opus 5.5 --- README.md | 28 +++++++++++-------- docs/DECISOES.md | 27 ++++++++++++++++++ docs/PRD.md | 26 +++++++++++++++-- docs/adr/0001-swiftui-appkit.md | 6 +++- docs/adr/0002-distribuicao-e-sandbox.md | 7 ++++- docs/adr/0003-emulator-adapters.md | 7 ++++- docs/adr/0004-biblioteca-nao-destrutiva.md | 7 ++++- docs/adr/0005-swiftdata-e-modelos.md | 7 ++++- docs/adr/0006-offline-first-metadata.md | 2 +- .../0007-gamecontroller-e-acessibilidade.md | 6 +++- docs/adr/0008-performance-e-scan.md | 6 +++- docs/adr/0009-seguranca-e-diagnosticos.md | 6 +++- docs/adr/0010-build-swiftpm-first.md | 22 +++++++++++++++ docs/adr/0012-deteccao-de-sistema.md | 24 ++++++++++++++++ .../origem/ConsoleShelf_PROMPT_COMPLETO.md | 0 .../origem/PROMPT_CLAUDE_CODE.md | 0 16 files changed, 157 insertions(+), 24 deletions(-) create mode 100644 docs/DECISOES.md create mode 100644 docs/adr/0010-build-swiftpm-first.md create mode 100644 docs/adr/0012-deteccao-de-sistema.md rename ConsoleShelf_PROMPT_COMPLETO.md => docs/origem/ConsoleShelf_PROMPT_COMPLETO.md (100%) rename PROMPT_CLAUDE_CODE.md => docs/origem/PROMPT_CLAUDE_CODE.md (100%) diff --git a/README.md b/README.md index 49e382c..31d397c 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,21 @@ -# ConsoleShelf — pacote de especificação para Claude Code +# RetroX -Contém: +Launcher nativo para macOS que reúne numa biblioteca visual os jogos de vários consoles e abre cada um no emulador externo que o usuário já tem instalado. O RetroX não inclui emuladores, jogos, BIOS nem chaves, e não copia, move ou altera os arquivos de jogo. -- `PROMPT_CLAUDE_CODE.md`: instruções de primeira sessão em Plan Mode. -- `docs/PRD.md`: produto, escopo, requisitos e critérios de aceite. -- `docs/adr/`: decisões de arquitetura propostas (não finalizadas). -- `ConsoleShelf_PROMPT_COMPLETO.md` (também disponível separadamente): tudo em um único texto para copiar e colar. +**Status:** Sprint 1 (prova técnica do launch com PCSX2). Nome anterior provisório: ConsoleShelf. -## Como usar +## Requisitos -1. Extraia este pacote no repositório vazio do projeto. -2. No terminal do macOS, execute `claude --permission-mode plan` (ou abra `claude` e use `/plan`). -3. Envie ao Claude Code: `Leia @PROMPT_CLAUDE_CODE.md, @docs/PRD.md e todos os @docs/adr/*.md. Produza o plano solicitado, sem implementar antes de minha aprovação.` -4. Revise o plano e **só depois** autorize a implementação, começando pela prova de conceito PCSX2. +- macOS 14 ou superior. +- Para compilar: Swift 6 (Command Line Tools ou Xcode). A persistência (Fase 2 em diante) exige o Xcode. +- Emuladores instalados pelo usuário. Hoje: PCSX2 (PS2). Dolphin (GameCube/Wii) está planejado. -**Nota:** A documentação citada é referência técnica, não licença para copiar ativos ou código de terceiros. +## Documentação + +- [`docs/PRD.md`](docs/PRD.md): produto, escopo, requisitos e critérios de aceite. +- [`docs/adr/`](docs/adr/): decisões de arquitetura. +- [`docs/DECISOES.md`](docs/DECISOES.md): decisões do usuário, suposições e pendências. +- [`docs/spikes/`](docs/spikes/): evidências de testes técnicos com emuladores reais. +- [`docs/origem/`](docs/origem/): especificação original usada para planejar o projeto. + +Ilustrações, logos e telas de terceiros citados como inspiração não são usados no projeto. diff --git a/docs/DECISOES.md b/docs/DECISOES.md new file mode 100644 index 0000000..e6915b8 --- /dev/null +++ b/docs/DECISOES.md @@ -0,0 +1,27 @@ +# Registro de decisões e suposições + +Decisões do usuário e suposições de trabalho que não cabem num ADR. Decisões de arquitetura ficam em `docs/adr/`. + +## Decisões do usuário (2026-10-27) + +| ID | Decisão | +|---|---| +| D1 | O usuário instala o Xcode antes da Fase 2. O SwiftData (ADR-0005) fica mantido. | +| D2 | Git autorizado: repositório local, commits pequenos por tarefa, sem remote e sem push. | +| D3 | O produto passa a se chamar **RetroX** (módulos `RetroXCore`, `RetroXApp`…). "ConsoleShelf" fica só como histórico em `docs/origem/`. | + +## Suposições de trabalho + +| ID | Suposição | Revisar em | +|---|---|---| +| S1 | Bundle ID provisório `local.retrox.RetroX`, trocado antes de qualquer assinatura Developer ID. | Fase 7 | +| S2 | A versão de PCSX2 validada é a 2.9.144 (macOS, x86_64 via Rosetta). Outras versões podem mudar a CLI. | A cada nova versão do PCSX2 | +| S3 | Por padrão o RetroX respeita a configuração do emulador (tela cheia, confirmação ao sair) e não grava nos arquivos de configuração dele. | — | +| S4 | Dolphin não está instalado na máquina de desenvolvimento; o adapter é testado com fakes até que esteja. | Fase 4 | +| S5 | Deployment target macOS 14 (do PRD), com a troca para macOS 15 em aberto. | Gate da Fase 1 | + +## Pendências que dependem do usuário + +- Instalar o Xcode e rodar `sudo xcode-select -s /Applications/Xcode.app/Contents/Developer` (Fase 1). +- Instalar o Dolphin para validar a Fase 4. +- Escolher o bundle ID definitivo e ter conta Apple Developer para assinatura e notarização (Fase 7). diff --git a/docs/PRD.md b/docs/PRD.md index 6675d29..3882ad5 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -1,10 +1,12 @@ -# PRD — ConsoleShelf (Product Requirements Document) +# PRD — RetroX (Product Requirements Document) -**Versão:** 0.1 | **Status:** proposta para validação | **Plataforma:** macOS 14+ | **Idioma da interface inicial:** português do Brasil (arquitetura pronta para localização) +**Versão:** 0.2 | **Status:** revisado após o plano técnico (ver §12) | **Plataforma:** macOS 14+ | **Idioma da interface inicial:** português do Brasil (arquitetura pronta para localização) + +> Nome anterior (provisório): ConsoleShelf. A especificação original está em `docs/origem/`. ## 1. Visão e problema -Pessoas que usam múltiplos emuladores no macOS guardam ROMs em diferentes pastas e precisam abrir manualmente cada emulador e escolher o jogo. A experiência é fragmentada e a organização depende de ferramentas diversas. **ConsoleShelf** resolve isso com uma biblioteca e um launcher unificados, de estética inspirada em interfaces de consoles portáteis, sem implementar emulação. +Pessoas que usam múltiplos emuladores no macOS guardam ROMs em diferentes pastas e precisam abrir manualmente cada emulador e escolher o jogo. A experiência é fragmentada e a organização depende de ferramentas diversas. **RetroX** resolve isso com uma biblioteca e um launcher unificados, de estética inspirada em interfaces de consoles portáteis, sem implementar emulação. ### Proposta de valor @@ -133,3 +135,21 @@ Pessoas que usam múltiplos emuladores no macOS guardam ROMs em diferentes pasta ## 11. Futuro, após MVP Extensões para outros adapters e formatos, RetroAchievements, provedores opcionais de metadados com limites de API, layouts alternativos (incluindo inspiração dual-screen), temas próprios, assets animados, importação gerenciada explicitamente opt-in e telemetria apenas se houver consentimento. Validar demanda antes de implementar cada item. + +## 12. Revisão 0.2 (2026-10-27) + +Resultado da revisão feita no plano técnico aprovado. Prevalece sobre as seções anteriores em caso de conflito. + +| Ref. | Ajuste | +|---|---| +| RF-03 | A detecção **exata** de arquivo movido (mesmo volume + mesmo `fileIdentifier`) passa a ser Must, porque sem ela o "ID persistente" se perde num simples mover de pasta. A UI de revisão de movidos/duplicatas continua em RF-14 (Should). | +| RF-02 | "Detecção assistida" significa, em ordem: (1) dica de sistema da pasta-fonte; (2) leitura de cabeçalho de até 64 KB, sem hash; (3) extensão inequívoca. Arquivo ambíguo fica em `needsReview` e nunca é atribuído em silêncio. Ver ADR-0012. | +| RF-05 | "Compatibilidade" = bundle válido, executável presente e executável, bundle ID esperado (aviso se diferente), arquitetura executável no host (x86_64 em Apple Silicon exige Rosetta) e versão registrada. Sem bloqueio por versão no MVP. | +| RF-06 | A evidência de "testado no macOS" fica em `docs/spikes/`. O critério do Dolphin fica pendente até haver Dolphin instalado na máquina de teste. | +| Jornadas 2 e 5 | Dependem de requisitos Should (RF-11, RF-12). No MVP Must, a home é o Library Mode; recentes e favoritos aparecem quando existirem. | +| RF-08 | Hipótese a medir, não promessa: filtro em menos de 100 ms com 5.000 itens. | +| §7 Dados | `GameSystem` vira catálogo estático em código; preferências do usuário por sistema ficam em `SystemPreference`. `GameEmulatorOverride` vira relacionamento opcional no jogo (1:1). | +| Formatos | PS2: `iso`, `chd`, `cso`, `zso` (declarados pelo bundle do PCSX2 2.9.144). `mdf`, `bin/cue` e `elf` depois, com teste. GameCube/Wii: `iso`, `gcm`, `rvz`, `wbfs`, `ciso`, `gcz`, `wia`, pendente de verificação com o Dolphin. ZIP/7z: nunca. | +| Jornada 2 | "Retornar à biblioteca" = o emulador é aberto em modo batch (fecha ao parar o jogo) e o RetroX volta à frente quando o processo termina. | +| RNF-09 | Além de Xcode/`xcodebuild`, o caminho reproduzível sem Xcode é `swift build` / `swift test` (SwiftPM). | +| Plataforma | O deployment target macOS 14 compila, mas não é testável na máquina de desenvolvimento atual (macOS 27). A escolha entre 14 e 15 será feita no gate da Fase 1 (ver ADR-0005). | diff --git a/docs/adr/0001-swiftui-appkit.md b/docs/adr/0001-swiftui-appkit.md index a8f5ad9..0ca41e7 100644 --- a/docs/adr/0001-swiftui-appkit.md +++ b/docs/adr/0001-swiftui-appkit.md @@ -1,6 +1,6 @@ # ADR-0001 — SwiftUI como UI principal e AppKit seletivo -**Status:** Proposto | **Data:** 2026-10-27 +**Status:** Aceito | **Data:** 2026-10-27 ## Contexto Precisamos de uma aplicação nativa macOS com experiência visual de console, navegação por mouse/teclado/controle e integração com janelas e processos. @@ -13,3 +13,7 @@ Integração macOS e rápida iteração visual, porém foco avançado, entrada d ## Alternativas AppKit-only (mais boilerplate); renderizador custom com Metal (complexidade injustificada no MVP); frontend web (não atende objetivo nativo). + +## Emenda (2026-10-27) +- View models são `@Observable` e isolados em `@MainActor`; regras de negócio ficam no target `RetroXCore`, sem SwiftUI. +- Foco e teclado usam as APIs do macOS 14: `@FocusState`, `.focusable`, `.onKeyPress` e `.onMoveCommand`. diff --git a/docs/adr/0002-distribuicao-e-sandbox.md b/docs/adr/0002-distribuicao-e-sandbox.md index 92f0d3e..337d6e7 100644 --- a/docs/adr/0002-distribuicao-e-sandbox.md +++ b/docs/adr/0002-distribuicao-e-sandbox.md @@ -1,6 +1,6 @@ # ADR-0002 — Distribuição direta inicialmente, sem App Sandbox -**Status:** Proposto | **Data:** 2026-10-27 +**Status:** Aceito | **Data:** 2026-10-27 ## Contexto Precisamos abrir aplicativos externos com caminho da ROM/argumentos e acessar diretórios escolhidos pelo usuário. Apple documenta que `NSWorkspace.OpenConfiguration.arguments` é ignorado quando o processo chamador está sandboxed; acesso/execução de programas externos também enfrenta restrições de sandbox. @@ -17,3 +17,8 @@ Mac App Store sandboxed (não validada para o launcher); helper privilegiado (co ## Referências - https://developer.apple.com/documentation/appkit/nsworkspace/openconfiguration/arguments - https://developer.apple.com/documentation/security/accessing-files-from-the-macos-app-sandbox + +## Emenda (2026-10-27) +- Sem sandbox, ler pastas em Documentos, Mesa, Downloads ou volumes removíveis ainda gera prompt de privacidade (TCC) atribuído ao RetroX. O onboarding explica isso, e o estado `denied` de uma fonte orienta o usuário até os Ajustes do Sistema. O app nunca pede Acesso Total ao Disco. +- Nenhum entitlement de Apple Events: o RetroX não automatiza outros apps. +- Assinatura Developer ID e notarização dependem de uma conta Apple Developer do usuário e ficam fora do MVP técnico. Até lá, os builds locais usam assinatura ad hoc. diff --git a/docs/adr/0003-emulator-adapters.md b/docs/adr/0003-emulator-adapters.md index 32a4838..76b33d8 100644 --- a/docs/adr/0003-emulator-adapters.md +++ b/docs/adr/0003-emulator-adapters.md @@ -1,6 +1,6 @@ # ADR-0003 — Adapters de emulador com validação e launch tipados -**Status:** Proposto | **Data:** 2026-10-27 +**Status:** Aceito | **Data:** 2026-10-27 ## Contexto Emuladores possuem executáveis, formatos e argumentos diferentes. Um launcher genérico baseado em string de shell é frágil e inseguro. @@ -17,3 +17,8 @@ Um switch gigante por console (evolui mal); comando livre sem validação (arris ## Referências - https://github.com/PCSX2/pcsx2-net-www/blob/main/docs/advanced/cli.md - https://github.com/dolphin-emu/dolphin/blob/master/Readme.md + +## Emenda (2026-10-27) +- O adapter não executa nada: ele produz um `LaunchPlan` puro (app, executável, argumentos, estratégia). O plano é testável sem processo real e é o que o modo simulado exibe. +- A escolha entre `NSWorkspace` e `Process` por adapter será registrada no ADR-0011, com a evidência do spike `docs/spikes/0001-launch-pcsx2-macos.md`. +- Política para emulador já aberto: o RetroX não encerra o emulador e não cria nova instância por padrão; oferece trazê-lo para frente. diff --git a/docs/adr/0004-biblioteca-nao-destrutiva.md b/docs/adr/0004-biblioteca-nao-destrutiva.md index 125b6ff..b34c910 100644 --- a/docs/adr/0004-biblioteca-nao-destrutiva.md +++ b/docs/adr/0004-biblioteca-nao-destrutiva.md @@ -1,6 +1,6 @@ # ADR-0004 — Biblioteca indexada não destrutiva -**Status:** Proposto | **Data:** 2026-10-27 +**Status:** Aceito | **Data:** 2026-10-27 ## Contexto ROMs podem estar em múltiplos discos, diretórios e mídias removíveis. Copiar tudo gera uso de espaço e risco de perda de dados. @@ -13,3 +13,8 @@ Importação rápida e menor custo de armazenamento, mas requer controle de arqu ## Alternativas Copiar toda a biblioteca (uso de disco elevado); symlinks gerenciados (fragilidade); reescrever a estrutura de origem (risco desnecessário). + +## Emenda (2026-10-27) +- A fonte guarda um bookmark comum (sem security scope) da pasta raiz, além do último caminho conhecido. Cada jogo guarda só o caminho relativo à fonte. +- `sourceOffline` (volume desmontado, bookmark irresolúvel) é diferente de `missing` (arquivo sumiu de uma fonte acessível). Fonte offline nunca marca jogos como ausentes. +- Fontes sobrepostas (uma dentro da outra) são bloqueadas ao adicionar. diff --git a/docs/adr/0005-swiftdata-e-modelos.md b/docs/adr/0005-swiftdata-e-modelos.md index 402ea3f..70525f9 100644 --- a/docs/adr/0005-swiftdata-e-modelos.md +++ b/docs/adr/0005-swiftdata-e-modelos.md @@ -1,6 +1,6 @@ # ADR-0005 — SwiftData para persistência local do MVP -**Status:** Proposto | **Data:** 2026-10-27 +**Status:** Aceito | **Data:** 2026-10-27 ## Contexto Precisamos persistir jogos, consoles, fontes, perfis de emuladores, favoritos e metadados sem servidor. @@ -13,3 +13,8 @@ Baixa dependência externa e integração com SwiftUI; exigirá testes de migra ## Alternativas SQLite direto/GRDB (mais controle, dependência e código); JSON único (escalabilidade/consistência fracas); Core Data (mais boilerplate). + +## Emenda (2026-10-27) +- O ambiente atual só tem Command Line Tools, e nele `@Model` não compila (o plugin `SwiftDataMacros` não existe nas CLT). Decisão do usuário: instalar o Xcode antes da Fase 2. Até lá, o target `RetroXPersistence` não entra no pacote. +- `VersionedSchema` desde a v1; escrita só por um `@ModelActor`; leitura na UI por `@Query`. +- **Pendente (gate da Fase 1):** manter macOS 14 ou subir para macOS 15. A favor do 15: `#Unique` composto, `#Index` e um SwiftData mais maduro. No 14, a unicidade vem de um `locationKey` com `@Attribute(.unique)`. diff --git a/docs/adr/0006-offline-first-metadata.md b/docs/adr/0006-offline-first-metadata.md index 9370dab..440ebcb 100644 --- a/docs/adr/0006-offline-first-metadata.md +++ b/docs/adr/0006-offline-first-metadata.md @@ -1,6 +1,6 @@ # ADR-0006 — Offline-first; metadata e capas opcionais -**Status:** Proposto | **Data:** 2026-10-27 +**Status:** Aceito | **Data:** 2026-10-27 ## Contexto O launcher deve ser útil sem contas/API/network, e provedores de capa podem fornecer correspondências incorretas ou ter limites de uso. diff --git a/docs/adr/0007-gamecontroller-e-acessibilidade.md b/docs/adr/0007-gamecontroller-e-acessibilidade.md index 482c9ac..c32b3a7 100644 --- a/docs/adr/0007-gamecontroller-e-acessibilidade.md +++ b/docs/adr/0007-gamecontroller-e-acessibilidade.md @@ -1,6 +1,6 @@ # ADR-0007 — Navegação por controle e acessibilidade no sistema de foco -**Status:** Proposto | **Data:** 2026-10-27 +**Status:** Aceito | **Data:** 2026-10-27 ## Contexto A experiência de console depende de navegação previsível por controle, mas precisa continuar totalmente funcional em teclado e mouse. @@ -13,3 +13,7 @@ Melhor consistência, ao custo de lidar com reconexão, múltiplos gamepads e re ## Alternativas Depender só de focus engine automática (pode não bastar); handlers soltos em cada View (comportamento divergente). + +## Emenda (2026-10-27) +- `GCController.shouldMonitorBackgroundEvents` fica `false` (default desde o macOS 11.3), de forma explícita: com o emulador em primeiro plano, o RetroX não recebe input do controle. +- O `InputCoordinator` só atua no Console Mode. No Library Mode vale o foco nativo do macOS. diff --git a/docs/adr/0008-performance-e-scan.md b/docs/adr/0008-performance-e-scan.md index 7186eeb..c7f1430 100644 --- a/docs/adr/0008-performance-e-scan.md +++ b/docs/adr/0008-performance-e-scan.md @@ -1,6 +1,6 @@ # ADR-0008 — Scan incremental e imagens sob demanda -**Status:** Proposto | **Data:** 2026-10-27 +**Status:** Aceito | **Data:** 2026-10-27 ## Contexto Bibliotecas podem ter milhares de entradas. O app não deve congelar por enumeração de diretórios, hash de ROMs grandes ou decodificação de thumbnails. @@ -13,3 +13,7 @@ UI responsiva, mas mais estado de progresso e complexidade de atualização/coer ## Alternativas Scans completos síncronos, full-size artwork no grid ou pre-hash de todas as ROMs (lentos). + +## Emenda (2026-10-27) +- O scanner usa `FileManager.enumerator` com pré-carga de resource keys, pula arquivos ocultos e packages, e publica em lotes de cerca de 200 itens. +- Thumbnails são geradas com ImageIO (`CGImageSourceCreateThumbnailAtIndex`), com `NSCache` em memória e cache em disco em `Caches/RetroX/Thumbnails`. diff --git a/docs/adr/0009-seguranca-e-diagnosticos.md b/docs/adr/0009-seguranca-e-diagnosticos.md index 4e41ee7..4974b70 100644 --- a/docs/adr/0009-seguranca-e-diagnosticos.md +++ b/docs/adr/0009-seguranca-e-diagnosticos.md @@ -1,6 +1,6 @@ # ADR-0009 — Segurança, logs e observabilidade locais -**Status:** Proposto | **Data:** 2026-10-27 +**Status:** Aceito | **Data:** 2026-10-27 ## Contexto O app pode iniciar programas externos escolhidos pelo usuário e ler estruturas de pastas pessoais. @@ -13,3 +13,7 @@ Menos risco e maior previsibilidade; troubleshooting requer logs locais bem deli ## Alternativas Logging irrestrito de paths, execução de comandos livres e telemetria automática (rejeitados). + +## Emenda (2026-10-27) +- Os argumentos de um launch são logados com caminhos marcados como `.private`. +- Argumentos extras do usuário são tokenizados ao salvar, guardados como array e validados contra uma lista de flags que o adapter gerencia (por exemplo `--`, `-batch`, `--exec`). diff --git a/docs/adr/0010-build-swiftpm-first.md b/docs/adr/0010-build-swiftpm-first.md new file mode 100644 index 0000000..fdb3314 --- /dev/null +++ b/docs/adr/0010-build-swiftpm-first.md @@ -0,0 +1,22 @@ +# ADR-0010 — Build SwiftPM-first + +**Status:** Aceito | **Data:** 2026-10-27 + +## Contexto +A máquina de desenvolvimento tem só as Command Line Tools (Swift 6.4, SDK macOS 27), sem Xcode. Nas CLT, SwiftUI, `@Observable` e Swift Testing compilam, mas a macro `@Model` do SwiftData não (o plugin `SwiftDataMacros` não existe nas CLT). Também não há `xcodebuild`, XCUITest nem Instruments. O usuário vai instalar o Xcode antes da Fase 2. + +## Decisão +O código vive num pacote SwiftPM (`Package.swift`), que compila com `swift build` e testa com `swift test` tanto nas CLT quanto no Xcode (que abre o pacote diretamente). + +- `RetroXCore`: regras de negócio, sem SwiftUI e sem SwiftData. Compila e testa só com as CLT. +- `RetroXApp`: executável SwiftUI. Para rodar como app de verdade (Dock, ativação, Info.plist), o script `scripts/bundle-app.sh` monta `RetroX.app` a partir do binário e assina ad hoc. +- `RetroXPersistence` (SwiftData) só entra no pacote quando o Xcode estiver instalado (Fase 2). +- Ferramentas de desenvolvimento (`rx-launch-probe`, `rx-fake-emulator`) são targets executáveis do mesmo pacote e não fazem parte do app distribuído. + +Um projeto `.xcodeproj` (gerado por XcodeGen, com consentimento) só será criado se XCUITest, asset catalogs ou o fluxo de distribuição exigirem. + +## Consequências +O núcleo é testável sem Xcode e o repositório não carrega um `.xcodeproj` difícil de revisar. Em troca, o bundle do app é montado por script, e recursos como asset catalog e String Catalog podem exigir passos extras até existir um projeto Xcode. + +## Alternativas +`.xcodeproj` escrito à mão sem Xcode (frágil); Tuist ou XcodeGen desde já (ferramenta externa sem necessidade imediata); esperar o Xcode para começar (atrasa a prova técnica do launch, que não depende dele). diff --git a/docs/adr/0012-deteccao-de-sistema.md b/docs/adr/0012-deteccao-de-sistema.md new file mode 100644 index 0000000..b1b6be0 --- /dev/null +++ b/docs/adr/0012-deteccao-de-sistema.md @@ -0,0 +1,24 @@ +# ADR-0012 — Detecção de sistema por fonte, cabeçalho e extensão + +**Status:** Aceito (assinaturas a validar com fixtures na Fase 2) | **Data:** 2026-10-27 + +## Contexto +A mesma extensão serve a vários consoles: `.iso` pode ser PS2, GameCube ou Wii; `.rvz` pode ser GameCube ou Wii. O RF-02 proíbe presumir o console só pela extensão. Hash integral é caro e não é exigido (ADR-0008). + +## Decisão +O `SystemDetector` decide o sistema de cada arquivo nesta ordem: + +1. **Dica da fonte:** o usuário pode declarar o sistema de uma pasta-fonte. Se a extensão é suportada por esse sistema, ela vale. +2. **Cabeçalho:** leitura de no máximo 64 KB do início do arquivo, sem hash. Assinaturas candidatas, a confirmar com fixtures sintéticas na Fase 2: + - ISO 9660 com `CD001` em `0x8001` e identificador de sistema `PLAYSTATION` → PS2 (o RetroX não suporta PS1 no MVP); + - magic GameCube `0xC2339F3D` em `0x1C`; + - magic Wii `0x5D1C9EA3` em `0x18`. +3. **Extensão inequívoca:** quando só um sistema do catálogo aceita a extensão. + +Se nenhuma regra decide, o arquivo entra como `needsReview` e o usuário escolhe. O método usado fica registrado no jogo (`detectionMethod`), e a escolha manual sempre prevalece. + +## Consequências +Menos falsos positivos e nenhum custo de hash. Formatos comprimidos (`chd`, `rvz`) dependem da dica da fonte ou de escolha manual até haver leitura específica do formato. + +## Alternativas +Só extensão (atribui errado `.iso` de outros consoles); hash completo contra banco de dados (lento e exige base externa); perguntar sempre (onboarding cansativo). diff --git a/ConsoleShelf_PROMPT_COMPLETO.md b/docs/origem/ConsoleShelf_PROMPT_COMPLETO.md similarity index 100% rename from ConsoleShelf_PROMPT_COMPLETO.md rename to docs/origem/ConsoleShelf_PROMPT_COMPLETO.md diff --git a/PROMPT_CLAUDE_CODE.md b/docs/origem/PROMPT_CLAUDE_CODE.md similarity index 100% rename from PROMPT_CLAUDE_CODE.md rename to docs/origem/PROMPT_CLAUDE_CODE.md From 3a2ff201e592bb0f22bbcacbafc100cf5a037bf5 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Tue, 27 Oct 2026 23:41:52 -0300 Subject: [PATCH 02/56] =?UTF-8?q?build:=20pacote=20SwiftPM,=20check-toolch?= =?UTF-8?q?ain=20e=20dom=C3=ADnio=20inicial?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Package.swift (tools 6.0, macOS 14, modo Swift 6) com RetroXCore e testes. - scripts/check-toolchain.sh informa Xcode, SwiftData e Rosetta. - GameSystemID, catálogo estático (PS2) e TitleParser, com testes. Co-Authored-By: Claude Opus 5.5 --- Package.swift | 12 +++++++ Sources/RetroXCore/Domain/GameSystem.swift | 38 ++++++++++++++++++++ Sources/RetroXCore/Domain/TitleParser.swift | 18 ++++++++++ Tests/RetroXCoreTests/TitleParserTests.swift | 32 +++++++++++++++++ scripts/check-toolchain.sh | 30 ++++++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 Package.swift create mode 100644 Sources/RetroXCore/Domain/GameSystem.swift create mode 100644 Sources/RetroXCore/Domain/TitleParser.swift create mode 100644 Tests/RetroXCoreTests/TitleParserTests.swift create mode 100755 scripts/check-toolchain.sh diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..13d7653 --- /dev/null +++ b/Package.swift @@ -0,0 +1,12 @@ +// swift-tools-version: 6.0 +import PackageDescription + +let package = Package( + name: "RetroX", + platforms: [.macOS(.v14)], + targets: [ + // Regras de negócio, sem SwiftUI e sem SwiftData: compila e testa só com as Command Line Tools. + .target(name: "RetroXCore"), + .testTarget(name: "RetroXCoreTests", dependencies: ["RetroXCore"]), + ] +) diff --git a/Sources/RetroXCore/Domain/GameSystem.swift b/Sources/RetroXCore/Domain/GameSystem.swift new file mode 100644 index 0000000..869489e --- /dev/null +++ b/Sources/RetroXCore/Domain/GameSystem.swift @@ -0,0 +1,38 @@ +import Foundation + +/// Identificador estável de um sistema (console). O valor bruto é persistido: não mude slugs existentes. +public struct GameSystemID: RawRepresentable, Hashable, Codable, Sendable, CustomStringConvertible { + public let rawValue: String + + public init(rawValue: String) { + self.rawValue = rawValue + } + + public var description: String { rawValue } + + public static let ps2 = GameSystemID(rawValue: "ps2") +} + +public struct GameSystem: Hashable, Sendable, Identifiable { + public let id: GameSystemID + public let displayName: String + public let shortName: String + /// Extensões (minúsculas, sem ponto) que o RetroX indexa para este sistema. + public let fileExtensions: Set +} + +/// Catálogo de sistemas definido em código e versionado com o app (PRD §12). +public enum SystemCatalog { + public static let ps2 = GameSystem( + id: .ps2, + displayName: "PlayStation 2", + shortName: "PS2", + fileExtensions: ["iso", "chd", "cso", "zso"] + ) + + public static let all: [GameSystem] = [ps2] + + public static func system(_ id: GameSystemID) -> GameSystem? { + all.first { $0.id == id } + } +} diff --git a/Sources/RetroXCore/Domain/TitleParser.swift b/Sources/RetroXCore/Domain/TitleParser.swift new file mode 100644 index 0000000..f523bae --- /dev/null +++ b/Sources/RetroXCore/Domain/TitleParser.swift @@ -0,0 +1,18 @@ +import Foundation + +public enum TitleParser { + /// Título de exibição derivado do nome do arquivo: sem extensão, `_` vira espaço, espaços colapsados e Unicode em NFC. + /// Marcas como região, entre parênteses, são mantidas. + public static func displayTitle(fromFilename filename: String) -> String { + let base = (filename as NSString).deletingPathExtension + let words = base.replacingOccurrences(of: "_", with: " ").split(whereSeparator: \.isWhitespace) + let title = words.joined(separator: " ").precomposedStringWithCanonicalMapping + return title.isEmpty ? filename.precomposedStringWithCanonicalMapping : title + } + + /// Chave de busca que ignora caixa, acentos e largura: "Ação" e "acao" geram a mesma chave. + public static func searchKey(_ text: String) -> String { + text.folding(options: [.caseInsensitive, .diacriticInsensitive, .widthInsensitive], locale: nil) + .precomposedStringWithCanonicalMapping + } +} diff --git a/Tests/RetroXCoreTests/TitleParserTests.swift b/Tests/RetroXCoreTests/TitleParserTests.swift new file mode 100644 index 0000000..2033184 --- /dev/null +++ b/Tests/RetroXCoreTests/TitleParserTests.swift @@ -0,0 +1,32 @@ +import Testing +@testable import RetroXCore + +struct TitleParserTests { + @Test("Remove a extensão e mantém a região") + func removesExtensionKeepsRegion() { + #expect(TitleParser.displayTitle(fromFilename: "Test Drive Unlimited (USA).iso") == "Test Drive Unlimited (USA)") + } + + @Test("Troca _ por espaço e colapsa espaços") + func normalizesSpacing() { + #expect(TitleParser.displayTitle(fromFilename: "Gran_Turismo 4 .chd") == "Gran Turismo 4") + } + + @Test("Converte nomes em NFD para NFC") + func convertsToNFC() { + let nfd = "Ac\u{0327}a\u{0303}o.iso" + let title = TitleParser.displayTitle(fromFilename: nfd) + #expect(Array(title.utf8) == Array("Ação".precomposedStringWithCanonicalMapping.utf8)) + } + + @Test("Nome sem base mantém o original") + func keepsFilenameWhenBaseIsEmpty() { + #expect(TitleParser.displayTitle(fromFilename: "___.iso") == "___.iso") + } + + @Test("Chave de busca ignora caixa, acentos e forma Unicode") + func searchKeyFolds() { + #expect(TitleParser.searchKey("AÇÃO") == TitleParser.searchKey("acao")) + #expect(TitleParser.searchKey("Ac\u{0327}a\u{0303}o") == TitleParser.searchKey("ação")) + } +} diff --git a/scripts/check-toolchain.sh b/scripts/check-toolchain.sh new file mode 100755 index 0000000..25bd790 --- /dev/null +++ b/scripts/check-toolchain.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Mostra o que o toolchain atual consegue fazer pelo RetroX. Só lê; não altera nada. +set -uo pipefail + +ok() { printf ' [ok] %s\n' "$1"; } +warn() { printf ' [falta] %s\n' "$1"; } + +echo "Sistema: macOS $(sw_vers -productVersion) ($(uname -m))" +echo "Toolchain: $(xcode-select -p 2>/dev/null || echo 'nenhum')" +echo "Swift: $(swift --version 2>/dev/null | head -1)" +echo + +if xcodebuild -version >/dev/null 2>&1; then + ok "Xcode: $(xcodebuild -version | head -1)" +else + warn "Xcode: só Command Line Tools. Sem xcodebuild, XCUITest e Instruments." +fi + +if printf 'import SwiftData\n@Model final class Probe { var x = 0; init() {} }\n' \ + | swiftc -typecheck -target "$(uname -m)-apple-macos14" - >/dev/null 2>&1; then + ok "SwiftData (@Model): compila. A Fase 2 pode começar." +else + warn "SwiftData (@Model): não compila neste toolchain (instale o Xcode)." +fi + +if [ -e /Library/Apple/usr/libexec/oah/libRosettaRuntime ]; then + ok "Rosetta: instalado (necessário para emuladores só x86_64, como o PCSX2 2.9)." +else + warn "Rosetta: não instalado. Emuladores só x86_64 não abrem em Apple Silicon." +fi From b7a361970822a0d5e3bd74526e2f36aa95b77b0d Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Tue, 27 Oct 2026 23:47:54 -0300 Subject: [PATCH 03/56] =?UTF-8?q?feat(core):=20inspe=C3=A7=C3=A3o=20de=20b?= =?UTF-8?q?undle,=20host=20e=20adapter=20PCSX2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AppBundleInspector lê Info.plist e arquiteturas Mach-O (thin/fat/fat64) sem carregar o bundle. - HostEnvironment classifica nativo / Rosetta / incompatível. - Contrato EmulatorAdapter, EmulatorRegistry e PCSX2Adapter com argv tipado ("-batch", "--", caminho) e validação de argumentos extras. - LaunchError com mensagens em pt-BR e ações de correção. - Testes com disco falso e cabeçalhos sintéticos; caminhos comparados byte a byte (NFC/NFD, hífen inicial, aspas, $(), newline, emoji). - scripts/test.sh contorna a descoberta intermitente do plugin do Swift Testing nas Command Line Tools (registrado no ADR-0010). Co-Authored-By: Claude Opus 5.5 --- .../Emulators/AppBundleInspector.swift | 49 ++++++++ .../Emulators/EmulatorAdapter.swift | 67 +++++++++++ .../Emulators/HostEnvironment.swift | 43 +++++++ .../RetroXCore/Emulators/MachOHeader.swift | 62 +++++++++++ .../RetroXCore/Emulators/PCSX2Adapter.swift | 78 +++++++++++++ .../RetroXCore/Launching/LaunchError.swift | 102 +++++++++++++++++ .../RetroXCore/Launching/LaunchModels.swift | 9 ++ .../Support/FileSystemProbing.swift | 42 +++++++ .../AppBundleInspectorTests.swift | 105 ++++++++++++++++++ Tests/RetroXCoreTests/PCSX2AdapterTests.swift | 91 +++++++++++++++ .../Support/FakeFileSystem.swift | 91 +++++++++++++++ docs/adr/0010-build-swiftpm-first.md | 4 + scripts/test.sh | 18 +++ 13 files changed, 761 insertions(+) create mode 100644 Sources/RetroXCore/Emulators/AppBundleInspector.swift create mode 100644 Sources/RetroXCore/Emulators/EmulatorAdapter.swift create mode 100644 Sources/RetroXCore/Emulators/HostEnvironment.swift create mode 100644 Sources/RetroXCore/Emulators/MachOHeader.swift create mode 100644 Sources/RetroXCore/Emulators/PCSX2Adapter.swift create mode 100644 Sources/RetroXCore/Launching/LaunchError.swift create mode 100644 Sources/RetroXCore/Launching/LaunchModels.swift create mode 100644 Sources/RetroXCore/Support/FileSystemProbing.swift create mode 100644 Tests/RetroXCoreTests/AppBundleInspectorTests.swift create mode 100644 Tests/RetroXCoreTests/PCSX2AdapterTests.swift create mode 100644 Tests/RetroXCoreTests/Support/FakeFileSystem.swift create mode 100755 scripts/test.sh diff --git a/Sources/RetroXCore/Emulators/AppBundleInspector.swift b/Sources/RetroXCore/Emulators/AppBundleInspector.swift new file mode 100644 index 0000000..cf9a658 --- /dev/null +++ b/Sources/RetroXCore/Emulators/AppBundleInspector.swift @@ -0,0 +1,49 @@ +import Foundation + +public struct AppBundleInfo: Sendable, Equatable { + public let bundleURL: URL + public let executableURL: URL + public let bundleIdentifier: String? + public let version: String? + public let architectures: Set +} + +/// Lê o Info.plist e o cabeçalho do executável de um `.app` sem carregá-lo (`Bundle(url:)` guardaria cache de versões antigas). +public struct AppBundleInspector: Sendable { + private let fileSystem: any FileSystemProbing + + public init(fileSystem: any FileSystemProbing = LocalFileSystem()) { + self.fileSystem = fileSystem + } + + public func inspect(_ bundleURL: URL) throws(LaunchError) -> AppBundleInfo { + switch fileSystem.kind(of: bundleURL) { + case .missing: throw .emulatorNotFound + case .regularFile: throw .emulatorBundleInvalid + case .directory: break + } + + let contentsURL = bundleURL.appending(path: "Contents", directoryHint: .isDirectory) + let plistURL = contentsURL.appending(path: "Info.plist", directoryHint: .notDirectory) + guard let plistData = try? fileSystem.readPrefix(of: plistURL, maxLength: 4 << 20), + let plist = try? PropertyListSerialization.propertyList(from: plistData, format: nil) as? [String: Any], + let executableName = plist["CFBundleExecutable"] as? String, + !executableName.isEmpty, !executableName.contains("/") + else { throw .emulatorBundleInvalid } + + let executableURL = contentsURL + .appending(path: "MacOS", directoryHint: .isDirectory) + .appending(path: executableName, directoryHint: .notDirectory) + guard fileSystem.kind(of: executableURL) == .regularFile else { throw .emulatorBundleInvalid } + guard fileSystem.isExecutable(executableURL) else { throw .emulatorNotExecutable } + + let header = (try? fileSystem.readPrefix(of: executableURL, maxLength: 4096)) ?? Data() + return AppBundleInfo( + bundleURL: bundleURL, + executableURL: executableURL, + bundleIdentifier: plist["CFBundleIdentifier"] as? String, + version: (plist["CFBundleShortVersionString"] ?? plist["CFBundleVersion"]) as? String, + architectures: MachOHeader.architectures(in: header) + ) + } +} diff --git a/Sources/RetroXCore/Emulators/EmulatorAdapter.swift b/Sources/RetroXCore/Emulators/EmulatorAdapter.swift new file mode 100644 index 0000000..8791400 --- /dev/null +++ b/Sources/RetroXCore/Emulators/EmulatorAdapter.swift @@ -0,0 +1,67 @@ +import Foundation + +/// Identificador estável de um adapter. O valor bruto é persistido nos perfis. +public struct EmulatorAdapterID: RawRepresentable, Hashable, Codable, Sendable, CustomStringConvertible { + public let rawValue: String + + public init(rawValue: String) { + self.rawValue = rawValue + } + + public var description: String { rawValue } + + public static let pcsx2 = EmulatorAdapterID(rawValue: "pcsx2") +} + +/// Opções tipadas por emulador. Um caso por adapter, para o compilador cobrar cada novo emulador. +public enum EmulatorOptions: Codable, Sendable, Equatable { + case pcsx2(PCSX2Options) +} + +/// Conhecimento específico de um emulador: o que ele abre e como montar seus argumentos. +/// O adapter não executa nada; o `GameLauncher` valida e lança (ADR-0003). +public protocol EmulatorAdapter: Sendable { + var id: EmulatorAdapterID { get } + var displayName: String { get } + var expectedBundleIdentifiers: Set { get } + var supportedSystems: Set { get } + var defaultStrategy: LaunchStrategy { get } + var defaultOptions: EmulatorOptions { get } + + /// Extensões (minúsculas, sem ponto) que este emulador abre para o sistema. + func supportedExtensions(for system: GameSystemID) -> Set + + /// argv sem o executável. O caminho da ROM é sempre um único elemento: nada passa por shell. + func arguments(romPath: String, options: EmulatorOptions, extraArguments: [String]) throws(LaunchError) -> [String] +} + +public struct EmulatorRegistry: Sendable { + private let adapters: [EmulatorAdapterID: any EmulatorAdapter] + + public init(_ adapters: [any EmulatorAdapter]) { + self.adapters = Dictionary(adapters.map { ($0.id, $0) }, uniquingKeysWith: { first, _ in first }) + } + + public static let standard = EmulatorRegistry([PCSX2Adapter()]) + + public func adapter(for id: EmulatorAdapterID) -> (any EmulatorAdapter)? { + adapters[id] + } + + public func adapters(for system: GameSystemID) -> [any EmulatorAdapter] { + adapters.values.filter { $0.supportedSystems.contains(system) }.sorted { $0.displayName < $1.displayName } + } +} + +enum ExtraArguments { + /// Recusa argumentos vazios, com NUL, ou que colidem com as flags controladas pelo adapter + /// (incluindo a forma `--flag=valor`). + static func validate(_ arguments: [String], managedFlags: Set) throws(LaunchError) { + for argument in arguments { + let flag = argument.split(separator: "=", maxSplits: 1).first.map(String.init) ?? argument + if argument.isEmpty || argument.contains("\0") || managedFlags.contains(flag) { + throw .invalidExtraArgument(argument) + } + } + } +} diff --git a/Sources/RetroXCore/Emulators/HostEnvironment.swift b/Sources/RetroXCore/Emulators/HostEnvironment.swift new file mode 100644 index 0000000..772a05c --- /dev/null +++ b/Sources/RetroXCore/Emulators/HostEnvironment.swift @@ -0,0 +1,43 @@ +import Foundation + +/// O que o Mac atual consegue executar. Valor simples para os testes simularem outros hosts. +public struct HostEnvironment: Sendable, Equatable { + public enum Compatibility: Sendable, Equatable { + case native + case rosetta + /// O executável não é Mach-O reconhecível (por exemplo, um script); não há como checar. + case unknown + case incompatible(rosettaMissing: Bool) + } + + /// Arquitetura do hardware (arm64 mesmo se o RetroX estiver rodando via Rosetta). + public var architecture: CPUArchitecture + public var isRosettaInstalled: Bool + + public init(architecture: CPUArchitecture, isRosettaInstalled: Bool) { + self.architecture = architecture + self.isRosettaInstalled = isRosettaInstalled + } + + /// A presença do runtime do Rosetta é uma heurística: não há API pública para isso. + static let rosettaRuntimeURL = URL(filePath: "/Library/Apple/usr/libexec/oah/libRosettaRuntime") + + public static func current(fileSystem: any FileSystemProbing = LocalFileSystem()) -> HostEnvironment { + var isAppleSilicon: Int32 = 0 + var size = MemoryLayout.size + let hasARM64 = sysctlbyname("hw.optional.arm64", &isAppleSilicon, &size, nil, 0) == 0 && isAppleSilicon == 1 + return HostEnvironment( + architecture: hasARM64 ? .arm64 : .x86_64, + isRosettaInstalled: fileSystem.kind(of: rosettaRuntimeURL) == .regularFile + ) + } + + public func compatibility(with architectures: Set) -> Compatibility { + if architectures.isEmpty { return .unknown } + if architectures.contains(architecture) { return .native } + if architecture == .arm64, architectures.contains(.x86_64) { + return isRosettaInstalled ? .rosetta : .incompatible(rosettaMissing: true) + } + return .incompatible(rosettaMissing: false) + } +} diff --git a/Sources/RetroXCore/Emulators/MachOHeader.swift b/Sources/RetroXCore/Emulators/MachOHeader.swift new file mode 100644 index 0000000..21a1437 --- /dev/null +++ b/Sources/RetroXCore/Emulators/MachOHeader.swift @@ -0,0 +1,62 @@ +import Foundation + +public enum CPUArchitecture: Hashable, Sendable, CustomStringConvertible { + case arm64 + case x86_64 + case other(cpuType: Int32) + + init(cpuType: Int32) { + switch cpuType { + case 0x0100_000C: self = .arm64 // CPU_TYPE_ARM64 + case 0x0100_0007: self = .x86_64 // CPU_TYPE_X86_64 + default: self = .other(cpuType: cpuType) + } + } + + public var description: String { + switch self { + case .arm64: "arm64" + case .x86_64: "x86_64" + case .other(let cpuType): "cpu(0x\(String(cpuType, radix: 16)))" + } + } +} + +enum MachOHeader { + /// Arquiteturas de um executável Mach-O, thin ou universal, a partir dos primeiros bytes do arquivo. + /// Retorna um conjunto vazio quando o formato não é reconhecido (por exemplo, um script). + static func architectures(in header: Data) -> Set { + guard let magic = header.uint32(at: 0, bigEndian: true) else { return [] } + switch magic { + case 0xCFFA_EDFE, 0xCEFA_EDFE: + // Thin little-endian (64 ou 32 bits): cputype logo após o magic. + guard let cpuType = header.uint32(at: 4, bigEndian: false) else { return [] } + return [CPUArchitecture(cpuType: Int32(bitPattern: cpuType))] + case 0xCAFE_BABE, 0xCAFE_BABF: + // Universal: cabeçalhos big-endian de 20 bytes (fat) ou 32 bytes (fat64). + let entrySize = magic == 0xCAFE_BABE ? 20 : 32 + // Arquivos .class de Java também começam com CAFEBABE, mas com uma "contagem" bem maior. + guard let count = header.uint32(at: 4, bigEndian: true), (1...32).contains(count) else { return [] } + var result: Set = [] + for index in 0.. UInt32? { + guard offset >= 0, offset + 4 <= count else { return nil } + var value: UInt32 = 0 + for byte in 0..<4 { + value = value << 8 | UInt32(self[startIndex + offset + (bigEndian ? byte : 3 - byte)]) + } + return value + } +} diff --git a/Sources/RetroXCore/Emulators/PCSX2Adapter.swift b/Sources/RetroXCore/Emulators/PCSX2Adapter.swift new file mode 100644 index 0000000..15f7ece --- /dev/null +++ b/Sources/RetroXCore/Emulators/PCSX2Adapter.swift @@ -0,0 +1,78 @@ +import Foundation + +public struct PCSX2Options: Codable, Sendable, Equatable { + public enum Fullscreen: String, Codable, Sendable, CaseIterable { + /// Não passa flag: vale a configuração do próprio PCSX2. + case emulatorDefault + case on + case off + } + + public enum Boot: String, Codable, Sendable, CaseIterable { + case emulatorDefault + case fast + case slow + } + + /// `-batch`: o PCSX2 fecha quando o jogo para, e o RetroX volta à frente. + public var batch: Bool + public var fullscreen: Fullscreen + public var bigPicture: Bool + public var boot: Boot + + public init(batch: Bool = true, fullscreen: Fullscreen = .emulatorDefault, bigPicture: Bool = false, boot: Boot = .emulatorDefault) { + self.batch = batch + self.fullscreen = fullscreen + self.bigPicture = bigPicture + self.boot = boot + } +} + +/// Flags conferidas no texto de ajuda do binário macOS do PCSX2 2.9.144: +/// `Usage: {} [parameters] [--] [boot filename]` (ver docs/spikes/0001-launch-pcsx2-macos.md). +public struct PCSX2Adapter: EmulatorAdapter { + public let id = EmulatorAdapterID.pcsx2 + public let displayName = "PCSX2" + public let expectedBundleIdentifiers: Set = ["net.pcsx2.pcsx2"] + public let supportedSystems: Set = [.ps2] + public let defaultStrategy = LaunchStrategy.workspace + public var defaultOptions: EmulatorOptions { .pcsx2(PCSX2Options()) } + + /// Flags que o RetroX gera, que trocariam o que é iniciado, ou que fazem o PCSX2 sair na hora. + static let managedFlags: Set = [ + "--", "-batch", "-nogui", "-fullscreen", "-nofullscreen", "-bigpicture", "-fastboot", "-slowboot", + "-elf", "-disc", "-bios", "-help", "-version", "-testconfig", + ] + + public init() {} + + public func supportedExtensions(for system: GameSystemID) -> Set { + system == .ps2 ? ["iso", "chd", "cso", "zso"] : [] + } + + public func arguments(romPath: String, options: EmulatorOptions, extraArguments: [String]) throws(LaunchError) -> [String] { + let pcsx2: PCSX2Options + switch options { + case .pcsx2(let given): pcsx2 = given + } + try ExtraArguments.validate(extraArguments, managedFlags: Self.managedFlags) + + var arguments: [String] = [] + if pcsx2.batch { arguments.append("-batch") } + switch pcsx2.fullscreen { + case .emulatorDefault: break + case .on: arguments.append("-fullscreen") + case .off: arguments.append("-nofullscreen") + } + if pcsx2.bigPicture { arguments.append("-bigpicture") } + switch pcsx2.boot { + case .emulatorDefault: break + case .fast: arguments.append("-fastboot") + case .slow: arguments.append("-slowboot") + } + arguments += extraArguments + // `--` encerra as opções: nomes com espaços ou iniciados por hífen chegam inteiros. + arguments += ["--", romPath] + return arguments + } +} diff --git a/Sources/RetroXCore/Launching/LaunchError.swift b/Sources/RetroXCore/Launching/LaunchError.swift new file mode 100644 index 0000000..acd3259 --- /dev/null +++ b/Sources/RetroXCore/Launching/LaunchError.swift @@ -0,0 +1,102 @@ +import Foundation + +/// Ações de correção oferecidas junto com cada erro (RNF-06). +public enum RecoveryAction: Sendable, Hashable { + case chooseEmulator + case locateROM + case retry + case openSettings + case bringEmulatorToFront + case showRosettaHelp + + public var title: String { + switch self { + case .chooseEmulator: String(localized: "Escolher emulador") + case .locateROM: String(localized: "Localizar arquivo") + case .retry: String(localized: "Tentar novamente") + case .openSettings: String(localized: "Abrir ajustes") + case .bringEmulatorToFront: String(localized: "Trazer emulador para frente") + case .showRosettaHelp: String(localized: "Como instalar o Rosetta") + } + } +} + +public enum LaunchError: Error, Sendable, Equatable { + case emulatorNotConfigured(GameSystemID) + case emulatorDoesNotSupportSystem(GameSystemID) + case emulatorNotFound + case emulatorBundleInvalid + case emulatorNotExecutable + case architectureUnsupported(rosettaMissing: Bool) + case romNotFound + case romIsDirectory + case romUnreadable + case unsupportedFormat(String) + case emulatorAlreadyRunning(bundleID: String) + case invalidExtraArgument(String) + case launchFailed(String) + case exitedEarly(status: Int32?, after: Duration) + + public var message: String { + switch self { + case .emulatorNotConfigured(let system): + String(localized: "Nenhum emulador configurado para \(Self.name(of: system)).") + case .emulatorDoesNotSupportSystem(let system): + String(localized: "O emulador escolhido não abre jogos de \(Self.name(of: system)).") + case .emulatorNotFound: + String(localized: "O emulador não foi encontrado no local configurado.") + case .emulatorBundleInvalid: + String(localized: "O item escolhido não parece ser um app de emulador válido.") + case .emulatorNotExecutable: + String(localized: "O macOS não permite executar o emulador escolhido.") + case .architectureUnsupported(rosettaMissing: true): + String(localized: "Este emulador foi feito para Mac com Intel e precisa do Rosetta, que não está instalado.") + case .architectureUnsupported(rosettaMissing: false): + String(localized: "Este emulador não roda na arquitetura deste Mac.") + case .romNotFound: + String(localized: "O arquivo do jogo não foi encontrado.") + case .romIsDirectory: + String(localized: "O item escolhido é uma pasta, não um arquivo de jogo.") + case .romUnreadable: + String(localized: "Sem permissão para ler o arquivo do jogo.") + case .unsupportedFormat(let fileExtension): + String(localized: "O formato “.\(fileExtension)” não é aberto por este emulador.") + case .emulatorAlreadyRunning: + String(localized: "O emulador já está aberto. Feche o jogo atual antes de abrir outro.") + case .invalidExtraArgument(let argument): + String(localized: "O argumento extra “\(argument)” não é permitido.") + case .launchFailed(let reason): + String(localized: "Não foi possível abrir o emulador: \(reason)") + case .exitedEarly: + String(localized: "O emulador fechou logo depois de abrir. Confira a BIOS e as configurações dele.") + } + } + + public var recoveryActions: [RecoveryAction] { + switch self { + case .emulatorNotConfigured, .emulatorDoesNotSupportSystem, .emulatorNotFound, + .emulatorBundleInvalid, .emulatorNotExecutable, .architectureUnsupported(rosettaMissing: false): + [.chooseEmulator] + case .architectureUnsupported(rosettaMissing: true): + [.showRosettaHelp, .chooseEmulator] + case .romNotFound, .romIsDirectory, .romUnreadable: + [.locateROM] + case .unsupportedFormat: + [.chooseEmulator, .locateROM] + case .emulatorAlreadyRunning: + [.bringEmulatorToFront] + case .invalidExtraArgument: + [.openSettings] + case .launchFailed, .exitedEarly: + [.retry, .openSettings] + } + } + + private static func name(of system: GameSystemID) -> String { + SystemCatalog.system(system)?.shortName ?? system.rawValue + } +} + +extension LaunchError: LocalizedError { + public var errorDescription: String? { message } +} diff --git a/Sources/RetroXCore/Launching/LaunchModels.swift b/Sources/RetroXCore/Launching/LaunchModels.swift new file mode 100644 index 0000000..c2760a7 --- /dev/null +++ b/Sources/RetroXCore/Launching/LaunchModels.swift @@ -0,0 +1,9 @@ +import Foundation + +/// Como o processo do emulador é criado. A escolha por adapter é registrada no ADR-0011. +public enum LaunchStrategy: String, Codable, Sendable, CaseIterable { + /// `NSWorkspace.openApplication`: LaunchServices, ativação e TCC por conta do emulador. + case workspace + /// `Process`: exec direto do binário; dá exit status, mas o emulador vira filho do RetroX. + case process +} diff --git a/Sources/RetroXCore/Support/FileSystemProbing.swift b/Sources/RetroXCore/Support/FileSystemProbing.swift new file mode 100644 index 0000000..12a4ba2 --- /dev/null +++ b/Sources/RetroXCore/Support/FileSystemProbing.swift @@ -0,0 +1,42 @@ +import Foundation + +public enum FileItemKind: Sendable, Equatable { + case missing + case regularFile + case directory +} + +/// Leituras de sistema de arquivos usadas na validação. Existe para os testes trocarem o disco por um fake. +public protocol FileSystemProbing: Sendable { + /// Segue symlinks, como o emulador fará ao abrir o caminho. + func kind(of url: URL) -> FileItemKind + func isReadable(_ url: URL) -> Bool + func isExecutable(_ url: URL) -> Bool + func readPrefix(of url: URL, maxLength: Int) throws -> Data +} + +public struct LocalFileSystem: FileSystemProbing { + public init() {} + + public func kind(of url: URL) -> FileItemKind { + var isDirectory: ObjCBool = false + guard FileManager.default.fileExists(atPath: url.path(percentEncoded: false), isDirectory: &isDirectory) else { + return .missing + } + return isDirectory.boolValue ? .directory : .regularFile + } + + public func isReadable(_ url: URL) -> Bool { + FileManager.default.isReadableFile(atPath: url.path(percentEncoded: false)) + } + + public func isExecutable(_ url: URL) -> Bool { + FileManager.default.isExecutableFile(atPath: url.path(percentEncoded: false)) + } + + public func readPrefix(of url: URL, maxLength: Int) throws -> Data { + let handle = try FileHandle(forReadingFrom: url) + defer { try? handle.close() } + return try handle.read(upToCount: maxLength) ?? Data() + } +} diff --git a/Tests/RetroXCoreTests/AppBundleInspectorTests.swift b/Tests/RetroXCoreTests/AppBundleInspectorTests.swift new file mode 100644 index 0000000..f8e0f40 --- /dev/null +++ b/Tests/RetroXCoreTests/AppBundleInspectorTests.swift @@ -0,0 +1,105 @@ +import Foundation +import Testing +@testable import RetroXCore + +private let recognizedHeaders: [(Data, Set)] = [ + (MachOSamples.thinX86_64, [.x86_64]), + (MachOSamples.thinARM64, [.arm64]), + (MachOSamples.universal, [.x86_64, .arm64]), + (MachOSamples.universal64, [.arm64]), +] + +struct MachOHeaderTests { + @Test("Lê arquiteturas de cabeçalhos thin e universais", arguments: recognizedHeaders) + func readsArchitectures(header: Data, expected: Set) { + #expect(MachOHeader.architectures(in: header) == expected) + } + + @Test("Não reconhece script, .class Java, dados truncados ou vazios", arguments: [ + MachOSamples.shellScript, MachOSamples.javaClass, Data([0xCF, 0xFA, 0xED]), Data(), + MachOSamples.universal.prefix(12), + ]) + func rejectsUnknownFormats(header: Data) { + #expect(MachOHeader.architectures(in: header).isEmpty) + } + + @Test("Funciona com Data fatiada (índice inicial diferente de zero)") + func handlesSlices() { + let padded = Data([0xFF, 0xFF]) + MachOSamples.thinARM64 + #expect(MachOHeader.architectures(in: padded.dropFirst(2)) == [.arm64]) + } +} + +struct AppBundleInspectorTests { + @Test("Lê executável, bundle ID, versão e arquitetura") + func inspectsBundle() throws { + var disk = FakeFileSystem() + disk.addAppBundle(at: "/Apps/PCSX2.app", executable: "PCSX2") + let info = try AppBundleInspector(fileSystem: disk).inspect(URL(filePath: "/Apps/PCSX2.app/")) + #expect(info.executableURL.path(percentEncoded: false) == "/Apps/PCSX2.app/Contents/MacOS/PCSX2") + #expect(info.bundleIdentifier == "net.pcsx2.pcsx2") + #expect(info.version == "v2.9.144") + #expect(info.architectures == [.x86_64]) + } + + @Test("App inexistente") + func missingApp() { + #expect(throws: LaunchError.emulatorNotFound) { + try AppBundleInspector(fileSystem: FakeFileSystem()).inspect(URL(filePath: "/Apps/Nada.app")) + } + } + + @Test("Arquivo comum no lugar do .app") + func plainFile() { + var disk = FakeFileSystem() + disk["/Apps/PCSX2.app"] = .file() + #expect(throws: LaunchError.emulatorBundleInvalid) { + try AppBundleInspector(fileSystem: disk).inspect(URL(filePath: "/Apps/PCSX2.app")) + } + } + + @Test("Pasta sem Info.plist") + func missingInfoPlist() { + var disk = FakeFileSystem() + disk["/Apps/PCSX2.app"] = .directory + #expect(throws: LaunchError.emulatorBundleInvalid) { + try AppBundleInspector(fileSystem: disk).inspect(URL(filePath: "/Apps/PCSX2.app")) + } + } + + @Test("Info.plist aponta para executável que não existe") + func missingExecutable() { + var disk = FakeFileSystem() + disk.addAppBundle(at: "/Apps/PCSX2.app", executable: "PCSX2") + disk.entries["/Apps/PCSX2.app/Contents/MacOS/PCSX2"] = nil + #expect(throws: LaunchError.emulatorBundleInvalid) { + try AppBundleInspector(fileSystem: disk).inspect(URL(filePath: "/Apps/PCSX2.app")) + } + } + + @Test("Executável sem permissão de execução") + func notExecutable() { + var disk = FakeFileSystem() + disk.addAppBundle(at: "/Apps/PCSX2.app", executableIsExecutable: false) + #expect(throws: LaunchError.emulatorNotExecutable) { + try AppBundleInspector(fileSystem: disk).inspect(URL(filePath: "/Apps/PCSX2.app")) + } + } +} + +struct HostEnvironmentTests { + let appleSilicon = HostEnvironment(architecture: .arm64, isRosettaInstalled: true) + let appleSiliconWithoutRosetta = HostEnvironment(architecture: .arm64, isRosettaInstalled: false) + let intel = HostEnvironment(architecture: .x86_64, isRosettaInstalled: false) + + @Test("Compatibilidade por arquitetura do executável") + func compatibility() { + #expect(appleSilicon.compatibility(with: [.arm64]) == .native) + #expect(appleSilicon.compatibility(with: [.x86_64, .arm64]) == .native) + #expect(appleSilicon.compatibility(with: [.x86_64]) == .rosetta) + #expect(appleSiliconWithoutRosetta.compatibility(with: [.x86_64]) == .incompatible(rosettaMissing: true)) + #expect(intel.compatibility(with: [.x86_64]) == .native) + #expect(intel.compatibility(with: [.arm64]) == .incompatible(rosettaMissing: false)) + #expect(appleSilicon.compatibility(with: []) == .unknown) + } +} diff --git a/Tests/RetroXCoreTests/PCSX2AdapterTests.swift b/Tests/RetroXCoreTests/PCSX2AdapterTests.swift new file mode 100644 index 0000000..dd20f63 --- /dev/null +++ b/Tests/RetroXCoreTests/PCSX2AdapterTests.swift @@ -0,0 +1,91 @@ +import Testing +@testable import RetroXCore + +struct PCSX2AdapterTests { + let adapter = PCSX2Adapter() + + @Test("Padrão: -batch, --, caminho") + func defaultArguments() throws { + let arguments = try adapter.arguments(romPath: "/Jogos/GT4.iso", options: adapter.defaultOptions, extraArguments: []) + #expect(arguments == ["-batch", "--", "/Jogos/GT4.iso"]) + } + + @Test("Opções tipadas viram flags na ordem esperada") + func typedOptions() throws { + let options = PCSX2Options(batch: false, fullscreen: .on, bigPicture: true, boot: .fast) + let arguments = try adapter.arguments(romPath: "/j.iso", options: .pcsx2(options), extraArguments: ["-portable"]) + #expect(arguments == ["-fullscreen", "-bigpicture", "-fastboot", "-portable", "--", "/j.iso"]) + } + + @Test("Tela cheia e boot desligáveis") + func offVariants() throws { + let options = PCSX2Options(fullscreen: .off, boot: .slow) + let arguments = try adapter.arguments(romPath: "/j.iso", options: .pcsx2(options), extraArguments: []) + #expect(arguments == ["-batch", "-nofullscreen", "-slowboot", "--", "/j.iso"]) + } + + /// Caminhos que quebrariam uma linha de shell. Aqui cada um tem que chegar como um único elemento, byte a byte. + @Test("O caminho da ROM chega inteiro, byte a byte", arguments: [ + "/Volumes/Jogos Ação/Test Drive Unlimited (USA).iso", + "/Volumes/Jogos Ac\u{0327}a\u{0303}o/NFD (Brasil).iso", + "/Jogos/-começa-com-hifen.iso", + "/Jogos/a=b.iso", + "/Jogos/\"aspas\" e 'apóstrofo'.iso", + "/Jogos/$(rm -rf ~); `x` & | > <.iso", + "/Jogos/quebra\nde linha.iso", + "/Jogos/🎮 日本語 ñ.iso", + "/Jogos/" + String(repeating: "longo ", count: 200) + ".iso", + ]) + func romPathIsSingleExactElement(path: String) throws { + let arguments = try adapter.arguments(romPath: path, options: adapter.defaultOptions, extraArguments: []) + #expect(arguments.count == 3) + #expect(arguments[1] == "--") + // String do Swift compara por equivalência canônica (NFC == NFD); aqui a forma exata importa. + #expect(Array(arguments[2].utf8) == Array(path.utf8)) + } + + @Test("Recusa argumentos extras que colidem com flags gerenciadas", arguments: [ + "--", "-batch", "-fullscreen", "-elf", "-bios", "-help", "", "-x\0y", + ]) + func rejectsManagedExtraArguments(extra: String) { + #expect(throws: LaunchError.invalidExtraArgument(extra)) { + try adapter.arguments(romPath: "/j.iso", options: adapter.defaultOptions, extraArguments: [extra]) + } + } + + @Test("Aceita argumentos extras legítimos") + func acceptsUserExtraArguments() throws { + let arguments = try adapter.arguments( + romPath: "/j.iso", options: adapter.defaultOptions, extraArguments: ["-datapath", "/Dados PCSX2"] + ) + #expect(arguments == ["-batch", "-datapath", "/Dados PCSX2", "--", "/j.iso"]) + } + + @Test("Formatos do MVP só para PS2") + func supportedExtensions() { + #expect(adapter.supportedExtensions(for: .ps2) == ["iso", "chd", "cso", "zso"]) + #expect(adapter.supportedExtensions(for: GameSystemID(rawValue: "wii")).isEmpty) + } +} + +struct LaunchErrorTests { + @Test("Todo erro oferece ao menos uma ação de correção e uma mensagem", arguments: [ + LaunchError.emulatorNotConfigured(.ps2), .emulatorDoesNotSupportSystem(.ps2), .emulatorNotFound, + .emulatorBundleInvalid, .emulatorNotExecutable, .architectureUnsupported(rosettaMissing: true), + .architectureUnsupported(rosettaMissing: false), .romNotFound, .romIsDirectory, .romUnreadable, + .unsupportedFormat("zip"), .emulatorAlreadyRunning(bundleID: "net.pcsx2.pcsx2"), + .invalidExtraArgument("--"), .launchFailed("x"), .exitedEarly(status: 1, after: .seconds(1)), + ]) + func everyErrorIsActionable(error: LaunchError) { + #expect(!error.recoveryActions.isEmpty) + #expect(!error.message.isEmpty) + } + + @Test("Mapeamentos principais") + func keyMappings() { + #expect(LaunchError.romNotFound.recoveryActions == [.locateROM]) + #expect(LaunchError.emulatorAlreadyRunning(bundleID: "x").recoveryActions == [.bringEmulatorToFront]) + #expect(LaunchError.architectureUnsupported(rosettaMissing: true).recoveryActions.first == .showRosettaHelp) + #expect(LaunchError.emulatorNotConfigured(.ps2).message.contains("PS2")) + } +} diff --git a/Tests/RetroXCoreTests/Support/FakeFileSystem.swift b/Tests/RetroXCoreTests/Support/FakeFileSystem.swift new file mode 100644 index 0000000..9aa954f --- /dev/null +++ b/Tests/RetroXCoreTests/Support/FakeFileSystem.swift @@ -0,0 +1,91 @@ +import Foundation +@testable import RetroXCore + +/// Disco em memória: caminho → entrada. Caminhos fictícios, nada da máquina real. +struct FakeFileSystem: FileSystemProbing { + enum Entry { + case directory + case file(Data = Data(), readable: Bool = true, executable: Bool = false) + } + + var entries: [String: Entry] = [:] + + subscript(path: String) -> Entry? { + get { entries[Self.normalize(path)] } + set { entries[Self.normalize(path)] = newValue } + } + + func kind(of url: URL) -> FileItemKind { + switch self[url.path(percentEncoded: false)] { + case nil: .missing + case .directory: .directory + case .file: .regularFile + } + } + + func isReadable(_ url: URL) -> Bool { + if case .file(_, let readable, _) = self[url.path(percentEncoded: false)] { return readable } + return false + } + + func isExecutable(_ url: URL) -> Bool { + if case .file(_, _, let executable) = self[url.path(percentEncoded: false)] { return executable } + return false + } + + func readPrefix(of url: URL, maxLength: Int) throws -> Data { + guard case .file(let data, true, _) = self[url.path(percentEncoded: false)] else { + throw CocoaError(.fileReadNoSuchFile) + } + return data.prefix(maxLength) + } + + /// Cria um `.app` mínimo: Info.plist e executável com o cabeçalho Mach-O dado. + mutating func addAppBundle( + at path: String, + executable: String = "Emu", + bundleIdentifier: String? = "net.pcsx2.pcsx2", + version: String? = "v2.9.144", + header: Data = MachOSamples.thinX86_64, + executableIsExecutable: Bool = true + ) { + var plist: [String: Any] = ["CFBundleExecutable": executable] + plist["CFBundleIdentifier"] = bundleIdentifier + plist["CFBundleShortVersionString"] = version + let plistData = try! PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0) + self[path] = .directory + self["\(path)/Contents"] = .directory + self["\(path)/Contents/Info.plist"] = .file(plistData) + self["\(path)/Contents/MacOS"] = .directory + self["\(path)/Contents/MacOS/\(executable)"] = .file(header, executable: executableIsExecutable) + } + + private static func normalize(_ path: String) -> String { + path.count > 1 && path.hasSuffix("/") ? String(path.dropLast()) : path + } +} + +enum MachOSamples { + /// MH_MAGIC_64 em little-endian + cputype. + static let thinX86_64 = Data([0xCF, 0xFA, 0xED, 0xFE, 0x07, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00]) + static let thinARM64 = Data([0xCF, 0xFA, 0xED, 0xFE, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]) + + /// FAT_MAGIC com duas entradas de 20 bytes: x86_64 e arm64. + static let universal: Data = { + var bytes: [UInt8] = [0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x02] + bytes += [0x01, 0x00, 0x00, 0x07] + [UInt8](repeating: 0, count: 16) + bytes += [0x01, 0x00, 0x00, 0x0C] + [UInt8](repeating: 0, count: 16) + return Data(bytes) + }() + + /// FAT_MAGIC_64 com uma entrada de 32 bytes: arm64. + static let universal64: Data = { + var bytes: [UInt8] = [0xCA, 0xFE, 0xBA, 0xBF, 0x00, 0x00, 0x00, 0x01] + bytes += [0x01, 0x00, 0x00, 0x0C] + [UInt8](repeating: 0, count: 28) + return Data(bytes) + }() + + /// Cabeçalho de um .class Java: CAFEBABE seguido de versão, não de contagem de arquiteturas. + static let javaClass = Data([0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x41]) + static let shellScript = Data("#!/bin/sh\n".utf8) +} diff --git a/docs/adr/0010-build-swiftpm-first.md b/docs/adr/0010-build-swiftpm-first.md index fdb3314..bf8ad85 100644 --- a/docs/adr/0010-build-swiftpm-first.md +++ b/docs/adr/0010-build-swiftpm-first.md @@ -18,5 +18,9 @@ Um projeto `.xcodeproj` (gerado por XcodeGen, com consentimento) só será criad ## Consequências O núcleo é testável sem Xcode e o repositório não carrega um `.xcodeproj` difícil de revisar. Em troca, o bundle do app é montado por script, e recursos como asset catalog e String Catalog podem exigir passos extras até existir um projeto Xcode. +Peculiaridades das CLT encontradas na Sprint 1 (Swift 6.4, backend `swiftbuild`): +- A descoberta do plugin de macros do Swift Testing é intermitente (2 falhas em 3 builds limpos). Os testes rodam por `scripts/test.sh`, que passa `-plugin-path` explicitamente quando o toolchain ativo é o das CLT. +- O backend antigo (`--build-system native`) não encontra o módulo `Testing` nas CLT. + ## Alternativas `.xcodeproj` escrito à mão sem Xcode (frágil); Tuist ou XcodeGen desde já (ferramenta externa sem necessidade imediata); esperar o Xcode para começar (atrasa a prova técnica do launch, que não depende dele). diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..9e72e07 --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Roda `swift test` repassando os argumentos recebidos. +# +# Nas Command Line Tools (Swift 6.4, backend swiftbuild), a descoberta do plugin de macros do +# Swift Testing é intermitente: às vezes o compilador não recebe o TestingMacros e o build falha +# com "plugin for module 'TestingMacros' not found". Passar o caminho do plugin explicitamente +# resolve. Com o Xcode ativo, nada é acrescentado. +set -euo pipefail +cd "$(dirname "$0")/.." + +extra=() +developer_dir="$(xcode-select -p 2>/dev/null || true)" +plugin_dir="$developer_dir/usr/lib/swift/host/plugins/testing" +if [[ "$developer_dir" == *CommandLineTools* && -d "$plugin_dir" ]]; then + extra=(-Xswiftc -plugin-path -Xswiftc "$plugin_dir") +fi + +exec swift test "${extra[@]}" "$@" From aa1a689da1f365ef201305eb82f1edac9bfd1d9a Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Tue, 27 Oct 2026 23:49:46 -0300 Subject: [PATCH 04/56] feat(core): GameLauncher, launchers NSWorkspace e Process MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GameLauncher.prepare valida ROM, emulador, arquitetura e instância aberta e devolve um LaunchPlan puro (base do modo simulado). - WorkspaceLauncher (LaunchServices) e FoundationProcessLauncher (exec direto, stdout/stderr para arquivo ou /dev/null), sem shell. - Término observado por kqueue (DispatchSource), sem depender de run loop. - SessionOutcome classifica saída precoce (< 5 s) como falha provável. - Logs os.Logger com argumentos privados e signpost do North Star. - Testes com disco, apps em execução e launcher falsos. Co-Authored-By: Claude Opus 5.5 --- .../Launching/FoundationProcessLauncher.swift | 56 ++++++ .../RetroXCore/Launching/GameLauncher.swift | 102 +++++++++++ .../RetroXCore/Launching/LaunchModels.swift | 134 +++++++++++++++ .../Launching/ProcessExitMonitor.swift | 22 +++ .../Launching/WorkspaceLauncher.swift | 23 +++ Sources/RetroXCore/Support/Log.swift | 9 + .../Support/RunningApplications.swift | 23 +++ Tests/RetroXCoreTests/GameLauncherTests.swift | 160 ++++++++++++++++++ .../RetroXCoreTests/Support/LaunchFakes.swift | 67 ++++++++ 9 files changed, 596 insertions(+) create mode 100644 Sources/RetroXCore/Launching/FoundationProcessLauncher.swift create mode 100644 Sources/RetroXCore/Launching/GameLauncher.swift create mode 100644 Sources/RetroXCore/Launching/ProcessExitMonitor.swift create mode 100644 Sources/RetroXCore/Launching/WorkspaceLauncher.swift create mode 100644 Sources/RetroXCore/Support/Log.swift create mode 100644 Sources/RetroXCore/Support/RunningApplications.swift create mode 100644 Tests/RetroXCoreTests/GameLauncherTests.swift create mode 100644 Tests/RetroXCoreTests/Support/LaunchFakes.swift diff --git a/Sources/RetroXCore/Launching/FoundationProcessLauncher.swift b/Sources/RetroXCore/Launching/FoundationProcessLauncher.swift new file mode 100644 index 0000000..d17f3ea --- /dev/null +++ b/Sources/RetroXCore/Launching/FoundationProcessLauncher.swift @@ -0,0 +1,56 @@ +import AppKit + +/// Executa o binário de dentro do `.app` diretamente, com argv em array (sem shell). +/// O emulador vira filho do RetroX: dá exit status, mas prompts de privacidade passam a ser atribuídos ao RetroX. +public struct FoundationProcessLauncher: ProcessLaunching { + /// Destino de stdout/stderr do emulador. `nil` descarta: um pipe sem leitor travaria ou mataria o emulador. + public var outputLogURL: URL? + + public init(outputLogURL: URL? = nil) { + self.outputLogURL = outputLogURL + } + + public func launch(_ plan: LaunchPlan) async throws(LaunchError) -> LaunchedProcess { + let process = Process() + process.executableURL = plan.executableURL + process.arguments = plan.arguments + process.standardInput = FileHandle.nullDevice + let output = openOutput() + process.standardOutput = output + process.standardError = output + + let (exits, continuation) = AsyncStream.makeStream(of: ProcessExit.self) + process.terminationHandler = { finished in + continuation.yield(ProcessExit(status: finished.terminationStatus, endedAt: Date())) + continuation.finish() + } + do { + try process.run() + } catch { + throw .launchFailed(error.localizedDescription) + } + + let pid = process.processIdentifier + if plan.activates { + await Self.activateWhenRegistered(pid: pid) + } + return LaunchedProcess(pid: pid, launchedAt: Date(), plan: plan, exits: exits) + } + + private func openOutput() -> FileHandle { + guard let outputLogURL else { return FileHandle.nullDevice } + FileManager.default.createFile(atPath: outputLogURL.path(percentEncoded: false), contents: nil) + return (try? FileHandle(forWritingTo: outputLogURL)) ?? FileHandle.nullDevice + } + + /// Um processo iniciado por exec não é ativado pelo sistema; o app só aparece para o AppKit depois de registrar. + private static func activateWhenRegistered(pid: pid_t) async { + for _ in 0..<20 { + if let app = NSRunningApplication(processIdentifier: pid), app.activationPolicy == .regular { + app.activate() + return + } + try? await Task.sleep(for: .milliseconds(150)) + } + } +} diff --git a/Sources/RetroXCore/Launching/GameLauncher.swift b/Sources/RetroXCore/Launching/GameLauncher.swift new file mode 100644 index 0000000..0f4a02a --- /dev/null +++ b/Sources/RetroXCore/Launching/GameLauncher.swift @@ -0,0 +1,102 @@ +import Foundation + +/// Valida ROM e emulador, monta o plano e o executa (ADR-0003). +public struct GameLauncher: Sendable { + private let registry: EmulatorRegistry + private let fileSystem: any FileSystemProbing + private let host: HostEnvironment + private let runningApplications: any RunningApplicationsProviding + private let launchers: [LaunchStrategy: any ProcessLaunching] + + public init( + registry: EmulatorRegistry = .standard, + fileSystem: any FileSystemProbing = LocalFileSystem(), + host: HostEnvironment = .current(), + runningApplications: any RunningApplicationsProviding = WorkspaceRunningApplications(), + launchers: [LaunchStrategy: any ProcessLaunching] = [.workspace: WorkspaceLauncher(), .process: FoundationProcessLauncher()] + ) { + self.registry = registry + self.fileSystem = fileSystem + self.host = host + self.runningApplications = runningApplications + self.launchers = launchers + } + + /// Valida tudo e monta o plano, sem executar nada. É também o que o modo simulado mostra. + public func prepare(_ request: LaunchRequest) throws(LaunchError) -> PreparedLaunch { + let profile = request.profile + guard let adapter = registry.adapter(for: profile.adapterID) else { + throw .emulatorNotConfigured(request.systemID) + } + guard adapter.supportedSystems.contains(request.systemID) else { + throw .emulatorDoesNotSupportSystem(request.systemID) + } + try validateROM(request.romURL, supportedExtensions: adapter.supportedExtensions(for: request.systemID)) + + let app = try AppBundleInspector(fileSystem: fileSystem).inspect(profile.appURL) + var warnings: [LaunchWarning] = [] + if !(app.bundleIdentifier.map(adapter.expectedBundleIdentifiers.contains) ?? false) { + warnings.append(.unexpectedBundleIdentifier(app.bundleIdentifier)) + } + switch host.compatibility(with: app.architectures) { + case .native: break + case .rosetta: warnings.append(.runsUnderRosetta) + case .unknown: warnings.append(.unknownArchitecture) + case .incompatible(let rosettaMissing): throw .architectureUnsupported(rosettaMissing: rosettaMissing) + } + + let createsNewInstance = request.alreadyRunningPolicy == .launchNewInstance + if !createsNewInstance, let bundleID = app.bundleIdentifier, runningApplications.isRunning(bundleIdentifier: bundleID) { + throw .emulatorAlreadyRunning(bundleID: bundleID) + } + + let arguments = try adapter.arguments( + romPath: request.romURL.path(percentEncoded: false), + options: profile.options, + extraArguments: profile.extraArguments + ) + let plan = LaunchPlan( + appURL: app.bundleURL, + executableURL: app.executableURL, + bundleIdentifier: app.bundleIdentifier, + arguments: arguments, + strategy: profile.strategy ?? adapter.defaultStrategy, + activates: true, + createsNewInstance: createsNewInstance + ) + return PreparedLaunch(plan: plan, app: app, warnings: warnings) + } + + public func launch(_ prepared: PreparedLaunch) async throws(LaunchError) -> LaunchedProcess { + let plan = prepared.plan + guard let launcher = launchers[plan.strategy] else { + throw .launchFailed(String(localized: "estratégia “\(plan.strategy.rawValue)” indisponível")) + } + let interval = Log.launchSignposter.beginInterval("launch") + defer { Log.launchSignposter.endInterval("launch", interval) } + + Log.launch.info(""" + Abrindo \(plan.bundleIdentifier ?? "?", privacy: .public) via \(plan.strategy.rawValue, privacy: .public) \ + com \(plan.arguments, privacy: .private) + """) + do { + let launched = try await launcher.launch(plan) + Log.launch.info("Emulador iniciado, pid \(launched.pid, privacy: .public)") + return launched + } catch { + Log.launch.error("Falha ao abrir o emulador: \(error.message, privacy: .private)") + throw error + } + } + + private func validateROM(_ url: URL, supportedExtensions: Set) throws(LaunchError) { + switch fileSystem.kind(of: url) { + case .missing: throw .romNotFound + case .directory: throw .romIsDirectory + case .regularFile: break + } + guard fileSystem.isReadable(url) else { throw .romUnreadable } + let fileExtension = url.pathExtension.lowercased() + guard supportedExtensions.contains(fileExtension) else { throw .unsupportedFormat(fileExtension) } + } +} diff --git a/Sources/RetroXCore/Launching/LaunchModels.swift b/Sources/RetroXCore/Launching/LaunchModels.swift index c2760a7..13aa3d1 100644 --- a/Sources/RetroXCore/Launching/LaunchModels.swift +++ b/Sources/RetroXCore/Launching/LaunchModels.swift @@ -7,3 +7,137 @@ public enum LaunchStrategy: String, Codable, Sendable, CaseIterable { /// `Process`: exec direto do binário; dá exit status, mas o emulador vira filho do RetroX. case process } + +/// Configuração de um emulador escolhida pelo usuário. +public struct EmulatorProfile: Sendable, Equatable, Identifiable { + public var id: UUID + public var name: String + public var adapterID: EmulatorAdapterID + public var appURL: URL + public var options: EmulatorOptions + public var extraArguments: [String] + /// `nil` usa a estratégia padrão do adapter. + public var strategy: LaunchStrategy? + + public init( + id: UUID = UUID(), + name: String, + adapterID: EmulatorAdapterID, + appURL: URL, + options: EmulatorOptions, + extraArguments: [String] = [], + strategy: LaunchStrategy? = nil + ) { + self.id = id + self.name = name + self.adapterID = adapterID + self.appURL = appURL + self.options = options + self.extraArguments = extraArguments + self.strategy = strategy + } +} + +public enum AlreadyRunningPolicy: Sendable, Equatable { + /// Padrão: não abre outra instância; o usuário decide (ADR-0003, emenda). + case refuse + case launchNewInstance +} + +public struct LaunchRequest: Sendable, Equatable { + public var romURL: URL + public var systemID: GameSystemID + public var profile: EmulatorProfile + public var alreadyRunningPolicy: AlreadyRunningPolicy + + public init(romURL: URL, systemID: GameSystemID, profile: EmulatorProfile, alreadyRunningPolicy: AlreadyRunningPolicy = .refuse) { + self.romURL = romURL + self.systemID = systemID + self.profile = profile + self.alreadyRunningPolicy = alreadyRunningPolicy + } +} + +/// Tudo o que é preciso para abrir o emulador, já validado. Puro: é o que o modo simulado mostra. +public struct LaunchPlan: Sendable, Equatable { + public let appURL: URL + public let executableURL: URL + public let bundleIdentifier: String? + /// argv sem o executável. + public let arguments: [String] + public let strategy: LaunchStrategy + public let activates: Bool + public let createsNewInstance: Bool +} + +public enum LaunchWarning: Sendable, Equatable { + case unexpectedBundleIdentifier(String?) + case runsUnderRosetta + case unknownArchitecture + + public var message: String { + switch self { + case .unexpectedBundleIdentifier(let found): + String(localized: "O app escolhido não se identifica como o emulador esperado (\(found ?? "sem identificador")).") + case .runsUnderRosetta: + String(localized: "Este emulador roda via Rosetta neste Mac.") + case .unknownArchitecture: + String(localized: "Não foi possível conferir a arquitetura do emulador.") + } + } +} + +public struct PreparedLaunch: Sendable, Equatable { + public let plan: LaunchPlan + public let app: AppBundleInfo + public let warnings: [LaunchWarning] +} + +public struct ProcessExit: Sendable, Equatable { + /// Só disponível quando o emulador é filho do RetroX (estratégia `process`). + public let status: Int32? + public let endedAt: Date + + public init(status: Int32?, endedAt: Date) { + self.status = status + self.endedAt = endedAt + } +} + +public struct LaunchedProcess: Sendable { + public let pid: pid_t + public let launchedAt: Date + public let plan: LaunchPlan + /// Entrega um único `ProcessExit` quando o processo termina. Tem um só consumidor. + public let exits: AsyncStream + + public init(pid: pid_t, launchedAt: Date, plan: LaunchPlan, exits: AsyncStream) { + self.pid = pid + self.launchedAt = launchedAt + self.plan = plan + self.exits = exits + } + + public func waitForExit() async -> ProcessExit? { + for await exit in exits { return exit } + return nil + } +} + +/// Como terminou uma sessão de jogo, do ponto de vista do RetroX. +public enum SessionOutcome: Sendable, Equatable { + case ended(after: Duration) + /// Fechou cedo demais para ter sido uma partida: provável falha (BIOS, formato, configuração). + case exitedEarly(status: Int32?, after: Duration) + + public static let earlyExitWindow: Duration = .seconds(5) + + public static func classify(launchedAt: Date, exit: ProcessExit, earlyExitWindow: Duration = earlyExitWindow) -> SessionOutcome { + let elapsed = Duration.milliseconds(Int64((exit.endedAt.timeIntervalSince(launchedAt) * 1000).rounded())) + return elapsed < earlyExitWindow ? .exitedEarly(status: exit.status, after: elapsed) : .ended(after: elapsed) + } +} + +public protocol ProcessLaunching: Sendable { + func launch(_ plan: LaunchPlan) async throws(LaunchError) -> LaunchedProcess +} diff --git a/Sources/RetroXCore/Launching/ProcessExitMonitor.swift b/Sources/RetroXCore/Launching/ProcessExitMonitor.swift new file mode 100644 index 0000000..66b6fad --- /dev/null +++ b/Sources/RetroXCore/Launching/ProcessExitMonitor.swift @@ -0,0 +1,22 @@ +import Foundation + +enum ProcessExitMonitor { + /// Avisa quando um processo qualquer termina, mesmo que não seja filho do RetroX (kqueue via Dispatch). + /// Não depende de run loop, então funciona também na CLI de diagnóstico. + static func exits(of pid: pid_t) -> AsyncStream { + AsyncStream { continuation in + let source = DispatchSource.makeProcessSource(identifier: pid, eventMask: .exit, queue: .global(qos: .utility)) + source.setEventHandler { + continuation.yield(ProcessExit(status: nil, endedAt: Date())) + continuation.finish() + } + continuation.onTermination = { _ in source.cancel() } + source.resume() + // Se o processo terminou antes de o monitor existir, o evento nunca chega. + if kill(pid, 0) == -1, errno == ESRCH { + continuation.yield(ProcessExit(status: nil, endedAt: Date())) + continuation.finish() + } + } + } +} diff --git a/Sources/RetroXCore/Launching/WorkspaceLauncher.swift b/Sources/RetroXCore/Launching/WorkspaceLauncher.swift new file mode 100644 index 0000000..6a9ed36 --- /dev/null +++ b/Sources/RetroXCore/Launching/WorkspaceLauncher.swift @@ -0,0 +1,23 @@ +import AppKit + +/// Abre o emulador pelo LaunchServices. Os argumentos só chegam se o app ainda não estiver aberto +/// e se o RetroX não estiver em sandbox (doc de `NSWorkspace.OpenConfiguration.arguments`). +public struct WorkspaceLauncher: ProcessLaunching { + public init() {} + + public func launch(_ plan: LaunchPlan) async throws(LaunchError) -> LaunchedProcess { + let configuration = NSWorkspace.OpenConfiguration() + configuration.arguments = plan.arguments + configuration.activates = plan.activates + configuration.createsNewApplicationInstance = plan.createsNewInstance + configuration.addsToRecentItems = false + + let pid: pid_t + do { + pid = try await NSWorkspace.shared.openApplication(at: plan.appURL, configuration: configuration).processIdentifier + } catch { + throw .launchFailed(error.localizedDescription) + } + return LaunchedProcess(pid: pid, launchedAt: Date(), plan: plan, exits: ProcessExitMonitor.exits(of: pid)) + } +} diff --git a/Sources/RetroXCore/Support/Log.swift b/Sources/RetroXCore/Support/Log.swift new file mode 100644 index 0000000..018df89 --- /dev/null +++ b/Sources/RetroXCore/Support/Log.swift @@ -0,0 +1,9 @@ +import os + +/// Caminhos e argumentos são sempre registrados como `.private` (ADR-0009). +enum Log { + static let subsystem = "local.retrox.RetroX" + static let launch = Logger(subsystem: subsystem, category: "launch") + /// Intervalo do North Star do PRD: do Play até o processo do emulador existir. + static let launchSignposter = OSSignposter(subsystem: subsystem, category: "launch") +} diff --git a/Sources/RetroXCore/Support/RunningApplications.swift b/Sources/RetroXCore/Support/RunningApplications.swift new file mode 100644 index 0000000..1024ab0 --- /dev/null +++ b/Sources/RetroXCore/Support/RunningApplications.swift @@ -0,0 +1,23 @@ +import AppKit + +public protocol RunningApplicationsProviding: Sendable { + func isRunning(bundleIdentifier: String) -> Bool + @discardableResult + func activate(bundleIdentifier: String) -> Bool +} + +public struct WorkspaceRunningApplications: RunningApplicationsProviding { + public init() {} + + public func isRunning(bundleIdentifier: String) -> Bool { + NSRunningApplication.runningApplications(withBundleIdentifier: bundleIdentifier).contains { !$0.isTerminated } + } + + @discardableResult + public func activate(bundleIdentifier: String) -> Bool { + guard let app = NSRunningApplication.runningApplications(withBundleIdentifier: bundleIdentifier) + .first(where: { !$0.isTerminated }) + else { return false } + return app.activate() + } +} diff --git a/Tests/RetroXCoreTests/GameLauncherTests.swift b/Tests/RetroXCoreTests/GameLauncherTests.swift new file mode 100644 index 0000000..b245e89 --- /dev/null +++ b/Tests/RetroXCoreTests/GameLauncherTests.swift @@ -0,0 +1,160 @@ +import Foundation +import Testing +@testable import RetroXCore + +struct GameLauncherPrepareTests { + @Test("Monta o plano do PCSX2 e avisa que roda via Rosetta") + func preparesPlan() throws { + let scenario = LaunchScenario() + let prepared = try scenario.launcher().prepare(scenario.request) + #expect(prepared.plan.arguments == ["-batch", "--", scenario.romPath]) + #expect(prepared.plan.executableURL.path(percentEncoded: false) == "/Apps/PCSX2.app/Contents/MacOS/PCSX2") + #expect(prepared.plan.bundleIdentifier == "net.pcsx2.pcsx2") + #expect(prepared.plan.strategy == .workspace) + #expect(prepared.plan.activates) + #expect(!prepared.plan.createsNewInstance) + #expect(prepared.warnings == [.runsUnderRosetta]) + } + + @Test("Estratégia do perfil prevalece sobre a do adapter") + func profileStrategyWins() throws { + var scenario = LaunchScenario() + scenario.profile.strategy = .process + #expect(try scenario.launcher().prepare(scenario.request).plan.strategy == .process) + } + + @Test("Extensão em maiúsculas é aceita") + func uppercaseExtension() throws { + var scenario = LaunchScenario() + scenario.romPath = "/Jogos/GT4.ISO" + scenario.disk[scenario.romPath] = .file() + #expect(try scenario.launcher().prepare(scenario.request).plan.arguments.last == "/Jogos/GT4.ISO") + } + + @Test("Universal nativo não gera aviso") + func nativeUniversal() throws { + var scenario = LaunchScenario() + scenario.disk.addAppBundle(at: scenario.appPath, executable: "PCSX2", header: MachOSamples.universal) + #expect(try scenario.launcher().prepare(scenario.request).warnings.isEmpty) + } + + @Test("Bundle ID inesperado e arquitetura desconhecida viram avisos, não erros") + func softWarnings() throws { + var scenario = LaunchScenario() + scenario.disk.addAppBundle( + at: scenario.appPath, executable: "PCSX2", bundleIdentifier: "org.exemplo.outro", header: MachOSamples.shellScript + ) + let warnings = try scenario.launcher().prepare(scenario.request).warnings + #expect(warnings == [.unexpectedBundleIdentifier("org.exemplo.outro"), .unknownArchitecture]) + } + + @Test("Emulador já aberto: recusa por padrão") + func refusesWhenRunning() { + var scenario = LaunchScenario() + scenario.running.running = ["net.pcsx2.pcsx2"] + #expect(throws: LaunchError.emulatorAlreadyRunning(bundleID: "net.pcsx2.pcsx2")) { + try scenario.launcher().prepare(scenario.request) + } + } + + @Test("Emulador já aberto: nova instância só se pedida") + func newInstanceWhenAsked() throws { + var scenario = LaunchScenario() + scenario.running.running = ["net.pcsx2.pcsx2"] + var request = scenario.request + request.alreadyRunningPolicy = .launchNewInstance + #expect(try scenario.launcher().prepare(request).plan.createsNewInstance) + } + + @Test("Erros de ROM") + func romErrors() { + var scenario = LaunchScenario() + scenario.disk[scenario.romPath] = nil + #expect(throws: LaunchError.romNotFound) { try scenario.launcher().prepare(scenario.request) } + + scenario.disk[scenario.romPath] = .directory + #expect(throws: LaunchError.romIsDirectory) { try scenario.launcher().prepare(scenario.request) } + + scenario.disk[scenario.romPath] = .file(readable: false) + #expect(throws: LaunchError.romUnreadable) { try scenario.launcher().prepare(scenario.request) } + + scenario.romPath = "/Jogos/jogo.zip" + scenario.disk[scenario.romPath] = .file() + #expect(throws: LaunchError.unsupportedFormat("zip")) { try scenario.launcher().prepare(scenario.request) } + } + + @Test("Erros de emulador") + func emulatorErrors() { + var scenario = LaunchScenario() + scenario.profile.appURL = URL(filePath: "/Apps/Inexistente.app") + #expect(throws: LaunchError.emulatorNotFound) { try scenario.launcher().prepare(scenario.request) } + + scenario = LaunchScenario() + scenario.profile.adapterID = EmulatorAdapterID(rawValue: "desconhecido") + #expect(throws: LaunchError.emulatorNotConfigured(.ps2)) { try scenario.launcher().prepare(scenario.request) } + + scenario = LaunchScenario() + let wii = GameSystemID(rawValue: "wii") + var request = scenario.request + request.systemID = wii + #expect(throws: LaunchError.emulatorDoesNotSupportSystem(wii)) { try scenario.launcher().prepare(request) } + + scenario = LaunchScenario() + scenario.profile.extraArguments = ["-batch"] + #expect(throws: LaunchError.invalidExtraArgument("-batch")) { try scenario.launcher().prepare(scenario.request) } + } + + @Test("Arquitetura: sem Rosetta e Intel com app só arm64") + func architectureErrors() { + var scenario = LaunchScenario() + scenario.host.isRosettaInstalled = false + #expect(throws: LaunchError.architectureUnsupported(rosettaMissing: true)) { + try scenario.launcher().prepare(scenario.request) + } + + scenario = LaunchScenario() + scenario.host = HostEnvironment(architecture: .x86_64, isRosettaInstalled: false) + scenario.disk.addAppBundle(at: scenario.appPath, executable: "PCSX2", header: MachOSamples.thinARM64) + #expect(throws: LaunchError.architectureUnsupported(rosettaMissing: false)) { + try scenario.launcher().prepare(scenario.request) + } + } +} + +struct GameLauncherLaunchTests { + @Test("Entrega ao launcher exatamente o plano validado") + func launchesPreparedPlan() async throws { + let scenario = LaunchScenario() + let recording = RecordingLauncher() + let launcher = scenario.launcher(recording: recording) + let prepared = try launcher.prepare(scenario.request) + let launched = try await launcher.launch(prepared) + #expect(launched.pid == 4242) + #expect(await recording.plans == [prepared.plan]) + #expect(await launched.waitForExit()?.status == 0) + } + + @Test("Estratégia sem launcher registrado falha com mensagem") + func missingStrategy() async throws { + let scenario = LaunchScenario() + let launcher = GameLauncher( + fileSystem: scenario.disk, host: scenario.host, runningApplications: scenario.running, launchers: [:] + ) + let prepared = try launcher.prepare(scenario.request) + await #expect(throws: LaunchError.self) { try await launcher.launch(prepared) } + } +} + +struct SessionOutcomeTests { + let start = Date(timeIntervalSince1970: 1_000) + + @Test("Saída antes de 5 s é falha provável; depois é sessão normal") + func classifies() { + #expect(SessionOutcome.classify(launchedAt: start, exit: ProcessExit(status: 1, endedAt: start + 1.5)) + == .exitedEarly(status: 1, after: .milliseconds(1500))) + #expect(SessionOutcome.classify(launchedAt: start, exit: ProcessExit(status: nil, endedAt: start + 600)) + == .ended(after: .seconds(600))) + #expect(SessionOutcome.classify(launchedAt: start, exit: ProcessExit(status: 0, endedAt: start + 5)) + == .ended(after: .seconds(5))) + } +} diff --git a/Tests/RetroXCoreTests/Support/LaunchFakes.swift b/Tests/RetroXCoreTests/Support/LaunchFakes.swift new file mode 100644 index 0000000..073f6c4 --- /dev/null +++ b/Tests/RetroXCoreTests/Support/LaunchFakes.swift @@ -0,0 +1,67 @@ +import Foundation +@testable import RetroXCore + +struct FakeRunningApplications: RunningApplicationsProviding { + var running: Set = [] + + func isRunning(bundleIdentifier: String) -> Bool { + running.contains(bundleIdentifier) + } + + func activate(bundleIdentifier: String) -> Bool { + running.contains(bundleIdentifier) + } +} + +/// Não executa nada: guarda os planos recebidos e devolve um processo que já terminou. +actor RecordingLauncher: ProcessLaunching { + private(set) var plans: [LaunchPlan] = [] + let exit: ProcessExit + + init(exit: ProcessExit = ProcessExit(status: 0, endedAt: Date(timeIntervalSince1970: 60))) { + self.exit = exit + } + + func launch(_ plan: LaunchPlan) async throws(LaunchError) -> LaunchedProcess { + plans.append(plan) + let (exits, continuation) = AsyncStream.makeStream(of: ProcessExit.self) + continuation.yield(exit) + continuation.finish() + return LaunchedProcess(pid: 4242, launchedAt: Date(timeIntervalSince1970: 0), plan: plan, exits: exits) + } +} + +/// Cenário padrão: PCSX2 x86_64 em Apple Silicon com Rosetta, e uma ROM legível. +struct LaunchScenario { + var disk = FakeFileSystem() + var host = HostEnvironment(architecture: .arm64, isRosettaInstalled: true) + var running = FakeRunningApplications() + var romPath = "/Volumes/Jogos Ação/Test Drive Unlimited (USA).iso" + var appPath = "/Apps/PCSX2.app" + var profile: EmulatorProfile + + init() { + profile = EmulatorProfile( + name: "PCSX2", + adapterID: .pcsx2, + appURL: URL(filePath: appPath), + options: PCSX2Adapter().defaultOptions + ) + disk.addAppBundle(at: appPath, executable: "PCSX2") + disk[romPath] = .file() + } + + var request: LaunchRequest { + LaunchRequest(romURL: URL(filePath: romPath), systemID: .ps2, profile: profile) + } + + func launcher(recording: RecordingLauncher = RecordingLauncher()) -> GameLauncher { + GameLauncher( + registry: .standard, + fileSystem: disk, + host: host, + runningApplications: running, + launchers: [.workspace: recording, .process: recording] + ) + } +} From 123d7a2a876d99ebcaa576c832444fa1251a8b40 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Tue, 27 Oct 2026 23:51:54 -0300 Subject: [PATCH 05/56] =?UTF-8?q?test:=20integra=C3=A7=C3=A3o=20do=20launc?= =?UTF-8?q?h=20com=20emulador=20falso?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rx-fake-emulator grava o argv recebido em JSON e fica aberto 4 s. - LaunchIntegrationTests (opt-in via scripts/integration-launch.sh): argv chega byte a byte via NSWorkspace e via Process (pasta NFD, CJK, emoji, nome com hífen inicial e caracteres de shell); com o app já aberto, o LaunchServices reaproveita a instância e descarta os novos argumentos. - FoundationProcessLauncher para de esperar assim que o app registra. Co-Authored-By: Claude Opus 5.5 --- Package.swift | 5 ++ Sources/RXFakeEmulator/main.swift | 17 +++++ .../Launching/FoundationProcessLauncher.swift | 4 +- .../LaunchIntegrationTests.swift | 76 +++++++++++++++++++ .../Support/FakeEmulatorBundle.swift | 65 ++++++++++++++++ scripts/integration-launch.sh | 9 +++ 6 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 Sources/RXFakeEmulator/main.swift create mode 100644 Tests/RetroXCoreTests/LaunchIntegrationTests.swift create mode 100644 Tests/RetroXCoreTests/Support/FakeEmulatorBundle.swift create mode 100755 scripts/integration-launch.sh diff --git a/Package.swift b/Package.swift index 13d7653..de6f646 100644 --- a/Package.swift +++ b/Package.swift @@ -4,9 +4,14 @@ import PackageDescription let package = Package( name: "RetroX", platforms: [.macOS(.v14)], + products: [ + .executable(name: "rx-fake-emulator", targets: ["RXFakeEmulator"]), + ], targets: [ // Regras de negócio, sem SwiftUI e sem SwiftData: compila e testa só com as Command Line Tools. .target(name: "RetroXCore"), + // Ferramentas de desenvolvimento; não fazem parte do app distribuído. + .executableTarget(name: "RXFakeEmulator"), .testTarget(name: "RetroXCoreTests", dependencies: ["RetroXCore"]), ] ) diff --git a/Sources/RXFakeEmulator/main.swift b/Sources/RXFakeEmulator/main.swift new file mode 100644 index 0000000..a84a5b2 --- /dev/null +++ b/Sources/RXFakeEmulator/main.swift @@ -0,0 +1,17 @@ +import AppKit + +// Emulador falso para os testes de integração: grava o argv recebido em JSON ao lado do .app +// (`argv-.json`) e fica aberto alguns segundos, para os testes simularem "emulador já aberto". + +let outputURL = Bundle.main.bundleURL.deletingLastPathComponent().appending(path: "argv-\(getpid()).json") +do { + try JSONEncoder().encode(Array(CommandLine.arguments.dropFirst())).write(to: outputURL) +} catch { + FileHandle.standardError.write(Data("rx-fake-emulator: \(error)\n".utf8)) + exit(1) +} + +let app = NSApplication.shared +app.setActivationPolicy(.accessory) +DispatchQueue.main.asyncAfter(deadline: .now() + 4) { exit(0) } +app.run() diff --git a/Sources/RetroXCore/Launching/FoundationProcessLauncher.swift b/Sources/RetroXCore/Launching/FoundationProcessLauncher.swift index d17f3ea..bc74b95 100644 --- a/Sources/RetroXCore/Launching/FoundationProcessLauncher.swift +++ b/Sources/RetroXCore/Launching/FoundationProcessLauncher.swift @@ -46,8 +46,8 @@ public struct FoundationProcessLauncher: ProcessLaunching { /// Um processo iniciado por exec não é ativado pelo sistema; o app só aparece para o AppKit depois de registrar. private static func activateWhenRegistered(pid: pid_t) async { for _ in 0..<20 { - if let app = NSRunningApplication(processIdentifier: pid), app.activationPolicy == .regular { - app.activate() + if let app = NSRunningApplication(processIdentifier: pid) { + if app.activationPolicy == .regular { app.activate() } return } try? await Task.sleep(for: .milliseconds(150)) diff --git a/Tests/RetroXCoreTests/LaunchIntegrationTests.swift b/Tests/RetroXCoreTests/LaunchIntegrationTests.swift new file mode 100644 index 0000000..37ff79a --- /dev/null +++ b/Tests/RetroXCoreTests/LaunchIntegrationTests.swift @@ -0,0 +1,76 @@ +import Foundation +import Testing +@testable import RetroXCore + +/// Abre de verdade um emulador falso, pelo LaunchServices e por exec direto, e confere o argv recebido. +/// Opt-in: `scripts/integration-launch.sh`. Não toca em emuladores nem em ROMs reais. +@Suite(.serialized, .enabled(if: FakeEmulatorBundle.binaryURL != nil)) +struct LaunchIntegrationTests { + /// Pasta com NFD, acentos, CJK e emoji; arquivo começando com hífen e com caracteres de shell. + static let folder = "Jogos Ac\u{0327}a\u{0303}o ñ 日本 🎮" + static let file = "-Teste $(echo x); 'q' \"a\" (USA).iso" + + @Test("argv chega byte a byte", arguments: LaunchStrategy.allCases) + func argvArrivesIntact(strategy: LaunchStrategy) async throws { + let fixture = try FakeEmulatorBundle() + defer { fixture.remove() } + let romURL = try fixture.makeROM(named: Self.file, inFolder: Self.folder) + + let launcher = GameLauncher() + let prepared = try launcher.prepare(request(romURL: romURL, appURL: fixture.appURL, strategy: strategy)) + #expect(prepared.warnings == [.unexpectedBundleIdentifier(FakeEmulatorBundle.bundleIdentifier)]) + + let launched = try await launcher.launch(prepared) + let received = try await fixture.waitForArguments(pid: launched.pid) + #expect(received.map { Array($0.utf8) } == prepared.plan.arguments.map { Array($0.utf8) }) + #expect(received.last.map { FileManager.default.fileExists(atPath: $0) } == true) + + let exit = await launched.waitForExit() + #expect(exit != nil) + if strategy == .process { + #expect(exit?.status == 0) + } + } + + @Test("Com o app aberto, o LaunchServices reaproveita a instância e não entrega os novos argumentos") + func workspaceReusesRunningInstance() async throws { + let fixture = try FakeEmulatorBundle() + defer { fixture.remove() } + let firstROM = try fixture.makeROM(named: "Primeiro.iso", inFolder: "roms") + let secondROM = try fixture.makeROM(named: "Segundo.iso", inFolder: "roms") + + let launcher = GameLauncher() + let first = try await launcher.launch(launcher.prepare(request(romURL: firstROM, appURL: fixture.appURL))) + _ = try await fixture.waitForArguments(pid: first.pid) + + // A validação já recusa o segundo launch... + #expect(throws: LaunchError.emulatorAlreadyRunning(bundleID: FakeEmulatorBundle.bundleIdentifier)) { + try launcher.prepare(request(romURL: secondROM, appURL: fixture.appURL)) + } + + // ...e este é o motivo: sem nova instância, o sistema só ativa o app que já está aberto. + let firstPlan = first.plan + let secondPlan = LaunchPlan( + appURL: firstPlan.appURL, + executableURL: firstPlan.executableURL, + bundleIdentifier: firstPlan.bundleIdentifier, + arguments: ["-batch", "--", secondROM.path(percentEncoded: false)], + strategy: .workspace, + activates: true, + createsNewInstance: false + ) + let second = try await WorkspaceLauncher().launch(secondPlan) + #expect(second.pid == first.pid) + try await Task.sleep(for: .seconds(1)) + #expect(try fixture.argumentFiles().count == 1) + + _ = await first.waitForExit() + } + + private func request(romURL: URL, appURL: URL, strategy: LaunchStrategy = .workspace) -> LaunchRequest { + let profile = EmulatorProfile( + name: "Fake", adapterID: .pcsx2, appURL: appURL, options: PCSX2Adapter().defaultOptions, strategy: strategy + ) + return LaunchRequest(romURL: romURL, systemID: .ps2, profile: profile) + } +} diff --git a/Tests/RetroXCoreTests/Support/FakeEmulatorBundle.swift b/Tests/RetroXCoreTests/Support/FakeEmulatorBundle.swift new file mode 100644 index 0000000..a21254e --- /dev/null +++ b/Tests/RetroXCoreTests/Support/FakeEmulatorBundle.swift @@ -0,0 +1,65 @@ +import Foundation + +/// Monta `FakeEmulator.app` num diretório temporário a partir do binário `rx-fake-emulator`. +/// O caminho do binário vem de `RX_FAKE_EMULATOR_BIN` (definido por `scripts/integration-launch.sh`). +struct FakeEmulatorBundle { + static let bundleIdentifier = "local.retrox.fake-emulator" + + static var binaryURL: URL? { + ProcessInfo.processInfo.environment["RX_FAKE_EMULATOR_BIN"].map { URL(filePath: $0) } + } + + let root: URL + let appURL: URL + + init() throws { + guard let binaryURL = Self.binaryURL else { throw CocoaError(.fileNoSuchFile) } + root = FileManager.default.temporaryDirectory + .appending(path: "RetroXIntegration-\(UUID().uuidString)", directoryHint: .isDirectory) + appURL = root.appending(path: "FakeEmulator.app", directoryHint: .isDirectory) + let macOSURL = appURL.appending(path: "Contents/MacOS", directoryHint: .isDirectory) + try FileManager.default.createDirectory(at: macOSURL, withIntermediateDirectories: true) + try FileManager.default.copyItem(at: binaryURL, to: macOSURL.appending(path: "FakeEmulator")) + let plist: [String: Any] = [ + "CFBundleExecutable": "FakeEmulator", + "CFBundleIdentifier": Self.bundleIdentifier, + "CFBundleName": "FakeEmulator", + "CFBundlePackageType": "APPL", + "LSUIElement": true, + ] + try PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0) + .write(to: appURL.appending(path: "Contents/Info.plist")) + } + + /// Cria um arquivo vazio com a extensão certa: o emulador falso não lê o conteúdo. + func makeROM(named name: String, inFolder folder: String) throws -> URL { + let folderURL = root.appending(path: folder, directoryHint: .isDirectory) + try FileManager.default.createDirectory(at: folderURL, withIntermediateDirectories: true) + let romURL = folderURL.appending(path: name, directoryHint: .notDirectory) + guard FileManager.default.createFile(atPath: romURL.path(percentEncoded: false), contents: Data()) else { + throw CocoaError(.fileWriteUnknown) + } + return romURL + } + + func argumentFiles() throws -> [URL] { + try FileManager.default.contentsOfDirectory(at: root, includingPropertiesForKeys: nil) + .filter { $0.lastPathComponent.hasPrefix("argv-") } + } + + func waitForArguments(pid: pid_t, timeout: Duration = .seconds(15)) async throws -> [String] { + let fileURL = root.appending(path: "argv-\(pid).json") + let deadline = ContinuousClock.now + timeout + while ContinuousClock.now < deadline { + if let data = try? Data(contentsOf: fileURL) { + return try JSONDecoder().decode([String].self, from: data) + } + try await Task.sleep(for: .milliseconds(100)) + } + throw CocoaError(.fileReadNoSuchFile) + } + + func remove() { + try? FileManager.default.removeItem(at: root) + } +} diff --git a/scripts/integration-launch.sh b/scripts/integration-launch.sh new file mode 100755 index 0000000..d64bb09 --- /dev/null +++ b/scripts/integration-launch.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Testes de integração do launch com um emulador falso (rx-fake-emulator), aberto de verdade +# pelo LaunchServices e por exec direto. Não toca em emuladores nem em ROMs reais. +set -euo pipefail +cd "$(dirname "$0")/.." + +swift build --product rx-fake-emulator +bin_dir="$(swift build --show-bin-path)" +RX_FAKE_EMULATOR_BIN="$bin_dir/rx-fake-emulator" exec scripts/test.sh --filter LaunchIntegrationTests "$@" From bcc5ac3fa99921a5507e736b64eda21ce8ce36d8 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Tue, 27 Oct 2026 23:53:20 -0300 Subject: [PATCH 06/56] feat(tools): rx-launch-probe para o spike de launch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CLI que usa o mesmo GameLauncher do app: valida, mostra emulador, avisos, estratégia e argv (JSON) e, sem --dry-run, abre o emulador e opcionalmente espera o término (--wait) para classificar a sessão. Co-Authored-By: Claude Opus 5.5 --- Package.swift | 2 + Sources/RXLaunchProbe/main.swift | 127 +++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 Sources/RXLaunchProbe/main.swift diff --git a/Package.swift b/Package.swift index de6f646..4ea49fc 100644 --- a/Package.swift +++ b/Package.swift @@ -5,12 +5,14 @@ let package = Package( name: "RetroX", platforms: [.macOS(.v14)], products: [ + .executable(name: "rx-launch-probe", targets: ["RXLaunchProbe"]), .executable(name: "rx-fake-emulator", targets: ["RXFakeEmulator"]), ], targets: [ // Regras de negócio, sem SwiftUI e sem SwiftData: compila e testa só com as Command Line Tools. .target(name: "RetroXCore"), // Ferramentas de desenvolvimento; não fazem parte do app distribuído. + .executableTarget(name: "RXLaunchProbe", dependencies: ["RetroXCore"]), .executableTarget(name: "RXFakeEmulator"), .testTarget(name: "RetroXCoreTests", dependencies: ["RetroXCore"]), ] diff --git a/Sources/RXLaunchProbe/main.swift b/Sources/RXLaunchProbe/main.swift new file mode 100644 index 0000000..b7694a7 --- /dev/null +++ b/Sources/RXLaunchProbe/main.swift @@ -0,0 +1,127 @@ +import Foundation +import RetroXCore + +// Ferramenta de diagnóstico do spike de launch: usa o mesmo GameLauncher do app, +// mostra o plano validado e, sem --dry-run, abre o emulador. + +let usage = """ + uso: rx-launch-probe --app --rom [opções] + + --strategy workspace|process como criar o processo (padrão: o do adapter) + --dry-run só valida e mostra o argv, sem abrir nada + --new-instance abre outra instância mesmo com o emulador aberto + --fullscreen on|off força ou desliga a tela cheia (padrão: config do emulador) + --no-batch não passa -batch (o emulador não fecha ao parar o jogo) + --log grava stdout/stderr do emulador (só com --strategy process) + --wait espera o emulador fechar e informa como a sessão terminou + """ + +func fail(_ message: String, code: Int32 = 64) -> Never { + FileHandle.standardError.write(Data("\(message)\n".utf8)) + exit(code) +} + +var appPath: String? +var romPath: String? +var strategy: LaunchStrategy? +var dryRun = false +var newInstance = false +var waitSeconds: Int? +var logPath: String? +var pcsx2 = PCSX2Options() + +var input = CommandLine.arguments.dropFirst().makeIterator() +@MainActor func value(for flag: String) -> String { + guard let next = input.next() else { fail("\(flag) precisa de um valor.\n\n\(usage)") } + return next +} +while let flag = input.next() { + switch flag { + case "--app": appPath = value(for: flag) + case "--rom": romPath = value(for: flag) + case "--strategy": + guard let parsed = LaunchStrategy(rawValue: value(for: flag)) else { fail("Estratégia inválida.\n\n\(usage)") } + strategy = parsed + case "--dry-run": dryRun = true + case "--new-instance": newInstance = true + case "--fullscreen": + switch value(for: flag) { + case "on": pcsx2.fullscreen = .on + case "off": pcsx2.fullscreen = .off + default: fail("--fullscreen aceita on ou off.") + } + case "--no-batch": pcsx2.batch = false + case "--log": logPath = value(for: flag) + case "--wait": + guard let seconds = Int(value(for: flag)), seconds > 0 else { fail("--wait precisa de segundos > 0.") } + waitSeconds = seconds + case "-h", "--help": print(usage); exit(0) + default: fail("Opção desconhecida: \(flag)\n\n\(usage)") + } +} +guard let appPath, let romPath else { fail(usage) } + +let profile = EmulatorProfile( + name: "PCSX2", + adapterID: .pcsx2, + appURL: URL(filePath: appPath), + options: .pcsx2(pcsx2), + strategy: strategy +) +let request = LaunchRequest( + romURL: URL(filePath: romPath), + systemID: .ps2, + profile: profile, + alreadyRunningPolicy: newInstance ? .launchNewInstance : .refuse +) +let launcher = GameLauncher(launchers: [ + .workspace: WorkspaceLauncher(), + .process: FoundationProcessLauncher(outputLogURL: logPath.map { URL(filePath: $0) }), +]) + +do { + let prepared = try launcher.prepare(request) + let app = prepared.app + let architectures = app.architectures.map(\.description).sorted().joined(separator: ", ") + print("emulador: \(app.bundleIdentifier ?? "?") \(app.version ?? "?") [\(architectures)]") + print("executável: \(prepared.plan.executableURL.path(percentEncoded: false))") + for warning in prepared.warnings { + print("aviso: \(warning.message)") + } + print("estratégia: \(prepared.plan.strategy.rawValue)") + let encoder = JSONEncoder() + encoder.outputFormatting = .withoutEscapingSlashes + print("argv: \(String(decoding: try! encoder.encode(prepared.plan.arguments), as: UTF8.self))") + if dryRun { + print("modo simulado: nada foi aberto.") + exit(0) + } + + let launched = try await launcher.launch(prepared) + print("pid: \(launched.pid)") + guard let waitSeconds else { exit(0) } + + let exit = await withTaskGroup(of: ProcessExit?.self) { group in + group.addTask { await launched.waitForExit() } + group.addTask { + try? await Task.sleep(for: .seconds(waitSeconds)) + return nil + } + let first = await group.next() ?? nil + group.cancelAll() + return first + } + guard let exit else { + print("o emulador continua aberto após \(waitSeconds) s.") + Foundation.exit(0) + } + let status = exit.status.map(String.init) ?? "n/d" + switch SessionOutcome.classify(launchedAt: launched.launchedAt, exit: exit) { + case .ended(let after): + print("término: sessão normal após \(after.formatted(.units(allowed: [.minutes, .seconds]))) (status \(status))") + case .exitedEarly(_, let after): + print("término: fechou cedo, após \(after.formatted(.units(allowed: [.seconds], fractionalPart: .show(length: 1)))) (status \(status))") + } +} catch { + fail("erro: \(error.message)\nações: \(error.recoveryActions.map(\.title).joined(separator: ", "))", code: 1) +} From 8f6d714782e3287187a3c7caf96f1524e7ca30e0 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Tue, 27 Oct 2026 23:55:39 -0300 Subject: [PATCH 07/56] =?UTF-8?q?feat(app):=20janela=20m=C3=ADnima=20de=20?= =?UTF-8?q?launch=20com=20modo=20simulado?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LaunchViewModel (@Observable, @MainActor): escolhe emulador e ROM, valida, mostra o plano no modo simulado ou abre o emulador e volta à frente quando ele fecha; erros vêm com ações de correção. - LaunchView em Form agrupado, Return joga, anúncios para VoiceOver. - Sem @State: no SDK 27 ele é macro e as CLT não têm o plugin SwiftUIMacros (registrado no ADR-0010). Co-Authored-By: Claude Opus 5.5 --- Package.swift | 2 + .../Features/Launch/LaunchView.swift | 193 ++++++++++++++++++ .../Features/Launch/LaunchViewModel.swift | 133 ++++++++++++ Sources/RetroXApp/RetroXApp.swift | 20 ++ docs/adr/0010-build-swiftpm-first.md | 1 + 5 files changed, 349 insertions(+) create mode 100644 Sources/RetroXApp/Features/Launch/LaunchView.swift create mode 100644 Sources/RetroXApp/Features/Launch/LaunchViewModel.swift create mode 100644 Sources/RetroXApp/RetroXApp.swift diff --git a/Package.swift b/Package.swift index 4ea49fc..f5499d5 100644 --- a/Package.swift +++ b/Package.swift @@ -5,12 +5,14 @@ let package = Package( name: "RetroX", platforms: [.macOS(.v14)], products: [ + .executable(name: "RetroX", targets: ["RetroXApp"]), .executable(name: "rx-launch-probe", targets: ["RXLaunchProbe"]), .executable(name: "rx-fake-emulator", targets: ["RXFakeEmulator"]), ], targets: [ // Regras de negócio, sem SwiftUI e sem SwiftData: compila e testa só com as Command Line Tools. .target(name: "RetroXCore"), + .executableTarget(name: "RetroXApp", dependencies: ["RetroXCore"]), // Ferramentas de desenvolvimento; não fazem parte do app distribuído. .executableTarget(name: "RXLaunchProbe", dependencies: ["RetroXCore"]), .executableTarget(name: "RXFakeEmulator"), diff --git a/Sources/RetroXApp/Features/Launch/LaunchView.swift b/Sources/RetroXApp/Features/Launch/LaunchView.swift new file mode 100644 index 0000000..06c7b5d --- /dev/null +++ b/Sources/RetroXApp/Features/Launch/LaunchView.swift @@ -0,0 +1,193 @@ +import RetroXCore +import SwiftUI +import UniformTypeIdentifiers + +struct LaunchView: View { + @Bindable var model: LaunchViewModel + + var body: some View { + Form { + Section { + emulatorRow + } header: { + Text("Emulador") + } footer: { + emulatorFooter + } + + Section("Jogo") { + romRow + } + + Section { + Toggle("Modo simulado", isOn: $model.isDryRun) + .help("Valida e mostra o comando que seria usado, sem abrir o emulador.") + HStack { + Spacer() + Button("Jogar") { + Task { await model.play() } + } + .keyboardShortcut(.defaultAction) + .controlSize(.large) + .disabled(!model.canPlay) + } + } + + if model.status != .idle { + Section("Status") { + StatusPanel(model: model, onRecovery: perform) + } + } + } + .formStyle(.grouped) + .frame(minWidth: 560, minHeight: 480) + .fileImporter( + isPresented: Binding(get: { model.importer != nil }, set: { if !$0 { model.importer = nil } }), + allowedContentTypes: contentTypes + ) { result in + guard case .success(let url) = result else { return } + switch model.importer { + case .emulator: model.selectEmulator(url) + case .rom: model.selectROM(url) + case nil: break + } + model.importer = nil + } + .onChange(of: model.status) { _, status in + announce(status) + } + } + + private var emulatorRow: some View { + LabeledContent { + Button("Escolher…") { model.importer = .emulator } + } label: { + if let url = model.emulatorURL { + Text(url.deletingPathExtension().lastPathComponent) + Text(url.deletingLastPathComponent().path(percentEncoded: false)) + .truncationMode(.middle) + } else { + Text("Nenhum emulador escolhido") + Text("Escolha o PCSX2.app instalado neste Mac.") + } + } + } + + @ViewBuilder + private var emulatorFooter: some View { + if let error = model.emulatorError { + Label(error.message, systemImage: "exclamationmark.triangle") + .foregroundStyle(.red) + } else if let info = model.emulatorInfo { + let architectures = info.architectures.map(\.description).sorted().joined(separator: ", ") + Text("\(info.bundleIdentifier ?? "?") · versão \(info.version ?? "?") · \(architectures.isEmpty ? "arquitetura desconhecida" : architectures)") + } + } + + private var romRow: some View { + LabeledContent { + Button("Escolher…") { model.importer = .rom } + } label: { + if let url = model.romURL { + Text(TitleParser.displayTitle(fromFilename: url.lastPathComponent)) + Text(url.lastPathComponent) + .truncationMode(.middle) + } else { + Text("Nenhum jogo escolhido") + Text("Formatos: \(model.adapter.supportedExtensions(for: .ps2).sorted().joined(separator: ", "))") + } + } + } + + private var contentTypes: [UTType] { + switch model.importer { + case .emulator: + [.applicationBundle] + case .rom, nil: + model.adapter.supportedExtensions(for: .ps2).sorted().compactMap { UTType(filenameExtension: $0) } + } + } + + private func perform(_ action: RecoveryAction) { + switch action { + case .chooseEmulator, .openSettings: model.importer = .emulator + case .locateROM: model.importer = .rom + case .retry: Task { await model.play() } + case .bringEmulatorToFront: model.bringEmulatorToFront() + case .showRosettaHelp: break + } + } + + private func announce(_ status: LaunchViewModel.Status) { + let message: String? = switch status { + case .failed(let error): error.message + case .running: String(localized: "Jogo aberto no emulador.") + case .ended: String(localized: "Sessão encerrada.") + default: nil + } + if let message { + AccessibilityNotification.Announcement(message).post() + } + } +} + +private struct StatusPanel: View { + let model: LaunchViewModel + let onRecovery: (RecoveryAction) -> Void + + var body: some View { + VStack(alignment: .leading, spacing: 10) { + ForEach(model.warnings, id: \.message) { warning in + Label(warning.message, systemImage: "info.circle") + .foregroundStyle(.secondary) + } + content + } + .frame(maxWidth: .infinity, alignment: .leading) + } + + @ViewBuilder + private var content: some View { + switch model.status { + case .idle: + EmptyView() + case .planned(let plan): + Label("Modo simulado: nada foi aberto.", systemImage: "eye") + Text("Estratégia: \(plan.strategy.rawValue)") + .foregroundStyle(.secondary) + VStack(alignment: .leading, spacing: 2) { + ForEach(Array(plan.arguments.enumerated()), id: \.offset) { index, argument in + Text("[\(index)] \(argument)") + } + } + .font(.system(.body, design: .monospaced)) + .textSelection(.enabled) + .accessibilityElement(children: .combine) + .accessibilityLabel("Argumentos: \(plan.arguments.joined(separator: ", "))") + case .launching: + HStack { + ProgressView().controlSize(.small) + Text("Abrindo no PCSX2…") + } + case .running: + Label("Em jogo no PCSX2. O RetroX volta à frente quando o emulador fechar.", systemImage: "gamecontroller") + Button("Trazer emulador para frente") { onRecovery(.bringEmulatorToFront) } + case .ended(let after): + Label("Sessão encerrada após \(after.formatted(.units(allowed: [.hours, .minutes, .seconds], width: .wide))).", + systemImage: "checkmark.circle") + case .failed(let error): + Label(error.message, systemImage: "exclamationmark.triangle") + .foregroundStyle(.red) + if error.recoveryActions.contains(.showRosettaHelp) { + Text("No Terminal: softwareupdate --install-rosetta") + .font(.system(.body, design: .monospaced)) + .textSelection(.enabled) + } + HStack { + ForEach(error.recoveryActions.filter { $0 != .showRosettaHelp }, id: \.self) { action in + Button(action.title) { onRecovery(action) } + } + } + } + } +} diff --git a/Sources/RetroXApp/Features/Launch/LaunchViewModel.swift b/Sources/RetroXApp/Features/Launch/LaunchViewModel.swift new file mode 100644 index 0000000..ae3c72d --- /dev/null +++ b/Sources/RetroXApp/Features/Launch/LaunchViewModel.swift @@ -0,0 +1,133 @@ +import AppKit +import RetroXCore + +/// Estado da tela de prova técnica: um emulador, uma ROM e o botão Jogar. +/// Sem persistência de biblioteca nesta fase; só lembra os dois últimos caminhos. +@MainActor +@Observable +final class LaunchViewModel { + enum Status: Equatable { + case idle + /// Modo simulado: o plano validado, sem abrir nada. + case planned(LaunchPlan) + case launching + case running(bundleIdentifier: String?) + case ended(after: Duration) + case failed(LaunchError) + } + + enum Importer { + case emulator, rom + } + + private(set) var emulatorURL: URL? + private(set) var emulatorInfo: AppBundleInfo? + private(set) var emulatorError: LaunchError? + private(set) var romURL: URL? + private(set) var warnings: [LaunchWarning] = [] + private(set) var status: Status = .idle + var isDryRun = false + /// Qual seletor de arquivo está aberto. Fica aqui, e não em `@State`, porque no SDK 27 `@State` + /// é uma macro que as Command Line Tools não trazem (ADR-0010). + var importer: Importer? + + let adapter = PCSX2Adapter() + + private let launcher: GameLauncher + private let inspector: AppBundleInspector + private let runningApplications: any RunningApplicationsProviding + private let defaults: UserDefaults + private let bringSelfToFront: @MainActor () -> Void + + private enum DefaultsKey { + static let emulatorPath = "launch.emulatorPath" + static let romPath = "launch.romPath" + } + + init( + launcher: GameLauncher = GameLauncher(), + inspector: AppBundleInspector = AppBundleInspector(), + runningApplications: any RunningApplicationsProviding = WorkspaceRunningApplications(), + defaults: UserDefaults = .standard, + bringSelfToFront: @escaping @MainActor () -> Void = { NSApplication.shared.activate() } + ) { + self.launcher = launcher + self.inspector = inspector + self.runningApplications = runningApplications + self.defaults = defaults + self.bringSelfToFront = bringSelfToFront + if let path = defaults.string(forKey: DefaultsKey.emulatorPath) { + selectEmulator(URL(filePath: path)) + } + romURL = defaults.string(forKey: DefaultsKey.romPath).map { URL(filePath: $0) } + } + + var isBusy: Bool { + switch status { + case .launching, .running: true + default: false + } + } + + var canPlay: Bool { emulatorURL != nil && romURL != nil && !isBusy } + + func selectEmulator(_ url: URL) { + emulatorURL = url + defaults.set(url.path(percentEncoded: false), forKey: DefaultsKey.emulatorPath) + do { + emulatorInfo = try inspector.inspect(url) + emulatorError = nil + } catch { + emulatorInfo = nil + emulatorError = error + } + if !isBusy { status = .idle } + } + + func selectROM(_ url: URL) { + romURL = url + defaults.set(url.path(percentEncoded: false), forKey: DefaultsKey.romPath) + if !isBusy { status = .idle } + } + + func play() async { + guard let emulatorURL, let romURL, !isBusy else { return } + let profile = EmulatorProfile( + name: adapter.displayName, + adapterID: adapter.id, + appURL: emulatorURL, + options: adapter.defaultOptions + ) + let request = LaunchRequest(romURL: romURL, systemID: .ps2, profile: profile) + do { + let prepared = try launcher.prepare(request) + warnings = prepared.warnings + if isDryRun { + status = .planned(prepared.plan) + return + } + status = .launching + let launched = try await launcher.launch(prepared) + status = .running(bundleIdentifier: launched.plan.bundleIdentifier) + guard let exit = await launched.waitForExit() else { return } + switch SessionOutcome.classify(launchedAt: launched.launchedAt, exit: exit) { + case .ended(let after): status = .ended(after: after) + case .exitedEarly(let code, let after): status = .failed(.exitedEarly(status: code, after: after)) + } + bringSelfToFront() + } catch { + status = .failed(error) + } + } + + func bringEmulatorToFront() { + let bundleID: String? = switch status { + case .running(let id): id + case .failed(.emulatorAlreadyRunning(let id)): id + default: emulatorInfo?.bundleIdentifier + } + if let bundleID { + runningApplications.activate(bundleIdentifier: bundleID) + } + } +} diff --git a/Sources/RetroXApp/RetroXApp.swift b/Sources/RetroXApp/RetroXApp.swift new file mode 100644 index 0000000..b382471 --- /dev/null +++ b/Sources/RetroXApp/RetroXApp.swift @@ -0,0 +1,20 @@ +import AppKit +import SwiftUI + +@main +struct RetroXApp: App { + // Constante em vez de `@State`: ver o comentário em `LaunchViewModel.importer`. + private let model = LaunchViewModel() + + init() { + // Rodando fora de um .app (swift run), o processo nasceria sem ícone no Dock nem foco. + NSApplication.shared.setActivationPolicy(.regular) + } + + var body: some Scene { + Window("RetroX", id: "main") { + LaunchView(model: model) + } + .windowResizability(.contentMinSize) + } +} diff --git a/docs/adr/0010-build-swiftpm-first.md b/docs/adr/0010-build-swiftpm-first.md index bf8ad85..ff91455 100644 --- a/docs/adr/0010-build-swiftpm-first.md +++ b/docs/adr/0010-build-swiftpm-first.md @@ -21,6 +21,7 @@ O núcleo é testável sem Xcode e o repositório não carrega um `.xcodeproj` d Peculiaridades das CLT encontradas na Sprint 1 (Swift 6.4, backend `swiftbuild`): - A descoberta do plugin de macros do Swift Testing é intermitente (2 falhas em 3 builds limpos). Os testes rodam por `scripts/test.sh`, que passa `-plugin-path` explicitamente quando o toolchain ativo é o das CLT. - O backend antigo (`--build-system native`) não encontra o módulo `Testing` nas CLT. +- No SDK do macOS 27, o `@State` do SwiftUI é uma macro (`SwiftUIMacros.StateMacro`), e as CLT não trazem o plugin `SwiftUIMacros` (no SDK 26.5 ainda era property wrapper). `@Observable` e `@Bindable` funcionam. Até o Xcode ser instalado, a UI evita `@State`: o estado de tela fica no view model `@Observable`. Isso reforça que as Fases 2 e 3 dependem do Xcode. ## Alternativas `.xcodeproj` escrito à mão sem Xcode (frágil); Tuist ou XcodeGen desde já (ferramenta externa sem necessidade imediata); esperar o Xcode para começar (atrasa a prova técnica do launch, que não depende dele). From deb10c7d09c5092765f98799469e1651a6da8876 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Tue, 27 Oct 2026 23:55:39 -0300 Subject: [PATCH 08/56] build: monta RetroX.app a partir do SwiftPM com assinatura ad hoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support/Info.plist (macOS 14, bundle ID provisório local.retrox.RetroX) e scripts/bundle-app.sh [debug|release]. Co-Authored-By: Claude Opus 5.5 --- Support/Info.plist | 33 +++++++++++++++++++++++++++++++++ scripts/bundle-app.sh | 23 +++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 Support/Info.plist create mode 100755 scripts/bundle-app.sh diff --git a/Support/Info.plist b/Support/Info.plist new file mode 100644 index 0000000..01a37c8 --- /dev/null +++ b/Support/Info.plist @@ -0,0 +1,33 @@ + + + + + CFBundleDevelopmentRegion + pt-BR + CFBundleDisplayName + RetroX + CFBundleExecutable + RetroX + CFBundleIdentifier + + local.retrox.RetroX + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + RetroX + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.1.0 + CFBundleVersion + 1 + LSApplicationCategoryType + public.app-category.games + LSMinimumSystemVersion + 14.0 + NSHighResolutionCapable + + NSPrincipalClass + NSApplication + + diff --git a/scripts/bundle-app.sh b/scripts/bundle-app.sh new file mode 100755 index 0000000..13db130 --- /dev/null +++ b/scripts/bundle-app.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Monta .build/RetroX.app a partir do executável do SwiftPM e assina ad hoc (ADR-0010). +# Uso: scripts/bundle-app.sh [debug|release] +set -euo pipefail +cd "$(dirname "$0")/.." + +configuration="${1:-debug}" +case "$configuration" in + debug|release) ;; + *) echo "uso: $0 [debug|release]" >&2; exit 64 ;; +esac + +swift build -c "$configuration" --product RetroX +bin_dir="$(swift build -c "$configuration" --show-bin-path)" + +app=".build/RetroX.app" +rm -rf "$app" +mkdir -p "$app/Contents/MacOS" +cp "$bin_dir/RetroX" "$app/Contents/MacOS/RetroX" +cp Support/Info.plist "$app/Contents/Info.plist" +codesign --force --sign - "$app" + +echo "$app" From 1ffb6a88fc9359a86ab583f66a9cdaaa70fab244 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 00:00:34 -0300 Subject: [PATCH 09/56] =?UTF-8?q?fix(tools):=20sa=C3=ADda=20por=20linha=20?= =?UTF-8?q?no=20rx-launch-probe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Redirecionada para arquivo, a saída só era gravada no fim, e scripts não conseguiam ler o "pid:" enquanto o emulador rodava. Co-Authored-By: Claude Opus 5.5 --- Sources/RXLaunchProbe/main.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sources/RXLaunchProbe/main.swift b/Sources/RXLaunchProbe/main.swift index b7694a7..f62a9f8 100644 --- a/Sources/RXLaunchProbe/main.swift +++ b/Sources/RXLaunchProbe/main.swift @@ -4,6 +4,9 @@ import RetroXCore // Ferramenta de diagnóstico do spike de launch: usa o mesmo GameLauncher do app, // mostra o plano validado e, sem --dry-run, abre o emulador. +// Saída por linha mesmo redirecionada para arquivo: scripts leem o "pid:" enquanto o emulador roda. +setvbuf(stdout, nil, _IOLBF, 0) + let usage = """ uso: rx-launch-probe --app --rom [opções] From 5c6f7c88c12de80b9687ec82d43b2d98344edc35 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 00:00:34 -0300 Subject: [PATCH 10/56] =?UTF-8?q?docs:=20spike=200001=20(PCSX2=20real)=20e?= =?UTF-8?q?=20ADR-0011=20de=20estrat=C3=A9gia=20de=20launch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Três launches reais do PCSX2 2.9.144 (NSWorkspace e Process; espaços, NFD/CJK/emoji, hífen inicial, NFC): o caminho no log do emulador é idêntico ao argv byte a byte e o jogo inicia. Pasta de ROMs com stat idêntico antes/depois. ADR-0011: NSWorkspace por padrão, Process como alternativa, recusa quando o emulador já está aberto. README com os comandos de build, teste e diagnóstico. Co-Authored-By: Claude Opus 5.5 --- README.md | 19 ++++++++++++ docs/adr/0003-emulator-adapters.md | 2 +- docs/adr/0011-estrategia-de-launch.md | 27 ++++++++++++++++ docs/spikes/0001-launch-pcsx2-macos.md | 43 ++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 docs/adr/0011-estrategia-de-launch.md create mode 100644 docs/spikes/0001-launch-pcsx2-macos.md diff --git a/README.md b/README.md index 31d397c..294cc8f 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,25 @@ Launcher nativo para macOS que reúne numa biblioteca visual os jogos de vários - Para compilar: Swift 6 (Command Line Tools ou Xcode). A persistência (Fase 2 em diante) exige o Xcode. - Emuladores instalados pelo usuário. Hoje: PCSX2 (PS2). Dolphin (GameCube/Wii) está planejado. +## Compilar, testar e rodar + +```sh +scripts/check-toolchain.sh # o que o toolchain atual consegue (Xcode, SwiftData, Rosetta) +swift build # app, ferramentas e núcleo +scripts/test.sh # testes unitários (Swift Testing) +scripts/integration-launch.sh # abre um emulador falso de verdade e confere o argv +scripts/bundle-app.sh debug # monta .build/RetroX.app (assinatura ad hoc) +open .build/RetroX.app +``` + +Diagnóstico de launch sem a interface (o mesmo código do app): + +```sh +swift run rx-launch-probe --app /Applications/PCSX2.app --rom "/caminho/do/jogo.iso" --dry-run +``` + +Sem `--dry-run`, o emulador é aberto de verdade. + ## Documentação - [`docs/PRD.md`](docs/PRD.md): produto, escopo, requisitos e critérios de aceite. diff --git a/docs/adr/0003-emulator-adapters.md b/docs/adr/0003-emulator-adapters.md index 76b33d8..ad6e2ba 100644 --- a/docs/adr/0003-emulator-adapters.md +++ b/docs/adr/0003-emulator-adapters.md @@ -20,5 +20,5 @@ Um switch gigante por console (evolui mal); comando livre sem validação (arris ## Emenda (2026-10-27) - O adapter não executa nada: ele produz um `LaunchPlan` puro (app, executável, argumentos, estratégia). O plano é testável sem processo real e é o que o modo simulado exibe. -- A escolha entre `NSWorkspace` e `Process` por adapter será registrada no ADR-0011, com a evidência do spike `docs/spikes/0001-launch-pcsx2-macos.md`. +- A escolha entre `NSWorkspace` e `Process` está no ADR-0011 (NSWorkspace por padrão), com a evidência do spike `docs/spikes/0001-launch-pcsx2-macos.md`. - Política para emulador já aberto: o RetroX não encerra o emulador e não cria nova instância por padrão; oferece trazê-lo para frente. diff --git a/docs/adr/0011-estrategia-de-launch.md b/docs/adr/0011-estrategia-de-launch.md new file mode 100644 index 0000000..b0618fa --- /dev/null +++ b/docs/adr/0011-estrategia-de-launch.md @@ -0,0 +1,27 @@ +# ADR-0011 — Estratégia de launch: NSWorkspace por padrão, Process como alternativa + +**Status:** Aceito | **Data:** 2026-10-27 + +## Contexto +O ADR-0003 deixou para um spike a escolha entre `NSWorkspace.openApplication` e `Process` para abrir cada emulador. O spike `docs/spikes/0001-launch-pcsx2-macos.md` abriu o PCSX2 2.9.144 real com caminhos difíceis pelas duas estratégias e checou o resultado no log do próprio emulador. + +## Decisão +- **Padrão para emuladores com app (`.app`): `NSWorkspace`** (`WorkspaceLauncher`), com `arguments` = argv do adapter, `activates = true`, `createsNewApplicationInstance = false`, `addsToRecentItems = false`. +- **`Process`** (`FoundationProcessLauncher`) continua disponível por perfil (`EmulatorProfile.strategy`) para diagnóstico e para emuladores sem `.app`. stdout e stderr vão para `/dev/null` ou para um arquivo escolhido, nunca para um pipe sem leitor. +- O término é observado por kqueue (`DispatchSource` de processo), que funciona para as duas estratégias e não depende de run loop. Exit status só existe com `Process`. +- Emulador já aberto: a validação recusa o launch (`emulatorAlreadyRunning`) e oferece trazê-lo para frente. O RetroX não encerra o emulador nem abre outra instância por padrão. +- PCSX2: argv `["-batch", "--", ]`. A tela cheia segue a configuração do próprio emulador, a menos que o perfil force `-fullscreen` ou `-nofullscreen`. + +## Por quê +- As duas estratégias entregaram o argv byte a byte e abriram o jogo. O desempate vem do resto: + - Com `NSWorkspace`, o emulador é lançado pelo LaunchServices: ganha ativação e Dock normais, e responde pelos próprios prompts de privacidade (TCC). Com `Process`, ele vira filho do RetroX e esses prompts são atribuídos ao RetroX. + - A vantagem do `Process` (exit status e stdout) pesou pouco: o stdout do PCSX2 é quase vazio e o log útil fica no `emulog.txt` dele. +- A documentação da Apple e o teste com emulador falso mostram que, com o app já aberto, o LaunchServices descarta os novos argumentos. Daí a recusa explícita em vez de um launch que "não faz nada". + +## Consequências +- Sem exit status na estratégia padrão: a detecção de falha usa a janela de saída precoce (5 s) do `SessionOutcome`. +- Cada novo adapter deve repetir um spike curto (argv + log do emulador) antes de virar padrão. +- Se o RetroX um dia for para sandbox, `arguments` passa a ser ignorado (ADR-0002) e esta decisão precisa ser revista. + +## Alternativas +`open -a … --args` via `Process` (mesmo efeito do `NSWorkspace`, com um processo intermediário); nova instância sempre (`createsNewApplicationInstance = true`), que arrisca conflito de memory cards e de configuração; Apple Events de abrir documento (não passam flags como `-batch`). diff --git a/docs/spikes/0001-launch-pcsx2-macos.md b/docs/spikes/0001-launch-pcsx2-macos.md new file mode 100644 index 0000000..7435a37 --- /dev/null +++ b/docs/spikes/0001-launch-pcsx2-macos.md @@ -0,0 +1,43 @@ +# Spike 0001 — Abrir uma ROM de PS2 no PCSX2 para macOS + +**Data:** 2026-10-27 · **Status:** concluído · **Decisão resultante:** ADR-0011 + +## Pergunta +O PCSX2 para macOS abre diretamente uma ROM recebida por argumento, com caminhos difíceis, quando lançado pelo RetroX? Qual forma de criar o processo usar: `NSWorkspace` ou `Process`? + +## Ambiente +- Mac Apple M4, macOS 27.2, Rosetta instalado. Só Command Line Tools (Swift 6.4, SDK 27.0). +- PCSX2 v2.9.144 (`net.pcsx2.pcsx2`), executável `Contents/MacOS/PCSX2`, **x86_64 apenas** (roda via Rosetta), hardened runtime. +- Configuração do PCSX2 do usuário, não alterada: `StartFullscreen=true`, `ConfirmShutdown=true`, BIOS configurada. +- ROM: uma ISO de PS2 do próprio usuário, com espaços e parênteses no nome. +- Ferramenta: `rx-launch-probe`, que usa o mesmo `GameLauncher` do app. + +## Evidência estática (sem executar o PCSX2) +O texto de ajuda dentro do binário macOS 2.9.144 (extraído com `strings`) traz `Usage: {} [parameters] [--] [boot filename]` e as flags `-batch`, `-nogui`, `-fullscreen`, `-nofullscreen`, `-bigpicture`, `-fastboot`, `-slowboot`, `-portable`, `-datapath`, `-gamecfg`, `-elf`, `-disc`, `-bios`, `-state`, `-statefile`, `-logfile`, `-testconfig`, `-setupwizard`, `-turbo`, `-unlimited` e `--` ("use quando o nome tem espaços ou começa com hífen"). Bate com a documentação oficial da CLI, que só mostra exemplos de Windows. + +## Execuções reais +Cada execução abriu o PCSX2 com `["-batch", "--", ]`. O critério de sucesso foi a linha `isoFile open ok: ` no log do próprio PCSX2 (`emulog.txt`), comparada byte a byte com o argv, mais o serial do disco e o início da execução do jogo. As sessões foram encerradas com SIGTERM só no pid aberto pelo teste, com autorização do usuário. + +| # | Estratégia | Caminho da ROM | Log == argv (bytes) | Jogo iniciou | Término detectado | +|---|---|---|---|---|---| +| A | `workspace` | original: espaços e parênteses | sim | sim (serial SLUS-21490, ELF executando em 6,3 s) | sim, sem exit status | +| B | `process` | symlink em pasta **NFD** com `ç`, `ã`, `ñ`, CJK e emoji; nome **começando com `-`** | sim | sim (4 s) | sim, status 0 | +| C | `workspace` | symlink em pasta e nome **NFC** com acentos | sim | sim (4 s) | sim, sem exit status | +| D | — | com o PCSX2 aberto (durante A), nova validação com outra ROM | — | — | recusada: `emulatorAlreadyRunning`, ação "Trazer emulador para frente" | + +Observações: +- O PCSX2 registra exatamente o caminho recebido (o do symlink, não o alvo), sem normalizar Unicode. NFD e NFC funcionaram. +- O `--` é o que permite o nome iniciado por hífen; sem ele, o PCSX2 trataria o nome como opção. +- O PCSX2 trata SIGTERM como Ctrl+C: "Received CTRL+C, attempting graceful shutdown". Saiu em cerca de 1 s, com status 0. +- Com a estratégia `process`, o stdout do PCSX2 é quase vazio (76 bytes). O log útil continua em `emulog.txt`, então capturar stdout ajuda pouco. +- As execuções B e C aparecem como "fechou cedo" porque o SIGTERM do teste veio antes de 5 s. Isso é artefato do teste, não falha. +- `stat` da pasta de ROMs (mtime, tamanho, inode) idêntico antes e depois. Os symlinks ficaram num diretório temporário e foram apagados no fim. O próprio PCSX2 atualiza os arquivos dele a cada jogo (log, `playtime.dat`), como em qualquer uso normal. + +## Evidência complementar (emulador falso, `scripts/integration-launch.sh`) +- O argv chega byte a byte pelas duas estratégias, inclusive com `$()`, aspas, NFD, CJK e emoji. O LaunchServices não injeta argumentos extras. +- Com o app já aberto e `createsNewApplicationInstance = false`, o LaunchServices devolve a instância existente (mesmo pid) e **não entrega os novos argumentos**. Isso confirma a documentação da Apple e justifica a recusa feita pela validação. + +## Não coberto aqui +- ROM em pasta protegida pelo TCC (Documentos, Mesa, Downloads, volume removível): o prompt de privacidade e a quem ele é atribuído ficam para a Fase 2. +- PCSX2 nativo arm64 (não há build oficial no momento) e macOS 14 em runtime. +- Interação com `ConfirmShutdown=true` quando o usuário fecha o jogo pela interface do PCSX2 (validação manual no Gate G0). From e553cf1afbe4a6fcf2fbf3e0bfe75d2448346a33 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 00:12:35 -0300 Subject: [PATCH 11/56] Add comprehensive SwiftUI design guidelines and templates - Introduced anti-AI-slop rules to avoid generic UI patterns in SwiftUI. - Created a structured 5-dimension design review framework for evaluating UI quality. - Compiled practical layout patterns for common SwiftUI design scenarios. - Added essential Swift extensions for color handling and typography. - Established a typography and color system with clear guidelines. - Provided a brand specification template for consistent branding. - Initialized skills-lock.json for versioning and tracking changes. --- .../skills/swiftui-design-skill/.gitignore | 5 + .claude/skills/swiftui-design-skill/LICENSE | 21 + .../skills/swiftui-design-skill/README-zh.md | 128 ++++++ .claude/skills/swiftui-design-skill/README.md | 127 ++++++ .../swiftui-design-skill/RELEASE-v1.0.0.md | 57 +++ .claude/skills/swiftui-design-skill/SKILL.md | 270 +++++++++++++ .../references/anti-ai-slop.md | 268 +++++++++++++ .../references/design-review.md | 151 +++++++ .../references/layout-patterns.md | 265 +++++++++++++ .../references/swift-extensions.md | 373 ++++++++++++++++++ .../references/typography-color.md | 172 ++++++++ .../templates/brand-spec.md | 77 ++++ skills-lock.json | 11 + 13 files changed, 1925 insertions(+) create mode 100644 .claude/skills/swiftui-design-skill/.gitignore create mode 100644 .claude/skills/swiftui-design-skill/LICENSE create mode 100644 .claude/skills/swiftui-design-skill/README-zh.md create mode 100644 .claude/skills/swiftui-design-skill/README.md create mode 100644 .claude/skills/swiftui-design-skill/RELEASE-v1.0.0.md create mode 100644 .claude/skills/swiftui-design-skill/SKILL.md create mode 100644 .claude/skills/swiftui-design-skill/references/anti-ai-slop.md create mode 100644 .claude/skills/swiftui-design-skill/references/design-review.md create mode 100644 .claude/skills/swiftui-design-skill/references/layout-patterns.md create mode 100644 .claude/skills/swiftui-design-skill/references/swift-extensions.md create mode 100644 .claude/skills/swiftui-design-skill/references/typography-color.md create mode 100644 .claude/skills/swiftui-design-skill/templates/brand-spec.md create mode 100644 skills-lock.json diff --git a/.claude/skills/swiftui-design-skill/.gitignore b/.claude/skills/swiftui-design-skill/.gitignore new file mode 100644 index 0000000..31f0a5f --- /dev/null +++ b/.claude/skills/swiftui-design-skill/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +*.swp +*.swo +*~ +node_modules/ diff --git a/.claude/skills/swiftui-design-skill/LICENSE b/.claude/skills/swiftui-design-skill/LICENSE new file mode 100644 index 0000000..573247b --- /dev/null +++ b/.claude/skills/swiftui-design-skill/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 wholiver + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/.claude/skills/swiftui-design-skill/README-zh.md b/.claude/skills/swiftui-design-skill/README-zh.md new file mode 100644 index 0000000..dcb3972 --- /dev/null +++ b/.claude/skills/swiftui-design-skill/README-zh.md @@ -0,0 +1,128 @@ +
+ +# SwiftUI Design Skill + +> *「一句话,一个能交付的 SwiftUI 界面。」* +> *"One prompt. A shippable SwiftUI interface."* + +[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) +[![Agent-Agnostic](https://img.shields.io/badge/Agent-Agnostic-blueviolet)](https://skills.sh) +[![Skills](https://img.shields.io/badge/skills.sh-Compatible-green)](https://skills.sh) + +
+ +

+ English + 中文 +

+ +**在你的 agent 里打一句话,拿回一个不 AI slop 的 SwiftUI 界面。** + +3 到 30 分钟,你能设计出一个**有签名感的 iOS 界面**——不是「AI 做的还行」那种水平,是看起来像有品味的设计师做的。 + +反 AI slop 六条铁律、设计方向顾问、品牌资产协议、五维评审——全部内置。给 skill 你的品牌色板,它会读懂你的气质;什么都不给,内置的 5 种设计语汇也能兜底到不出丑。 + +跨 agent 通用——Claude Code、Cursor、Codex、OpenCode、Hermes 都能装。 + +## 装上就能用 + +```bash +npx skills add wholiver/swiftui-design-skill -g -y +``` + +## 能做什么 + +| 能力 | 交付物 | 典型耗时 | +|------|--------|----------| +| SwiftUI 界面设计 | 可编译的 SwiftUI 代码 · 设计系统 token · 布局模式 | 10–15 min | +| 设计方向顾问 | 5 流派 × N 种设计哲学 · 推荐 3 方向 · 视觉锚点描述 | 5 min | +| 品牌资产集成 | brand-spec.md · 色板 · 字体 · 间距系统 | 5–10 min | +| 反 AI Slop 审查 | 逐条检查 · 具体修复代码 · 替代方案 | 3–5 min | +| 五维评审 | 雷达图评分 · Keep/Fix/Quick Wins · 可操作修复清单 | 3 min | +| 布局模式库 | 9 种常见布局 · 可复制的 SwiftUI 代码 | 即时 | +| 动画设计 | spring/parallax/pull-to-refresh · 可编译代码 | 5–10 min | + +## 核心机制 + +### 反 AI Slop 六条铁律 + +这是 skill 里最硬的一段规则。所有设计都必须通过这 6 条检查: + +| # | 铁律 | ❌ 禁止 | ✅ 替代方案 | +|---|------|---------|------------| +| 1 | 起点从上下文开始 | 空白画布凭空捏造 | 先问设计系统/UI kit/品牌资产 | +| 2 | 初级设计师模式 | 等完美方案 | 灰色占位符 > 烂 SVG | +| 3 | 给变体不给终稿 | 一个「最终答案」 | 2–3 个差异化方向 | +| 4 | 占位符 > 烂实现 | AI 生成的剪贴画 | 干净的灰色占位 + 文字标注 | +| 5 | 系统优先,别填充 | 塞满每一个像素 | 每个元素必须证明自己存在的理由 | +| 6 | 禁止 AI slop 模式 | 紫蓝渐变、emoji 图标、圆角卡片+左边框 | 单一暖色强调色、SF Symbols、衬线标题 | + +详见 `references/anti-ai-slop.md`。 + +### 设计方向顾问 + +当需求模糊时,skill 会从 5 大设计流派中推荐 3 个差异化方向: + +| 流派 | 特征 | 代表风格 | +|------|------|----------| +| **信息型** | 数据优先、图表密集 | Bloomberg Terminal | +| **编辑型** | 杂志排版、衬线字体、大量留白 | NYT、Medium | +| **表现型** | 大胆配色、不对称布局、动效前置 | Stripe、Linear | +| **功能型** | 密集工具感、等宽字体点缀 | Things、OmniFocus | +| **温暖极简** | 柔和中性色、圆角、微妙质感 | Notion、Craft | + +### 品牌资产协议 + +涉及具体品牌时强制执行 5 步硬流程: + +| 步骤 | 动作 | 目的 | +|------|------|------| +| 1 · 问 | 用户有 brand guidelines 吗? | 尊重已有资源 | +| 2 · 搜 | 搜索品牌官方页面 | 获取真实素材 | +| 3 · 下 | 下载实际资产文件 | PNG/SVG logo、字体 | +| 4 · 验 | 验证颜色匹配官方来源 | 核对 hex 值 | +| 5 · 写 | 生成 brand-spec.md | 记录完整设计系统 | + +质量门槛:5 个真实品牌色、10 个设计 token、2 个字体家族、8pt 间距网格。 + +### 五维评审 + +每个设计交付前必须通过 5 个维度的评审: + +| 维度 | 评分标准 | 最低分 | +|------|----------|--------| +| 🎯 哲学一致性 | 设计是否贯彻了选定的设计哲学 | ≥ 7/10 | +| 📐 视觉层级 | 信息优先级是否清晰 | ≥ 7/10 | +| 🔧 细节执行 | 间距、字体、颜色是否精确 | ≥ 7/10 | +| ⚡ 功能性 | 布局是否服务用户目标 | ≥ 7/10 | +| ✨ 原创性 | 是否有 1 个签名细节 | ≥ 7/10 | + +## 文件结构 + +``` +swiftui-design-skill/ +├── SKILL.md ← 核心定义(278 行) +├── references/ +│ ├── anti-ai-slop.md ← 反 AI Slop 详细规则(268 行) +│ ├── layout-patterns.md ← 9 种布局模式 + 可复制代码(265 行) +│ ├── typography-color.md ← 字体层级 + 色彩系统(172 行) +│ ├── design-review.md ← 五维评审流程(151 行) +│ └── swift-extensions.md ← Color/Font/Animation 扩展(373 行,必备) +└── templates/ + └── brand-spec.md ← 品牌规范模板(77 行) +``` + +## 与 swiftui-expert-skill 的区别 + +| | SwiftUI Design Skill | swiftui-expert-skill | +|---|---|---| +| **焦点** | 视觉设计、美学、品牌感 | 代码质量、性能、正确性 | +| **问题** | 「看起来怎么样?」 | 「代码写得对不对?」 | +| **输出** | 设计方向、色板、布局、评审 | 代码审查、Instruments 分析、API 现代化 | +| **互补** | 先用 design 确定方向 | 再用 expert 确保代码质量 | + +两个 skill 可以配合使用:Design 确定「做什么」,Expert 确保「怎么做对」。 + +## License + +MIT — 随便用,但请保留原作者署名。 diff --git a/.claude/skills/swiftui-design-skill/README.md b/.claude/skills/swiftui-design-skill/README.md new file mode 100644 index 0000000..6db14a4 --- /dev/null +++ b/.claude/skills/swiftui-design-skill/README.md @@ -0,0 +1,127 @@ +
+ +# SwiftUI Design Skill + +> *"One prompt. A shippable SwiftUI interface."* + +[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) +[![Agent-Agnostic](https://img.shields.io/badge/Agent-Agnostic-blueviolet)](https://skills.sh) +[![Skills](https://img.shields.io/badge/skills.sh-Compatible-green)](https://skills.sh) + +
+ +

+ English + 中文 +

+ +**Type one line in your agent. Get back a SwiftUI interface that doesn't look AI-generated.** + +In 3 to 30 minutes, you can design a **signature iOS interface** — not "AI-made-it-looks-okay" quality, but something that looks like it was crafted by a designer with taste. + +Anti-AI Slop 6 Iron Rules, Design Direction Advisor, Brand Asset Protocol, 5-Dimension Review — all built in. Give the skill your brand palette and it will read your vibe; give nothing and the 5 built-in design languages will still hold their ground. + +Works across agents — Claude Code, Cursor, Codex, OpenCode, Hermes, all supported. + +## Install & Go + +```bash +npx skills add wholiver/swiftui-design-skill -g -y +``` + +## What Can It Do + +| Capability | Deliverable | Typical Time | +|------------|-------------|--------------| +| SwiftUI Interface Design | Compilable SwiftUI code · Design system tokens · Layout patterns | 10–15 min | +| Design Direction Advisor | 5 schools × N design philosophies · 3 recommended directions · Visual anchor descriptions | 5 min | +| Brand Asset Integration | brand-spec.md · Color palette · Typography · Spacing system | 5–10 min | +| Anti-AI Slop Review | Item-by-item check · Concrete fix code · Alternative approaches | 3–5 min | +| 5-Dimension Review | Radar chart scoring · Keep/Fix/Quick Wins · Actionable fix checklist | 3 min | +| Layout Pattern Library | 9 common layouts · Copy-paste SwiftUI code | Instant | +| Animation Design | Spring/parallax/pull-to-refresh · Compilable code | 5–10 min | + +## Core Mechanisms + +### Anti-AI Slop 6 Iron Rules + +This is the hardest set of rules in the skill. All designs must pass these 6 checks: + +| # | Iron Rule | ❌ Forbidden | ✅ Alternative | +|---|-----------|-------------|----------------| +| 1 | Start from context | Inventing from a blank canvas | Ask about design system / UI kit / brand assets first | +| 2 | Junior Designer Mode | Waiting for the perfect solution | Gray placeholder > bad SVG | +| 3 | Give variants, not finals | One "final answer" | 2–3 differentiated directions | +| 4 | Placeholder > bad implementation | AI-generated clip art | Clean gray placeholder + text label | +| 5 | System-first, don't fill | Packing every pixel | Every element must justify its existence | +| 6 | Ban AI slop patterns | Purple-blue gradients, emoji icons, rounded cards + left border | Single warm accent color, SF Symbols, serif headlines | + +See `references/anti-ai-slop.md` for details. + +### Design Direction Advisor + +When requirements are vague, the skill recommends 3 differentiated directions from 5 major design schools: + +| School | Characteristics | Signature Style | +|--------|-----------------|-----------------| +| **Informational** | Data-first, chart-dense | Bloomberg Terminal | +| **Editorial** | Magazine layout, serif type, generous whitespace | NYT, Medium | +| **Expressive** | Bold color, asymmetric layout, motion-forward | Stripe, Linear | +| **Functional** | Dense tool feel, monospace accents | Things, OmniFocus | +| **Warm Minimal** | Soft neutrals, rounded corners, subtle texture | Notion, Craft | + +### Brand Asset Protocol + +A mandatory 5-step hard process when working with a specific brand: + +| Step | Action | Purpose | +|------|--------|---------| +| 1 · Ask | Does the user have brand guidelines? | Respect existing assets | +| 2 · Search | Search the brand's official pages | Obtain real materials | +| 3 · Download | Download actual asset files | PNG/SVG logos, fonts | +| 4 · Verify | Verify colors match official sources | Cross-check hex values | +| 5 · Write | Generate brand-spec.md | Record complete design system | + +Quality threshold: 5 real brand colors, 10 design tokens, 2 font families, 8pt spacing grid. + +### 5-Dimension Review + +Every design must pass a 5-dimension review before delivery: + +| Dimension | Scoring Criteria | Minimum Score | +|-----------|------------------|---------------| +| 🎯 Philosophy Consistency | Does the design embody the chosen design philosophy? | ≥ 7/10 | +| 📐 Visual Hierarchy | Is the information priority clear? | ≥ 7/10 | +| 🔧 Detail Execution | Are spacing, typography, and colors precise? | ≥ 7/10 | +| ⚡ Functionality | Does the layout serve user goals? | ≥ 7/10 | +| ✨ Originality | Is there at least 1 signature detail? | ≥ 7/10 | + +## File Structure + +``` +swiftui-design-skill/ +├── SKILL.md ← Core definition (278 lines) +├── references/ +│ ├── anti-ai-slop.md ← Anti-AI Slop detailed rules (268 lines) +│ ├── layout-patterns.md ← 9 layout patterns + copy-paste code (265 lines) +│ ├── typography-color.md ← Typography hierarchy + color system (172 lines) +│ ├── design-review.md ← 5-Dimension Review process (151 lines) +│ └── swift-extensions.md ← Color/Font/Animation extensions (373 lines, essential) +└── templates/ + └── brand-spec.md ← Brand spec template (77 lines) +``` + +## Difference from swiftui-expert-skill + +| | SwiftUI Design Skill | swiftui-expert-skill | +|---|---|---| +| **Focus** | Visual design, aesthetics, brand feel | Code quality, performance, correctness | +| **Question** | "How does it look?" | "Is the code correct?" | +| **Output** | Design direction, color palette, layout, review | Code review, Instruments analysis, API modernization | +| **Complementary** | Use Design first to set direction | Then use Expert to ensure code quality | + +The two skills work together: Design decides **what to build**, Expert ensures **how to build it right**. + +## License + +MIT — use freely, but please keep the original author attribution. diff --git a/.claude/skills/swiftui-design-skill/RELEASE-v1.0.0.md b/.claude/skills/swiftui-design-skill/RELEASE-v1.0.0.md new file mode 100644 index 0000000..92f2d9f --- /dev/null +++ b/.claude/skills/swiftui-design-skill/RELEASE-v1.0.0.md @@ -0,0 +1,57 @@ +## SwiftUI Design Skill v1.0.0 + +> 一句话,一个能交付的 SwiftUI 界面。 + +首个正式版本。跨 agent 通用的 SwiftUI 前端视觉设计 skill——不 AI slop。 + +### ✨ 内置能力 + +| 能力 | 说明 | +|------|------| +| 反 AI Slop 六条铁律 | 6 条硬规则 + 详细参考文档 | +| 设计方向顾问 | 5 大设计流派 × N 种哲学,推荐 3 方向 | +| 品牌资产协议 | 5 步硬流程,从问到写 brand-spec.md | +| 五维评审 | 哲学一致性 / 视觉层级 / 细节执行 / 功能性 / 原创性 | +| 布局模式库 | 9 种常见布局,可复制 SwiftUI 代码 | +| 字体与色彩系统 | 层级字体 + 色彩 token + 设计系统模板 | +| Swift 扩展 | Color(hex:)、动画模式、SF Symbols 指南 | + +### 📦 安装 + +```bash +npx skills add wholiver/swiftui-design-skill -g -y +``` + +### 📁 文件结构 + +``` +swiftui-design-skill/ +├── SKILL.md ← 核心定义(278 行) +├── references/ +│ ├── anti-ai-slop.md ← 反 AI Slop 详细规则(268 行) +│ ├── layout-patterns.md ← 9 种布局模式(265 行) +│ ├── typography-color.md ← 字体层级 + 色彩系统(172 行) +│ ├── design-review.md ← 五维评审流程(151 行) +│ └── swift-extensions.md ← Color/Font/Animation 扩展(373 行) +└── templates/ + └── brand-spec.md ← 品牌规范模板(77 行) +``` + +### 🎯 与 swiftui-expert-skill 的区别 + +| | SwiftUI Design Skill | swiftui-expert-skill | +|---|---|---| +| 焦点 | 视觉设计、美学、品牌感 | 代码质量、性能、正确性 | +| 问题 | 「看起来怎么样?」 | 「代码写得对不对?」 | + +### 📋 Changelog + +- ✅ 反 AI Slop 六条铁律 + 详细参考 +- ✅ 设计方向顾问(5 流派) +- ✅ 品牌资产协议(5 步流程) +- ✅ 五维评审系统 +- ✅ 9 种布局模式 + 可复制代码 +- ✅ 字体层级与色彩系统 +- ✅ Swift 扩展(Color/Font/Animation) +- ✅ 品牌规范模板 +- ✅ MIT License diff --git a/.claude/skills/swiftui-design-skill/SKILL.md b/.claude/skills/swiftui-design-skill/SKILL.md new file mode 100644 index 0000000..9ae08a2 --- /dev/null +++ b/.claude/skills/swiftui-design-skill/SKILL.md @@ -0,0 +1,270 @@ +--- +name: swiftui-design-skill +description: SwiftUI frontend visual design skill. Creates beautiful, distinctive iOS/macOS interfaces that avoid generic AI slop patterns. Covers design direction, layout systems, typography, color, spacing, brand integration, and design review. Use when designing new SwiftUI views, reviewing UI quality, creating iOS prototypes, choosing visual styles, improving app aesthetics, or when the UI looks generic or AI-generated. +license: MIT +metadata: + author: wholiver + version: "1.0.0" +--- + +# SwiftUI Design Skill + +> **TL;DR**: Design SwiftUI apps that look intentionally crafted, not AI-generated. Follow the 6 Anti-Slop Rules, use the Design Direction workflow when requirements are vague, and always pass the 5-Dimension Review before shipping. + +## When to Use + +- Designing new SwiftUI views or screens from scratch +- Reviewing or improving existing UI quality +- Creating iOS app prototypes or mockups +- Choosing a visual style or design direction +- Integrating brand assets into SwiftUI +- When someone says "the UI looks generic" or "make it look better" +- When building a new feature that needs visual design + +## When NOT to Use + +- Pure backend / API work with no UI +- Fixing SwiftUI compilation errors (use swiftui-expert-skill instead) +- Performance optimization of existing views (use swiftui-expert-skill) +- Accessibility compliance only (use swiftui-expert-skill's accessibility topic) + +## Prerequisites + +- Xcode 16+ with iOS 18+ / macOS 15+ SDK +- SwiftUI framework (not UIKit unless explicitly requested) +- Familiarity with SwiftUI view hierarchy and modifiers + +--- + +## Core Design Philosophy + +These 6 principles guide every design decision. They are distilled from real-world design practice and anti-patterns observed in AI-generated UI. + +### Principle 1: Start From Context, Never Blank + +Before designing any screen, ask: +- Is there an existing design system, UI kit, or Figma file? +- Is there an existing codebase with established visual language? +- Are there brand guidelines or a style guide? + +If no context exists, create a **brand-spec.md** first (see Brand Asset Protocol below). + +### Principle 2: Junior Designer Mode — Hypothesize Early, Iterate Fast + +Don't wait for the "perfect" design. Show hypotheses with placeholders early: +- Gray boxes for images are **better** than bad AI-generated SVGs +- System fonts with good spacing > custom fonts with bad spacing +- A rough but honest layout > a polished but generic one + +### Principle 3: Offer Variations, Not Finals + +Always present **2-3 distinct design directions**, not one "final answer." Each variation should: +- Represent a different design philosophy (e.g., editorial, functional, expressive) +- Have a clear rationale for why it works +- Be visually distinct — not just color swaps + +### Principle 4: Placeholder > Bad Implementation + +If you cannot source a real asset (icon, image, illustration): +- Use a clean gray placeholder with clear labeling +- Never use AI-generated SVG clipart +- Never use emoji as icon substitutes in production UI +- For icons, prefer SF Symbols (Apple's built-in icon library) + +### Principle 5: System First, Don't Fill + +Every element must earn its place. Before adding any UI element, ask: +- Does this serve the user's goal? +- Can this be combined with something else? +- What happens if I remove it? + +Whitespace is a feature, not emptiness. + +### Principle 6: Anti-AI-Slop + +These patterns are **banned** in production UI. See `references/anti-ai-slop.md` for detailed rules. + +**Banned visual patterns:** +- ❌ Purple-to-blue gradient backgrounds +- ❌ Emoji as functional icons +- ❌ Rounded cards with left-border accent color +- ❌ Generic "hero section" with centered text over gradient +- ❌ Inter/Roboto as display fonts on Apple platforms +- ❌ Neon-on-dark "cyber" aesthetic (#0D1117 base) +- ❌ Symmetric 3-column feature grids +- ❌ AI-drawn SVG illustrations or CSS silhouettes + +**What to do instead:** +- ✅ Single warm accent color on neutral background +- ✅ SF Symbols for icons, or custom icon set +- ✅ Serif display font (e.g., New York, Georgia) for headings +- ✅ Restrained info density — let content breathe +- ✅ One signature detail at 120% effort per screen +- ✅ Real photography or clean placeholders + +--- + +## Brand Asset Protocol + +When building UI for a specific brand, follow this 5-step hard flow: + +1. **Ask** — Request brand guidelines, logo files, color palette, typography +2. **Search** — If not provided, search the web for "[brand name] brand guidelines" +3. **Download** — Get actual asset files (PNG/SVG logos, font files) +4. **Verify** — Confirm colors match official sources (check hex values) +5. **Write brand-spec.md** — Document: primary/secondary colors, fonts, logo usage rules, spacing tokens + +**Quality threshold**: 5 real brand colors, 10 verified design tokens, 2 font families, 8pt spacing grid. + +If no brand exists, create a brand-spec.md with: +- 1 primary accent color (warm, not purple-blue gradient) +- 1 neutral palette (grays with warm undertone) +- 1 display font + 1 body font (SF Pro default is fine) +- 8pt spacing grid + +--- + +## Design Direction Workflow + +When requirements are vague or the user asks "what style should we use?", follow this workflow: + +### Phase 1: Understand Context (5 min) +1. Ask: What is the app? Who is the user? What platform (iOS/macOS/watchOS)? +2. Ask: Any reference apps or websites they admire? +3. Check: Existing design system or brand assets? + +### Phase 2: Recommend 3 Directions +Present 3 distinct design philosophies from different schools: + +| School | Example Directions | +| --------------- | ------------------------------------------- | +| **Information** | Clean data-first, chart-heavy, Bloomberg-style | +| **Editorial** | Magazine layout, serif typography, generous whitespace | +| **Expressive** | Bold color, asymmetric layout, motion-forward | +| **Functional** | Dense utility, monospace accents, minimal decoration | +| **Warm Minimal** | Soft neutrals, rounded shapes, subtle texture | + +### Phase 3: Present Visual Anchors +For each direction, describe: +- Color palette (3-5 colors with hex values) +- Typography pairing (display + body) +- Layout density (comfortable / compact / spacious) +- Signature detail (one standout element per screen) + +### Phase 4: Let User Choose +Present options clearly. After choice, lock in the design system. + +--- + +## SwiftUI Design Workflow + +### Step 1: Define the Design System (Before Coding) + +Create or confirm these design tokens: + +```swift +// Requires: references/swift-extensions.md (Color(hex:) extension) +// DesignTokens.swift +enum DesignTokens { + // Colors + static let accent = Color(hex: "E85D3A") // Warm coral + static let background = Color(hex: "FAFAF8") // Warm white + static let textPrimary = Color(hex: "1A1A1A") // Near-black + static let textSecondary = Color(hex: "6B6B6B") // Muted gray + + // Typography + static let displayFont = "New York" // Serif for headings + static let bodyFont = "SF Pro" // System default + + // Spacing (8pt grid) + static let spaceXS: CGFloat = 4 + static let spaceS: CGFloat = 8 + static let spaceM: CGFloat = 16 + static let spaceL: CGFloat = 24 + static let spaceXL: CGFloat = 32 + static let spaceXXL: CGFloat = 48 + + // Corner radius + static let radiusS: CGFloat = 8 + static let radiusM: CGFloat = 12 + static let radiusL: CGFloat = 16 +} +``` + +### Step 2: Build the Layout Hierarchy + +Follow the layout patterns in `references/layout-patterns.md`: +- Start with the primary content container +- Use `VStack` for vertical flow, `HStack` for horizontal +- Use `LazyVGrid` / `LazyHGrid` for grid layouts +- Use `ScrollView` with `.scrollTargetBehavior(.paging)` for paged content +- Avoid `GeometryReader` — prefer `containerRelativeFrame` (iOS 17+) + +### Step 3: Apply Typography Hierarchy + +Follow `references/typography-color.md`: +- **Display** (screen titles): Serif font, 28-34pt, bold +- **Heading** (section titles): Sans-serif, 20-24pt, semibold +- **Body** (content text): Sans-serif, 15-17pt, regular +- **Caption** (labels, metadata): Sans-serif, 12-13pt, secondary color + +### Step 4: Add the Signature Detail + +Each screen should have ONE element that goes 120% — a custom animation, a unique layout choice, a distinctive color moment. This is what makes the design memorable. + +Examples: +- A custom pull-to-refresh with brand-colored animation +- A card that expands with a spring animation on tap +- A header that uses the brand's display font at an oversized scale +- A subtle parallax effect on scroll + +### Step 5: Review Against Checklist + +Before shipping, run the 5-Dimension Review (see `references/design-review.md`). + +--- + +## Common Mistakes to Avoid + +| Mistake | Fix | +| ------------------------------------------ | -------------------------------------------------------- | +| Using `UIColor` or `NSColor` | Use `Color` (SwiftUI native) | +| `UIScreen.main.bounds` for sizing | Use `containerRelativeFrame` or geometry-based modifiers | +| Default blue tint everywhere | Define a custom accent color in design tokens | +| No spacing system (random padding values) | Use 8pt grid: 4, 8, 16, 24, 32, 48 | +| Emoji as icons | Use SF Symbols or custom icon assets | +| Purple-blue gradient background | Use solid warm neutrals | +| All content in one giant VStack | Break into semantic sections with clear hierarchy | +| No visual hierarchy (everything same size) | Use 3+ type scales (display, heading, body, caption) | +| Ignoring dark mode | Define semantic colors that adapt to appearance | +| Generic "Welcome!" hero section | Show actual content immediately | + +--- + +## Quick Reference: Topic Router + +| Topic | Reference File | +| ---------------------------- | ----------------------------------- | +| Anti-AI-Slop Rules (detail) | `references/anti-ai-slop.md` | +| Layout Patterns & Grids | `references/layout-patterns.md` | +| Typography & Color Systems | `references/typography-color.md` | +| 5-Dimension Design Review | `references/design-review.md` | +| Swift Extensions (required) | `references/swift-extensions.md` | +| Brand Spec Template | `templates/brand-spec.md` | + +--- + +## Validation Checklist + +Before considering any SwiftUI design complete, verify: + +- [ ] Design tokens defined (colors, fonts, spacing) +- [ ] No banned AI-slop patterns present +- [ ] Typography has clear hierarchy (3+ scales) +- [ ] Spacing follows 8pt grid +- [ ] Dark mode colors defined and tested +- [ ] One signature detail per screen +- [ ] SF Symbols used for icons (not emoji) +- [ ] Minimum 44×44pt tap targets +- [ ] No `GeometryReader` or `UIScreen.main.bounds` +- [ ] 5-Dimension Review score ≥ 7/10 on all dimensions diff --git a/.claude/skills/swiftui-design-skill/references/anti-ai-slop.md b/.claude/skills/swiftui-design-skill/references/anti-ai-slop.md new file mode 100644 index 0000000..9d5c1aa --- /dev/null +++ b/.claude/skills/swiftui-design-skill/references/anti-ai-slop.md @@ -0,0 +1,268 @@ +# Anti-AI-Slop Rules for SwiftUI + +These are specific patterns that make UI look "AI-generated" or generic. Each rule has a banned pattern, why it's bad, and what to do instead. + +## Rule 1: No Purple-Blue Gradient Backgrounds + +**Banned:** +```swift +LinearGradient( + colors: [.purple, .blue], + startPoint: .topLeading, + endPoint: .bottomTrailing +) +``` + +**Why:** Every AI tool defaults to this gradient. It signals "I didn't think about the design." + +**Instead:** Use a solid warm neutral background: +```swift +Color(hex: "FAFAF8") // Warm white +// or +Color(hex: "F5F3EF") // Light warm gray +``` + +If you must use a gradient, make it subtle and brand-specific: +```swift +LinearGradient( + colors: [Color(hex: "FFF5F0"), Color(hex: "FAFAF8")], + startPoint: .top, + endPoint: .bottom +) +``` + +## Rule 2: No Emoji as Icons + +**Banned:** +```swift +Text("🏠") // As a tab icon +Text("❤️") // As a like button +``` + +**Why:** Emoji rendering varies by platform, can't be styled, and looks unprofessional. + +**Instead:** Use SF Symbols: +```swift +Image(systemName: "house.fill") +Image(systemName: "heart.fill") +``` + +For custom needs, use a proper icon set (SF Symbols has 5,000+ icons). + +## Rule 3: No Rounded Cards with Left Border Accent + +**Banned:** +```swift +HStack { + Rectangle() + .fill(Color.purple) + .frame(width: 4) + VStack(alignment: .leading) { + Text("Title") + Text("Description") + } +} +.padding() +.background(Color(.systemBackground)) +.cornerRadius(12) +``` + +**Why:** This is the most common AI-generated card pattern. It's lazy and generic. + +**Instead:** Use proper card design: +```swift +VStack(alignment: .leading, spacing: DesignTokens.spaceS) { + Text("Title") + .font(.system(size: 18, weight: .semibold, design: .serif)) + Text("Description") + .font(.body) + .foregroundStyle(.secondary) +} +.padding(DesignTokens.spaceM) +.frame(maxWidth: .infinity, alignment: .leading) +.background(DesignTokens.surface) +.clipShape(RoundedRectangle(cornerRadius: DesignTokens.radiusM)) +``` + +## Rule 4: No Generic Hero Sections + +**Banned:** +```swift +VStack(spacing: 16) { + Text("Welcome to App") + .font(.largeTitle.bold()) + Text("The best app for everything") + .font(.title3) + .foregroundColor(.gray) + Button("Get Started") { } + .buttonStyle(.borderedProminent) +} +.frame(maxWidth: .infinity) +.padding(.vertical, 80) +.background( + LinearGradient(colors: [.purple, .blue], ...) +) +``` + +**Why:** This pattern is everywhere. It wastes the most valuable screen real estate on marketing copy nobody reads. + +**Instead:** Show actual content immediately: +```swift +VStack(alignment: .leading, spacing: DesignTokens.spaceL) { + // Small, tasteful header + Text("Today") + .font(.system(size: 28, weight: .bold, design: .serif)) + + // Real content + ForEach(items) { item in + ItemRow(item: item) + } +} +.padding(DesignTokens.spaceM) +``` + +## Rule 5: No Inter/Roboto on Apple Platforms + +**Banned:** +```swift +Text("Hello") + .font(.custom("Inter", size: 16)) +``` + +**Why:** Inter and Roboto are Google's fonts for Android/web. Using them on Apple platforms looks like a web app ported to native. + +**Instead:** Use Apple's system fonts: +```swift +// Default: SF Pro (sans-serif) +Text("Hello") + .font(.body) + +// Display: New York (serif) for headings +Text("Hello") + .font(.system(size: 28, weight: .bold, design: .serif)) + +// If you need a custom font, choose one that fits Apple's ecosystem: +// - Charter, Georgia, Iowan (serif alternatives) +// - Avenir, Futura, Gill Sans (geometric sans) +``` + +## Rule 6: No Neon-on-Dark Cyber Aesthetic + +**Banned:** +```swift +Color(hex: "0D1117") // GitHub dark +// with neon accent colors like #00FF88, #00D4FF +``` + +**Why:** This is the "I built a crypto dashboard" default. It's overused and hard to read. + +**Instead:** Use Apple's native dark mode colors: +```swift +// Let the system handle dark/light +Color(.systemBackground) +Color(.secondarySystemBackground) + +// Or define warm dark colors +Color(hex: "1C1C1E") // iOS dark background +Color(hex: "2C2C2E") // iOS dark secondary +``` + +## Rule 7: No Symmetric 3-Column Feature Grids + +**Banned:** +```swift +LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3)) { + FeatureCard(icon: "star", title: "Fast") + FeatureCard(icon: "shield", title: "Secure") + FeatureCard(icon: "bolt", title: "Easy") +} +``` + +**Why:** This is the SaaS landing page default. It doesn't work for native apps. + +**Instead:** Use asymmetric, content-driven layouts: +```swift +VStack(spacing: DesignTokens.spaceL) { + // Primary feature — large + FeaturedCard(item: featuredItem) + .frame(height: 200) + + // Secondary features — smaller, horizontal + HStack(spacing: DesignTokens.spaceM) { + SecondaryCard(item: item1) + SecondaryCard(item: item2) + } + .frame(height: 120) +} +``` + +## Rule 8: No AI-Drawn SVG Illustrations + +**Banned:** +- Inline SVG paths that draw abstract "people working" illustrations +- CSS-drawn silhouettes +- Any illustration that looks like it came from unDraw or Humaaans + +**Why:** These are immediately recognizable as AI-generated stock content. + +**Instead:** +- Use real photography (from Unsplash, Pexels, or the brand's own photos) +- Use SF Symbols at large scale as visual elements +- Use clean geometric shapes or patterns from the brand +- Use a simple placeholder with a note: "Replace with brand photo" + +## Rule 9: No Default Blue Tint Everywhere + +**Banned:** +```swift +// Everything uses the default blue accent +Button("Action") { } // Blue +Toggle("Setting", isOn: $value) // Blue +Link("Visit", url: url) // Blue +``` + +**Why:** Default blue means "I didn't customize anything." + +**Instead:** Define a custom accent color: +```swift +@main +struct MyApp: App { + var body: some Scene { + WindowGroup { + ContentView() + .tint(DesignTokens.accent) // Your brand color + } + } +} +``` + +## Rule 10: No Random Spacing + +**Banned:** +```swift +.padding(.horizontal, 13) +.padding(.vertical, 7) +.frame(height: 43) +``` + +**Why:** Odd numbers look accidental. They create visual inconsistency. + +**Instead:** Use an 8pt grid: +```swift +.padding(.horizontal, DesignTokens.spaceM) // 16 +.padding(.vertical, DesignTokens.spaceS) // 8 +.frame(height: 44) // Minimum tap target +``` + +## Self-Check: Is Your UI AI Slop? + +Ask these questions: +1. Would this look at home on a generic SaaS landing page? +2. Are there purple-blue gradients? +3. Are emoji used as functional icons? +4. Is the spacing random or systematic? +5. Could you swap the brand name and it would still look the same? +6. Is there a "Welcome to [App]" hero section? +7. Are all cards the same rounded rectangle with a left accent border? + +If you answered "yes" to 3+ questions, the design needs work. diff --git a/.claude/skills/swiftui-design-skill/references/design-review.md b/.claude/skills/swiftui-design-skill/references/design-review.md new file mode 100644 index 0000000..a75af80 --- /dev/null +++ b/.claude/skills/swiftui-design-skill/references/design-review.md @@ -0,0 +1,151 @@ +# 5-Dimension SwiftUI Design Review + +A structured framework for evaluating SwiftUI UI quality. Score each dimension 1-10. + +## How to Use + +1. Take a screenshot of the UI +2. Evaluate each dimension below +3. Score honestly (most AI-generated UI scores 3-5) +4. Fix issues scoring < 7 +5. Re-evaluate after fixes + +--- + +## Dimension 1: Philosophy Alignment (1-10) + +Does the design follow a coherent philosophy, or is it a random collection of trends? + +| Score | Criteria | +| ----- | -------------------------------------------------------------------- | +| 1-3 | Random elements, no coherent style, looks like template mashup | +| 4-5 | Some consistency, but generic (could be any app) | +| 6-7 | Clear style direction, recognizable identity | +| 8-10 | Strong philosophical foundation, every element supports the vision | + +**Check:** +- [ ] Design follows one of the 5 schools (Informational / Editorial / Expressive / Functional / Warm Minimal) +- [ ] Every element supports the chosen philosophy +- [ ] No contradictory design choices (e.g., playful icons + corporate typography) +- [ ] The design would be recognizable if the brand name were removed + +--- + +## Dimension 2: Visual Hierarchy (1-10) + +Can the user immediately understand what's important? + +| Score | Criteria | +| ----- | -------------------------------------------------------------------- | +| 1-3 | Everything looks the same size/weight, no clear reading order | +| 4-5 | Some hierarchy, but competing elements | +| 6-7 | Clear primary/secondary/tertiary levels | +| 8-10 | Instant comprehension, natural eye flow, nothing competing | + +**Check:** +- [ ] Screen title is the largest text element +- [ ] Primary action is visually dominant +- [ ] Secondary information is visually subordinate +- [ ] Whitespace creates natural grouping +- [ ] The eye knows where to go first, second, third + +--- + +## Dimension 3: Craft Quality (1-10) + +Are the details right? This is where AI-generated UI fails most. + +| Score | Criteria | +| ----- | -------------------------------------------------------------------- | +| 1-3 | Random spacing, inconsistent sizing, alignment issues | +| 4-5 | Generally okay, but noticeable rough edges | +| 6-7 | Consistent spacing, good alignment, clean typography | +| 8-10 | Pixel-perfect, every detail intentional, feels handcrafted | + +**Check:** +- [ ] Spacing follows 8pt grid consistently +- [ ] Font sizes are from the defined scale (not random) +- [ ] Colors are from the design token system +- [ ] Corner radii are consistent +- [ ] Icons are the same weight/style throughout +- [ ] No orphaned text (single word on a line) +- [ ] Images have consistent aspect ratios + +--- + +## Dimension 4: Functionality (1-10) + +Does the design serve the user's actual needs? + +| Score | Criteria | +| ----- | -------------------------------------------------------------------- | +| 1-3 | Form over function, important actions hidden, confusing flow | +| 4-5 | Usable but not efficient, some friction points | +| 6-7 | Good usability, clear actions, logical flow | +| 8-10 | Effortless to use, anticipates needs, zero friction | + +**Check:** +- [ ] Primary action is immediately visible (not hidden in menus) +- [ ] Touch targets are ≥ 44×44pt +- [ ] Loading states are handled (no blank screens) +- [ ] Error states are handled with helpful messages +- [ ] Empty states guide the user on what to do +- [ ] Navigation is predictable (back goes back) +- [ ] Form inputs have clear labels and validation + +--- + +## Dimension 5: Originality (1-10) + +Does this look like a real product, or an AI template? + +| Score | Criteria | +| ----- | -------------------------------------------------------------------- | +| 1-3 | Clearly AI-generated, uses banned slop patterns, template-like | +| 4-5 | Generic but not offensive, could be any app | +| 6-7 | Has personality, some unique elements, feels intentional | +| 8-10 | Distinctive, memorable, would stand out in App Store | + +**Check:** +- [ ] No banned AI-slop patterns (see anti-ai-slop.md) +- [ ] At least one signature detail per screen +- [ ] Typography has personality (not just system defaults) +- [ ] Color palette is distinctive (not generic blue/purple) +- [ ] Layout is asymmetric where appropriate +- [ ] The design would not be confused with a template + +--- + +## Review Summary Template + +``` +## Design Review: [Screen Name] + +| Dimension | Score | Notes | +| ----------------- | ----- | ------------------------ | +| Philosophy | ?/10 | [specific feedback] | +| Visual Hierarchy | ?/10 | [specific feedback] | +| Craft Quality | ?/10 | [specific feedback] | +| Functionality | ?/10 | [specific feedback] | +| Originality | ?/10 | [specific feedback] | +| **Average** | **?/10** | | + +### Issues to Fix (score < 7) +1. [Issue]: [Specific fix] +2. [Issue]: [Specific fix] + +### What's Working Well +1. [Strength] +2. [Strength] +``` + +## Common Score Ranges + +| Range | Meaning | +| ------- | -------------------------------------------------- | +| 1-3 | AI slop — needs complete redesign | +| 4-5 | Generic — functional but no personality | +| 6-7 | Good — professional, minor issues | +| 8-10 | Excellent — distinctive, crafted, ship-ready | + +**Shipping threshold**: All dimensions ≥ 7, no dimension below 5. diff --git a/.claude/skills/swiftui-design-skill/references/layout-patterns.md b/.claude/skills/swiftui-design-skill/references/layout-patterns.md new file mode 100644 index 0000000..a514eaf --- /dev/null +++ b/.claude/skills/swiftui-design-skill/references/layout-patterns.md @@ -0,0 +1,265 @@ +# SwiftUI Layout Patterns + +Practical layout patterns for common SwiftUI design scenarios. Each pattern includes code and when to use it. + +## Core Layout Principles + +1. **Vertical flow first** — SwiftUI naturally flows top-to-bottom +2. **Semantic grouping** — Group related content, not just visual elements +3. **Progressive disclosure** — Show summary first, details on demand +4. **Content-driven sizing** — Let content determine heights, not arbitrary frames + +## Pattern 1: Screen Structure + +Every screen follows this skeleton: + +```swift +struct ScreenView: View { + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: DesignTokens.spaceL) { + // 1. Header (small, tasteful) + ScreenHeader(title: "Screen Title") + + // 2. Primary content + PrimaryContentSection() + + // 3. Secondary content + SecondaryContentSection() + } + .padding(DesignTokens.spaceM) + } + .background(DesignTokens.background) + } +} +``` + +**Key rules:** +- Never use `GeometryReader` for basic layout — use `containerRelativeFrame` or `frame(maxWidth: .infinity)` +- Always wrap scrollable content in `ScrollView` +- Use `.scrollTargetBehavior(.paging)` for paged scrolling +- Use `.scrollClipDisabled()` if content needs to overflow scroll bounds + +## Pattern 2: Card Layout + +```swift +struct CardView: View { + let content: Content + + init(@ViewBuilder content: () -> Content) { + self.content = content() + } + + var body: some View { + content + .padding(DesignTokens.spaceM) + .frame(maxWidth: .infinity, alignment: .leading) + .background(DesignTokens.surface) + .clipShape(RoundedRectangle(cornerRadius: DesignTokens.radiusM)) + .shadow(color: .black.opacity(0.04), radius: 8, y: 2) + } +} +``` + +**Key rules:** +- Cards should have subtle shadow, not heavy borders +- Corner radius should be consistent (12-16pt for cards) +- Always use `clipShape(RoundedRectangle(...))` not `.cornerRadius()` +- Content inside cards should have clear hierarchy + +## Pattern 3: List Layout + +```swift +struct ItemListView: View { + let items: [Item] + + var body: some View { + LazyVStack(spacing: 0) { + ForEach(items) { item in + ItemRow(item: item) + + if item.id != items.last?.id { + Divider() + .padding(.leading, DesignTokens.spaceM) + } + } + } + .background(DesignTokens.surface) + .clipShape(RoundedRectangle(cornerRadius: DesignTokens.radiusM)) + } +} +``` + +**Key rules:** +- Use `LazyVStack` for moderate lists, `List` for very long lists +- Separators should be inset, not full-width +- Group related items visually (with section headers, not just dividers) + +## Pattern 4: Grid Layout + +```swift +// 2-column adaptive grid +let columns = [ + GridItem(.adaptive(minimum: 160), spacing: DesignTokens.spaceM) +] + +LazyVGrid(columns: columns, spacing: DesignTokens.spaceM) { + ForEach(items) { item in + GridItemView(item: item) + } +} +``` + +**Key rules:** +- Use `GridItem(.adaptive(minimum:))` for responsive grids +- Avoid fixed column counts — let content determine layout +- Never do symmetric 3-column feature grids (anti-slop rule) +- Grid items should have consistent heights within a row + +## Pattern 5: Header + Content + +```swift +struct ScreenHeader: View { + let title: String + let subtitle: String? + + var body: some View { + VStack(alignment: .leading, spacing: DesignTokens.spaceXS) { + Text(title) + .font(.system(size: 28, weight: .bold, design: .serif)) + + if let subtitle { + Text(subtitle) + .font(.body) + .foregroundStyle(.secondary) + } + } + .padding(.bottom, DesignTokens.spaceS) + } +} +``` + +**Key rules:** +- Headers should be left-aligned (not centered) for most apps +- Use serif display font for main titles +- Keep headers compact — don't waste vertical space +- Large title navigation: use `.navigationBarTitleDisplayMode(.large)` only for root views + +## Pattern 6: Tab Bar Layout + +```swift +TabView { + HomeView() + .tabItem { + Label("Home", systemImage: "house") + } + + SearchView() + .tabItem { + Label("Search", systemImage: "magnifyingglass") + } + + ProfileView() + .tabItem { + Label("Profile", systemImage: "person") + } +} +.tint(DesignTokens.accent) +``` + +**Key rules:** +- 3-5 tabs maximum +- Use SF Symbols for tab icons +- Active tab uses the accent color +- Don't put settings in tabs — use a gear icon in the navigation bar + +## Pattern 7: Modal / Sheet + +```swift +.sheet(isPresented: $showSheet) { + NavigationStack { + SheetContent() + .navigationTitle("Details") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .cancellationAction) { + Button("Cancel") { showSheet = false } + } + } + } + .presentationDetents([.medium, .large]) + .presentationDragIndicator(.visible) +} +``` + +**Key rules:** +- Always wrap sheets in `NavigationStack` +- Use `.presentationDetents` for half-sheets +- Provide a clear dismiss action +- Use `.presentationDragIndicator(.visible)` for discoverability + +## Pattern 8: Empty State + +```swift +struct EmptyStateView: View { + let icon: String + let title: String + let message: String + + var body: some View { + ContentUnavailableView { + Label(title, systemImage: icon) + } description: { + Text(message) + } + } +} +``` + +**Key rules:** +- Use `ContentUnavailableView` (iOS 17+) for empty states +- Don't use emoji — use SF Symbols +- Keep messaging concise and helpful +- Include a call-to-action if appropriate + +## Pattern 9: Loading State + +```swift +struct LoadingView: View { + var body: some View { + ProgressView() + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(DesignTokens.background) + } +} +``` + +**Key rules:** +- Use `ProgressView()` for simple loading +- For skeleton screens, use `.redacted(reason: .placeholder)` +- Never show a blank screen during loading +- Consider shimmer effects for premium feel + +## Pattern 10: Responsive Layout (iPhone + iPad) + +```swift +struct ResponsiveView: View { + @Environment(\.horizontalSizeClass) var sizeClass + + var body: some View { + if sizeClass == .compact { + // iPhone layout + VStack { ... } + } else { + // iPad layout + HStack { ... } + } + } +} +``` + +**Key rules:** +- Use `horizontalSizeClass` for layout adaptation +- Don't just scale up — use the extra space meaningfully +- iPad should show more content, not bigger content +- Use `NavigationSplitView` for multi-column on iPad diff --git a/.claude/skills/swiftui-design-skill/references/swift-extensions.md b/.claude/skills/swiftui-design-skill/references/swift-extensions.md new file mode 100644 index 0000000..a41cdf2 --- /dev/null +++ b/.claude/skills/swiftui-design-skill/references/swift-extensions.md @@ -0,0 +1,373 @@ +# Swift Extensions for SwiftUI Design + +These extensions are required for the code examples in this skill to compile. Copy them into your project. + +## Color Extensions + +### Color(hex:) + +Converts hex string to SwiftUI Color. Supports 3, 4, 6, and 8 character hex strings. + +```swift +import SwiftUI + +extension Color { + init(hex: String) { + let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) + var int: UInt64 = 0 + Scanner(string: hex).scanHexInt64(&int) + let a, r, g, b: UInt64 + switch hex.count { + case 3: // RGB (12-bit) + (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) + case 6: // RGB (24-bit) + (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) + case 8: // ARGB (32-bit) + (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) + default: + (a, r, g, b) = (255, 0, 0, 0) + } + self.init( + .sRGB, + red: Double(r) / 255, + green: Double(g) / 255, + blue: Double(b) / 255, + opacity: Double(a) / 255 + ) + } +} +``` + +### Color(light:dark:) — Adaptive Colors + +Creates colors that automatically adapt to light/dark mode. + +```swift +extension Color { + init(light lightHex: String, dark darkHex: String) { + self.init(uiColor: UIColor( + light: UIColor(Color(hex: lightHex)), + dark: UIColor(Color(hex: darkHex)) + )) + } +} + +extension UIColor { + convenience init(light: UIColor, dark: UIColor) { + self.init { traitCollection in + traitCollection.userInterfaceStyle == .dark ? dark : light + } + } +} +``` + +### Predefined Design Colors + +```swift +extension Color { + // Warm accent (coral) + static let appAccent = Color(hex: "E85D3A") + static let appAccentLight = Color(hex: "FFF0EB") + static let appAccentDark = Color(hex: "C44A2E") + + // Warm neutrals + static let appBackground = Color(light: "FAFAF8", dark: "1C1C1E") + static let appSurface = Color(light: "FFFFFF", dark: "2C2C2E") + static let appTextPrimary = Color(light: "1A1A1A", dark: "F2F2F7") + static let appTextSecondary = Color(light: "6B6B6B", dark: "8E8E93") + static let appDivider = Color(light: "E5E5E5", dark: "38383A") +} +``` + +--- + +## Font Extensions + +### Correct "New York" Font Usage + +SwiftUI has built-in serif support. Use `design: .serif` instead of `Font.custom("New York", ...)`: + +```swift +// ✅ CORRECT — iOS 17+ +Font.system(size: 28, weight: .bold, design: .serif) + +// ✅ CORRECT — Shorthand +Font.system(.title, design: .serif).bold() + +// ❌ WRONG — "New York" is not a custom font name +Font.custom("New York", size: 28) +``` + +### AppFont Enum (Corrected) + +```swift +enum AppFont { + // Display: Serif for personality (use .serif design) + static let display = Font.system(size: 28, weight: .bold, design: .serif) + static let displaySmall = Font.system(size: 22, weight: .bold, design: .serif) + + // Heading: Sans-serif for clarity + static let heading = Font.system(size: 20, weight: .semibold, design: .default) + static let subheading = Font.system(size: 17, weight: .medium, design: .default) + + // Body: System default + static let body = Font.system(size: 16, weight: .regular, design: .default) + static let bodySmall = Font.system(size: 14, weight: .regular, design: .default) + + // Caption: Smaller, lighter + static let caption = Font.system(size: 12, weight: .regular, design: .default) + static let captionMedium = Font.system(size: 12, weight: .medium, design: .default) +} +``` + +### Using Custom Fonts (If Needed) + +If you must use a custom font (e.g., from a brand), use the PostScript name: + +```swift +// Find the PostScript name in Font Book.app → Select font → Info tab +Font.custom("NewYork-Regular", size: 17) +Font.custom("NewYork-Bold", size: 28) +``` + +--- + +## Animation Design Patterns + +### Spring Animation (Card Expand) + +```swift +struct ExpandableCard: View { + @State private var isExpanded = false + + var body: some View { + VStack(alignment: .leading, spacing: 12) { + Text("Title") + .font(AppFont.heading) + + if isExpanded { + Text("Detailed content that appears with a spring animation.") + .font(AppFont.body) + .foregroundStyle(.secondary) + .transition(.opacity.combined(with: .move(edge: .top))) + } + } + .padding(16) + .frame(maxWidth: .infinity, alignment: .leading) + .background(Color.appSurface) + .clipShape(RoundedRectangle(cornerRadius: 12)) + .onTapGesture { + withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) { + isExpanded.toggle() + } + } + } +} +``` + +### Pull-to-Refresh with Brand Color + +```swift +struct BrandRefreshable: View { + @State private var items: [String] = ["Item 1", "Item 2"] + + var body: some View { + List(items, id: \.self) { item in + Text(item) + } + .refreshable { + // Simulate refresh + try? await Task.sleep(for: .seconds(1)) + } + .tint(Color.appAccent) // Brand-colored refresh indicator + } +} +``` + +### Subtle Parallax on Scroll + +```swift +struct ParallaxHeader: View { + var body: some View { + ScrollView { + GeometryReader { geo in + let offset = geo.frame(in: .global).minY + Image("header-photo") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(height: 300 + max(0, -offset)) + .offset(y: max(0, -offset) * 0.5) // Parallax factor + .clipped() + } + .frame(height: 300) + + // Content below + VStack(spacing: 16) { + Text("Content") + } + .padding() + } + } +} +``` + +### Tab Selection Animation + +```swift +struct AnimatedTabBar: View { + @State private var selectedTab = 0 + + var body: some View { + TabView(selection: $selectedTab) { + HomeView() + .tabItem { Label("Home", systemImage: "house") } + .tag(0) + + SearchView() + .tabItem { Label("Search", systemImage: "magnifyingglass") } + .tag(1) + } + .tint(Color.appAccent) + } +} +``` + +--- + +## SF Symbols Selection Guide + +### Weight and Scale + +SF Symbols have 9 weights: ultralight, light, thin, regular, medium, semibold, bold, heavy, black. + +```swift +// Use weight to match text hierarchy +Image(systemName: "star.fill") + .font(.system(size: 20, weight: .semibold)) // Match heading weight + +// Use scale for size adjustment +Image(systemName: "star.fill") + .imageScale(.small) // 16pt + .imageScale(.medium) // 20pt (default) + .imageScale(.large) // 28pt +``` + +### Fill vs Outline + +Use `.fill` variants for: +- Active/selected states +- Tab bar active icons +- Toggle states + +Use outline (default) for: +- Inactive states +- Navigation bar buttons +- Decorative icons + +```swift +// Active state +Image(systemName: selected ? "heart.fill" : "heart") + .foregroundStyle(selected ? Color.appAccent : Color.appTextSecondary) +``` + +### Common SF Symbols by Category + +| Category | Symbols | +| ---------- | ------------------------------------------------------------------------------------------ | +| Navigation | `chevron.left`, `chevron.right`, `chevron.down`, `arrow.left`, `arrow.right` | +| Actions | `plus`, `minus`, `pencil`, `trash`, `square.and.arrow.up`, `doc.on.doc` | +| Status | `checkmark.circle.fill`, `xmark.circle.fill`, `exclamationmark.triangle.fill`, `info.circle` | +| Media | `play.fill`, `pause.fill`, `forward.fill`, `backward.fill`, `speaker.wave.2.fill` | +| People | `person`, `person.fill`, `person.2`, `person.circle.fill`, `person.badge.plus` | +| Objects | `star`, `star.fill`, `heart`, `heart.fill`, `bell`, `bell.fill`, `gear`, `gearshape` | + +### Rendering Mode + +```swift +// Monochrome (default) — uses foregroundStyle +Image(systemName: "star.fill") + .foregroundStyle(Color.appAccent) + +// Hierarchical — adds depth with opacity +Image(systemName: "star.fill") + .symbolRenderingMode(.hierarchical) + .foregroundStyle(Color.appAccent) + +// Palette — multiple colors +Image(systemName: "star.fill") + .symbolRenderingMode(.palette) + .foregroundStyle(Color.appAccent, Color.appAccentLight) + +// Multicolor — uses original symbol colors +Image(systemName: "star.fill") + .symbolRenderingMode(.multicolor) +``` + +--- + +## Image & Asset Handling + +### AsyncImage (Loading Remote Images) + +```swift +struct RemoteImage: View { + let url: URL? + + var body: some View { + AsyncImage(url: url) { phase in + switch phase { + case .success(let image): + image + .resizable() + .aspectRatio(contentMode: .fill) + case .failure: + // Fallback: clean placeholder + Rectangle() + .fill(Color.appDivider) + .overlay { + Image(systemName: "photo") + .foregroundStyle(Color.appTextSecondary) + } + case .empty: + // Loading: subtle shimmer or progress + Rectangle() + .fill(Color.appDivider) + .overlay { + ProgressView() + } + @unknown default: + EmptyView() + } + } + } +} +``` + +### Placeholder Best Practices + +```swift +// ✅ GOOD: Clean placeholder with icon +Rectangle() + .fill(Color.appDivider) + .overlay { + Image(systemName: "photo") + .font(.system(size: 32)) + .foregroundStyle(Color.appTextSecondary.opacity(0.5)) + } + .clipShape(RoundedRectangle(cornerRadius: 12)) + +// ❌ BAD: Emoji placeholder +Text("🖼️") + +// ❌ BAD: AI-generated SVG +// (inline SVG paths) +``` + +### Image Caching Strategy + +For production apps, consider: +- `Kingfisher` (popular, well-maintained) — `KFImage(url)` +- `Nuke` (high performance) +- Or roll your own with `NSCache` + `AsyncImage` + +Never load images synchronously on the main thread. diff --git a/.claude/skills/swiftui-design-skill/references/typography-color.md b/.claude/skills/swiftui-design-skill/references/typography-color.md new file mode 100644 index 0000000..7f51115 --- /dev/null +++ b/.claude/skills/swiftui-design-skill/references/typography-color.md @@ -0,0 +1,172 @@ +> **Note**: Requires `swift-extensions.md` for `Color(hex:)` and `Color(light:dark:)` implementations. + +# Typography & Color Systems for SwiftUI + +## Typography System + +### Font Hierarchy + +| Level | Size | Weight | Font | Use For | +| -------- | ------- | ---------- | ---------- | -------------------------- | +| Display | 28-34pt | Bold | New York | Screen titles | +| Heading | 20-24pt | Semibold | SF Pro | Section titles | +| Subhead | 17pt | Medium | SF Pro | Card titles, list items | +| Body | 15-17pt | Regular | SF Pro | Paragraph text | +| Caption | 12-13pt | Regular | SF Pro | Labels, metadata, timestamps | +| Footnote | 11pt | Regular | SF Pro | Legal text, disclaimers | + +### Font Implementation + +```swift +enum AppFont { + // Display: Serif for personality (use .serif design) + static let display = Font.system(size: 28, weight: .bold, design: .serif) + static let displaySmall = Font.system(size: 22, weight: .bold, design: .serif) + + // Heading: Sans-serif for clarity + static let heading = Font.system(size: 20, weight: .semibold, design: .default) + static let subheading = Font.system(size: 17, weight: .medium, design: .default) + + // Body: System default + static let body = Font.system(size: 16, weight: .regular, design: .default) + static let bodySmall = Font.system(size: 14, weight: .regular, design: .default) + + // Caption: Smaller, lighter + static let caption = Font.system(size: 12, weight: .regular, design: .default) + static let captionMedium = Font.system(size: 12, weight: .medium, design: .default) +} +``` + +### Typography Rules + +1. **Maximum 2 font families** per screen (e.g., New York + SF Pro) +2. **Maximum 4 font sizes** per screen (e.g., display + heading + body + caption) +3. **Line height**: 1.4× for body text, 1.2× for headings +4. **Line length**: 45-75 characters per line for body text +5. **Never** use Inter, Roboto, or Poppins on Apple platforms +6. **Always** use `.font()` modifier, not raw `UIFont`/`NSFont` + +### Dynamic Type Support + +```swift +// Use @ScaledMetric for size-dependent values +@ScaledMetric(relativeTo: .body) var iconSize: CGFloat = 20 + +Image(systemName: "star") + .font(.system(size: iconSize)) +``` + +### When to Use Serif (New York) + +- App title / branding +- Article/blog post headings +- Editorial content +- Landing page hero text +- When you want to feel "premium" or "literary" + +**Don't use serif for:** +- Body text (harder to read at small sizes) +- Data-heavy interfaces +- Technical/admin UIs + +--- + +## Color System + +### Color Palette Structure + +```swift +enum AppColors { + // Accent — 1 warm color that defines the brand + static let accent = Color(hex: "E85D3A") // Warm coral + static let accentLight = Color(hex: "FFF0EB") // Very light accent + static let accentDark = Color(hex: "C44A2E") // Dark accent + + // Neutrals — warm undertone, not pure gray + static let background = Color(light: "FAFAF8", dark: "1C1C1E") + static let surface = Color(light: "FFFFFF", dark: "2C2C2E") + static let textPrimary = Color(light: "1A1A1A", dark: "F2F2F7") + static let textSecondary = Color(light: "6B6B6B", dark: "8E8E93") + static let textTertiary = Color(light: "999999", dark: "636366") + static let divider = Color(light: "E5E5E5", dark: "38383A") + + // Semantic — contextual colors + static let success = Color(hex: "34C759") + static let warning = Color(hex: "FF9500") + static let error = Color(hex: "FF3B30") + static let info = Color(hex: "007AFF") +} +``` + +### Color Rules + +1. **One accent color** — not a rainbow. One warm color defines the brand. +2. **Warm neutrals** — grays should have a warm undertone (slightly yellow/red), not blue. +3. **Semantic colors** — use context-based names (`textPrimary`) not appearance-based (`darkGray`). +4. **Dark mode** — every color must have a light AND dark variant. +5. **Contrast** — minimum 4.5:1 for body text, 3:1 for large text (WCAG AA). +6. **No pure black** — use `#1A1A1A` or `#1C1C1E`, not `#000000`. +7. **No pure white** — use `#FAFAF8` or `#FFFFFF` with slight warmth. + +### Dark Mode Implementation + +```swift +extension Color { + init(light lightHex: String, dark darkHex: String) { + self.init(uiColor: UIColor( + light: UIColor(Color(hex: lightHex)), + dark: UIColor(Color(hex: darkHex)) + )) + } +} + +extension UIColor { + convenience init(light: UIColor, dark: UIColor) { + self.init { traitCollection in + traitCollection.userInterfaceStyle == .dark ? dark : light + } + } +} +``` + +### Accent Color Usage + +``` +Primary actions: accent (buttons, links, active states) +Hover/pressed: accentDark (interactive feedback) +Selection: accentLight (background highlight) +Decorative: accent at 10-20% opacity (subtle accents) +``` + +### Color Anti-Patterns + +| Banned | Why | Instead | +| ----------------------------- | -------------------------- | -------------------------- | +| Purple-blue gradient | AI slop default | Solid warm accent | +| Neon green (#00FF88) | Crypto/dashboard cliché | Muted success green | +| Pure black background (#000) | Too harsh, no depth | Dark gray (#1C1C1E) | +| Rainbow accent colors | No visual identity | One consistent accent | +| Gray text on gray background | Low contrast | Ensure 4.5:1 ratio | +| Random hex values | Inconsistent | Use design token system | + +### Spacing System (8pt Grid) + +```swift +enum Spacing { + static let xxs: CGFloat = 2 // Hairline gaps + static let xs: CGFloat = 4 // Tight spacing + static let s: CGFloat = 8 // Default small + static let m: CGFloat = 16 // Default medium + static let l: CGFloat = 24 // Section spacing + static let xl: CGFloat = 32 // Large section spacing + static let xxl: CGFloat = 48 // Screen-level spacing + static let xxxl: CGFloat = 64 // Hero spacing +} +``` + +**Rules:** +- All spacing values must be multiples of 4 (preferably 8) +- Horizontal padding: 16pt (phone), 20-24pt (tablet) +- Vertical spacing between sections: 24-32pt +- Vertical spacing within sections: 8-16pt +- Minimum touch target: 44×44pt diff --git a/.claude/skills/swiftui-design-skill/templates/brand-spec.md b/.claude/skills/swiftui-design-skill/templates/brand-spec.md new file mode 100644 index 0000000..f2413ad --- /dev/null +++ b/.claude/skills/swiftui-design-skill/templates/brand-spec.md @@ -0,0 +1,77 @@ +# Brand Specification Template + +Use this template when creating a brand-spec.md for your project. Fill in each section. + +## Brand Name +[Your Brand Name] + +## Colors + +### Primary Accent +- **Color**: [e.g., Warm Coral] +- **Hex**: [e.g., #E85D3A] +- **Usage**: Primary buttons, active states, links, key UI elements + +### Accent Light +- **Hex**: [e.g., #FFF0EB] +- **Usage**: Selection highlights, hover states, subtle backgrounds + +### Accent Dark +- **Hex**: [e.g., #C44A2E] +- **Usage**: Pressed states, dark mode accent + +### Neutrals +| Token | Light Mode | Dark Mode | Usage | +| --------------- | ---------- | --------- | ----------------------- | +| Background | #FAFAF8 | #1C1C1E | Main background | +| Surface | #FFFFFF | #2C2C2E | Cards, elevated surfaces | +| Text Primary | #1A1A1A | #F2F2F7 | Main text | +| Text Secondary | #6B6B6B | #8E8E93 | Subtitles, metadata | +| Divider | #E5E5E5 | #38383A | Separators | + +### Semantic Colors +| Token | Hex | Usage | +| ------- | ------- | ---------------- | +| Success | #34C759 | Confirmations | +| Warning | #FF9500 | Cautions | +| Error | #FF3B30 | Errors, destructive actions | +| Info | #007AFF | Informational | + +## Typography + +### Display Font +- **Font**: [e.g., SF Serif (system serif)] +- **Usage**: Screen titles, hero text + +### Body Font +- **Font**: [e.g., SF Pro (system default)] +- **Usage**: All body text, labels, buttons + +### Type Scale +| Level | Size | Weight | Font | +| -------- | ------- | -------- | ------------- | +| Display | 28pt | Bold | Serif | +| Heading | 20pt | Semibold | Sans-serif | +| Body | 16pt | Regular | Sans-serif | +| Caption | 12pt | Regular | Sans-serif | + +## Spacing +- **Grid**: 8pt base +- **Horizontal padding**: 16pt (phone), 20pt (tablet) +- **Section spacing**: 24pt +- **Element spacing**: 8-16pt + +## Corner Radius +| Level | Value | Usage | +| ------ | ----- | ------------------- | +| Small | 8pt | Buttons, small cards | +| Medium | 12pt | Cards, inputs | +| Large | 16pt | Sheets, modals | + +## Logo Usage +- **Minimum size**: [e.g., 44×44pt] +- **Clear space**: [e.g., 16pt on all sides] +- **Variations**: [Light / Dark / Monochrome] + +## Notes +[Any additional brand guidelines, voice/tone, or design principles] diff --git a/skills-lock.json b/skills-lock.json new file mode 100644 index 0000000..172645b --- /dev/null +++ b/skills-lock.json @@ -0,0 +1,11 @@ +{ + "version": 1, + "skills": { + "swiftui-design-skill": { + "source": "Wholiver/swiftui-design-skill", + "sourceType": "github", + "skillPath": "SKILL.md", + "computedHash": "e566cd9af70769555a866c11a8037f326a699f600de200a9dde8518122fb0b32" + } + } +} From 2872d1f236a4979a18fb85260ad387854d6f44b4 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 00:17:53 -0300 Subject: [PATCH 12/56] feat(core): emuladores como plugins e plugin nativo do PCSX2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Contrato EmulatorPlugin: o usuário ativa um plugin e escolhe a pasta raiz do emulador; o plugin descobre app, pastas de jogos, capas e BIOS. - PCSX2Plugin lê (sem alterar) o PCSX2.ini, inclusive no modo portátil: pastas da lista de jogos (Paths/RecursivePaths), capas e BIOS. - GameScanner e LibraryBuilder montam a biblioteca sem tocar nas ROMs; CoverMatcher associa capas locais pelo nome (ex.: gt4-cover.png). - JSONFileStore para configuração de plugins e histórico até a Fase 2. - Paleta "Portátil quente" como dados, com teste de contraste WCAG. Co-Authored-By: Claude Opus 5.5 --- Sources/RetroXCore/Design/Palette.swift | 87 +++++++++ Sources/RetroXCore/Library/CoverMatcher.swift | 40 +++++ .../RetroXCore/Library/CoverThumbnailer.swift | 19 ++ Sources/RetroXCore/Library/Game.swift | 41 +++++ Sources/RetroXCore/Library/GameScanner.swift | 58 ++++++ .../RetroXCore/Plugins/EmulatorPlugin.swift | 117 ++++++++++++ Sources/RetroXCore/Plugins/PCSX2Plugin.swift | 138 +++++++++++++++ .../Support/FileSystemProbing.swift | 15 ++ Sources/RetroXCore/Support/INIFile.swift | 43 +++++ .../RetroXCore/Support/JSONFileStore.swift | 33 ++++ Tests/RetroXCoreTests/LibraryTests.swift | 158 +++++++++++++++++ Tests/RetroXCoreTests/PCSX2PluginTests.swift | 167 ++++++++++++++++++ .../Support/FakeFileSystem.swift | 8 + 13 files changed, 924 insertions(+) create mode 100644 Sources/RetroXCore/Design/Palette.swift create mode 100644 Sources/RetroXCore/Library/CoverMatcher.swift create mode 100644 Sources/RetroXCore/Library/CoverThumbnailer.swift create mode 100644 Sources/RetroXCore/Library/Game.swift create mode 100644 Sources/RetroXCore/Library/GameScanner.swift create mode 100644 Sources/RetroXCore/Plugins/EmulatorPlugin.swift create mode 100644 Sources/RetroXCore/Plugins/PCSX2Plugin.swift create mode 100644 Sources/RetroXCore/Support/INIFile.swift create mode 100644 Sources/RetroXCore/Support/JSONFileStore.swift create mode 100644 Tests/RetroXCoreTests/LibraryTests.swift create mode 100644 Tests/RetroXCoreTests/PCSX2PluginTests.swift diff --git a/Sources/RetroXCore/Design/Palette.swift b/Sources/RetroXCore/Design/Palette.swift new file mode 100644 index 0000000..77380de --- /dev/null +++ b/Sources/RetroXCore/Design/Palette.swift @@ -0,0 +1,87 @@ +import Foundation + +/// Cor sRGB em hexadecimal ("F4F0EA"). Os tokens ficam aqui como dados, sem SwiftUI, para os testes +/// conferirem o contraste (docs/design/brand-spec.md). +public struct HexColor: Sendable, Equatable { + public let red: Double + public let green: Double + public let blue: Double + + public init(_ hex: String) { + let value = UInt32(hex.trimmingCharacters(in: CharacterSet(charactersIn: "#")), radix: 16) ?? 0 + red = Double((value >> 16) & 0xFF) / 255 + green = Double((value >> 8) & 0xFF) / 255 + blue = Double(value & 0xFF) / 255 + } + + /// Luminância relativa (WCAG 2.x). + public var luminance: Double { + func linear(_ channel: Double) -> Double { + channel <= 0.03928 ? channel / 12.92 : pow((channel + 0.055) / 1.055, 2.4) + } + return 0.2126 * linear(red) + 0.7152 * linear(green) + 0.0722 * linear(blue) + } + + public static func contrast(_ first: HexColor, _ second: HexColor) -> Double { + let (lighter, darker) = first.luminance >= second.luminance ? (first, second) : (second, first) + return (lighter.luminance + 0.05) / (darker.luminance + 0.05) + } +} + +/// Par claro/escuro de um token. +public struct Tone: Sendable, Equatable { + public let light: HexColor + public let dark: HexColor + + public init(light: String, dark: String) { + self.light = HexColor(light) + self.dark = HexColor(dark) + } +} + +/// Paleta "Portátil quente": neutros quentes (papel de dia, grafite à noite) e um único acento. +public enum Palette { + public static let background = Tone(light: "F4F0EA", dark: "1B1916") + public static let surface = Tone(light: "FFFDF9", dark: "262320") + public static let raised = Tone(light: "EAE4DB", dark: "312D29") + public static let textPrimary = Tone(light: "1E1B18", dark: "F3EEE7") + public static let textSecondary = Tone(light: "6A625A", dark: "ADA59B") + public static let divider = Tone(light: "DDD5CA", dark: "3B3632") + + /// Cor de tema escolhida pelo usuário. Só uma por vez; nunca em texto pequeno, só em preenchimentos, + /// anéis de foco e títulos grandes. + public enum Accent: String, CaseIterable, Codable, Sendable { + case coral, ambar, salvia, ardosia + + public var fill: Tone { + switch self { + case .coral: Tone(light: "C7472A", dark: "F07A57") + case .ambar: Tone(light: "A85E12", dark: "E9A23B") + case .salvia: Tone(light: "4F7A52", dark: "8DBB8F") + case .ardosia: Tone(light: "44657F", dark: "8DB3CF") + } + } + + /// Texto e ícones sobre o preenchimento do acento. + public var onFill: Tone { Tone(light: "FFFDF9", dark: "1B1916") } + + public var title: String { + switch self { + case .coral: String(localized: "Coral") + case .ambar: String(localized: "Âmbar") + case .salvia: String(localized: "Sálvia") + case .ardosia: String(localized: "Ardósia") + } + } + } + + /// Tom das capas geradas quando não há imagem, por sistema. Não usa cores de marca. + public static func coverTone(for system: GameSystemID) -> Tone { + switch system { + case .ps2: Tone(light: "2E3742", dark: "2E3742") + default: Tone(light: "3A3530", dark: "3A3530") + } + } + + public static let onCover = Tone(light: "F3EEE7", dark: "F3EEE7") +} diff --git a/Sources/RetroXCore/Library/CoverMatcher.swift b/Sources/RetroXCore/Library/CoverMatcher.swift new file mode 100644 index 0000000..e3f2019 --- /dev/null +++ b/Sources/RetroXCore/Library/CoverMatcher.swift @@ -0,0 +1,40 @@ +import Foundation + +/// Associa capas locais (fornecidas pelo usuário) a ROMs pelo nome do arquivo. Sem rede (ADR-0006). +public enum CoverMatcher { + public static let imageExtensions: Set = ["png", "jpg", "jpeg", "webp"] + + /// Palavras que costumam enfeitar o nome de uma capa e não identificam o jogo. + static let noiseWords: Set = ["cover", "covers", "front", "box", "boxart", "capa", "art"] + + /// Chave curta demais casaria com jogos demais ("gt" é prefixo de muita coisa). + static let minimumKeyLength = 3 + + /// "GT 4 Spec II v1.08.iso" → "gt4speciiv108"; "gt4-cover.png" → "gt4". + static func key(_ filename: String) -> String { + let base = (filename as NSString).deletingPathExtension + let folded = base.folding(options: [.caseInsensitive, .diacriticInsensitive, .widthInsensitive], locale: nil) + return folded + .split(whereSeparator: { !$0.isLetter && !$0.isNumber }) + .map(String.init) + .filter { !noiseWords.contains($0) } + .joined() + } + + /// Prefere o nome idêntico; senão, a capa cujo nome é o prefixo mais longo do nome da ROM (ou vice-versa). + public static func match(romFilename: String, covers: [URL]) -> URL? { + let romKey = key(romFilename) + guard romKey.count >= minimumKeyLength else { return nil } + var best: (url: URL, length: Int)? + for cover in covers { + let coverKey = key(cover.lastPathComponent) + guard coverKey.count >= minimumKeyLength else { continue } + if coverKey == romKey { return cover } + if romKey.hasPrefix(coverKey) || coverKey.hasPrefix(romKey) { + let length = min(coverKey.count, romKey.count) + if length > (best?.length ?? 0) { best = (cover, length) } + } + } + return best?.url + } +} diff --git a/Sources/RetroXCore/Library/CoverThumbnailer.swift b/Sources/RetroXCore/Library/CoverThumbnailer.swift new file mode 100644 index 0000000..ea1f194 --- /dev/null +++ b/Sources/RetroXCore/Library/CoverThumbnailer.swift @@ -0,0 +1,19 @@ +import Foundation +import ImageIO + +public enum CoverThumbnailer { + /// Decodifica a capa já reduzida (ImageIO), sem carregar a imagem inteira em memória (ADR-0008). + /// Síncrono: chame fora da main thread. + public static func thumbnail(of url: URL, maxPixelSize: Int) -> CGImage? { + guard let source = CGImageSourceCreateWithURL(url as CFURL, [kCGImageSourceShouldCache: false] as CFDictionary) else { + return nil + } + let options: [CFString: Any] = [ + kCGImageSourceCreateThumbnailFromImageAlways: true, + kCGImageSourceCreateThumbnailWithTransform: true, + kCGImageSourceShouldCacheImmediately: true, + kCGImageSourceThumbnailMaxPixelSize: maxPixelSize, + ] + return CGImageSourceCreateThumbnailAtIndex(source, 0, options as CFDictionary) + } +} diff --git a/Sources/RetroXCore/Library/Game.swift b/Sources/RetroXCore/Library/Game.swift new file mode 100644 index 0000000..88e984d --- /dev/null +++ b/Sources/RetroXCore/Library/Game.swift @@ -0,0 +1,41 @@ +import Foundation + +public struct Game: Identifiable, Hashable, Sendable { + /// Caminho padronizado da ROM. Estável enquanto o arquivo não muda de lugar; a Fase 2 troca por UUID + /// persistido com detecção de arquivo movido (ADR-0004, ADR-0013). + public let id: String + public let title: String + public let systemID: GameSystemID + public let pluginID: EmulatorPluginID + public let romURL: URL + public let fileSize: Int64 + public let coverURL: URL? + public let searchKey: String + + public init(romURL: URL, systemID: GameSystemID, pluginID: EmulatorPluginID, fileSize: Int64, coverURL: URL?) { + let title = TitleParser.displayTitle(fromFilename: romURL.lastPathComponent) + self.id = romURL.standardizedFileURL.path(percentEncoded: false) + self.title = title + self.systemID = systemID + self.pluginID = pluginID + self.romURL = romURL + self.fileSize = fileSize + self.coverURL = coverURL + self.searchKey = TitleParser.searchKey(title) + } + + public var fileExtension: String { romURL.pathExtension.uppercased() } +} + +/// O que o usuário fez com um jogo: favorito e histórico de partidas. +public struct GameHistory: Codable, Sendable, Equatable { + public var isFavorite: Bool + public var lastPlayedAt: Date? + public var playCount: Int + + public init(isFavorite: Bool = false, lastPlayedAt: Date? = nil, playCount: Int = 0) { + self.isFavorite = isFavorite + self.lastPlayedAt = lastPlayedAt + self.playCount = playCount + } +} diff --git a/Sources/RetroXCore/Library/GameScanner.swift b/Sources/RetroXCore/Library/GameScanner.swift new file mode 100644 index 0000000..bce6517 --- /dev/null +++ b/Sources/RetroXCore/Library/GameScanner.swift @@ -0,0 +1,58 @@ +import Foundation + +public struct ScannedROM: Sendable, Equatable { + public let url: URL + public let fileSize: Int64 +} + +public enum GameScanner { + /// Lista as ROMs das pastas, sem abrir nem alterar os arquivos (ADR-0004). Pula arquivos ocultos e + /// o conteúdo de packages, e conta só uma vez o mesmo arquivo alcançado por caminhos diferentes. + /// Síncrono e possivelmente lento: chame fora da main thread. + public static func scan(_ directories: [ROMDirectory], extensions: Set) -> [ScannedROM] { + var seen: Set = [] + var result: [ScannedROM] = [] + for directory in directories { + var options: FileManager.DirectoryEnumerationOptions = [.skipsHiddenFiles, .skipsPackageDescendants] + if !directory.isRecursive { options.insert(.skipsSubdirectoryDescendants) } + guard let enumerator = FileManager.default.enumerator( + at: directory.url, includingPropertiesForKeys: [.isRegularFileKey, .fileSizeKey], options: options + ) else { continue } + + for case let url as URL in enumerator { + if Task.isCancelled { return result } + guard extensions.contains(url.pathExtension.lowercased()), + let values = try? url.resourceValues(forKeys: [.isRegularFileKey, .fileSizeKey]), + values.isRegularFile == true + else { continue } + let identity = url.resolvingSymlinksInPath().standardizedFileURL.path(percentEncoded: false) + guard seen.insert(identity).inserted else { continue } + result.append(ScannedROM(url: url, fileSize: Int64(values.fileSize ?? 0))) + } + } + return result + } +} + +public enum LibraryBuilder { + /// Monta os jogos de um plugin pronto: varre as pastas de ROM e associa capas pelo nome. + public static func games(for plugin: any EmulatorPlugin, discovery: PluginDiscovery, fileSystem: any FileSystemProbing = LocalFileSystem()) -> [Game] { + // Plugins de um sistema só (o PCSX2) não precisam de detecção; os de vários sistemas usarão o ADR-0012. + guard let system = plugin.systems.first, plugin.systems.count == 1 else { return [] } + let extensions = plugin.adapter.supportedExtensions(for: system) + let covers = discovery.coverDirectories + .flatMap { fileSystem.contentsOfDirectory(at: $0) } + .filter { CoverMatcher.imageExtensions.contains($0.pathExtension.lowercased()) } + return GameScanner.scan(discovery.romDirectories, extensions: extensions) + .map { rom in + Game( + romURL: rom.url, + systemID: system, + pluginID: plugin.id, + fileSize: rom.fileSize, + coverURL: CoverMatcher.match(romFilename: rom.url.lastPathComponent, covers: covers) + ) + } + .sorted { $0.title.localizedStandardCompare($1.title) == .orderedAscending } + } +} diff --git a/Sources/RetroXCore/Plugins/EmulatorPlugin.swift b/Sources/RetroXCore/Plugins/EmulatorPlugin.swift new file mode 100644 index 0000000..5f06b4f --- /dev/null +++ b/Sources/RetroXCore/Plugins/EmulatorPlugin.swift @@ -0,0 +1,117 @@ +import Foundation + +/// Identificador estável de um plugin de emulador. O valor bruto é persistido na configuração. +public struct EmulatorPluginID: RawRepresentable, Hashable, Codable, Sendable, CustomStringConvertible { + public let rawValue: String + + public init(rawValue: String) { + self.rawValue = rawValue + } + + public var description: String { rawValue } + + public static let pcsx2 = EmulatorPluginID(rawValue: "pcsx2") +} + +/// Um emulador que o usuário ativa no RetroX (ADR-0013). O plugin sabe encontrar o emulador e os jogos +/// a partir de uma pasta raiz, e entrega um `EmulatorAdapter` para abrir cada jogo. +public protocol EmulatorPlugin: Sendable { + var id: EmulatorPluginID { get } + var displayName: String { get } + var summary: String { get } + var systems: [GameSystemID] { get } + var adapter: any EmulatorAdapter { get } + + /// Inspeciona a pasta raiz escolhida pelo usuário. Só lê; pode demorar em discos lentos, então + /// deve ser chamado fora da main thread. + func discover(root: URL) -> PluginDiscovery +} + +public struct ROMDirectory: Sendable, Equatable, Hashable { + public enum Origin: Sendable, Equatable, Hashable { + /// Pasta encontrada dentro da pasta raiz do emulador. + case rootFolder + /// Pasta que o próprio emulador já conhece pela configuração dele. + case emulatorSettings + } + + public let url: URL + public let origin: Origin + public let isRecursive: Bool + + public init(url: URL, origin: Origin, isRecursive: Bool) { + self.url = url + self.origin = origin + self.isRecursive = isRecursive + } +} + +public enum PluginIssue: Sendable, Equatable { + case rootNotFound + case appNotFound + case noROMDirectories + case settingsFolderMissing(String) + + public var message: String { + switch self { + case .rootNotFound: + String(localized: "A pasta escolhida não existe mais ou não pode ser lida.") + case .appNotFound: + String(localized: "Nenhum app do emulador foi encontrado nesta pasta.") + case .noROMDirectories: + String(localized: "Nenhuma pasta de jogos encontrada (por exemplo, “roms”).") + case .settingsFolderMissing(let path): + String(localized: "A configuração do emulador aponta para uma pasta que não existe: \(path)") + } + } +} + +public struct PluginDiscovery: Sendable, Equatable { + public enum BIOSStatus: Sendable, Equatable { + case configured(String) + case fileMissing(String) + case notConfigured + /// O emulador ainda não tem configuração (nunca foi aberto ou é outra instalação). + case unknown + } + + public var root: URL + public var app: AppBundleInfo? + public var romDirectories: [ROMDirectory] = [] + public var coverDirectories: [URL] = [] + public var settingsFile: URL? + public var bios: BIOSStatus = .unknown + public var issues: [PluginIssue] = [] + + public init(root: URL) { + self.root = root + } + + public var isReady: Bool { app != nil && !romDirectories.isEmpty } +} + +/// Configuração de um plugin escolhida pelo usuário, persistida entre sessões. +public struct PluginConfig: Codable, Sendable, Equatable { + public var isEnabled: Bool + public var rootPath: String? + + public init(isEnabled: Bool = false, rootPath: String? = nil) { + self.isEnabled = isEnabled + self.rootPath = rootPath + } +} + +/// Plugins que o RetroX oferece. Os "em breve" aparecem na tela de emuladores, mas não podem ser ativados. +public enum PluginCatalog { + public struct Upcoming: Sendable, Identifiable { + public let id: String + public let name: String + public let systems: String + } + + public static let available: [any EmulatorPlugin] = [PCSX2Plugin()] + + public static let upcoming: [Upcoming] = [ + Upcoming(id: "dolphin", name: "Dolphin", systems: "GameCube · Wii"), + ] +} diff --git a/Sources/RetroXCore/Plugins/PCSX2Plugin.swift b/Sources/RetroXCore/Plugins/PCSX2Plugin.swift new file mode 100644 index 0000000..a93f906 --- /dev/null +++ b/Sources/RetroXCore/Plugins/PCSX2Plugin.swift @@ -0,0 +1,138 @@ +import Foundation + +/// Plugin nativo do PCSX2. A partir da pasta raiz do emulador (a que guarda o `.app`, as ROMs, as capas e a BIOS), +/// encontra o app e as pastas de jogos, e lê, sem alterar, a configuração do próprio PCSX2 (`inis/PCSX2.ini`): +/// pastas da lista de jogos, pasta de capas e BIOS escolhida. +public struct PCSX2Plugin: EmulatorPlugin { + public let id = EmulatorPluginID.pcsx2 + public let displayName = "PCSX2" + public var summary: String { String(localized: "PlayStation 2 · plugin nativo") } + public let systems: [GameSystemID] = [.ps2] + public var adapter: any EmulatorAdapter { PCSX2Adapter() } + + /// Nomes de subpastas tratadas como pastas de jogos (sem diferença de caixa). + static let romFolderNames: Set = ["roms", "rom", "games", "jogos", "isos", "iso", "ps2"] + static let coverFolderNames: Set = ["covers", "capas", "boxart", "artwork"] + + private let fileSystem: any FileSystemProbing + private let defaultDataDirectory: URL + + /// `defaultDataDirectory` é onde o PCSX2 guarda a configuração fora do modo portátil. + public init( + fileSystem: any FileSystemProbing = LocalFileSystem(), + defaultDataDirectory: URL = URL.homeDirectory.appending(path: "Library/Application Support/PCSX2", directoryHint: .isDirectory) + ) { + self.fileSystem = fileSystem + self.defaultDataDirectory = defaultDataDirectory + } + + public func discover(root selected: URL) -> PluginDiscovery { + // Aceita também o próprio .app: a raiz passa a ser a pasta que o contém. + let root = selected.pathExtension.lowercased() == "app" ? selected.deletingLastPathComponent() : selected + var discovery = PluginDiscovery(root: root) + guard fileSystem.kind(of: root) == .directory else { + discovery.issues = [.rootNotFound] + return discovery + } + + let children = fileSystem.contentsOfDirectory(at: root) + discovery.app = findApp(in: children) + if discovery.app == nil { discovery.issues.append(.appNotFound) } + + let dataDirectory = discovery.app.flatMap(portableDataDirectory) ?? defaultDataDirectory + let settingsURL = dataDirectory.appending(path: "inis/PCSX2.ini", directoryHint: .notDirectory) + let settings = fileSystem.readText(of: settingsURL).map(INIFile.init) + if settings != nil { discovery.settingsFile = settingsURL } + + var romDirectories: [ROMDirectory] = [] + for child in children where fileSystem.kind(of: child) == .directory && child.pathExtension.lowercased() != "app" { + if Self.romFolderNames.contains(child.lastPathComponent.lowercased()) { + romDirectories.append(ROMDirectory(url: child, origin: .rootFolder, isRecursive: true)) + } else if Self.coverFolderNames.contains(child.lastPathComponent.lowercased()) { + discovery.coverDirectories.append(child) + } + } + let extensions = adapter.supportedExtensions(for: .ps2) + if children.contains(where: { extensions.contains($0.pathExtension.lowercased()) }) { + romDirectories.append(ROMDirectory(url: root, origin: .rootFolder, isRecursive: false)) + } + + if let settings { + let listed = settings.values("Paths", in: "GameList").map { ($0, false) } + + settings.values("RecursivePaths", in: "GameList").map { ($0, true) } + for (path, isRecursive) in listed where !path.isEmpty { + let url = resolve(path, relativeTo: dataDirectory) + if fileSystem.kind(of: url) == .directory { + romDirectories.append(ROMDirectory(url: url, origin: .emulatorSettings, isRecursive: isRecursive)) + } else { + discovery.issues.append(.settingsFolderMissing(path)) + } + } + let coversURL = resolve(settings.value("Covers", in: "Folders") ?? "covers", relativeTo: dataDirectory) + if fileSystem.kind(of: coversURL) == .directory { discovery.coverDirectories.append(coversURL) } + discovery.bios = biosStatus(settings: settings, dataDirectory: dataDirectory) + } + + discovery.romDirectories = Self.merged(romDirectories) + if discovery.romDirectories.isEmpty { discovery.issues.append(.noROMDirectories) } + return discovery + } + + private func findApp(in children: [URL]) -> AppBundleInfo? { + let inspector = AppBundleInspector(fileSystem: fileSystem) + let expected = adapter.expectedBundleIdentifiers + // O app pode estar direto na raiz ou uma pasta abaixo (por exemplo, "PCSX2/PCSX2.app"). + let nested = children + .filter { fileSystem.kind(of: $0) == .directory && $0.pathExtension.lowercased() != "app" } + .flatMap { fileSystem.contentsOfDirectory(at: $0) } + for candidate in (children + nested) where candidate.pathExtension.lowercased() == "app" { + if let info = try? inspector.inspect(candidate), let bundleID = info.bundleIdentifier, expected.contains(bundleID) { + return info + } + } + return nil + } + + /// No modo portátil, o PCSX2 guarda a configuração na pasta que contém o `.app`. + private func portableDataDirectory(for app: AppBundleInfo) -> URL? { + let folder = app.bundleURL.deletingLastPathComponent() + let markers = ["portable.ini", "portable.txt"].map { folder.appending(path: $0, directoryHint: .notDirectory) } + return markers.contains(where: { fileSystem.kind(of: $0) == .regularFile }) ? folder : nil + } + + private func biosStatus(settings: INIFile, dataDirectory: URL) -> PluginDiscovery.BIOSStatus { + guard let name = settings.value("BIOS", in: "Filenames") else { return .notConfigured } + let folder = resolve(settings.value("Bios", in: "Folders") ?? "bios", relativeTo: dataDirectory) + let file = folder.appending(path: name, directoryHint: .notDirectory) + return fileSystem.kind(of: file) == .regularFile ? .configured(name) : .fileMissing(name) + } + + private func resolve(_ path: String, relativeTo base: URL) -> URL { + let expanded = (path as NSString).expandingTildeInPath + let url = expanded.hasPrefix("/") + ? URL(filePath: expanded, directoryHint: .isDirectory) + : base.appending(path: expanded, directoryHint: .isDirectory) + return url.standardizedFileURL + } + + /// Junta pastas repetidas (raiz e configuração apontando para o mesmo lugar), mantendo a primeira origem. + static func merged(_ directories: [ROMDirectory]) -> [ROMDirectory] { + var result: [ROMDirectory] = [] + for directory in directories { + let key = directory.url.standardizedFileURL.path(percentEncoded: false).trimmingSuffix("/") + if let index = result.firstIndex(where: { $0.url.standardizedFileURL.path(percentEncoded: false).trimmingSuffix("/") == key }) { + let existing = result[index] + result[index] = ROMDirectory(url: existing.url, origin: existing.origin, isRecursive: existing.isRecursive || directory.isRecursive) + } else { + result.append(directory) + } + } + return result + } +} + +extension String { + func trimmingSuffix(_ suffix: String) -> String { + count > suffix.count && hasSuffix(suffix) ? String(dropLast(suffix.count)) : self + } +} diff --git a/Sources/RetroXCore/Support/FileSystemProbing.swift b/Sources/RetroXCore/Support/FileSystemProbing.swift index 12a4ba2..a0fd3ab 100644 --- a/Sources/RetroXCore/Support/FileSystemProbing.swift +++ b/Sources/RetroXCore/Support/FileSystemProbing.swift @@ -13,6 +13,14 @@ public protocol FileSystemProbing: Sendable { func isReadable(_ url: URL) -> Bool func isExecutable(_ url: URL) -> Bool func readPrefix(of url: URL, maxLength: Int) throws -> Data + /// Itens visíveis de uma pasta, em ordem de nome. Vazio se a pasta não existe ou não pode ser lida. + func contentsOfDirectory(at url: URL) -> [URL] +} + +extension FileSystemProbing { + func readText(of url: URL, maxLength: Int = 1 << 20) -> String? { + (try? readPrefix(of: url, maxLength: maxLength)).map { String(decoding: $0, as: UTF8.self) } + } } public struct LocalFileSystem: FileSystemProbing { @@ -39,4 +47,11 @@ public struct LocalFileSystem: FileSystemProbing { defer { try? handle.close() } return try handle.read(upToCount: maxLength) ?? Data() } + + public func contentsOfDirectory(at url: URL) -> [URL] { + let items = (try? FileManager.default.contentsOfDirectory( + at: url, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles] + )) ?? [] + return items.sorted { $0.lastPathComponent.localizedStandardCompare($1.lastPathComponent) == .orderedAscending } + } } diff --git a/Sources/RetroXCore/Support/INIFile.swift b/Sources/RetroXCore/Support/INIFile.swift new file mode 100644 index 0000000..cf24369 --- /dev/null +++ b/Sources/RetroXCore/Support/INIFile.swift @@ -0,0 +1,43 @@ +import Foundation + +/// Leitor mínimo de INI (só leitura), no formato que o PCSX2 grava: `[Seção]` e `chave = valor`. +/// Chaves podem se repetir (por exemplo, várias `RecursivePaths`); a ordem é preservada. +public struct INIFile: Sendable, Equatable { + struct Entry: Sendable, Equatable { + let section: String + let key: String + let value: String + } + + private let entries: [Entry] + + public init(_ text: String) { + var section = "" + var entries: [Entry] = [] + for rawLine in text.split(whereSeparator: \.isNewline) { + let line = rawLine.trimmingCharacters(in: .whitespaces) + if line.isEmpty || line.hasPrefix(";") || line.hasPrefix("#") { continue } + if line.hasPrefix("["), line.hasSuffix("]") { + section = String(line.dropFirst().dropLast()).trimmingCharacters(in: .whitespaces) + continue + } + guard let equals = line.firstIndex(of: "=") else { continue } + let key = line[.. [String] { + entries + .filter { $0.section.caseInsensitiveCompare(section) == .orderedSame && $0.key.caseInsensitiveCompare(key) == .orderedSame } + .map(\.value) + } + + /// O último valor não vazio da chave, como o próprio PCSX2 faria ao reler o arquivo. + public func value(_ key: String, in section: String) -> String? { + values(key, in: section).last { !$0.isEmpty } + } +} diff --git a/Sources/RetroXCore/Support/JSONFileStore.swift b/Sources/RetroXCore/Support/JSONFileStore.swift new file mode 100644 index 0000000..40af40d --- /dev/null +++ b/Sources/RetroXCore/Support/JSONFileStore.swift @@ -0,0 +1,33 @@ +import Foundation + +/// Configurações pequenas do RetroX em JSON (plugins ativos, favoritos, histórico). +/// A biblioteca completa vai para o SwiftData na Fase 2 (ADR-0005); isto cobre o que precisa sobreviver até lá. +public struct JSONFileStore: Sendable { + public let url: URL + + public init(url: URL) { + self.url = url + } + + /// `nil` se o arquivo não existe ou não pôde ser lido; quem chama decide o valor padrão. + public func load() -> Value? { + guard let data = try? Data(contentsOf: url) else { return nil } + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .iso8601 + return try? decoder.decode(Value.self, from: data) + } + + public func save(_ value: Value) throws { + try FileManager.default.createDirectory(at: url.deletingLastPathComponent(), withIntermediateDirectories: true) + let encoder = JSONEncoder() + encoder.outputFormatting = [.prettyPrinted, .sortedKeys] + encoder.dateEncodingStrategy = .iso8601 + try encoder.encode(value).write(to: url, options: .atomic) + } +} + +public enum RetroXDirectories { + public static var applicationSupport: URL { + URL.applicationSupportDirectory.appending(path: "RetroX", directoryHint: .isDirectory) + } +} diff --git a/Tests/RetroXCoreTests/LibraryTests.swift b/Tests/RetroXCoreTests/LibraryTests.swift new file mode 100644 index 0000000..2496dab --- /dev/null +++ b/Tests/RetroXCoreTests/LibraryTests.swift @@ -0,0 +1,158 @@ +import Foundation +import Testing +@testable import RetroXCore + +/// Pasta temporária real, apagada ao fim do teste. +final class TemporaryFolder { + let url: URL + + init() throws { + url = FileManager.default.temporaryDirectory.appending(path: "RetroXTests-\(UUID().uuidString)", directoryHint: .isDirectory) + try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) + } + + deinit { + try? FileManager.default.removeItem(at: url) + } + + @discardableResult + func file(_ relativePath: String, bytes: Int = 0) throws -> URL { + let fileURL = url.appending(path: relativePath, directoryHint: .notDirectory) + try FileManager.default.createDirectory(at: fileURL.deletingLastPathComponent(), withIntermediateDirectories: true) + try Data(count: bytes).write(to: fileURL) + return fileURL + } +} + +struct GameScannerTests { + @Test("Varre recursivamente, ignora caixa da extensão, ocultos e formatos não suportados") + func scans() throws { + let folder = try TemporaryFolder() + try folder.file("roms/Jogo A (USA).iso", bytes: 10) + try folder.file("roms/sub/Jogo B.CHD", bytes: 20) + try folder.file("roms/.oculto.iso") + try folder.file("roms/leia-me.txt") + try folder.file("roms/jogo.zip") + let roms = GameScanner.scan( + [ROMDirectory(url: folder.url.appending(path: "roms"), origin: .rootFolder, isRecursive: true)], + extensions: ["iso", "chd"] + ) + #expect(roms.map(\.url.lastPathComponent).sorted() == ["Jogo A (USA).iso", "Jogo B.CHD"]) + #expect(roms.first { $0.url.lastPathComponent == "Jogo B.CHD" }?.fileSize == 20) + } + + @Test("Pasta não recursiva não desce em subpastas") + func shallow() throws { + let folder = try TemporaryFolder() + try folder.file("A.iso") + try folder.file("sub/B.iso") + let roms = GameScanner.scan([ROMDirectory(url: folder.url, origin: .rootFolder, isRecursive: false)], extensions: ["iso"]) + #expect(roms.map(\.url.lastPathComponent) == ["A.iso"]) + } + + @Test("O mesmo arquivo por duas pastas sobrepostas ou por symlink conta uma vez") + func deduplicates() throws { + let folder = try TemporaryFolder() + let original = try folder.file("roms/A.iso") + try FileManager.default.createDirectory(at: folder.url.appending(path: "atalhos"), withIntermediateDirectories: true) + try FileManager.default.createSymbolicLink(at: folder.url.appending(path: "atalhos/A.iso"), withDestinationURL: original) + let roms = GameScanner.scan([ + ROMDirectory(url: folder.url, origin: .rootFolder, isRecursive: true), + ROMDirectory(url: folder.url.appending(path: "roms"), origin: .emulatorSettings, isRecursive: true), + ], extensions: ["iso"]) + #expect(roms.count == 1) + } + + @Test("Não altera nada nas pastas de jogos") + func readOnly() throws { + let folder = try TemporaryFolder() + let rom = try folder.file("roms/A.iso", bytes: 4) + let before = try FileManager.default.attributesOfItem(atPath: rom.path(percentEncoded: false)) + _ = GameScanner.scan([ROMDirectory(url: folder.url, origin: .rootFolder, isRecursive: true)], extensions: ["iso"]) + let after = try FileManager.default.attributesOfItem(atPath: rom.path(percentEncoded: false)) + #expect(before[.modificationDate] as? Date == after[.modificationDate] as? Date) + #expect(try FileManager.default.contentsOfDirectory(atPath: folder.url.appending(path: "roms").path(percentEncoded: false)) == ["A.iso"]) + } +} + +struct LibraryBuilderTests { + @Test("Monta jogos do plugin com título, sistema e capa") + func buildsGames() throws { + let folder = try TemporaryFolder() + try folder.file("roms/GT 4 Spec II v1.08.iso") + try folder.file("roms/Test Drive Unlimited (USA).iso") + let cover = try folder.file("covers/gt4-cover.png") + var discovery = PluginDiscovery(root: folder.url) + discovery.romDirectories = [ROMDirectory(url: folder.url.appending(path: "roms"), origin: .rootFolder, isRecursive: true)] + discovery.coverDirectories = [folder.url.appending(path: "covers")] + + let games = LibraryBuilder.games(for: PCSX2Plugin(), discovery: discovery) + #expect(games.map(\.title) == ["GT 4 Spec II v1.08", "Test Drive Unlimited (USA)"]) + #expect(games.allSatisfy { $0.systemID == .ps2 && $0.pluginID == .pcsx2 }) + #expect(games[0].coverURL?.lastPathComponent == cover.lastPathComponent) + #expect(games[1].coverURL == nil) + } +} + +struct CoverMatcherTests { + let covers = [ + "gt4-cover.png", "Test Drive Unlimited (USA).jpg", "god of war front.webp", "x.png", "notas.txt", + ].map { URL(filePath: "/capas/\($0)") } + + @Test("Associações esperadas", arguments: [ + ("GT 4 Spec II v1.08.iso", "gt4-cover.png"), + ("Test Drive Unlimited (USA).iso", "Test Drive Unlimited (USA).jpg"), + ("God of War (USA).chd", "god of war front.webp"), + ("Gran Turismo 3.iso", nil), + ("X.iso", nil), + ] as [(String, String?)]) + func matches(rom: String, expected: String?) { + #expect(CoverMatcher.match(romFilename: rom, covers: covers)?.lastPathComponent == expected) + } + + @Test("Nome idêntico vence prefixo") + func exactWins() { + let covers = ["Jogo.png", "Jogo 2.png"].map { URL(filePath: "/c/\($0)") } + #expect(CoverMatcher.match(romFilename: "Jogo 2.iso", covers: covers)?.lastPathComponent == "Jogo 2.png") + } +} + +struct JSONFileStoreTests { + @Test("Salva e relê; arquivo ausente devolve nil") + func roundTrip() throws { + let folder = try TemporaryFolder() + let store = JSONFileStore<[String: GameHistory]>(url: folder.url.appending(path: "sub/historico.json")) + #expect(store.load() == nil) + let value = ["/a.iso": GameHistory(isFavorite: true, lastPlayedAt: Date(timeIntervalSince1970: 1_000_000), playCount: 2)] + try store.save(value) + #expect(store.load() == value) + } +} + +struct PaletteTests { + private func check(_ first: Tone, _ second: Tone, atLeast minimum: Double) { + #expect(HexColor.contrast(first.light, second.light) >= minimum) + #expect(HexColor.contrast(first.dark, second.dark) >= minimum) + } + + @Test("Texto sobre fundos atinge 4,5:1 nos dois modos") + func textContrast() { + for background in [Palette.background, Palette.surface, Palette.raised] { + check(Palette.textPrimary, background, atLeast: 4.5) + check(Palette.textSecondary, background, atLeast: 4.5) + } + } + + @Test("Acentos: texto sobre o preenchimento 4,5:1; anel de foco sobre o fundo 3:1", arguments: Palette.Accent.allCases) + func accentContrast(accent: Palette.Accent) { + check(accent.onFill, accent.fill, atLeast: 4.5) + check(accent.fill, Palette.background, atLeast: 3) + check(accent.fill, Palette.surface, atLeast: 3) + } + + @Test("Texto das capas geradas é legível") + func coverContrast() { + check(Palette.onCover, Palette.coverTone(for: .ps2), atLeast: 4.5) + check(Palette.onCover, Palette.coverTone(for: GameSystemID(rawValue: "outro")), atLeast: 4.5) + } +} diff --git a/Tests/RetroXCoreTests/PCSX2PluginTests.swift b/Tests/RetroXCoreTests/PCSX2PluginTests.swift new file mode 100644 index 0000000..9d83079 --- /dev/null +++ b/Tests/RetroXCoreTests/PCSX2PluginTests.swift @@ -0,0 +1,167 @@ +import Foundation +import Testing +@testable import RetroXCore + +/// Pasta raiz no formato "emulador + roms + capas + bios", com a configuração do PCSX2 fora dela. +struct PluginScenario { + var disk = FakeFileSystem() + let root = "/Emuladores/ps2" + let dataDirectory = "/Dados/PCSX2" + + init(settings: String? = PluginScenario.defaultSettings) { + for folder in [ + "/Emuladores", root, "\(root)/roms", "\(root)/covers", "\(root)/ps2 bios", + "/Outra", "/Outra/Jogos", "/Dados", dataDirectory, "\(dataDirectory)/inis", + ] { + disk[folder] = .directory + } + disk.addAppBundle(at: "\(root)/PCSX2-v2.9.144.app", executable: "PCSX2") + disk["\(root)/roms/Jogo (USA).iso"] = .file() + disk["\(root)/covers/jogo-cover.png"] = .file() + disk["\(root)/ps2 bios/SCPH-0001.bin"] = .file() + if let settings { + disk["\(dataDirectory)/inis/PCSX2.ini"] = .file(Data(settings.utf8)) + } + } + + static let defaultSettings = """ + [UI] + StartFullscreen = true + + [Folders] + Bios = ../../Emuladores/ps2/ps2 bios + + [Filenames] + BIOS = SCPH-0001.bin + + [GameList] + RecursivePaths = /Emuladores/ps2/roms + Paths = /Outra/Jogos + """ + + var plugin: PCSX2Plugin { + PCSX2Plugin(fileSystem: disk, defaultDataDirectory: URL(filePath: dataDirectory, directoryHint: .isDirectory)) + } + + func discover(_ path: String? = nil) -> PluginDiscovery { + plugin.discover(root: URL(filePath: path ?? root, directoryHint: .isDirectory)) + } +} + +private func path(_ url: URL) -> String { + url.standardizedFileURL.path(percentEncoded: false).trimmingSuffix("/") +} + +struct PCSX2PluginTests { + @Test("Encontra app, pastas de jogos, capas e BIOS a partir da pasta raiz e do PCSX2.ini") + func discoversEverything() { + let discovery = PluginScenario().discover() + #expect(discovery.issues.isEmpty) + #expect(discovery.isReady) + #expect(discovery.app?.bundleIdentifier == "net.pcsx2.pcsx2") + #expect(discovery.romDirectories.map { path($0.url) } == ["/Emuladores/ps2/roms", "/Outra/Jogos"]) + // A pasta "roms" aparece na raiz e no PCSX2.ini: fica uma vez só, recursiva, com a origem da raiz. + #expect(discovery.romDirectories[0].origin == .rootFolder) + #expect(discovery.romDirectories[0].isRecursive) + #expect(discovery.romDirectories[1] == ROMDirectory(url: discovery.romDirectories[1].url, origin: .emulatorSettings, isRecursive: false)) + #expect(discovery.coverDirectories.map(path) == ["/Emuladores/ps2/covers"]) + #expect(discovery.bios == .configured("SCPH-0001.bin")) + #expect(discovery.settingsFile.map(path) == "/Dados/PCSX2/inis/PCSX2.ini") + } + + @Test("Escolher o próprio .app usa a pasta que o contém como raiz") + func acceptsAppAsRoot() { + let discovery = PluginScenario().discover("/Emuladores/ps2/PCSX2-v2.9.144.app") + #expect(path(discovery.root) == "/Emuladores/ps2") + #expect(discovery.isReady) + } + + @Test("App numa subpasta da raiz também é encontrado") + func findsNestedApp() { + var scenario = PluginScenario() + for key in scenario.disk.entries.keys where key.hasPrefix("/Emuladores/ps2/PCSX2-v2.9.144.app") { + scenario.disk.entries[key] = nil + } + scenario.disk["/Emuladores/ps2/emulador"] = .directory + scenario.disk.addAppBundle(at: "/Emuladores/ps2/emulador/PCSX2.app", executable: "PCSX2") + #expect(scenario.discover().app.map { path($0.bundleURL) } == "/Emuladores/ps2/emulador/PCSX2.app") + } + + @Test("Modo portátil: lê a configuração ao lado do .app") + func portableMode() { + var scenario = PluginScenario(settings: nil) + scenario.disk["/Emuladores/ps2/portable.ini"] = .file() + scenario.disk["/Emuladores/ps2/inis"] = .directory + scenario.disk["/Emuladores/ps2/inis/PCSX2.ini"] = .file(Data("[Filenames]\nBIOS = SCPH-0001.bin\n[Folders]\nBios = ps2 bios\n".utf8)) + let discovery = scenario.discover() + #expect(discovery.settingsFile.map(path) == "/Emuladores/ps2/inis/PCSX2.ini") + #expect(discovery.bios == .configured("SCPH-0001.bin")) + } + + @Test("Sem configuração do PCSX2: BIOS desconhecida, mas a raiz ainda basta") + func withoutSettings() { + let discovery = PluginScenario(settings: nil).discover() + #expect(discovery.settingsFile == nil) + #expect(discovery.bios == .unknown) + #expect(discovery.romDirectories.map { path($0.url) } == ["/Emuladores/ps2/roms"]) + #expect(discovery.isReady) + } + + @Test("BIOS configurada mas ausente e pasta da lista de jogos que sumiu") + func brokenSettings() { + var scenario = PluginScenario(settings: """ + [Filenames] + BIOS = Sumiu.bin + [GameList] + RecursivePaths = /Disco Externo/PS2 + """) + scenario.disk["/Emuladores/ps2/ps2 bios/SCPH-0001.bin"] = nil + let discovery = scenario.discover() + #expect(discovery.bios == .fileMissing("Sumiu.bin")) + #expect(discovery.issues == [.settingsFolderMissing("/Disco Externo/PS2")]) + } + + @Test("Problemas: raiz inexistente, sem app, sem pastas de jogos") + func issues() { + #expect(PluginScenario().discover("/Nada").issues == [.rootNotFound]) + + var noApp = PluginScenario() + for key in noApp.disk.entries.keys where key.contains(".app") { noApp.disk.entries[key] = nil } + #expect(noApp.discover().issues == [.appNotFound]) + #expect(!noApp.discover().isReady) + + var noGames = PluginScenario(settings: nil) + noGames.disk["/Emuladores/ps2/roms"] = nil + noGames.disk["/Emuladores/ps2/roms/Jogo (USA).iso"] = nil + #expect(noGames.discover().issues == [.noROMDirectories]) + } + + @Test("ROMs soltas na raiz viram uma pasta não recursiva") + func loosROMsAtRoot() { + var scenario = PluginScenario(settings: nil) + scenario.disk["/Emuladores/ps2/Solto.chd"] = .file() + let directories = scenario.discover().romDirectories + #expect(directories.contains(ROMDirectory(url: directories.last!.url, origin: .rootFolder, isRecursive: false))) + #expect(directories.map { path($0.url) }.contains("/Emuladores/ps2")) + } +} + +struct INIFileTests { + @Test("Seções, chaves repetidas, comentários e espaços") + func parses() { + let ini = INIFile(""" + ; comentário + [GameList] + RecursivePaths = /a + recursivepaths=/b c + Paths = + # outro comentário + [Folders] + Bios = ../bios = com igual + """) + #expect(ini.values("RecursivePaths", in: "gamelist") == ["/a", "/b c"]) + #expect(ini.value("Paths", in: "GameList") == nil) + #expect(ini.value("Bios", in: "Folders") == "../bios = com igual") + #expect(ini.value("Bios", in: "GameList") == nil) + } +} diff --git a/Tests/RetroXCoreTests/Support/FakeFileSystem.swift b/Tests/RetroXCoreTests/Support/FakeFileSystem.swift index 9aa954f..419be8e 100644 --- a/Tests/RetroXCoreTests/Support/FakeFileSystem.swift +++ b/Tests/RetroXCoreTests/Support/FakeFileSystem.swift @@ -40,6 +40,14 @@ struct FakeFileSystem: FileSystemProbing { return data.prefix(maxLength) } + func contentsOfDirectory(at url: URL) -> [URL] { + let parent = Self.normalize(url.path(percentEncoded: false)) + return entries.keys + .filter { ($0 as NSString).deletingLastPathComponent == parent && !($0 as NSString).lastPathComponent.hasPrefix(".") } + .sorted() + .map { URL(filePath: $0) } + } + /// Cria um `.app` mínimo: Info.plist e executável com o cabeçalho Mach-O dado. mutating func addAppBundle( at path: String, From b6485234422ad9c9082455580f0575d205ca7568 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 00:34:17 -0300 Subject: [PATCH 13/56] feat(core): serial do disco PS2 e capas do PCSX2 por serial MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PS2DiscReader lê o SYSTEM.CNF de ISOs (ISO 9660, poucos KB, sem hash) e devolve o serial ("SLUS-21490"). - CoverMatcher prefere a capa nomeada pelo serial, que é como o PCSX2 salva as capas que baixa; depois tenta pelo nome. - PCSX2Plugin escolhe a versão mais nova quando há mais de um app. Co-Authored-By: Claude Opus 5.5 --- Sources/RetroXCore/Library/CoverMatcher.swift | 10 ++- Sources/RetroXCore/Library/Game.swift | 5 +- Sources/RetroXCore/Library/GameScanner.swift | 7 +- .../RetroXCore/Library/PS2DiscReader.swift | 83 ++++++++++++++++++ Sources/RetroXCore/Plugins/PCSX2Plugin.swift | 12 +-- .../RetroXCoreTests/PS2DiscReaderTests.swift | 86 +++++++++++++++++++ 6 files changed, 192 insertions(+), 11 deletions(-) create mode 100644 Sources/RetroXCore/Library/PS2DiscReader.swift create mode 100644 Tests/RetroXCoreTests/PS2DiscReaderTests.swift diff --git a/Sources/RetroXCore/Library/CoverMatcher.swift b/Sources/RetroXCore/Library/CoverMatcher.swift index e3f2019..5cc1cfd 100644 --- a/Sources/RetroXCore/Library/CoverMatcher.swift +++ b/Sources/RetroXCore/Library/CoverMatcher.swift @@ -21,8 +21,14 @@ public enum CoverMatcher { .joined() } - /// Prefere o nome idêntico; senão, a capa cujo nome é o prefixo mais longo do nome da ROM (ou vice-versa). - public static func match(romFilename: String, covers: [URL]) -> URL? { + /// Prefere o serial do disco (como o PCSX2 nomeia as capas que baixa); depois o nome idêntico; senão, + /// a capa cujo nome é o prefixo mais longo do nome da ROM (ou vice-versa). + public static func match(romFilename: String, serial: String? = nil, covers: [URL]) -> URL? { + if let serial, let cover = covers.first(where: { + ($0.lastPathComponent as NSString).deletingPathExtension.caseInsensitiveCompare(serial) == .orderedSame + }) { + return cover + } let romKey = key(romFilename) guard romKey.count >= minimumKeyLength else { return nil } var best: (url: URL, length: Int)? diff --git a/Sources/RetroXCore/Library/Game.swift b/Sources/RetroXCore/Library/Game.swift index 88e984d..98ef4f4 100644 --- a/Sources/RetroXCore/Library/Game.swift +++ b/Sources/RetroXCore/Library/Game.swift @@ -9,10 +9,12 @@ public struct Game: Identifiable, Hashable, Sendable { public let pluginID: EmulatorPluginID public let romURL: URL public let fileSize: Int64 + /// Serial do disco ("SLUS-21490"), quando o formato permite ler. + public let serial: String? public let coverURL: URL? public let searchKey: String - public init(romURL: URL, systemID: GameSystemID, pluginID: EmulatorPluginID, fileSize: Int64, coverURL: URL?) { + public init(romURL: URL, systemID: GameSystemID, pluginID: EmulatorPluginID, fileSize: Int64, serial: String? = nil, coverURL: URL?) { let title = TitleParser.displayTitle(fromFilename: romURL.lastPathComponent) self.id = romURL.standardizedFileURL.path(percentEncoded: false) self.title = title @@ -20,6 +22,7 @@ public struct Game: Identifiable, Hashable, Sendable { self.pluginID = pluginID self.romURL = romURL self.fileSize = fileSize + self.serial = serial self.coverURL = coverURL self.searchKey = TitleParser.searchKey(title) } diff --git a/Sources/RetroXCore/Library/GameScanner.swift b/Sources/RetroXCore/Library/GameScanner.swift index bce6517..cbe937f 100644 --- a/Sources/RetroXCore/Library/GameScanner.swift +++ b/Sources/RetroXCore/Library/GameScanner.swift @@ -45,12 +45,15 @@ public enum LibraryBuilder { .filter { CoverMatcher.imageExtensions.contains($0.pathExtension.lowercased()) } return GameScanner.scan(discovery.romDirectories, extensions: extensions) .map { rom in - Game( + // O PCSX2 nomeia as capas que baixa pelo serial do disco. + let serial = system == .ps2 ? PS2DiscReader.serial(of: rom.url) : nil + return Game( romURL: rom.url, systemID: system, pluginID: plugin.id, fileSize: rom.fileSize, - coverURL: CoverMatcher.match(romFilename: rom.url.lastPathComponent, covers: covers) + serial: serial, + coverURL: CoverMatcher.match(romFilename: rom.url.lastPathComponent, serial: serial, covers: covers) ) } .sorted { $0.title.localizedStandardCompare($1.title) == .orderedAscending } diff --git a/Sources/RetroXCore/Library/PS2DiscReader.swift b/Sources/RetroXCore/Library/PS2DiscReader.swift new file mode 100644 index 0000000..b1c55bc --- /dev/null +++ b/Sources/RetroXCore/Library/PS2DiscReader.swift @@ -0,0 +1,83 @@ +import Foundation + +/// Lê o serial de um disco de PS2 em ISO (por exemplo, "SLUS-21490"), do mesmo jeito que o PCSX2 nomeia +/// as capas que baixa. Lê só o descritor de volume, a pasta raiz e o `SYSTEM.CNF`: poucos KB, sem hash +/// e sem alterar o arquivo. Formatos comprimidos (CHD, CSO, ZSO) não são lidos. +public enum PS2DiscReader { + static let sectorSize = 2048 + static let maxDirectorySize = 64 * 1024 + static let maxConfigSize = 4 * 1024 + + public static func serial(of url: URL) -> String? { + guard url.pathExtension.lowercased() == "iso", let handle = try? FileHandle(forReadingFrom: url) else { return nil } + defer { try? handle.close() } + + // Descritor de volume primário no setor 16: tipo 1 + "CD001". + guard let descriptor = read(handle, offset: 16 * sectorSize, length: sectorSize), + descriptor.count == sectorSize, descriptor[0] == 1, + String(decoding: descriptor[1...5], as: UTF8.self) == "CD001" + else { return nil } + let blockSize = Int(descriptor.uint16LE(at: 128) ?? 0) + guard blockSize > 0, + let rootSector = descriptor.uint32LE(at: 156 + 2), + let rootSize = descriptor.uint32LE(at: 156 + 10), + let root = read(handle, offset: Int(rootSector) * blockSize, length: min(Int(rootSize), maxDirectorySize)), + let entry = findFile(named: "SYSTEM.CNF", in: root, blockSize: blockSize), + let config = read(handle, offset: entry.sector * blockSize, length: min(entry.size, maxConfigSize)) + else { return nil } + return serial(fromSystemConfig: String(decoding: config, as: UTF8.self)) + } + + /// `BOOT2 = cdrom0:\SLUS_214.90;1` → "SLUS-21490". Só PS2 (`BOOT2`); discos de PS1 usam `BOOT`. + static func serial(fromSystemConfig text: String) -> String? { + let ini = INIFile(text) + guard let boot = ini.value("BOOT2", in: "") else { return nil } + let file = boot.split(whereSeparator: { $0 == "\\" || $0 == ":" || $0 == "/" }).last.map(String.init) ?? boot + let name = file.split(separator: ";").first.map(String.init) ?? file + let parts = name.split(separator: "_", maxSplits: 1) + guard parts.count == 2, parts[0].count == 4, parts[0].allSatisfy(\.isLetter) else { return nil } + let digits = parts[1].filter(\.isNumber) + guard digits.count == 5 else { return nil } + return "\(parts[0].uppercased())-\(digits)" + } + + private static func findFile(named name: String, in directory: Data, blockSize: Int) -> (sector: Int, size: Int)? { + var offset = 0 + while offset < directory.count { + let length = Int(directory[directory.startIndex + offset]) + if length == 0 { + // Registros não atravessam o fim do bloco: o resto do bloco é preenchimento. + offset = (offset / blockSize + 1) * blockSize + continue + } + guard offset + 33 <= directory.count, length >= 34, offset + length <= directory.count else { return nil } + let nameLength = Int(directory[directory.startIndex + offset + 32]) + guard offset + 33 + nameLength <= offset + length else { return nil } + let start = directory.startIndex + offset + 33 + let entryName = String(decoding: directory[start..<(start + nameLength)], as: UTF8.self) + if entryName.split(separator: ";").first.map({ $0.uppercased() == name }) == true, + let sector = directory.uint32LE(at: offset + 2), let size = directory.uint32LE(at: offset + 10) { + return (Int(sector), Int(size)) + } + offset += length + } + return nil + } + + private static func read(_ handle: FileHandle, offset: Int, length: Int) -> Data? { + guard length > 0, (try? handle.seek(toOffset: UInt64(offset))) != nil else { return nil } + return try? handle.read(upToCount: length) + } +} + +extension Data { + func uint16LE(at offset: Int) -> UInt16? { + guard offset >= 0, offset + 2 <= count else { return nil } + return UInt16(self[startIndex + offset]) | UInt16(self[startIndex + offset + 1]) << 8 + } + + func uint32LE(at offset: Int) -> UInt32? { + guard offset >= 0, offset + 4 <= count else { return nil } + return (0..<4).reduce(UInt32(0)) { value, byte in value | UInt32(self[startIndex + offset + byte]) << (8 * byte) } + } +} diff --git a/Sources/RetroXCore/Plugins/PCSX2Plugin.swift b/Sources/RetroXCore/Plugins/PCSX2Plugin.swift index a93f906..0ceafca 100644 --- a/Sources/RetroXCore/Plugins/PCSX2Plugin.swift +++ b/Sources/RetroXCore/Plugins/PCSX2Plugin.swift @@ -85,12 +85,12 @@ public struct PCSX2Plugin: EmulatorPlugin { let nested = children .filter { fileSystem.kind(of: $0) == .directory && $0.pathExtension.lowercased() != "app" } .flatMap { fileSystem.contentsOfDirectory(at: $0) } - for candidate in (children + nested) where candidate.pathExtension.lowercased() == "app" { - if let info = try? inspector.inspect(candidate), let bundleID = info.bundleIdentifier, expected.contains(bundleID) { - return info - } - } - return nil + let matches = (children + nested) + .filter { $0.pathExtension.lowercased() == "app" } + .compactMap { try? inspector.inspect($0) } + .filter { $0.bundleIdentifier.map(expected.contains) == true } + // Com versões lado a lado (ex.: depois de atualizar), usa a mais nova. + return matches.max { ($0.version ?? "").compare($1.version ?? "", options: .numeric) == .orderedAscending } } /// No modo portátil, o PCSX2 guarda a configuração na pasta que contém o `.app`. diff --git a/Tests/RetroXCoreTests/PS2DiscReaderTests.swift b/Tests/RetroXCoreTests/PS2DiscReaderTests.swift new file mode 100644 index 0000000..a3d7a7f --- /dev/null +++ b/Tests/RetroXCoreTests/PS2DiscReaderTests.swift @@ -0,0 +1,86 @@ +import Foundation +import Testing +@testable import RetroXCore + +/// ISO 9660 mínima: descritor de volume, pasta raiz e um SYSTEM.CNF. Sem nenhum dado de jogo. +enum SyntheticISO { + static func make(systemConfig: String, fileName: String = "SYSTEM.CNF;1") -> Data { + let sector = 2048 + var bytes = [UInt8](repeating: 0, count: 22 * sector) + func put(_ value: UInt32, at offset: Int) { + for byte in 0..<4 { bytes[offset + byte] = UInt8((value >> (8 * UInt32(byte))) & 0xFF) } + } + func record(at offset: Int, sector extent: UInt32, size: UInt32, name: [UInt8]) -> Int { + let length = (33 + name.count + 1) & ~1 + bytes[offset] = UInt8(length) + put(extent, at: offset + 2) + put(size, at: offset + 10) + bytes[offset + 32] = UInt8(name.count) + bytes.replaceSubrange((offset + 33)..<(offset + 33 + name.count), with: name) + return length + } + + let descriptor = 16 * sector + bytes[descriptor] = 1 + bytes.replaceSubrange((descriptor + 1)...(descriptor + 5), with: Array("CD001".utf8)) + bytes[descriptor + 128] = 0x00 + bytes[descriptor + 129] = 0x08 // 2048, little-endian + _ = record(at: descriptor + 156, sector: 20, size: UInt32(sector), name: [0]) + + var offset = 20 * sector + offset += record(at: offset, sector: 20, size: UInt32(sector), name: [0]) + offset += record(at: offset, sector: 20, size: UInt32(sector), name: [1]) + let config = Array(systemConfig.utf8) + _ = record(at: offset, sector: 21, size: UInt32(config.count), name: Array(fileName.utf8)) + bytes.replaceSubrange((21 * sector)..<(21 * sector + config.count), with: config) + return Data(bytes) + } +} + +struct PS2DiscReaderTests { + @Test("Lê o serial do SYSTEM.CNF de uma ISO") + func readsSerial() throws { + let folder = try TemporaryFolder() + let iso = folder.url.appending(path: "Jogo (USA).iso") + try SyntheticISO.make(systemConfig: "BOOT2 = cdrom0:\\SLUS_214.90;1\r\nVER = 1.00\r\nVMODE = NTSC\r\n").write(to: iso) + #expect(PS2DiscReader.serial(of: iso) == "SLUS-21490") + } + + @Test("Sem SYSTEM.CNF, arquivo que não é ISO 9660, ou formato comprimido: sem serial") + func noSerial() throws { + let folder = try TemporaryFolder() + let other = folder.url.appending(path: "Outro.iso") + try SyntheticISO.make(systemConfig: "x", fileName: "README.TXT;1").write(to: other) + #expect(PS2DiscReader.serial(of: other) == nil) + #expect(PS2DiscReader.serial(of: try folder.file("Vazio.iso", bytes: 40_000)) == nil) + #expect(PS2DiscReader.serial(of: try folder.file("Jogo.chd", bytes: 10)) == nil) + } + + @Test("Formatos do BOOT2", arguments: [ + ("BOOT2 = cdrom0:\\SLUS_214.90;1", "SLUS-21490"), + ("boot2=cdrom0:\\sces_502.94;1", "SCES-50294"), + ("BOOT2 = cdrom0:\\SLES_556.76;1\nVER = 1.01", "SLES-55676"), + ("BOOT = cdrom:\\SLUS_000.01;1", nil), + ("BOOT2 = cdrom0:\\GAME.ELF;1", nil), + ] as [(String, String?)]) + func parsesBootLine(text: String, expected: String?) { + #expect(PS2DiscReader.serial(fromSystemConfig: text) == expected) + } + + @Test("Capa nomeada pelo serial vence a capa pelo nome") + func serialCoverWins() { + let covers = ["Test Drive Unlimited (USA).png", "SLUS-21490.jpg"].map { URL(filePath: "/c/\($0)") } + let match = CoverMatcher.match(romFilename: "Test Drive Unlimited (USA).iso", serial: "SLUS-21490", covers: covers) + #expect(match?.lastPathComponent == "SLUS-21490.jpg") + } +} + +struct PCSX2PluginVersionTests { + @Test("Com duas versões na pasta, usa a mais nova (comparação numérica)") + func prefersNewestVersion() { + var scenario = PluginScenario(settings: nil) + scenario.disk.addAppBundle(at: "/Emuladores/ps2/PCSX2-v2.10.0.app", executable: "PCSX2", version: "v2.10.0") + scenario.disk.addAppBundle(at: "/Emuladores/ps2/PCSX2-v2.9.147.app", executable: "PCSX2", version: "v2.9.147") + #expect(scenario.discover().app?.version == "v2.10.0") + } +} From edaf836110197f070d4b518db3bbb138dc2d7175 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 00:34:17 -0300 Subject: [PATCH 14/56] =?UTF-8?q?fix(core):=20emulador=20rec=C3=A9m-fechad?= =?UTF-8?q?o=20n=C3=A3o=20conta=20mais=20como=20aberto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O LaunchServices ainda lista o app por um instante depois que o processo termina; jogar de novo logo em seguida dava "já aberto". Agora só conta como aberto se o processo existe (kill(pid, 0)). Achado pela integração com o emulador falso. Co-Authored-By: Claude Opus 5.5 --- .../RetroXCore/Support/RunningApplications.swift | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Sources/RetroXCore/Support/RunningApplications.swift b/Sources/RetroXCore/Support/RunningApplications.swift index 1024ab0..e040970 100644 --- a/Sources/RetroXCore/Support/RunningApplications.swift +++ b/Sources/RetroXCore/Support/RunningApplications.swift @@ -10,14 +10,19 @@ public struct WorkspaceRunningApplications: RunningApplicationsProviding { public init() {} public func isRunning(bundleIdentifier: String) -> Bool { - NSRunningApplication.runningApplications(withBundleIdentifier: bundleIdentifier).contains { !$0.isTerminated } + Self.alive(bundleIdentifier).first != nil } @discardableResult public func activate(bundleIdentifier: String) -> Bool { - guard let app = NSRunningApplication.runningApplications(withBundleIdentifier: bundleIdentifier) - .first(where: { !$0.isTerminated }) - else { return false } - return app.activate() + Self.alive(bundleIdentifier).first?.activate() ?? false + } + + /// Logo depois que um app fecha, o LaunchServices ainda o lista por um instante; o processo, não. + /// Sem esse filtro, jogar de novo logo após fechar o emulador daria "já aberto". + private static func alive(_ bundleIdentifier: String) -> [NSRunningApplication] { + NSRunningApplication.runningApplications(withBundleIdentifier: bundleIdentifier).filter { + !$0.isTerminated && kill($0.processIdentifier, 0) == 0 + } } } From 70726f5d316c6e2ebbfe765138106ca6b58b39e1 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 00:34:17 -0300 Subject: [PATCH 15/56] =?UTF-8?q?feat(app):=20home=20de=20port=C3=A1til,?= =?UTF-8?q?=20emuladores=20como=20plugins=20e=20novo=20visual?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Substitui a janela de prova técnica, cujo seletor de arquivos perdia a escolha: o fileImporter zerava o estado antes de entregar o arquivo. - Home "Portátil quente": palco com o jogo em foco, prateleira de capas (Recentes, Todos, Favoritos) com a capa em foco subindo, halo na cor de tema e reflexo no chão; barra de comandos com os glifos do controle conectado ou as teclas. - Emuladores: ativar o plugin, escolher a pasta raiz (NSOpenPanel) e ver o que foi encontrado (app, jogos, capas, BIOS do PCSX2.ini). - Detalhes do jogo (com o argv exato), sobreposição da partida com recuperação de erros, Ajustes de aparência e cor de tema. - Teclado e controle (GameController) passam pelo mesmo roteador; Reduce Motion respeitado; anúncios para VoiceOver. - Favoritos e histórico persistidos em JSON até a Fase 2. - Argumentos de revisão visual: -RetroXSnapshot e -RetroXInitialScreen. Co-Authored-By: Claude Opus 5.5 --- Sources/RetroXApp/App/AppModel.swift | 141 ++++++++ Sources/RetroXApp/App/DebugSnapshot.swift | 17 + Sources/RetroXApp/App/FilePanel.swift | 25 ++ Sources/RetroXApp/App/LibraryModel.swift | 142 ++++++++ Sources/RetroXApp/App/PluginsModel.swift | 93 +++++ Sources/RetroXApp/App/SessionModel.swift | 105 ++++++ .../RetroXApp/DesignSystem/Components.swift | 129 +++++++ .../RetroXApp/DesignSystem/CoverArtView.swift | 63 ++++ .../DesignSystem/CoverImageStore.swift | 28 ++ Sources/RetroXApp/DesignSystem/Theme.swift | 104 ++++++ .../Features/Details/GameDetailsView.swift | 117 +++++++ .../Features/Emulators/EmulatorsView.swift | 274 +++++++++++++++ .../RetroXApp/Features/Home/HomeView.swift | 321 ++++++++++++++++++ .../RetroXApp/Features/Home/ShelfView.swift | 154 +++++++++ .../Features/Launch/LaunchView.swift | 193 ----------- .../Features/Launch/LaunchViewModel.swift | 133 -------- .../Features/Session/SessionOverlay.swift | 127 +++++++ .../Features/Settings/SettingsView.swift | 54 +++ .../RetroXApp/Input/InputCoordinator.swift | 103 ++++++ Sources/RetroXApp/RetroXApp.swift | 73 +++- 20 files changed, 2066 insertions(+), 330 deletions(-) create mode 100644 Sources/RetroXApp/App/AppModel.swift create mode 100644 Sources/RetroXApp/App/DebugSnapshot.swift create mode 100644 Sources/RetroXApp/App/FilePanel.swift create mode 100644 Sources/RetroXApp/App/LibraryModel.swift create mode 100644 Sources/RetroXApp/App/PluginsModel.swift create mode 100644 Sources/RetroXApp/App/SessionModel.swift create mode 100644 Sources/RetroXApp/DesignSystem/Components.swift create mode 100644 Sources/RetroXApp/DesignSystem/CoverArtView.swift create mode 100644 Sources/RetroXApp/DesignSystem/CoverImageStore.swift create mode 100644 Sources/RetroXApp/DesignSystem/Theme.swift create mode 100644 Sources/RetroXApp/Features/Details/GameDetailsView.swift create mode 100644 Sources/RetroXApp/Features/Emulators/EmulatorsView.swift create mode 100644 Sources/RetroXApp/Features/Home/HomeView.swift create mode 100644 Sources/RetroXApp/Features/Home/ShelfView.swift delete mode 100644 Sources/RetroXApp/Features/Launch/LaunchView.swift delete mode 100644 Sources/RetroXApp/Features/Launch/LaunchViewModel.swift create mode 100644 Sources/RetroXApp/Features/Session/SessionOverlay.swift create mode 100644 Sources/RetroXApp/Features/Settings/SettingsView.swift create mode 100644 Sources/RetroXApp/Input/InputCoordinator.swift diff --git a/Sources/RetroXApp/App/AppModel.swift b/Sources/RetroXApp/App/AppModel.swift new file mode 100644 index 0000000..41d643d --- /dev/null +++ b/Sources/RetroXApp/App/AppModel.swift @@ -0,0 +1,141 @@ +import AppKit +import Observation +import RetroXCore + +/// Raiz do estado do app: navegação, plugins, biblioteca, partida e entrada. +@MainActor +@Observable +final class AppModel { + enum Screen { + case home, emulators + } + + var screen: Screen = .home + var detailsGame: Game? + + let plugins = PluginsModel() + let library = LibraryModel() + let session = SessionModel() + let covers = CoverImageStore() + let input = InputCoordinator() + + init() { + // Para revisão visual sem clicar: `open RetroX.app --args -RetroXInitialScreen emulators`. + if UserDefaults.standard.string(forKey: "RetroXInitialScreen") == "emulators" { + screen = .emulators + } + input.onAction = { [weak self] action in self?.handle(action) } + session.onLaunched = { [weak self] game, date in self?.library.recordPlay(game, at: date) } + } + + func start() async { + await plugins.discoverAll() + await reloadLibrary() + } + + func reloadLibrary() async { + await library.reload(from: plugins.readyPlugins) + } + + // MARK: Plugins + + func setPlugin(_ id: EmulatorPluginID, enabled: Bool) async { + await plugins.setEnabled(id, enabled) + await reloadLibrary() + } + + func chooseRoot(for id: EmulatorPluginID) async { + await plugins.chooseRoot(for: id) + await reloadLibrary() + } + + func rediscover(_ id: EmulatorPluginID) async { + await plugins.discover(id) + await reloadLibrary() + } + + // MARK: Jogos + + func play(_ game: Game) { + detailsGame = nil + guard let entry = plugins.entry(game.pluginID) else { return } + Task { await session.play(game, plugin: entry.plugin, app: entry.discovery?.app) } + } + + func plan(for game: Game) -> Result { + guard let entry = plugins.entry(game.pluginID), let app = entry.discovery?.app else { + return .failure(.emulatorNotConfigured(game.systemID)) + } + do { + return .success(try session.plan(for: game, plugin: entry.plugin, app: app)) + } catch { + return .failure(error) + } + } + + func perform(_ action: RecoveryAction, for game: Game) { + switch action { + case .chooseEmulator, .openSettings: + session.dismiss() + screen = .emulators + case .locateROM: + session.dismiss() + Task { await reloadLibrary() } + case .retry: + session.dismiss() + play(game) + case .bringEmulatorToFront: + session.bringEmulatorToFront() + case .showRosettaHelp: + break + } + } + + // MARK: Entrada + + /// Um só roteador para teclado e controle: a mesma ação faz a mesma coisa em qualquer dispositivo. + func handle(_ action: InputAction) { + if session.isPresenting { + handleSession(action) + } else if let game = detailsGame { + switch action { + case .confirm: play(game) + case .back, .details: detailsGame = nil + case .favorite: library.toggleFavorite(game) + default: break + } + } else if screen == .emulators { + if action == .back || action == .menu { screen = .home } + } else { + handleHome(action) + } + } + + private func handleHome(_ action: InputAction) { + switch action { + case .left: library.moveFocus(by: -1) + case .right: library.moveFocus(by: 1) + case .up, .previousShelf: library.cycleShelf(by: -1) + case .down, .nextShelf: library.cycleShelf(by: 1) + case .confirm: library.focusedGame.map(play) + case .details: detailsGame = library.focusedGame + case .favorite: library.focusedGame.map(library.toggleFavorite) + case .menu: screen = .emulators + case .back: break + } + } + + private func handleSession(_ action: InputAction) { + switch session.phase { + case .running: + if action == .confirm { session.bringEmulatorToFront() } + case .failed(let game, let error): + if action == .confirm, let first = error.recoveryActions.first { perform(first, for: game) } + if action == .back { session.dismiss() } + case .ended: + if action == .back || action == .confirm { session.dismiss() } + case .idle, .launching: + break + } + } +} diff --git a/Sources/RetroXApp/App/DebugSnapshot.swift b/Sources/RetroXApp/App/DebugSnapshot.swift new file mode 100644 index 0000000..41112be --- /dev/null +++ b/Sources/RetroXApp/App/DebugSnapshot.swift @@ -0,0 +1,17 @@ +import AppKit + +/// Revisão visual sem permissão de Gravação de Tela: o app grava a própria janela em PNG. +/// `open RetroX.app --args -RetroXSnapshot /caminho/tela.png [-RetroXInitialScreen emulators]` +@MainActor +enum DebugSnapshot { + static func captureIfRequested() async { + guard let path = UserDefaults.standard.string(forKey: "RetroXSnapshot") else { return } + try? await Task.sleep(for: .seconds(3)) + guard let window = NSApp.windows.first(where: { $0.isVisible && $0.contentView != nil }), + let view = window.contentView, + let representation = view.bitmapImageRepForCachingDisplay(in: view.bounds) + else { return } + view.cacheDisplay(in: view.bounds, to: representation) + try? representation.representation(using: .png, properties: [:])?.write(to: URL(filePath: path)) + } +} diff --git a/Sources/RetroXApp/App/FilePanel.swift b/Sources/RetroXApp/App/FilePanel.swift new file mode 100644 index 0000000..2fa7c9a --- /dev/null +++ b/Sources/RetroXApp/App/FilePanel.swift @@ -0,0 +1,25 @@ +import AppKit + +/// Seletor nativo de pasta. Usa `NSOpenPanel` diretamente: o `fileImporter` do SwiftUI fechava o seletor +/// antes de entregar a escolha, e a escolha se perdia. +@MainActor +enum FilePanel { + static func chooseFolder(message: String, startingAt directory: URL?) async -> URL? { + let panel = NSOpenPanel() + panel.message = message + panel.prompt = String(localized: "Escolher") + panel.canChooseDirectories = true + panel.canChooseFiles = false + panel.allowsMultipleSelection = false + panel.canCreateDirectories = false + panel.directoryURL = directory + let response = await withCheckedContinuation { continuation in + if let window = NSApp.keyWindow { + panel.beginSheetModal(for: window) { continuation.resume(returning: $0) } + } else { + panel.begin { continuation.resume(returning: $0) } + } + } + return response == .OK ? panel.url : nil + } +} diff --git a/Sources/RetroXApp/App/LibraryModel.swift b/Sources/RetroXApp/App/LibraryModel.swift new file mode 100644 index 0000000..26f2510 --- /dev/null +++ b/Sources/RetroXApp/App/LibraryModel.swift @@ -0,0 +1,142 @@ +import Foundation +import Observation +import RetroXCore + +/// Os jogos dos plugins prontos, organizados em prateleiras, com o jogo em foco. +@MainActor +@Observable +final class LibraryModel { + enum Shelf: Hashable, Identifiable { + case recent, all, favorites + case system(GameSystemID) + + var id: Self { self } + + var title: String { + switch self { + case .recent: String(localized: "Recentes") + case .all: String(localized: "Todos") + case .favorites: String(localized: "Favoritos") + case .system(let id): SystemCatalog.system(id)?.shortName ?? id.rawValue + } + } + } + + private(set) var games: [Game] = [] + private(set) var history: [String: GameHistory] + private(set) var isScanning = false + private(set) var hasLoaded = false + private(set) var shelf: Shelf = .all + private(set) var focusedGameID: Game.ID? + + @ObservationIgnored private let store: JSONFileStore<[String: GameHistory]> + + init(store: JSONFileStore<[String: GameHistory]> = JSONFileStore(url: RetroXDirectories.applicationSupport.appending(path: "history.json"))) { + self.store = store + history = store.load() ?? [:] + } + + var shelves: [Shelf] { + var result: [Shelf] = [] + if games.contains(where: { history[$0.id]?.lastPlayedAt != nil }) { result.append(.recent) } + result += [.all, .favorites] + let systems = Set(games.map(\.systemID)) + if systems.count > 1 { + result += SystemCatalog.all.map(\.id).filter(systems.contains).map(Shelf.system) + } + return result + } + + var visibleGames: [Game] { + switch shelf { + case .all: + games + case .favorites: + games.filter { history[$0.id]?.isFavorite == true } + case .recent: + games + .filter { history[$0.id]?.lastPlayedAt != nil } + .sorted { (history[$0.id]?.lastPlayedAt ?? .distantPast) > (history[$1.id]?.lastPlayedAt ?? .distantPast) } + case .system(let id): + games.filter { $0.systemID == id } + } + } + + var focusedIndex: Int? { + let visible = visibleGames + return visible.firstIndex { $0.id == focusedGameID } ?? (visible.isEmpty ? nil : 0) + } + + var focusedGame: Game? { + focusedIndex.map { visibleGames[$0] } + } + + func history(for game: Game) -> GameHistory { + history[game.id] ?? GameHistory() + } + + func gameCount(for plugin: EmulatorPluginID) -> Int { + games.filter { $0.pluginID == plugin }.count + } + + func reload(from ready: [(any EmulatorPlugin, PluginDiscovery)]) async { + isScanning = true + let scanned = await Task.detached(priority: .userInitiated) { + ready.flatMap { plugin, discovery in LibraryBuilder.games(for: plugin, discovery: discovery) } + }.value + let isFirstLoad = !hasLoaded + games = scanned + hasLoaded = true + isScanning = false + if isFirstLoad, shelves.contains(.recent) { + shelf = .recent + } else if !shelves.contains(shelf) { + shelf = .all + } + if focusedGame?.id != focusedGameID { + focusedGameID = visibleGames.first?.id + } + } + + func focus(_ game: Game) { + focusedGameID = game.id + } + + func moveFocus(by offset: Int) { + let visible = visibleGames + guard let index = focusedIndex, !visible.isEmpty else { return } + focusedGameID = visible[min(max(index + offset, 0), visible.count - 1)].id + } + + func select(_ shelf: Shelf) { + guard shelf != self.shelf else { return } + let previous = focusedGameID + self.shelf = shelf + // Mantém o mesmo jogo em foco se ele também está na nova prateleira. + focusedGameID = visibleGames.contains { $0.id == previous } ? previous : visibleGames.first?.id + } + + func cycleShelf(by offset: Int) { + let all = shelves + guard let index = all.firstIndex(of: shelf) else { return select(.all) } + select(all[(index + offset + all.count) % all.count]) + } + + func toggleFavorite(_ game: Game) { + edit(game) { $0.isFavorite.toggle() } + } + + func recordPlay(_ game: Game, at date: Date) { + edit(game) { + $0.lastPlayedAt = date + $0.playCount += 1 + } + } + + private func edit(_ game: Game, _ change: (inout GameHistory) -> Void) { + var entry = history[game.id] ?? GameHistory() + change(&entry) + history[game.id] = entry + try? store.save(history) + } +} diff --git a/Sources/RetroXApp/App/PluginsModel.swift b/Sources/RetroXApp/App/PluginsModel.swift new file mode 100644 index 0000000..dda2370 --- /dev/null +++ b/Sources/RetroXApp/App/PluginsModel.swift @@ -0,0 +1,93 @@ +import Foundation +import Observation +import RetroXCore + +/// Emuladores (plugins) que o usuário ativou, a pasta raiz de cada um e o que foi encontrado nela. +@MainActor +@Observable +final class PluginsModel { + struct Entry: Identifiable { + let plugin: any EmulatorPlugin + var config: PluginConfig + var discovery: PluginDiscovery? + var isDiscovering = false + + var id: EmulatorPluginID { plugin.id } + var rootURL: URL? { config.rootPath.map { URL(filePath: $0, directoryHint: .isDirectory) } } + var isReady: Bool { config.isEnabled && discovery?.isReady == true } + } + + private(set) var entries: [Entry] + @ObservationIgnored private let store: JSONFileStore<[String: PluginConfig]> + + init( + catalog: [any EmulatorPlugin] = PluginCatalog.available, + store: JSONFileStore<[String: PluginConfig]> = JSONFileStore(url: RetroXDirectories.applicationSupport.appending(path: "plugins.json")) + ) { + self.store = store + let saved = store.load() ?? [:] + entries = catalog.map { Entry(plugin: $0, config: saved[$0.id.rawValue] ?? PluginConfig()) } + } + + var readyPlugins: [(any EmulatorPlugin, PluginDiscovery)] { + entries.compactMap { entry in + guard entry.isReady, let discovery = entry.discovery else { return nil } + return (entry.plugin, discovery) + } + } + + var hasEnabledPlugin: Bool { entries.contains { $0.config.isEnabled } } + + func entry(_ id: EmulatorPluginID) -> Entry? { + entries.first { $0.id == id } + } + + /// Ativar sem pasta raiz abre o seletor; cancelar o seletor deixa o plugin desativado. + func setEnabled(_ id: EmulatorPluginID, _ isEnabled: Bool) async { + guard let entry = entry(id) else { return } + if isEnabled, entry.config.rootPath == nil { + await chooseRoot(for: id) + return + } + update(id) { $0.config.isEnabled = isEnabled } + if isEnabled, entry.discovery == nil { await discover(id) } + } + + func chooseRoot(for id: EmulatorPluginID) async { + guard let entry = entry(id) else { return } + let message = String(localized: "Escolha a pasta do \(entry.plugin.displayName): a que tem o app do emulador e as pastas de jogos.") + guard let url = await FilePanel.chooseFolder(message: message, startingAt: entry.rootURL) else { return } + update(id) { + $0.config.rootPath = url.path(percentEncoded: false) + $0.config.isEnabled = true + $0.discovery = nil + } + await discover(id) + } + + func discover(_ id: EmulatorPluginID) async { + guard let entry = entry(id), let root = entry.rootURL else { return } + update(id) { $0.isDiscovering = true } + let plugin = entry.plugin + let discovery = await Task.detached(priority: .userInitiated) { plugin.discover(root: root) }.value + update(id) { + $0.discovery = discovery + $0.isDiscovering = false + } + } + + func discoverAll() async { + for entry in entries where entry.config.isEnabled { + await discover(entry.id) + } + } + + private func update(_ id: EmulatorPluginID, _ change: (inout Entry) -> Void) { + guard let index = entries.firstIndex(where: { $0.id == id }) else { return } + let previous = entries[index].config + change(&entries[index]) + if entries[index].config != previous { + try? store.save(Dictionary(uniqueKeysWithValues: entries.map { ($0.id.rawValue, $0.config) })) + } + } +} diff --git a/Sources/RetroXApp/App/SessionModel.swift b/Sources/RetroXApp/App/SessionModel.swift new file mode 100644 index 0000000..399381f --- /dev/null +++ b/Sources/RetroXApp/App/SessionModel.swift @@ -0,0 +1,105 @@ +import AppKit +import Observation +import RetroXCore + +/// Uma partida: abrir o emulador, acompanhar enquanto ele roda e voltar à frente quando ele fecha. +@MainActor +@Observable +final class SessionModel { + enum Phase: Equatable { + case idle + case launching(Game) + case running(Game, emulator: String) + case ended(Game, after: Duration) + case failed(Game, LaunchError) + } + + private(set) var phase: Phase = .idle + private(set) var warnings: [LaunchWarning] = [] + + @ObservationIgnored var onLaunched: ((Game, Date) -> Void)? + @ObservationIgnored private let launcher: GameLauncher + @ObservationIgnored private let runningApplications: any RunningApplicationsProviding + @ObservationIgnored private var runningBundleID: String? + @ObservationIgnored private var dismissTask: Task? + + init(launcher: GameLauncher = GameLauncher(), runningApplications: any RunningApplicationsProviding = WorkspaceRunningApplications()) { + self.launcher = launcher + self.runningApplications = runningApplications + } + + var isPresenting: Bool { phase != .idle } + + var isBusy: Bool { + switch phase { + case .launching, .running: true + default: false + } + } + + /// O plano que seria usado, sem abrir nada (aparece nos detalhes do jogo). + func plan(for game: Game, plugin: any EmulatorPlugin, app: AppBundleInfo) throws(LaunchError) -> PreparedLaunch { + try launcher.prepare(request(for: game, plugin: plugin, app: app)) + } + + func play(_ game: Game, plugin: any EmulatorPlugin, app: AppBundleInfo?) async { + guard !isBusy else { return } + dismissTask?.cancel() + guard let app else { + phase = .failed(game, .emulatorNotConfigured(game.systemID)) + return + } + phase = .launching(game) + do { + let prepared = try launcher.prepare(request(for: game, plugin: plugin, app: app)) + warnings = prepared.warnings + let launched = try await launcher.launch(prepared) + runningBundleID = launched.plan.bundleIdentifier + phase = .running(game, emulator: plugin.displayName) + onLaunched?(game, launched.launchedAt) + guard let exit = await launched.waitForExit() else { return } + switch SessionOutcome.classify(launchedAt: launched.launchedAt, exit: exit) { + case .ended(let after): + phase = .ended(game, after: after) + scheduleDismiss() + case .exitedEarly(let status, let after): + phase = .failed(game, .exitedEarly(status: status, after: after)) + } + NSApplication.shared.activate() + } catch { + phase = .failed(game, error) + } + } + + func bringEmulatorToFront() { + let bundleID: String? = switch phase { + case .failed(_, .emulatorAlreadyRunning(let id)): id + default: runningBundleID + } + if let bundleID { runningApplications.activate(bundleIdentifier: bundleID) } + } + + func dismiss() { + guard !isBusy else { return } + dismissTask?.cancel() + phase = .idle + } + + private func scheduleDismiss() { + dismissTask = Task { [weak self] in + try? await Task.sleep(for: .seconds(3)) + guard !Task.isCancelled else { return } + self?.dismiss() + } + } + + private func request(for game: Game, plugin: any EmulatorPlugin, app: AppBundleInfo) -> LaunchRequest { + let profile = EmulatorProfile( + name: plugin.displayName, + adapterID: plugin.adapter.id, + appURL: app.bundleURL, + options: plugin.adapter.defaultOptions + ) + return LaunchRequest(romURL: game.romURL, systemID: game.systemID, profile: profile) + } +} diff --git a/Sources/RetroXApp/DesignSystem/Components.swift b/Sources/RetroXApp/DesignSystem/Components.swift new file mode 100644 index 0000000..ba50068 --- /dev/null +++ b/Sources/RetroXApp/DesignSystem/Components.swift @@ -0,0 +1,129 @@ +import RetroXCore +import SwiftUI + +/// Ação principal: preenchida com a cor de tema. +struct PrimaryButtonStyle: ButtonStyle { + @Environment(\.accent) private var accent + @Environment(\.isEnabled) private var isEnabled + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .font(Typography.bodyEmphasis) + .foregroundStyle(Color(accent.onFill)) + .padding(.horizontal, Spacing.l) + .frame(minHeight: 44) + .background(Color(accent.fill).opacity(configuration.isPressed ? 0.85 : 1), in: Capsule()) + .opacity(isEnabled ? 1 : 0.45) + .contentShape(Capsule()) + } +} + +/// Ação secundária: superfície neutra, sem cor de tema. +struct SecondaryButtonStyle: ButtonStyle { + @Environment(\.isEnabled) private var isEnabled + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.textPrimary) + .padding(.horizontal, Spacing.m) + .frame(minHeight: 44) + .background(Theme.raised.opacity(configuration.isPressed ? 0.7 : 1), in: Capsule()) + .opacity(isEnabled ? 1 : 0.45) + .contentShape(Capsule()) + } +} + +/// Botão redondo só com ícone (favoritar, detalhes). Sempre com rótulo para VoiceOver. +struct IconButtonStyle: ButtonStyle { + var isActive = false + @Environment(\.accent) private var accent + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .font(.system(size: 17, weight: .semibold)) + .foregroundStyle(isActive ? Color(accent.onFill) : Theme.textPrimary) + .frame(width: 44, height: 44) + .background(isActive ? Color(accent.fill) : Theme.raised, in: Circle()) + .opacity(configuration.isPressed ? 0.8 : 1) + .contentShape(Circle()) + } +} + +/// Dica de comando na barra inferior: glifo do controle conectado ou tecla do teclado. +struct CommandHint: View { + /// Símbolos SF do controle conectado; `nil` mostra a tecla. + let glyphs: [String]? + let key: String + let label: String + + var body: some View { + HStack(spacing: Spacing.s) { + if let glyphs { + HStack(spacing: Spacing.xs) { + ForEach(glyphs, id: \.self) { glyph in + Image(systemName: glyph) + .font(.system(size: 17, weight: .semibold)) + } + } + } else { + Text(key) + .font(.system(size: 11, weight: .semibold, design: .rounded)) + .padding(.horizontal, Spacing.s) + .frame(minWidth: 24, minHeight: 22) + .background(Theme.raised, in: RoundedRectangle(cornerRadius: 6, style: .continuous)) + } + Text(label) + .font(Typography.caption) + } + .foregroundStyle(Theme.textSecondary) + .accessibilityElement(children: .ignore) + .accessibilityLabel("\(label): \(glyphs == nil ? key : String(localized: "botão do controle"))") + } +} + +/// Linha de verificação na tela de emuladores: ícone de estado + texto. +struct StatusLine: View { + enum Kind { + case ok, warning, info + + var symbol: String { + switch self { + case .ok: "checkmark.circle.fill" + case .warning: "exclamationmark.triangle.fill" + case .info: "info.circle" + } + } + } + + let kind: Kind + let text: String + @Environment(\.accent) private var accent + + var body: some View { + Label { + Text(text) + .font(Typography.body) + .foregroundStyle(kind == .info ? Theme.textSecondary : Theme.textPrimary) + .fixedSize(horizontal: false, vertical: true) + } icon: { + Image(systemName: kind.symbol) + .foregroundStyle(kind == .ok ? Color(accent.fill) : Theme.textSecondary) + } + } +} + +/// Selo quadrado com a sigla do sistema (no lugar de logotipos de terceiros). +struct SystemBadge: View { + let system: GameSystemID + var size: CGFloat = 48 + + var body: some View { + Text(SystemCatalog.system(system)?.shortName ?? system.rawValue.uppercased()) + .font(.system(size: size * 0.3, weight: .heavy, design: .rounded)) + .foregroundStyle(Theme.onCover) + .frame(width: size, height: size) + .background(Theme.coverTone(system), in: RoundedRectangle(cornerRadius: Radius.m, style: .continuous)) + .accessibilityHidden(true) + } +} diff --git a/Sources/RetroXApp/DesignSystem/CoverArtView.swift b/Sources/RetroXApp/DesignSystem/CoverArtView.swift new file mode 100644 index 0000000..ae66b54 --- /dev/null +++ b/Sources/RetroXApp/DesignSystem/CoverArtView.swift @@ -0,0 +1,63 @@ +import RetroXCore +import SwiftUI + +/// Capa do jogo na proporção 5:7. Sem imagem local, desenha uma capa própria: tom do sistema, +/// sigla e título, e um disco em relevo discreto. Nada de arte de terceiros. +struct CoverArtView: View { + let game: Game + let width: CGFloat + @Environment(CoverImageStore.self) private var covers + + static let aspectRatio: CGFloat = 7 / 5 + + var body: some View { + ZStack { + if let image = covers.image(for: game.coverURL) { + Image(nsImage: image) + .resizable() + .aspectRatio(contentMode: .fill) + .transition(.opacity) + } else { + GeneratedCover(game: game, width: width) + } + } + .frame(width: width, height: width * Self.aspectRatio) + .clipShape(RoundedRectangle(cornerRadius: Radius.m, style: .continuous)) + .overlay { + RoundedRectangle(cornerRadius: Radius.m, style: .continuous) + .strokeBorder(.white.opacity(0.06), lineWidth: 1) + } + .task(id: game.coverURL) { + if let url = game.coverURL { await covers.load(url) } + } + .accessibilityHidden(true) + } +} + +private struct GeneratedCover: View { + let game: Game + let width: CGFloat + + var body: some View { + ZStack(alignment: .topLeading) { + Theme.coverTone(game.systemID) + Circle() + .strokeBorder(Theme.onCover.opacity(0.07), lineWidth: width * 0.09) + .frame(width: width * 0.9, height: width * 0.9) + .offset(x: width * 0.38, y: width * 0.78) + VStack(alignment: .leading, spacing: width * 0.04) { + Text(SystemCatalog.system(game.systemID)?.shortName ?? "") + .font(.system(size: max(width * 0.075, 9), weight: .heavy, design: .rounded)) + .tracking(1.5) + .foregroundStyle(Theme.onCover.opacity(0.75)) + Spacer(minLength: 0) + Text(game.title) + .font(.system(size: max(width * 0.12, 11), weight: .bold, design: .rounded)) + .foregroundStyle(Theme.onCover) + .lineLimit(4) + .minimumScaleFactor(0.7) + } + .padding(width * 0.09) + } + } +} diff --git a/Sources/RetroXApp/DesignSystem/CoverImageStore.swift b/Sources/RetroXApp/DesignSystem/CoverImageStore.swift new file mode 100644 index 0000000..f509735 --- /dev/null +++ b/Sources/RetroXApp/DesignSystem/CoverImageStore.swift @@ -0,0 +1,28 @@ +import AppKit +import Observation +import RetroXCore + +/// Capas já reduzidas, decodificadas fora da main thread e guardadas em memória (ADR-0008). +@MainActor +@Observable +final class CoverImageStore { + private var images: [URL: NSImage] = [:] + @ObservationIgnored private var inFlight: Set = [] + + nonisolated static let maxPixelSize = 900 + + func image(for url: URL?) -> NSImage? { + url.flatMap { images[$0] } + } + + func load(_ url: URL) async { + guard images[url] == nil, inFlight.insert(url).inserted else { return } + let cgImage = await Task.detached(priority: .utility) { + CoverThumbnailer.thumbnail(of: url, maxPixelSize: Self.maxPixelSize) + }.value + inFlight.remove(url) + if let cgImage { + images[url] = NSImage(cgImage: cgImage, size: NSSize(width: cgImage.width, height: cgImage.height)) + } + } +} diff --git a/Sources/RetroXApp/DesignSystem/Theme.swift b/Sources/RetroXApp/DesignSystem/Theme.swift new file mode 100644 index 0000000..7704bba --- /dev/null +++ b/Sources/RetroXApp/DesignSystem/Theme.swift @@ -0,0 +1,104 @@ +import AppKit +import RetroXCore +import SwiftUI + +extension Color { + /// Cor que acompanha o modo claro/escuro, a partir de um token da paleta. + init(_ tone: Tone) { + self.init(nsColor: NSColor(name: nil) { appearance in + let isDark = appearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua + let color = isDark ? tone.dark : tone.light + return NSColor(srgbRed: color.red, green: color.green, blue: color.blue, alpha: 1) + }) + } +} + +/// Tokens da direção "Portátil quente" (docs/design/brand-spec.md). +enum Theme { + static let background = Color(Palette.background) + static let surface = Color(Palette.surface) + static let raised = Color(Palette.raised) + static let textPrimary = Color(Palette.textPrimary) + static let textSecondary = Color(Palette.textSecondary) + static let divider = Color(Palette.divider) + static let onCover = Color(Palette.onCover) + + static func coverTone(_ system: GameSystemID) -> Color { + Color(Palette.coverTone(for: system)) + } +} + +/// Grade de 8 pt. +enum Spacing { + static let xs: CGFloat = 4 + static let s: CGFloat = 8 + static let m: CGFloat = 16 + static let l: CGFloat = 24 + static let xl: CGFloat = 32 + static let xxl: CGFloat = 48 +} + +enum Radius { + static let s: CGFloat = 8 + static let m: CGFloat = 12 + static let l: CGFloat = 16 +} + +/// No máximo quatro tamanhos por tela: título, seção, corpo e legenda. +enum Typography { + static let display = Font.system(size: 34, weight: .bold, design: .rounded) + static let heading = Font.system(size: 20, weight: .semibold, design: .rounded) + static let body = Font.system(size: 15) + static let bodyEmphasis = Font.system(size: 15, weight: .semibold) + static let caption = Font.system(size: 12, weight: .medium) +} + +enum Motion { + static let standard = Animation.spring(response: 0.32, dampingFraction: 0.82) + static let fade = Animation.easeOut(duration: 0.15) + + /// Com Reduce Motion, só esmaece; nada se desloca ou cresce. + static func animation(reduceMotion: Bool) -> Animation { + reduceMotion ? fade : standard + } +} + +/// O português é o idioma da interface; datas e tamanhos seguem a mesma língua. +enum AppLocale { + static let current = Locale(identifier: "pt_BR") +} + +// MARK: Acento escolhido pelo usuário + +private struct AccentKey: EnvironmentKey { + static let defaultValue = Palette.Accent.coral +} + +extension EnvironmentValues { + var accent: Palette.Accent { + get { self[AccentKey.self] } + set { self[AccentKey.self] = newValue } + } +} + +enum Appearance: String, CaseIterable, Identifiable { + case system, light, dark + + var id: Self { self } + + var title: String { + switch self { + case .system: String(localized: "Sistema") + case .light: String(localized: "Claro") + case .dark: String(localized: "Escuro") + } + } + + var colorScheme: ColorScheme? { + switch self { + case .system: nil + case .light: .light + case .dark: .dark + } + } +} diff --git a/Sources/RetroXApp/Features/Details/GameDetailsView.swift b/Sources/RetroXApp/Features/Details/GameDetailsView.swift new file mode 100644 index 0000000..77b0209 --- /dev/null +++ b/Sources/RetroXApp/Features/Details/GameDetailsView.swift @@ -0,0 +1,117 @@ +import AppKit +import RetroXCore +import SwiftUI + +struct GameDetailsView: View { + let game: Game + @Environment(AppModel.self) private var model + + var body: some View { + let history = model.library.history(for: game) + HStack(alignment: .top, spacing: Spacing.xl) { + CoverArtView(game: game, width: 200) + .shadow(color: .black.opacity(0.2), radius: 16, y: 8) + VStack(alignment: .leading, spacing: Spacing.m) { + Text((SystemCatalog.system(game.systemID)?.displayName ?? "").uppercased()) + .font(Typography.caption) + .tracking(1.4) + .foregroundStyle(Theme.textSecondary) + Text(game.title) + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + .fixedSize(horizontal: false, vertical: true) + Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: Spacing.m, verticalSpacing: Spacing.s) { + row(String(localized: "Arquivo"), game.romURL.lastPathComponent) + row(String(localized: "Pasta"), (game.romURL.deletingLastPathComponent().path(percentEncoded: false) as NSString).abbreviatingWithTildeInPath) + row(String(localized: "Tamanho"), game.fileSize.formatted(.byteCount(style: .file).locale(AppLocale.current))) + if let serial = game.serial { + row(String(localized: "Serial"), serial) + } + row(String(localized: "Emulador"), emulatorDescription) + row(String(localized: "Partidas"), playsDescription(history)) + } + DisclosureGroup("Comando de abertura") { + commandPlan + .padding(.top, Spacing.s) + } + .font(Typography.body) + Spacer(minLength: 0) + HStack(spacing: Spacing.s) { + Button { + model.play(game) + } label: { + Label("Jogar", systemImage: "play.fill") + } + .buttonStyle(PrimaryButtonStyle()) + .keyboardShortcut(.defaultAction) + Button { + model.library.toggleFavorite(game) + } label: { + Label(history.isFavorite ? "Favorito" : "Favoritar", systemImage: history.isFavorite ? "star.fill" : "star") + } + .buttonStyle(SecondaryButtonStyle()) + Button { + NSWorkspace.shared.activateFileViewerSelecting([game.romURL]) + } label: { + Label("Mostrar no Finder", systemImage: "folder") + } + .buttonStyle(SecondaryButtonStyle()) + Spacer() + Button("Fechar") { + model.detailsGame = nil + } + .buttonStyle(SecondaryButtonStyle()) + .keyboardShortcut(.cancelAction) + } + } + } + .padding(Spacing.xl) + .frame(width: 760, height: 460) + .background(Theme.surface) + } + + private func row(_ label: String, _ value: String) -> some View { + GridRow { + Text(label) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + Text(value) + .font(Typography.body) + .foregroundStyle(Theme.textPrimary) + .lineLimit(2) + .truncationMode(.middle) + .textSelection(.enabled) + } + } + + private var emulatorDescription: String { + guard let entry = model.plugins.entry(game.pluginID) else { return "—" } + return [entry.plugin.displayName, entry.discovery?.app?.version].compactMap { $0 }.joined(separator: " ") + } + + private func playsDescription(_ history: GameHistory) -> String { + guard let last = history.lastPlayedAt else { return String(localized: "Nunca jogado") } + let date = last.formatted(.dateTime.day().month(.wide).hour().minute().locale(AppLocale.current)) + return history.playCount == 1 + ? String(localized: "1 vez · última em \(date)") + : String(localized: "\(history.playCount) vezes · última em \(date)") + } + + /// O argv exato que seria usado, para diagnóstico. Nada é executado aqui. + @ViewBuilder + private var commandPlan: some View { + switch model.plan(for: game) { + case .success(let prepared): + VStack(alignment: .leading, spacing: Spacing.xs) { + ForEach(Array(prepared.plan.arguments.enumerated()), id: \.offset) { index, argument in + Text("[\(index)] \(argument)") + } + } + .font(.system(size: 12, design: .monospaced)) + .foregroundStyle(Theme.textSecondary) + .textSelection(.enabled) + case .failure(let error): + StatusLine(kind: .warning, text: error.message) + } + } +} diff --git a/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift b/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift new file mode 100644 index 0000000..3a831f4 --- /dev/null +++ b/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift @@ -0,0 +1,274 @@ +import AppKit +import RetroXCore +import SwiftUI + +/// Os emuladores como plugins: ativar, escolher a pasta raiz e ver o que foi encontrado nela. +struct EmulatorsView: View { + @Environment(AppModel.self) private var model + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + header + ScrollView { + VStack(alignment: .leading, spacing: Spacing.l) { + ForEach(model.plugins.entries) { entry in + PluginCard(entry: entry) + } + ForEach(PluginCatalog.upcoming) { upcoming in + UpcomingCard(upcoming: upcoming) + } + } + .frame(maxWidth: 760, alignment: .leading) + .padding(.horizontal, Spacing.xxl) + .padding(.bottom, Spacing.xxl) + // Mesma margem esquerda da tela inicial, em vez de uma coluna centralizada. + .frame(maxWidth: .infinity, alignment: .leading) + } + } + .frame(maxWidth: .infinity, alignment: .leading) + } + + private var header: some View { + VStack(alignment: .leading, spacing: Spacing.s) { + Button { + model.screen = .home + } label: { + Label("Início", systemImage: "chevron.left") + } + .buttonStyle(SecondaryButtonStyle()) + .keyboardShortcut(.cancelAction) + Text("Emuladores") + .font(Typography.display) + .foregroundStyle(Theme.textPrimary) + .padding(.top, Spacing.m) + Text("Ative os emuladores instalados neste Mac e diga onde eles estão. O RetroX só lê essas pastas: nada é copiado, movido ou alterado.") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + .frame(maxWidth: 560, alignment: .leading) + .fixedSize(horizontal: false, vertical: true) + } + .padding(.leading, Spacing.xxl) + .padding(.top, 56) + .padding(.bottom, Spacing.l) + } +} + +private struct PluginCard: View { + let entry: PluginsModel.Entry + @Environment(AppModel.self) private var model + + var body: some View { + VStack(alignment: .leading, spacing: Spacing.m) { + HStack(alignment: .center, spacing: Spacing.m) { + SystemBadge(system: entry.plugin.systems.first ?? .ps2) + VStack(alignment: .leading, spacing: Spacing.xs) { + Text(entry.plugin.displayName) + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + Text(entry.plugin.summary) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + Spacer() + Toggle("Ativado", isOn: Binding( + get: { entry.config.isEnabled }, + set: { isEnabled in Task { await model.setPlugin(entry.id, enabled: isEnabled) } } + )) + .toggleStyle(.switch) + .font(Typography.body) + } + + if entry.config.isEnabled { + Theme.divider.frame(height: 1) + rootFolder + if entry.isDiscovering { + HStack(spacing: Spacing.s) { + ProgressView().controlSize(.small) + Text("Procurando o emulador e os jogos…") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + } + } else if let discovery = entry.discovery { + DiscoveryReport(entry: entry, discovery: discovery) + } + } + } + .padding(Spacing.l) + .background(Theme.surface, in: RoundedRectangle(cornerRadius: Radius.l, style: .continuous)) + } + + private var rootFolder: some View { + HStack(alignment: .center, spacing: Spacing.m) { + VStack(alignment: .leading, spacing: Spacing.xs) { + Text("Pasta do emulador") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + Text(entry.rootURL.map(abbreviated) ?? String(localized: "Nenhuma pasta escolhida")) + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.textPrimary) + .lineLimit(1) + .truncationMode(.middle) + .textSelection(.enabled) + } + Spacer() + Button("Escolher pasta…") { + Task { await model.chooseRoot(for: entry.id) } + } + .buttonStyle(SecondaryButtonStyle()) + } + } +} + +private struct DiscoveryReport: View { + let entry: PluginsModel.Entry + let discovery: PluginDiscovery + @Environment(AppModel.self) private var model + + private static let host = HostEnvironment.current() + + var body: some View { + VStack(alignment: .leading, spacing: Spacing.s) { + if discovery.issues.contains(.rootNotFound) { + StatusLine(kind: .warning, text: PluginIssue.rootNotFound.message) + } else { + appLine + gamesLines + coversLine + biosLine + ForEach(Array(otherIssues.enumerated()), id: \.offset) { _, issue in + StatusLine(kind: .warning, text: issue.message) + } + if discovery.settingsFile != nil { + StatusLine(kind: .info, text: String(localized: "Lendo a configuração do \(entry.plugin.displayName) (só leitura).")) + } + } + HStack(spacing: Spacing.s) { + Button { + Task { await model.rediscover(entry.id) } + } label: { + Label("Procurar de novo", systemImage: "arrow.clockwise") + } + Button { + NSWorkspace.shared.activateFileViewerSelecting([discovery.root]) + } label: { + Label("Mostrar no Finder", systemImage: "folder") + } + } + .buttonStyle(SecondaryButtonStyle()) + .padding(.top, Spacing.s) + } + } + + @ViewBuilder + private var appLine: some View { + if let app = discovery.app { + let architectures = app.architectures.map(\.description).sorted().joined(separator: ", ") + let viaRosetta = Self.host.compatibility(with: app.architectures) == .rosetta + StatusLine(kind: .ok, text: [ + "\(entry.plugin.displayName) \(app.version ?? "")", + architectures, + viaRosetta ? String(localized: "roda via Rosetta") : nil, + ].compactMap { $0?.isEmpty == false ? $0 : nil }.joined(separator: " · ")) + } else { + StatusLine(kind: .warning, text: String(localized: "O app do \(entry.plugin.displayName) não está nesta pasta nem numa subpasta dela.")) + } + } + + @ViewBuilder + private var gamesLines: some View { + if discovery.romDirectories.isEmpty { + StatusLine(kind: .warning, text: String(localized: "Nenhuma pasta de jogos. Crie uma pasta “roms” aqui ou configure a lista de jogos no próprio emulador.")) + } else { + let count = model.library.gameCount(for: entry.id) + StatusLine(kind: .ok, text: count == 1 ? String(localized: "1 jogo encontrado") : String(localized: "\(count) jogos encontrados")) + ForEach(discovery.romDirectories, id: \.self) { directory in + StatusLine(kind: .info, text: "\(abbreviated(directory.url)) · \(origin(directory.origin))") + .padding(.leading, Spacing.l) + } + } + } + + @ViewBuilder + private var coversLine: some View { + if discovery.coverDirectories.isEmpty { + StatusLine(kind: .info, text: String(localized: "Capas são opcionais: crie uma pasta “covers” com imagens nomeadas como os jogos ou pelo serial do disco.")) + } else { + let withCover = model.library.games.filter { $0.pluginID == entry.id && $0.coverURL != nil }.count + StatusLine(kind: .ok, text: String(localized: "Capas para \(withCover) de \(model.library.gameCount(for: entry.id)) jogos")) + ForEach(discovery.coverDirectories, id: \.self) { directory in + let isInRoot = directory.standardizedFileURL.path(percentEncoded: false) + .hasPrefix(discovery.root.standardizedFileURL.path(percentEncoded: false)) + StatusLine(kind: .info, text: "\(abbreviated(directory)) · \(isInRoot ? String(localized: "na pasta do emulador") : String(localized: "capas do \(entry.plugin.displayName)"))") + .padding(.leading, Spacing.l) + } + } + } + + @ViewBuilder + private var biosLine: some View { + switch discovery.bios { + case .configured(let name): + StatusLine(kind: .ok, text: String(localized: "BIOS configurada no emulador: \(name)")) + case .fileMissing(let name): + StatusLine(kind: .warning, text: String(localized: "A BIOS configurada no emulador (\(name)) não foi encontrada.")) + case .notConfigured: + StatusLine(kind: .warning, text: String(localized: "BIOS não configurada: abra o emulador e conclua a configuração inicial.")) + case .unknown: + StatusLine(kind: .info, text: String(localized: "Configuração do emulador não encontrada: ele pedirá a BIOS na primeira vez.")) + } + } + + private var otherIssues: [PluginIssue] { + discovery.issues.filter { + switch $0 { + case .settingsFolderMissing: true + default: false + } + } + } + + private func origin(_ origin: ROMDirectory.Origin) -> String { + switch origin { + case .rootFolder: String(localized: "na pasta do emulador") + case .emulatorSettings: String(localized: "da lista de jogos do \(entry.plugin.displayName)") + } + } +} + +private struct UpcomingCard: View { + let upcoming: PluginCatalog.Upcoming + + var body: some View { + HStack(spacing: Spacing.m) { + Image(systemName: "puzzlepiece.extension") + .font(.system(size: 20, weight: .semibold)) + .foregroundStyle(Theme.textSecondary) + .frame(width: 48, height: 48) + .background(Theme.raised, in: RoundedRectangle(cornerRadius: Radius.m, style: .continuous)) + .accessibilityHidden(true) + VStack(alignment: .leading, spacing: Spacing.xs) { + Text(upcoming.name) + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + Text(upcoming.systems) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + Spacer() + Text("Em breve") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + .padding(.horizontal, Spacing.s) + .padding(.vertical, Spacing.xs) + .background(Theme.raised, in: Capsule()) + } + .padding(Spacing.l) + .background(Theme.surface.opacity(0.6), in: RoundedRectangle(cornerRadius: Radius.l, style: .continuous)) + .accessibilityElement(children: .combine) + } +} + +private func abbreviated(_ url: URL) -> String { + (url.path(percentEncoded: false).trimmingCharacters(in: CharacterSet(charactersIn: "/")).isEmpty + ? "/" : (url.path(percentEncoded: false) as NSString).abbreviatingWithTildeInPath) +} diff --git a/Sources/RetroXApp/Features/Home/HomeView.swift b/Sources/RetroXApp/Features/Home/HomeView.swift new file mode 100644 index 0000000..c805edd --- /dev/null +++ b/Sources/RetroXApp/Features/Home/HomeView.swift @@ -0,0 +1,321 @@ +import RetroXCore +import SwiftUI + +/// Tela inicial no estilo de portátil: palco com o jogo em foco em cima, prateleira de capas embaixo. +/// Teclado e controle passam pelo mesmo roteador (`AppModel.handle`). +struct HomeView: View { + @Environment(AppModel.self) private var model + @FocusState private var isFocused: Bool + + var body: some View { + VStack(spacing: 0) { + TopBar() + content + HintBar() + } + .focusable() + .focusEffectDisabled() + .focused($isFocused) + .onAppear { isFocused = true } + .onChange(of: model.detailsGame) { _, game in + if game == nil { isFocused = true } + } + .onKeyPress(phases: [.down, .repeat]) { press in + guard !press.modifiers.contains(.command), let action = Self.action(for: press) else { return .ignored } + model.handle(action) + return .handled + } + } + + @ViewBuilder + private var content: some View { + let library = model.library + if !model.plugins.hasEnabledPlugin { + EmptyHome(kind: .noEmulator) + } else if !library.hasLoaded || (library.games.isEmpty && library.isScanning) { + EmptyHome(kind: .loading) + } else if library.games.isEmpty { + EmptyHome(kind: .noGames) + } else { + StageView() + .frame(maxWidth: .infinity, maxHeight: .infinity) + ShelfView() + } + } + + static func action(for press: KeyPress) -> InputAction? { + switch press.key { + case .leftArrow: return .left + case .rightArrow: return .right + case .upArrow: return .up + case .downArrow: return .down + case .return: return .confirm + case .space: return .details + case .escape: return .back + default: break + } + switch press.characters.lowercased() { + case "f": return .favorite + case "q": return .previousShelf + case "e": return .nextShelf + case "m": return .menu + default: return nil + } + } +} + +private struct TopBar: View { + @Environment(AppModel.self) private var model + + var body: some View { + HStack(spacing: Spacing.m) { + Text("RetroX") + .font(.system(size: 20, weight: .heavy, design: .rounded)) + .foregroundStyle(Theme.textPrimary) + Spacer() + if model.library.isScanning || model.plugins.entries.contains(where: \.isDiscovering) { + HStack(spacing: Spacing.s) { + ProgressView().controlSize(.small) + Text("Atualizando biblioteca…") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + } + if let controller = model.input.controllerName { + Image(systemName: "gamecontroller.fill") + .foregroundStyle(Theme.textSecondary) + .help(controller) + .accessibilityLabel("Controle conectado: \(controller)") + } + TimelineView(.everyMinute) { context in + Text(context.date, format: .dateTime.hour().minute().locale(AppLocale.current)) + .font(Typography.bodyEmphasis) + .monospacedDigit() + .foregroundStyle(Theme.textPrimary) + } + Button { + model.screen = .emulators + } label: { + Label("Emuladores", systemImage: "puzzlepiece.extension") + } + .buttonStyle(SecondaryButtonStyle()) + SettingsLink { + Image(systemName: "gearshape") + } + .buttonStyle(IconButtonStyle()) + .accessibilityLabel("Ajustes") + } + // Espaço para os botões da janela (a barra de título fica escondida). + .padding(.leading, 88) + .padding(.trailing, Spacing.xl) + .padding(.top, Spacing.m) + .frame(height: 72) + } +} + +private struct StageView: View { + @Environment(AppModel.self) private var model + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + /// A capa do palco acompanha a altura disponível (janela pequena ou tela cheia), até este limite. + static let maxCoverWidth: CGFloat = 240 + + var body: some View { + GeometryReader { proxy in + let coverWidth = min(Self.maxCoverWidth, max(120, (proxy.size.height - Spacing.xl) / CoverArtView.aspectRatio)) + ZStack(alignment: .leading) { + if let game = model.library.focusedGame { + HStack(alignment: .center, spacing: Spacing.xxl) { + CoverArtView(game: game, width: coverWidth) + .shadow(color: .black.opacity(0.22), radius: 24, y: 12) + StageDetails(game: game) + Spacer(minLength: 0) + } + .padding(.horizontal, Spacing.xxl) + .id(game.id) + .transition(.opacity) + } else { + EmptyShelfMessage(shelf: model.library.shelf) + .padding(.horizontal, Spacing.xxl) + } + } + .frame(width: proxy.size.width, height: proxy.size.height) + } + .padding(.bottom, Spacing.l) + .animation(Motion.animation(reduceMotion: reduceMotion), value: model.library.focusedGame?.id) + } +} + +private struct StageDetails: View { + let game: Game + @Environment(AppModel.self) private var model + + var body: some View { + let history = model.library.history(for: game) + VStack(alignment: .leading, spacing: Spacing.m) { + Text(overline) + .font(Typography.caption) + .tracking(1.4) + .foregroundStyle(Theme.textSecondary) + Text(game.title) + .font(Typography.display) + .foregroundStyle(Theme.textPrimary) + .lineLimit(2) + .fixedSize(horizontal: false, vertical: true) + Text(Self.metadata(game: game, history: history)) + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + HStack(spacing: Spacing.s) { + Button { + model.play(game) + } label: { + Label("Jogar", systemImage: "play.fill") + } + .buttonStyle(PrimaryButtonStyle()) + Button { + model.library.toggleFavorite(game) + } label: { + Image(systemName: history.isFavorite ? "star.fill" : "star") + } + .buttonStyle(IconButtonStyle(isActive: history.isFavorite)) + .accessibilityLabel(history.isFavorite ? "Remover dos favoritos" : "Favoritar") + Button { + model.detailsGame = game + } label: { + Image(systemName: "info") + } + .buttonStyle(IconButtonStyle()) + .accessibilityLabel("Detalhes") + } + .padding(.top, Spacing.s) + } + .frame(maxWidth: 520, alignment: .leading) + } + + private var overline: String { + let system = SystemCatalog.system(game.systemID)?.displayName ?? game.systemID.rawValue + let emulator = model.plugins.entry(game.pluginID)?.plugin.displayName ?? "" + return "\(system) · \(emulator)".uppercased() + } + + static func metadata(game: Game, history: GameHistory) -> String { + var parts: [String] = [] + if let last = history.lastPlayedAt { + let relative = RelativeDateTimeFormatter() + relative.locale = AppLocale.current + relative.unitsStyle = .full + parts.append(String(localized: "Jogado \(relative.localizedString(for: last, relativeTo: .now))")) + } else { + parts.append(String(localized: "Ainda não jogado")) + } + parts.append(game.fileSize.formatted(.byteCount(style: .file).locale(AppLocale.current))) + parts.append(game.fileExtension) + return parts.joined(separator: " · ") + } +} + +private struct EmptyShelfMessage: View { + let shelf: LibraryModel.Shelf + + var body: some View { + VStack(alignment: .leading, spacing: Spacing.s) { + Text(shelf == .favorites ? "Nenhum favorito ainda" : "Nada por aqui") + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + Text(shelf == .favorites + ? "Escolha um jogo em Todos e pressione F (ou o botão de favoritar do controle)." + : "Troque de prateleira com Q e E, ou com os botões de ombro do controle.") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) + } +} + +/// Estados de tela inteira: sem emulador, procurando jogos, nenhum jogo encontrado. +private struct EmptyHome: View { + enum Kind { + case noEmulator, loading, noGames + } + + let kind: Kind + @Environment(AppModel.self) private var model + @Environment(\.accent) private var accent + + var body: some View { + VStack(alignment: .leading, spacing: Spacing.m) { + if kind == .loading { + ProgressView() + .controlSize(.large) + } else { + Image(systemName: kind == .noEmulator ? "puzzlepiece.extension" : "tray") + .font(.system(size: 34, weight: .semibold)) + .foregroundStyle(Color(accent.fill)) + .accessibilityHidden(true) + } + Text(title) + .font(Typography.display) + .foregroundStyle(Theme.textPrimary) + Text(message) + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + .frame(maxWidth: 480, alignment: .leading) + .fixedSize(horizontal: false, vertical: true) + if kind != .loading { + Button(kind == .noEmulator ? "Ativar emuladores" : "Abrir Emuladores") { + model.screen = .emulators + } + .buttonStyle(PrimaryButtonStyle()) + .padding(.top, Spacing.s) + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) + .padding(.horizontal, Spacing.xxl) + } + + private var title: String { + switch kind { + case .noEmulator: String(localized: "Nenhum emulador ativo") + case .loading: String(localized: "Procurando seus jogos…") + case .noGames: String(localized: "Nenhum jogo encontrado") + } + } + + private var message: String { + switch kind { + case .noEmulator: + String(localized: "Ative o PCSX2 e escolha a pasta dele. O RetroX encontra o app, os jogos e as capas sozinho, sem copiar nem alterar nada.") + case .loading: + String(localized: "Lendo as pastas dos emuladores ativos.") + case .noGames: + String(localized: "Os emuladores ativos não têm jogos nas pastas encontradas. Confira as pastas em Emuladores.") + } + } +} + +private struct HintBar: View { + @Environment(AppModel.self) private var model + + var body: some View { + let glyphs = model.input.glyphs + HStack(spacing: Spacing.l) { + CommandHint(glyphs: glyphs[.confirm].map { [$0] }, key: "↩", label: String(localized: "Jogar")) + CommandHint(glyphs: glyphs[.details].map { [$0] }, key: "Espaço", label: String(localized: "Detalhes")) + CommandHint(glyphs: glyphs[.favorite].map { [$0] }, key: "F", label: String(localized: "Favoritar")) + CommandHint( + glyphs: [glyphs[.previousShelf], glyphs[.nextShelf]].allSatisfy { $0 != nil } + ? [glyphs[.previousShelf]!, glyphs[.nextShelf]!] : nil, + key: "Q E", + label: String(localized: "Prateleira") + ) + Spacer() + CommandHint(glyphs: glyphs[.menu].map { [$0] }, key: "M", label: String(localized: "Emuladores")) + } + .padding(.horizontal, Spacing.xxl) + .frame(height: 48) + .background(Theme.surface) + .overlay(alignment: .top) { + Theme.divider.frame(height: 1) + } + } +} diff --git a/Sources/RetroXApp/Features/Home/ShelfView.swift b/Sources/RetroXApp/Features/Home/ShelfView.swift new file mode 100644 index 0000000..dc10f57 --- /dev/null +++ b/Sources/RetroXApp/Features/Home/ShelfView.swift @@ -0,0 +1,154 @@ +import RetroXCore +import SwiftUI + +/// Prateleira de capas. Detalhe de assinatura: a capa em foco sobe, ganha um halo na cor de tema +/// e se reflete no "chão" da prateleira. Com Reduce Motion, fica só o anel de foco. +struct ShelfView: View { + @Environment(AppModel.self) private var model + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + static let tileWidth: CGFloat = 128 + static let reflectionHeight: CGFloat = 32 + + var body: some View { + let library = model.library + VStack(alignment: .leading, spacing: Spacing.s) { + ShelfTabs() + ScrollViewReader { proxy in + ScrollView(.horizontal, showsIndicators: false) { + LazyHStack(alignment: .bottom, spacing: Spacing.l) { + ForEach(library.visibleGames) { game in + ShelfTile(game: game, isFocused: game.id == library.focusedGame?.id) + .id(game.id) + } + } + .padding(.horizontal, Spacing.xxl) + .padding(.top, Spacing.xl) + } + .scrollClipDisabled() + .frame(height: Self.tileWidth * CoverArtView.aspectRatio + Self.reflectionHeight + Spacing.xl + Spacing.s) + .background(alignment: .bottom) { ShelfFloor() } + .onChange(of: library.focusedGameID) { _, id in + guard let id else { return } + withAnimation(Motion.animation(reduceMotion: reduceMotion)) { + proxy.scrollTo(id, anchor: .center) + } + } + } + } + .padding(.bottom, Spacing.m) + } +} + +private struct ShelfTabs: View { + @Environment(AppModel.self) private var model + @Environment(\.accent) private var accent + + var body: some View { + let library = model.library + HStack(spacing: Spacing.l) { + ForEach(library.shelves) { shelf in + let isSelected = shelf == library.shelf + Button { + library.select(shelf) + } label: { + VStack(spacing: Spacing.xs) { + Text(shelf.title) + .font(Typography.bodyEmphasis) + .foregroundStyle(isSelected ? Theme.textPrimary : Theme.textSecondary) + Capsule() + .fill(isSelected ? Color(accent.fill) : .clear) + .frame(width: 20, height: 3) + } + .contentShape(Rectangle()) + } + .buttonStyle(.plain) + .accessibilityAddTraits(isSelected ? .isSelected : []) + } + Spacer() + Text(countLabel(library.visibleGames.count)) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + .padding(.horizontal, Spacing.xxl) + } + + private func countLabel(_ count: Int) -> String { + count == 1 ? String(localized: "1 jogo") : String(localized: "\(count) jogos") + } +} + +private struct ShelfTile: View { + let game: Game + let isFocused: Bool + @Environment(AppModel.self) private var model + @Environment(\.accent) private var accent + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + var body: some View { + let lifts = isFocused && !reduceMotion + VStack(spacing: 0) { + CoverArtView(game: game, width: ShelfView.tileWidth) + .overlay { + RoundedRectangle(cornerRadius: Radius.m + 5, style: .continuous) + .strokeBorder(Color(accent.fill), lineWidth: 3) + .padding(-6) + .opacity(isFocused ? 1 : 0) + } + .shadow( + color: isFocused ? Color(accent.fill).opacity(0.45) : .black.opacity(0.16), + radius: isFocused ? 22 : 6, + y: isFocused ? 10 : 3 + ) + .scaleEffect(lifts ? 1.1 : 1, anchor: .bottom) + .offset(y: lifts ? -6 : 0) + Reflection(game: game) + .opacity(isFocused ? 1 : 0) + } + .animation(Motion.animation(reduceMotion: reduceMotion), value: isFocused) + .contentShape(Rectangle()) + .onTapGesture { model.library.focus(game) } + .simultaneousGesture(TapGesture(count: 2).onEnded { model.play(game) }) + .accessibilityElement(children: .ignore) + .accessibilityLabel(accessibilityLabel) + .accessibilityAddTraits(isFocused ? [.isButton, .isSelected] : .isButton) + .accessibilityAction { model.library.focus(game) } + .accessibilityAction(named: "Jogar") { model.play(game) } + .accessibilityAction(named: "Favoritar") { model.library.toggleFavorite(game) } + } + + private var accessibilityLabel: String { + let system = SystemCatalog.system(game.systemID)?.shortName ?? "" + let favorite = model.library.history(for: game).isFavorite ? String(localized: ", favorito") : "" + return "\(game.title), \(system)\(favorite)" + } +} + +/// O pé da capa espelhado e esmaecido, como num piso brilhante. +private struct Reflection: View { + let game: Game + + var body: some View { + CoverArtView(game: game, width: ShelfView.tileWidth) + .scaleEffect(x: 1, y: -1) + .frame(height: ShelfView.reflectionHeight, alignment: .top) + .clipped() + .mask { + LinearGradient(colors: [.black.opacity(0.3), .clear], startPoint: .top, endPoint: .bottom) + } + .padding(.top, 2) + .accessibilityHidden(true) + } +} + +/// O "chão" da prateleira: uma linha fina e uma faixa que escurece suavemente para baixo. +private struct ShelfFloor: View { + var body: some View { + VStack(spacing: 0) { + Theme.divider.frame(height: 1) + LinearGradient(colors: [Theme.raised.opacity(0.9), Theme.background], startPoint: .top, endPoint: .bottom) + } + .frame(height: ShelfView.reflectionHeight + Spacing.m) + .accessibilityHidden(true) + } +} diff --git a/Sources/RetroXApp/Features/Launch/LaunchView.swift b/Sources/RetroXApp/Features/Launch/LaunchView.swift deleted file mode 100644 index 06c7b5d..0000000 --- a/Sources/RetroXApp/Features/Launch/LaunchView.swift +++ /dev/null @@ -1,193 +0,0 @@ -import RetroXCore -import SwiftUI -import UniformTypeIdentifiers - -struct LaunchView: View { - @Bindable var model: LaunchViewModel - - var body: some View { - Form { - Section { - emulatorRow - } header: { - Text("Emulador") - } footer: { - emulatorFooter - } - - Section("Jogo") { - romRow - } - - Section { - Toggle("Modo simulado", isOn: $model.isDryRun) - .help("Valida e mostra o comando que seria usado, sem abrir o emulador.") - HStack { - Spacer() - Button("Jogar") { - Task { await model.play() } - } - .keyboardShortcut(.defaultAction) - .controlSize(.large) - .disabled(!model.canPlay) - } - } - - if model.status != .idle { - Section("Status") { - StatusPanel(model: model, onRecovery: perform) - } - } - } - .formStyle(.grouped) - .frame(minWidth: 560, minHeight: 480) - .fileImporter( - isPresented: Binding(get: { model.importer != nil }, set: { if !$0 { model.importer = nil } }), - allowedContentTypes: contentTypes - ) { result in - guard case .success(let url) = result else { return } - switch model.importer { - case .emulator: model.selectEmulator(url) - case .rom: model.selectROM(url) - case nil: break - } - model.importer = nil - } - .onChange(of: model.status) { _, status in - announce(status) - } - } - - private var emulatorRow: some View { - LabeledContent { - Button("Escolher…") { model.importer = .emulator } - } label: { - if let url = model.emulatorURL { - Text(url.deletingPathExtension().lastPathComponent) - Text(url.deletingLastPathComponent().path(percentEncoded: false)) - .truncationMode(.middle) - } else { - Text("Nenhum emulador escolhido") - Text("Escolha o PCSX2.app instalado neste Mac.") - } - } - } - - @ViewBuilder - private var emulatorFooter: some View { - if let error = model.emulatorError { - Label(error.message, systemImage: "exclamationmark.triangle") - .foregroundStyle(.red) - } else if let info = model.emulatorInfo { - let architectures = info.architectures.map(\.description).sorted().joined(separator: ", ") - Text("\(info.bundleIdentifier ?? "?") · versão \(info.version ?? "?") · \(architectures.isEmpty ? "arquitetura desconhecida" : architectures)") - } - } - - private var romRow: some View { - LabeledContent { - Button("Escolher…") { model.importer = .rom } - } label: { - if let url = model.romURL { - Text(TitleParser.displayTitle(fromFilename: url.lastPathComponent)) - Text(url.lastPathComponent) - .truncationMode(.middle) - } else { - Text("Nenhum jogo escolhido") - Text("Formatos: \(model.adapter.supportedExtensions(for: .ps2).sorted().joined(separator: ", "))") - } - } - } - - private var contentTypes: [UTType] { - switch model.importer { - case .emulator: - [.applicationBundle] - case .rom, nil: - model.adapter.supportedExtensions(for: .ps2).sorted().compactMap { UTType(filenameExtension: $0) } - } - } - - private func perform(_ action: RecoveryAction) { - switch action { - case .chooseEmulator, .openSettings: model.importer = .emulator - case .locateROM: model.importer = .rom - case .retry: Task { await model.play() } - case .bringEmulatorToFront: model.bringEmulatorToFront() - case .showRosettaHelp: break - } - } - - private func announce(_ status: LaunchViewModel.Status) { - let message: String? = switch status { - case .failed(let error): error.message - case .running: String(localized: "Jogo aberto no emulador.") - case .ended: String(localized: "Sessão encerrada.") - default: nil - } - if let message { - AccessibilityNotification.Announcement(message).post() - } - } -} - -private struct StatusPanel: View { - let model: LaunchViewModel - let onRecovery: (RecoveryAction) -> Void - - var body: some View { - VStack(alignment: .leading, spacing: 10) { - ForEach(model.warnings, id: \.message) { warning in - Label(warning.message, systemImage: "info.circle") - .foregroundStyle(.secondary) - } - content - } - .frame(maxWidth: .infinity, alignment: .leading) - } - - @ViewBuilder - private var content: some View { - switch model.status { - case .idle: - EmptyView() - case .planned(let plan): - Label("Modo simulado: nada foi aberto.", systemImage: "eye") - Text("Estratégia: \(plan.strategy.rawValue)") - .foregroundStyle(.secondary) - VStack(alignment: .leading, spacing: 2) { - ForEach(Array(plan.arguments.enumerated()), id: \.offset) { index, argument in - Text("[\(index)] \(argument)") - } - } - .font(.system(.body, design: .monospaced)) - .textSelection(.enabled) - .accessibilityElement(children: .combine) - .accessibilityLabel("Argumentos: \(plan.arguments.joined(separator: ", "))") - case .launching: - HStack { - ProgressView().controlSize(.small) - Text("Abrindo no PCSX2…") - } - case .running: - Label("Em jogo no PCSX2. O RetroX volta à frente quando o emulador fechar.", systemImage: "gamecontroller") - Button("Trazer emulador para frente") { onRecovery(.bringEmulatorToFront) } - case .ended(let after): - Label("Sessão encerrada após \(after.formatted(.units(allowed: [.hours, .minutes, .seconds], width: .wide))).", - systemImage: "checkmark.circle") - case .failed(let error): - Label(error.message, systemImage: "exclamationmark.triangle") - .foregroundStyle(.red) - if error.recoveryActions.contains(.showRosettaHelp) { - Text("No Terminal: softwareupdate --install-rosetta") - .font(.system(.body, design: .monospaced)) - .textSelection(.enabled) - } - HStack { - ForEach(error.recoveryActions.filter { $0 != .showRosettaHelp }, id: \.self) { action in - Button(action.title) { onRecovery(action) } - } - } - } - } -} diff --git a/Sources/RetroXApp/Features/Launch/LaunchViewModel.swift b/Sources/RetroXApp/Features/Launch/LaunchViewModel.swift deleted file mode 100644 index ae3c72d..0000000 --- a/Sources/RetroXApp/Features/Launch/LaunchViewModel.swift +++ /dev/null @@ -1,133 +0,0 @@ -import AppKit -import RetroXCore - -/// Estado da tela de prova técnica: um emulador, uma ROM e o botão Jogar. -/// Sem persistência de biblioteca nesta fase; só lembra os dois últimos caminhos. -@MainActor -@Observable -final class LaunchViewModel { - enum Status: Equatable { - case idle - /// Modo simulado: o plano validado, sem abrir nada. - case planned(LaunchPlan) - case launching - case running(bundleIdentifier: String?) - case ended(after: Duration) - case failed(LaunchError) - } - - enum Importer { - case emulator, rom - } - - private(set) var emulatorURL: URL? - private(set) var emulatorInfo: AppBundleInfo? - private(set) var emulatorError: LaunchError? - private(set) var romURL: URL? - private(set) var warnings: [LaunchWarning] = [] - private(set) var status: Status = .idle - var isDryRun = false - /// Qual seletor de arquivo está aberto. Fica aqui, e não em `@State`, porque no SDK 27 `@State` - /// é uma macro que as Command Line Tools não trazem (ADR-0010). - var importer: Importer? - - let adapter = PCSX2Adapter() - - private let launcher: GameLauncher - private let inspector: AppBundleInspector - private let runningApplications: any RunningApplicationsProviding - private let defaults: UserDefaults - private let bringSelfToFront: @MainActor () -> Void - - private enum DefaultsKey { - static let emulatorPath = "launch.emulatorPath" - static let romPath = "launch.romPath" - } - - init( - launcher: GameLauncher = GameLauncher(), - inspector: AppBundleInspector = AppBundleInspector(), - runningApplications: any RunningApplicationsProviding = WorkspaceRunningApplications(), - defaults: UserDefaults = .standard, - bringSelfToFront: @escaping @MainActor () -> Void = { NSApplication.shared.activate() } - ) { - self.launcher = launcher - self.inspector = inspector - self.runningApplications = runningApplications - self.defaults = defaults - self.bringSelfToFront = bringSelfToFront - if let path = defaults.string(forKey: DefaultsKey.emulatorPath) { - selectEmulator(URL(filePath: path)) - } - romURL = defaults.string(forKey: DefaultsKey.romPath).map { URL(filePath: $0) } - } - - var isBusy: Bool { - switch status { - case .launching, .running: true - default: false - } - } - - var canPlay: Bool { emulatorURL != nil && romURL != nil && !isBusy } - - func selectEmulator(_ url: URL) { - emulatorURL = url - defaults.set(url.path(percentEncoded: false), forKey: DefaultsKey.emulatorPath) - do { - emulatorInfo = try inspector.inspect(url) - emulatorError = nil - } catch { - emulatorInfo = nil - emulatorError = error - } - if !isBusy { status = .idle } - } - - func selectROM(_ url: URL) { - romURL = url - defaults.set(url.path(percentEncoded: false), forKey: DefaultsKey.romPath) - if !isBusy { status = .idle } - } - - func play() async { - guard let emulatorURL, let romURL, !isBusy else { return } - let profile = EmulatorProfile( - name: adapter.displayName, - adapterID: adapter.id, - appURL: emulatorURL, - options: adapter.defaultOptions - ) - let request = LaunchRequest(romURL: romURL, systemID: .ps2, profile: profile) - do { - let prepared = try launcher.prepare(request) - warnings = prepared.warnings - if isDryRun { - status = .planned(prepared.plan) - return - } - status = .launching - let launched = try await launcher.launch(prepared) - status = .running(bundleIdentifier: launched.plan.bundleIdentifier) - guard let exit = await launched.waitForExit() else { return } - switch SessionOutcome.classify(launchedAt: launched.launchedAt, exit: exit) { - case .ended(let after): status = .ended(after: after) - case .exitedEarly(let code, let after): status = .failed(.exitedEarly(status: code, after: after)) - } - bringSelfToFront() - } catch { - status = .failed(error) - } - } - - func bringEmulatorToFront() { - let bundleID: String? = switch status { - case .running(let id): id - case .failed(.emulatorAlreadyRunning(let id)): id - default: emulatorInfo?.bundleIdentifier - } - if let bundleID { - runningApplications.activate(bundleIdentifier: bundleID) - } - } -} diff --git a/Sources/RetroXApp/Features/Session/SessionOverlay.swift b/Sources/RetroXApp/Features/Session/SessionOverlay.swift new file mode 100644 index 0000000..2adc5d8 --- /dev/null +++ b/Sources/RetroXApp/Features/Session/SessionOverlay.swift @@ -0,0 +1,127 @@ +import RetroXCore +import SwiftUI + +/// Cobre a tela enquanto o emulador abre e roda, e mostra como a partida terminou. +struct SessionOverlay: View { + @Environment(AppModel.self) private var model + + var body: some View { + ZStack { + Theme.background.opacity(0.94) + .ignoresSafeArea() + if let game { + HStack(alignment: .center, spacing: Spacing.xl) { + CoverArtView(game: game, width: 140) + .shadow(color: .black.opacity(0.2), radius: 16, y: 8) + VStack(alignment: .leading, spacing: Spacing.m) { + Text(overline) + .font(Typography.caption) + .tracking(1.4) + .foregroundStyle(Theme.textSecondary) + Text(game.title) + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + .fixedSize(horizontal: false, vertical: true) + detail(for: game) + } + .frame(maxWidth: 420, alignment: .leading) + } + .padding(Spacing.xl) + .background(Theme.surface, in: RoundedRectangle(cornerRadius: Radius.l, style: .continuous)) + .accessibilityElement(children: .contain) + } + } + } + + private var game: Game? { + switch model.session.phase { + case .idle: nil + case .launching(let game), .running(let game, _), .ended(let game, _), .failed(let game, _): game + } + } + + private var overline: String { + switch model.session.phase { + case .idle: "" + case .launching: String(localized: "Abrindo") + case .running(_, let emulator): String(localized: "Em jogo no \(emulator)") + case .ended: String(localized: "Partida encerrada") + case .failed: String(localized: "Não foi possível jogar") + } + } + + @ViewBuilder + private func detail(for game: Game) -> some View { + switch model.session.phase { + case .idle: + EmptyView() + case .launching: + HStack(spacing: Spacing.s) { + ProgressView().controlSize(.small) + Text("Preparando o emulador…") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + } + case .running: + Text("O RetroX volta para cá quando o emulador fechar.") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + ForEach(model.session.warnings, id: \.message) { warning in + StatusLine(kind: .info, text: warning.message) + } + Button("Trazer emulador para frente") { + model.session.bringEmulatorToFront() + } + .buttonStyle(SecondaryButtonStyle()) + case .ended(_, let after): + Text("Você jogou por \(after.formatted(.units(allowed: [.hours, .minutes, .seconds], width: .wide, maximumUnitCount: 2).locale(AppLocale.current))).") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + Button("Continuar") { + model.session.dismiss() + } + .buttonStyle(PrimaryButtonStyle()) + case .failed(_, let error): + StatusLine(kind: .warning, text: error.message) + if error.recoveryActions.contains(.showRosettaHelp) { + Text("No Terminal: softwareupdate --install-rosetta") + .font(.system(size: 12, design: .monospaced)) + .foregroundStyle(Theme.textSecondary) + .textSelection(.enabled) + } + HStack(spacing: Spacing.s) { + ForEach(Array(error.recoveryActions.filter { $0 != .showRosettaHelp }.enumerated()), id: \.element) { index, action in + Button(title(for: action)) { + model.perform(action, for: game) + } + .buttonStyle(RecoveryButtonStyle(isPrimary: index == 0)) + } + Button("Fechar") { + model.session.dismiss() + } + .buttonStyle(SecondaryButtonStyle()) + } + } + } + + /// "Localizar arquivo" vira "Procurar jogos de novo": a biblioteca vem das pastas do emulador. + private func title(for action: RecoveryAction) -> String { + switch action { + case .locateROM: String(localized: "Procurar jogos de novo") + case .chooseEmulator, .openSettings: String(localized: "Abrir Emuladores") + default: action.title + } + } +} + +private struct RecoveryButtonStyle: ButtonStyle { + let isPrimary: Bool + + func makeBody(configuration: Configuration) -> some View { + if isPrimary { + PrimaryButtonStyle().makeBody(configuration: configuration) + } else { + SecondaryButtonStyle().makeBody(configuration: configuration) + } + } +} diff --git a/Sources/RetroXApp/Features/Settings/SettingsView.swift b/Sources/RetroXApp/Features/Settings/SettingsView.swift new file mode 100644 index 0000000..737c5f4 --- /dev/null +++ b/Sources/RetroXApp/Features/Settings/SettingsView.swift @@ -0,0 +1,54 @@ +import RetroXCore +import SwiftUI + +struct SettingsView: View { + @AppStorage("appearance") private var appearance = Appearance.system + @AppStorage("accent") private var accent = Palette.Accent.coral + + var body: some View { + Form { + Picker("Aparência", selection: $appearance) { + ForEach(Appearance.allCases) { option in + Text(option.title).tag(option) + } + } + .pickerStyle(.segmented) + + LabeledContent("Cor do tema") { + HStack(spacing: Spacing.m) { + ForEach(Palette.Accent.allCases, id: \.self) { option in + Button { + accent = option + } label: { + Circle() + .fill(Color(option.fill)) + .frame(width: 24, height: 24) + .overlay { + Circle() + .strokeBorder(Theme.textPrimary, lineWidth: 2) + .padding(-5) + .opacity(option == accent ? 1 : 0) + } + .frame(width: 36, height: 36) + .contentShape(Circle()) + } + .buttonStyle(.plain) + .help(option.title) + .accessibilityLabel(option.title) + .accessibilityAddTraits(option == accent ? .isSelected : []) + } + } + } + + Section { + Text("O RetroX segue os ajustes de Reduzir Movimento, Reduzir Transparência e Aumentar Contraste do macOS.") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + } + .formStyle(.grouped) + .frame(width: 460) + .preferredColorScheme(appearance.colorScheme) + .tint(Color(accent.fill)) + } +} diff --git a/Sources/RetroXApp/Input/InputCoordinator.swift b/Sources/RetroXApp/Input/InputCoordinator.swift new file mode 100644 index 0000000..d848771 --- /dev/null +++ b/Sources/RetroXApp/Input/InputCoordinator.swift @@ -0,0 +1,103 @@ +import GameController +import Observation + +/// Ações semânticas da interface. Teclado e controle produzem as mesmas ações (ADR-0007). +enum InputAction: Hashable, Sendable { + case up, down, left, right + case confirm, back, details, favorite + case previousShelf, nextShelf + case menu +} + +/// Traduz o controle de jogo em `InputAction`, com repetição ao segurar uma direção. +/// O teclado chega pelas views (`onKeyPress`) e é roteado para o mesmo lugar. +@MainActor +@Observable +final class InputCoordinator { + private(set) var controllerName: String? + /// Símbolos SF do controle conectado para cada ação (ex.: "xmark.circle" num controle PlayStation). + private(set) var glyphs: [InputAction: String] = [:] + + @ObservationIgnored var onAction: ((InputAction) -> Void)? + @ObservationIgnored private var heldDirection: InputAction? + @ObservationIgnored private var repeatTask: Task? + @ObservationIgnored private var observers: [NSObjectProtocol] = [] + + static let initialRepeatDelay: Duration = .milliseconds(400) + static let repeatInterval: Duration = .milliseconds(90) + + init() { + // Com o emulador na frente, o RetroX não deve receber nada do controle (é o default; fica explícito). + GCController.shouldMonitorBackgroundEvents = false + let center = NotificationCenter.default + // As notificações chegam na fila principal; o controle é relido de lá, sem atravessar isolamento. + observers.append(center.addObserver(forName: .GCControllerDidConnect, object: nil, queue: .main) { [weak self] _ in + MainActor.assumeIsolated { self?.refreshCurrentController() } + }) + observers.append(center.addObserver(forName: .GCControllerDidDisconnect, object: nil, queue: .main) { [weak self] _ in + MainActor.assumeIsolated { self?.refreshCurrentController() } + }) + refreshCurrentController() + } + + private func attach(_ controller: GCController) { + guard let pad = controller.extendedGamepad else { return } + // O GameController entrega os eventos na fila principal (handlerQueue padrão). + pad.dpad.valueChangedHandler = { [weak self] _, x, y in + MainActor.assumeIsolated { self?.hold(Self.direction(x: x, y: y, threshold: 0.5)) } + } + pad.leftThumbstick.valueChangedHandler = { [weak self] _, x, y in + MainActor.assumeIsolated { self?.hold(Self.direction(x: x, y: y, threshold: 0.6)) } + } + let buttons: [(GCControllerButtonInput?, InputAction)] = [ + (pad.buttonA, .confirm), (pad.buttonB, .back), (pad.buttonX, .details), (pad.buttonY, .favorite), + (pad.leftShoulder, .previousShelf), (pad.rightShoulder, .nextShelf), (pad.buttonMenu, .menu), + ] + for (button, action) in buttons { + button?.pressedChangedHandler = { [weak self] _, _, pressed in + guard pressed else { return } + MainActor.assumeIsolated { self?.send(action) } + } + } + controllerName = controller.vendorName ?? String(localized: "Controle") + glyphs = Dictionary(uniqueKeysWithValues: buttons.compactMap { button, action in + button?.sfSymbolsName.map { (action, $0) } + }) + } + + private func refreshCurrentController() { + hold(nil) + if let next = GCController.controllers().first(where: { $0.extendedGamepad != nil }) { + attach(next) + } else { + controllerName = nil + glyphs = [:] + } + } + + private func send(_ action: InputAction) { + onAction?(action) + } + + /// Envia a direção na hora e, se ela continuar segurada, repete depois de um atraso. + private func hold(_ direction: InputAction?) { + guard direction != heldDirection else { return } + heldDirection = direction + repeatTask?.cancel() + guard let direction else { return } + send(direction) + repeatTask = Task { [weak self] in + try? await Task.sleep(for: Self.initialRepeatDelay) + while !Task.isCancelled { + self?.send(direction) + try? await Task.sleep(for: Self.repeatInterval) + } + } + } + + nonisolated static func direction(x: Float, y: Float, threshold: Float) -> InputAction? { + if abs(x) < threshold, abs(y) < threshold { return nil } + if abs(x) >= abs(y) { return x > 0 ? .right : .left } + return y > 0 ? .up : .down + } +} diff --git a/Sources/RetroXApp/RetroXApp.swift b/Sources/RetroXApp/RetroXApp.swift index b382471..1961461 100644 --- a/Sources/RetroXApp/RetroXApp.swift +++ b/Sources/RetroXApp/RetroXApp.swift @@ -1,10 +1,13 @@ import AppKit +import RetroXCore import SwiftUI @main struct RetroXApp: App { - // Constante em vez de `@State`: ver o comentário em `LaunchViewModel.importer`. - private let model = LaunchViewModel() + // Constante em vez de `@State`: no SDK 27 `@State` é uma macro que as Command Line Tools não trazem (ADR-0010). + private let model = AppModel() + @AppStorage("appearance") private var appearance = Appearance.system + @AppStorage("accent") private var accent = Palette.Accent.coral init() { // Rodando fora de um .app (swift run), o processo nasceria sem ícone no Dock nem foco. @@ -13,8 +16,70 @@ struct RetroXApp: App { var body: some Scene { Window("RetroX", id: "main") { - LaunchView(model: model) + RootView() + .environment(model) + .environment(model.covers) + .environment(\.accent, accent) + .tint(Color(accent.fill)) + .preferredColorScheme(appearance.colorScheme) + } + .windowStyle(.hiddenTitleBar) + .defaultSize(width: 1240, height: 800) + + Settings { + SettingsView() + .environment(\.accent, accent) + } + } +} + +struct RootView: View { + @Environment(AppModel.self) private var model + @Environment(\.accent) private var accent + + var body: some View { + @Bindable var model = model + ZStack { + Theme.background + .ignoresSafeArea() + switch model.screen { + case .home: + HomeView() + .transition(.opacity) + case .emulators: + EmulatorsView() + .transition(.opacity) + } + if model.session.isPresenting { + SessionOverlay() + .transition(.opacity) + } + } + .animation(Motion.fade, value: model.screen) + .animation(Motion.fade, value: model.session.isPresenting) + .sheet(item: $model.detailsGame) { game in + GameDetailsView(game: game) + .environment(model) + .environment(model.covers) + .environment(\.accent, accent) + } + .frame(minWidth: 1024, minHeight: 680) + .task { await model.start() } + .task { await DebugSnapshot.captureIfRequested() } + .onChange(of: model.session.phase) { _, phase in + announce(phase) + } + } + + private func announce(_ phase: SessionModel.Phase) { + let message: String? = switch phase { + case .running(let game, let emulator): String(localized: "\(game.title) aberto no \(emulator).") + case .ended: String(localized: "Partida encerrada.") + case .failed(_, let error): error.message + default: nil + } + if let message { + AccessibilityNotification.Announcement(message).post() } - .windowResizability(.contentMinSize) } } From 122c3f9eaf88d26885a22efafd803b3e31b9e50d Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 00:36:03 -0300 Subject: [PATCH 16/56] =?UTF-8?q?docs:=20ADR-0013=20(emuladores=20como=20p?= =?UTF-8?q?lugins),=20brand=20spec=20e=20decis=C3=B5es=20D4-D7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ADR-0013: plugin por emulador com pasta raiz; leitura só leitura do PCSX2.ini; capas por serial; JSON até a Fase 2. - docs/design/brand-spec.md com a direção "Portátil quente". - PRD, DECISOES e README atualizados (como usar, teclado). - Spike 0001: CLI do PCSX2 2.9.147 conferida no binário. Co-Authored-By: Claude Opus 5.5 --- README.md | 10 ++++- docs/DECISOES.md | 11 +++++ docs/PRD.md | 2 + docs/adr/0013-emuladores-como-plugins.md | 26 +++++++++++ docs/design/brand-spec.md | 57 ++++++++++++++++++++++++ docs/spikes/0001-launch-pcsx2-macos.md | 3 ++ 6 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 docs/adr/0013-emuladores-como-plugins.md create mode 100644 docs/design/brand-spec.md diff --git a/README.md b/README.md index 294cc8f..dcd2e47 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,15 @@ Launcher nativo para macOS que reúne numa biblioteca visual os jogos de vários consoles e abre cada um no emulador externo que o usuário já tem instalado. O RetroX não inclui emuladores, jogos, BIOS nem chaves, e não copia, move ou altera os arquivos de jogo. -**Status:** Sprint 1 (prova técnica do launch com PCSX2). Nome anterior provisório: ConsoleShelf. +**Status:** Sprint 1 (launch com PCSX2, home e emuladores como plugins). Nome anterior provisório: ConsoleShelf. + +## Como usar + +1. Abra o RetroX e vá em **Emuladores**. +2. Ative o **PCSX2** e escolha a pasta dele: a que tem o `PCSX2.app` e as pastas de jogos (por exemplo `~/Emulators/ps2`, com `roms/` e `covers/`). O RetroX também usa as pastas de jogos, as capas e a BIOS que o próprio PCSX2 já conhece. +3. Na tela inicial, navegue com as setas ou com o controle e pressione **Return** (ou o botão de confirmar) para jogar. Quando o PCSX2 fecha, o RetroX volta para a frente. + +Teclado: ←/→ escolhe o jogo, ↑/↓ ou Q/E troca de prateleira, Espaço abre os detalhes, F favorita, M abre Emuladores. Nada nas pastas dos jogos é copiado, movido ou alterado. ## Requisitos diff --git a/docs/DECISOES.md b/docs/DECISOES.md index e6915b8..fe36d39 100644 --- a/docs/DECISOES.md +++ b/docs/DECISOES.md @@ -10,6 +10,15 @@ Decisões do usuário e suposições de trabalho que não cabem num ADR. Decisõ | D2 | Git autorizado: repositório local, commits pequenos por tarefa, sem remote e sem push. | | D3 | O produto passa a se chamar **RetroX** (módulos `RetroXCore`, `RetroXApp`…). "ConsoleShelf" fica só como histórico em `docs/origem/`. | +## Decisões do usuário (2026-10-28) + +| ID | Decisão | +|---|---| +| D4 | Emuladores são **plugins** que o usuário ativa; o primeiro é o plugin nativo do PCSX2 (ADR-0013). | +| D5 | A "pasta raiz" de um emulador é a pasta que guarda o app dele junto com ROMs, capas e BIOS (ex.: `~/Emulators/ps2`). | +| D6 | Direção visual **"Portátil quente"** (docs/design/brand-spec.md), com a usabilidade de launcher de portátil inspirada no iiSU e identidade própria. | +| D7 | A skill `swiftui-design-skill` faz parte do projeto (`.claude/skills/`); os passos dela de baixar assets de marca não se aplicam. | + ## Suposições de trabalho | ID | Suposição | Revisar em | @@ -19,6 +28,8 @@ Decisões do usuário e suposições de trabalho que não cabem num ADR. Decisõ | S3 | Por padrão o RetroX respeita a configuração do emulador (tela cheia, confirmação ao sair) e não grava nos arquivos de configuração dele. | — | | S4 | Dolphin não está instalado na máquina de desenvolvimento; o adapter é testado com fakes até que esteja. | Fase 4 | | S5 | Deployment target macOS 14 (do PRD), com a troca para macOS 15 em aberto. | Gate da Fase 1 | +| S6 | Até a Fase 2, o ID de um jogo é o caminho do arquivo; favoritos e histórico ficam em JSON. | Fase 2 | +| S7 | A CLI do PCSX2 2.9.147 é igual à da 2.9.144 validada no spike (conferido no texto de ajuda do binário). | A cada versão | ## Pendências que dependem do usuário diff --git a/docs/PRD.md b/docs/PRD.md index 3882ad5..ee7b50d 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -153,3 +153,5 @@ Resultado da revisão feita no plano técnico aprovado. Prevalece sobre as seç | Jornada 2 | "Retornar à biblioteca" = o emulador é aberto em modo batch (fecha ao parar o jogo) e o RetroX volta à frente quando o processo termina. | | RNF-09 | Além de Xcode/`xcodebuild`, o caminho reproduzível sem Xcode é `swift build` / `swift test` (SwiftPM). | | Plataforma | O deployment target macOS 14 compila, mas não é testável na máquina de desenvolvimento atual (macOS 27). A escolha entre 14 e 15 será feita no gate da Fase 1 (ver ADR-0005). | +| Emuladores (2026-10-28) | Emuladores viram plugins ativados pelo usuário, cada um com uma pasta raiz (ADR-0013). O onboarding e a jornada 1 passam a ser "ativar o emulador → escolher a pasta dele → ver os jogos"; o RF-01 (escolher pastas de ROMs) é atendido pela descoberta do plugin e pelas pastas que o próprio emulador já conhece. | +| Home (2026-10-28) | A home é o layout de portátil (palco + prateleira) desde já, com teclado, mouse e controle; o Console Mode em tela cheia (RF-11) continua Should. | diff --git a/docs/adr/0013-emuladores-como-plugins.md b/docs/adr/0013-emuladores-como-plugins.md new file mode 100644 index 0000000..969ec52 --- /dev/null +++ b/docs/adr/0013-emuladores-como-plugins.md @@ -0,0 +1,26 @@ +# ADR-0013 — Emuladores como plugins com pasta raiz + +**Status:** Aceito | **Data:** 2026-10-28 + +## Contexto +A primeira interface pedia o caminho do `.app` do emulador e o de cada ROM. Na prática, quem usa emuladores já organiza tudo numa pasta por emulador (o app, `roms/`, `covers/`, a BIOS), e o próprio emulador já conhece as pastas de jogos dele. Pedir arquivo por arquivo era a usabilidade errada, e o seletor ainda perdia a escolha (ver o commit da nova interface). + +## Decisão +- Cada emulador é um **plugin** (`EmulatorPlugin`) que o usuário **ativa** na tela Emuladores e para o qual escolhe uma **pasta raiz**: a pasta que guarda o app do emulador e as pastas de jogos. +- O plugin descobre, só lendo: + - o app (direto na raiz ou uma subpasta abaixo; com várias versões, a mais nova); + - as pastas de jogos (`roms`, `games`, `jogos`, `isos`…) e as ROMs soltas na raiz; + - as capas (`covers`…). +- O plugin nativo do PCSX2 também lê, **sem alterar**, a configuração do próprio PCSX2 (`inis/PCSX2.ini`, inclusive no modo portátil): as pastas da lista de jogos (`Paths`, `RecursivePaths`), a pasta de capas e a BIOS escolhida. +- O serial do disco (`SYSTEM.CNF` da ISO) é lido para casar as capas que o PCSX2 baixa, que ele nomeia pelo serial. +- O plugin entrega o `EmulatorAdapter` (ADR-0003) que abre cada jogo. O perfil por sistema do PRD vira "o plugin ativo para aquele sistema"; o override por jogo continua previsto (RF-13). +- Configuração dos plugins e histórico de jogos (favoritos, últimas partidas) ficam em JSON em `~/Library/Application Support/RetroX/` até a Fase 2. Nessa fase a biblioteca vai para o SwiftData (ADR-0005), com ID persistente e detecção de arquivo movido. + +## Consequências +- O onboarding encolhe para "ativar o emulador e escolher a pasta dele". +- Até a Fase 2, o ID de um jogo é o caminho do arquivo: mover uma ROM de lugar perde favorito e histórico dela. +- Cada plugin novo (Dolphin, por exemplo) precisa do seu próprio conhecimento de pastas e configuração, e de um spike de launch (ADR-0011). +- Plugins de vários sistemas (GameCube e Wii no Dolphin) dependem da detecção do ADR-0012. + +## Alternativas +Perfis por sistema com caminhos manuais, como no PRD original (mais passos, sem aproveitar o que o emulador já sabe); importar a lista de jogos de dentro do cache binário do PCSX2 (formato interno, sem garantia entre versões); copiar as ROMs para uma biblioteca própria (proibido pelo ADR-0004). diff --git a/docs/design/brand-spec.md b/docs/design/brand-spec.md new file mode 100644 index 0000000..a84a29a --- /dev/null +++ b/docs/design/brand-spec.md @@ -0,0 +1,57 @@ +# Brand spec — RetroX ("Portátil quente") + +Direção escolhida em 2026-10-28 entre três propostas (Portátil quente, Editorial de caixa, Console funcional). A usabilidade se inspira na filosofia de launchers de portáteis como o iiSU: palco do jogo em foco, prateleira de capas, controle primeiro. A identidade é própria: nenhum logo, tela, som ou asset do iiSU, da Sony ou da Nintendo é usado. As capas exibidas são as que o usuário tem no próprio disco. + +Os valores abaixo são a fonte da verdade em `Sources/RetroXCore/Design/Palette.swift`, e o contraste é verificado por teste (`PaletteTests`). + +## Cores + +### Neutros (quentes, nunca preto ou branco puros) +| Token | Claro | Escuro | Uso | +|---|---|---|---| +| background | #F4F0EA | #1B1916 | Fundo das telas | +| surface | #FFFDF9 | #262320 | Cartões, barra de comandos, folhas | +| raised | #EAE4DB | #312D29 | Botões secundários, teclas, chão da prateleira | +| textPrimary | #1E1B18 | #F3EEE7 | Texto principal | +| textSecondary | #6A625A | #ADA59B | Legendas, metadados | +| divider | #DDD5CA | #3B3632 | Separadores | + +### Cor de tema (uma por vez, escolhida nos Ajustes) +| Tema | Preenchimento claro | Preenchimento escuro | +|---|---|---| +| Coral (padrão) | #C7472A | #F07A57 | +| Âmbar | #A85E12 | #E9A23B | +| Sálvia | #4F7A52 | #8DBB8F | +| Ardósia | #44657F | #8DB3CF | + +Texto sobre o preenchimento: #FFFDF9 no claro, #1B1916 no escuro. A cor de tema aparece só em preenchimentos (Jogar, chave ligada), anéis de foco, halo da capa em foco e marcadores. **Nunca em texto pequeno.** + +### Capas geradas (quando não há imagem) +Tom por sistema (PS2: #2E3742), texto #F3EEE7. Sem cores de marca de console. + +### Contraste mínimo (testado) +Texto ≥ 4,5:1 sobre background, surface e raised, nos dois modos. Texto sobre a cor de tema ≥ 4,5:1. Anel de foco ≥ 3:1 sobre o fundo. + +## Tipografia +SF Pro Rounded para títulos (tom de console), SF Pro para o resto. No máximo quatro tamanhos por tela. + +| Nível | Tamanho | Peso | +|---|---|---| +| Display | 34 pt | Bold, rounded | +| Heading | 20 pt | Semibold, rounded | +| Body | 15 pt | Regular (Semibold para ênfase) | +| Caption | 12 pt | Medium; em caixa alta com tracking 1,4 nas linhas de sistema | + +## Espaçamento e forma +- Grade de 8 pt: 4, 8, 16, 24, 32, 48. Margem lateral das telas: 48 pt. +- Raios: 8, 12 (capas e cartões pequenos), 16 (cartões grandes). Botões são cápsulas com altura mínima de 44 pt. +- Capas sempre na proporção 5:7. + +## Detalhe de assinatura +Na prateleira, a capa em foco sobe 10%, ganha um halo na cor de tema e se reflete no "chão" da prateleira. Com Reduzir Movimento, fica só o anel de foco: nada cresce nem se desloca. + +## Movimento +Mola curta (0,32 s) para foco; esmaecimento de 0,15 s para trocas de tela e, com Reduzir Movimento, para tudo. + +## Voz +Português do Brasil, direto e calmo. Mensagens de erro dizem o que aconteceu e oferecem a ação que resolve. diff --git a/docs/spikes/0001-launch-pcsx2-macos.md b/docs/spikes/0001-launch-pcsx2-macos.md index 7435a37..15630a0 100644 --- a/docs/spikes/0001-launch-pcsx2-macos.md +++ b/docs/spikes/0001-launch-pcsx2-macos.md @@ -41,3 +41,6 @@ Observações: - ROM em pasta protegida pelo TCC (Documentos, Mesa, Downloads, volume removível): o prompt de privacidade e a quem ele é atribuído ficam para a Fase 2. - PCSX2 nativo arm64 (não há build oficial no momento) e macOS 14 em runtime. - Interação com `ConfirmShutdown=true` quando o usuário fecha o jogo pela interface do PCSX2 (validação manual no Gate G0). + +## Atualização (2026-10-28) +O usuário atualizou para o PCSX2 2.9.147. O texto de ajuda do binário novo traz o mesmo `Usage` e as mesmas flags usadas aqui (`-batch`, `--`, `-fullscreen`, `-nofullscreen`, `-bigpicture`, `-fastboot`, `-slowboot`), com o mesmo bundle ID e ainda x86_64. Não houve novo launch real nesta verificação. From 8cc0c7ae8db197971957852f11c071bb96e23613 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 00:48:53 -0300 Subject: [PATCH 17/56] =?UTF-8?q?feat(core):=20cat=C3=A1logo=20de=20consol?= =?UTF-8?q?es=20ampliado=20e=2011=20temas=20de=20cor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SystemCatalog com PS1, PS2, PS3, PSP, GameCube, Wii, NDS, 3DS, Switch, GBA, SNES e N64 (para o filtro por console; só o PS2 tem plugin por enquanto) e tons de capa gerada por sistema. - ThemeID: RetroX, Gruvbox, Catppuccin, Tokyo Night, Nord, Solarized, Dracula, Rosé Pine, Everforest, Kanagawa e One, cada um claro e escuro, com cores oficiais ajustadas só onde não atingiam AA. - ThemeTests confere contraste e hierarquia de todos os temas. Co-Authored-By: Claude Opus 5.5 --- Sources/RetroXCore/Design/Palette.swift | 12 +- Sources/RetroXCore/Design/Themes.swift | 132 +++++++++++++++++++++ Sources/RetroXCore/Domain/GameSystem.swift | 40 +++++-- Tests/RetroXCoreTests/ThemeTests.swift | 42 +++++++ 4 files changed, 212 insertions(+), 14 deletions(-) create mode 100644 Sources/RetroXCore/Design/Themes.swift create mode 100644 Tests/RetroXCoreTests/ThemeTests.swift diff --git a/Sources/RetroXCore/Design/Palette.swift b/Sources/RetroXCore/Design/Palette.swift index 77380de..1e9d11d 100644 --- a/Sources/RetroXCore/Design/Palette.swift +++ b/Sources/RetroXCore/Design/Palette.swift @@ -77,11 +77,15 @@ public enum Palette { /// Tom das capas geradas quando não há imagem, por sistema. Não usa cores de marca. public static func coverTone(for system: GameSystemID) -> Tone { - switch system { - case .ps2: Tone(light: "2E3742", dark: "2E3742") - default: Tone(light: "3A3530", dark: "3A3530") - } + let hex = coverTones[system] ?? "3A3530" + return Tone(light: hex, dark: hex) } + /// Tons escuros e dessaturados, um por sistema, para distinguir capas geradas sem imitar cores de marca. + private static let coverTones: [GameSystemID: String] = [ + .ps1: "4A4440", .ps2: "2E3742", .ps3: "2A2D33", .psp: "3A3550", .gamecube: "3F3A5A", .wii: "4A5560", + .nds: "3F4A45", .n3ds: "5A3A3A", .switchConsole: "5A3434", .gba: "3E3A5E", .snes: "46424F", .n64: "2F4A3F", + ] + public static let onCover = Tone(light: "F3EEE7", dark: "F3EEE7") } diff --git a/Sources/RetroXCore/Design/Themes.swift b/Sources/RetroXCore/Design/Themes.swift new file mode 100644 index 0000000..e12d651 --- /dev/null +++ b/Sources/RetroXCore/Design/Themes.swift @@ -0,0 +1,132 @@ +import Foundation + +/// Um conjunto completo de cores para um modo (claro ou escuro). +public struct ThemePalette: Sendable, Equatable { + public let background: HexColor + public let surface: HexColor + public let raised: HexColor + public let textPrimary: HexColor + public let textSecondary: HexColor + public let divider: HexColor + public let accent: HexColor + public let onAccent: HexColor + + /// Ordem: fundo, superfície, elevado, texto, texto secundário, divisória, acento, texto sobre o acento. + init(_ hex: [String]) { + precondition(hex.count == 8) + background = HexColor(hex[0]) + surface = HexColor(hex[1]) + raised = HexColor(hex[2]) + textPrimary = HexColor(hex[3]) + textSecondary = HexColor(hex[4]) + divider = HexColor(hex[5]) + accent = HexColor(hex[6]) + onAccent = HexColor(hex[7]) + } +} + +public enum AppearancePreference: String, Codable, CaseIterable, Sendable, Identifiable { + case system, light, dark + + public var id: Self { self } + + public var title: String { + switch self { + case .system: String(localized: "Sistema") + case .light: String(localized: "Claro") + case .dark: String(localized: "Escuro") + } + } +} + +/// Temas de cor. Os esquemas conhecidos usam as cores oficiais de cada projeto, com ajustes mínimos +/// onde a cor original não atingia o contraste AA (texto ≥ 4,5:1, anel de foco ≥ 3:1). `PaletteTests` confere. +public enum ThemeID: String, CaseIterable, Codable, Sendable, Identifiable { + case retrox, gruvbox, catppuccin, tokyoNight, nord, solarized, dracula, rosePine, everforest, kanagawa, one + + public var id: Self { self } + + public var title: String { + switch self { + case .retrox: "RetroX" + case .gruvbox: "Gruvbox" + case .catppuccin: "Catppuccin" + case .tokyoNight: "Tokyo Night" + case .nord: "Nord" + case .solarized: "Solarized" + case .dracula: "Dracula" + case .rosePine: "Rosé Pine" + case .everforest: "Everforest" + case .kanagawa: "Kanagawa" + case .one: "One" + } + } + + /// Nome de cada variante, como o próprio esquema chama. + public func variantName(dark: Bool) -> String { + switch self { + case .catppuccin: dark ? "Mocha" : "Latte" + case .tokyoNight: dark ? "Night" : "Day" + case .rosePine: dark ? "Main" : "Dawn" + case .kanagawa: dark ? "Wave" : "Lotus" + case .dracula: dark ? "Dracula" : "Alucard" + default: dark ? String(localized: "Escuro") : String(localized: "Claro") + } + } + + /// `retroXAccent` só vale para o tema RetroX; os outros esquemas têm acento próprio. + public func palette(dark: Bool, retroXAccent: Palette.Accent = .coral) -> ThemePalette { + switch self { + case .retrox: + let pick = { (tone: Tone) in Self.hex(dark ? tone.dark : tone.light) } + return ThemePalette([ + pick(Palette.background), pick(Palette.surface), pick(Palette.raised), pick(Palette.textPrimary), + pick(Palette.textSecondary), pick(Palette.divider), pick(retroXAccent.fill), pick(retroXAccent.onFill), + ]) + case .gruvbox: + return dark + ? ThemePalette(["282828", "32302F", "3C3836", "EBDBB2", "BDAE93", "504945", "FE8019", "282828"]) + : ThemePalette(["FBF1C7", "F9F5D7", "EBDBB2", "3C3836", "665C54", "D5C4A1", "AF3A03", "FBF1C7"]) + case .catppuccin: + return dark + ? ThemePalette(["1E1E2E", "313244", "45475A", "CDD6F4", "B2B8D0", "585B70", "CBA6F7", "1E1E2E"]) + : ThemePalette(["E6E9EF", "EFF1F5", "CCD0DA", "3A3D56", "545768", "BCC0CC", "8839EF", "EFF1F5"]) + case .tokyoNight: + return dark + ? ThemePalette(["1A1B26", "24283B", "292E42", "C0CAF5", "A9B1D6", "3B4261", "7AA2F7", "1A1B26"]) + : ThemePalette(["E1E2E7", "EEEFF3", "D0D5E3", "2A4A94", "4C5989", "C4C8DA", "2A73D6", "FFFFFF"]) + case .nord: + return dark + ? ThemePalette(["2E3440", "3B4252", "434C5E", "ECEFF4", "D8DEE9", "4C566A", "88C0D0", "2E3440"]) + : ThemePalette(["E5E9F0", "ECEFF4", "D8DEE9", "2E3440", "4C566A", "C9D0DC", "4F6C90", "ECEFF4"]) + case .solarized: + return dark + ? ThemePalette(["002B36", "073642", "0B404D", "EEE8D5", "9CA9AB", "1E4C57", "B58900", "002B36"]) + : ThemePalette(["FDF6E3", "FFFBEF", "EEE8D5", "073642", "576A71", "E2DBC5", "BF4615", "FDF6E3"]) + case .dracula: + return dark + ? ThemePalette(["282A36", "343746", "44475A", "F8F8F2", "BFC3D9", "4D5066", "BD93F9", "282A36"]) + : ThemePalette(["FFFBEB", "FFFFFF", "EFEDDC", "1F1F1F", "635D97", "DCD9C6", "644AC9", "FFFBEB"]) + case .rosePine: + return dark + ? ThemePalette(["191724", "1F1D2E", "26233A", "E0DEF4", "908CAA", "403D52", "EBBCBA", "191724"]) + : ThemePalette(["FAF4ED", "FFFAF3", "F2E9E1", "575279", "68657E", "DFDAD9", "286983", "FAF4ED"]) + case .everforest: + return dark + ? ThemePalette(["2D353B", "343F44", "3D484D", "D3C6AA", "AFB8B1", "475258", "A7C080", "2D353B"]) + : ThemePalette(["F4F0D9", "FDF6E3", "E6E2CC", "3C474D", "57646B", "E0DCC7", "687701", "FDF6E3"]) + case .kanagawa: + return dark + ? ThemePalette(["1F1F28", "2A2A37", "363646", "DCD7BA", "C8C093", "54546D", "7E9CD8", "1F1F28"]) + : ThemePalette(["F2ECBC", "F5F0C8", "E5DDB0", "545464", "5D5D6C", "D5CEA3", "4B6798", "F2ECBC"]) + case .one: + return dark + ? ThemePalette(["282C34", "2C313A", "3E4451", "DCDFE4", "ADB4C0", "4B5263", "61AFEF", "282C34"]) + : ThemePalette(["FAFAFA", "FFFFFF", "EAEAEB", "383A42", "656872", "DBDBDC", "3B6EDF", "FFFFFF"]) + } + } + + private static func hex(_ color: HexColor) -> String { + String(format: "%02X%02X%02X", Int((color.red * 255).rounded()), Int((color.green * 255).rounded()), Int((color.blue * 255).rounded())) + } +} diff --git a/Sources/RetroXCore/Domain/GameSystem.swift b/Sources/RetroXCore/Domain/GameSystem.swift index 869489e..15c0782 100644 --- a/Sources/RetroXCore/Domain/GameSystem.swift +++ b/Sources/RetroXCore/Domain/GameSystem.swift @@ -10,27 +10,47 @@ public struct GameSystemID: RawRepresentable, Hashable, Codable, Sendable, Custo public var description: String { rawValue } + public static let ps1 = GameSystemID(rawValue: "ps1") public static let ps2 = GameSystemID(rawValue: "ps2") + public static let ps3 = GameSystemID(rawValue: "ps3") + public static let psp = GameSystemID(rawValue: "psp") + public static let gamecube = GameSystemID(rawValue: "gamecube") + public static let wii = GameSystemID(rawValue: "wii") + public static let nds = GameSystemID(rawValue: "nds") + public static let n3ds = GameSystemID(rawValue: "3ds") + public static let gba = GameSystemID(rawValue: "gba") + public static let snes = GameSystemID(rawValue: "snes") + public static let n64 = GameSystemID(rawValue: "n64") + public static let switchConsole = GameSystemID(rawValue: "switch") } public struct GameSystem: Hashable, Sendable, Identifiable { public let id: GameSystemID public let displayName: String public let shortName: String - /// Extensões (minúsculas, sem ponto) que o RetroX indexa para este sistema. + /// Formatos comuns do sistema (minúsculas, sem ponto). O que é indexado de fato depende do plugin ativo. public let fileExtensions: Set } -/// Catálogo de sistemas definido em código e versionado com o app (PRD §12). +/// Catálogo de sistemas definido em código e versionado com o app (PRD §12). Estar no catálogo não +/// significa ter emulador: hoje só o PS2 tem plugin (PCSX2). Os outros aparecem no filtro de console. public enum SystemCatalog { - public static let ps2 = GameSystem( - id: .ps2, - displayName: "PlayStation 2", - shortName: "PS2", - fileExtensions: ["iso", "chd", "cso", "zso"] - ) - - public static let all: [GameSystem] = [ps2] + public static let ps2 = GameSystem(id: .ps2, displayName: "PlayStation 2", shortName: "PS2", fileExtensions: ["iso", "chd", "cso", "zso"]) + + public static let all: [GameSystem] = [ + GameSystem(id: .ps1, displayName: "PlayStation", shortName: "PS1", fileExtensions: ["cue", "chd", "pbp", "m3u"]), + ps2, + GameSystem(id: .ps3, displayName: "PlayStation 3", shortName: "PS3", fileExtensions: ["iso", "pkg"]), + GameSystem(id: .psp, displayName: "PSP", shortName: "PSP", fileExtensions: ["iso", "cso", "chd"]), + GameSystem(id: .gamecube, displayName: "GameCube", shortName: "GC", fileExtensions: ["iso", "gcm", "rvz", "ciso", "gcz"]), + GameSystem(id: .wii, displayName: "Wii", shortName: "Wii", fileExtensions: ["iso", "wbfs", "rvz", "wia"]), + GameSystem(id: .nds, displayName: "Nintendo DS", shortName: "NDS", fileExtensions: ["nds"]), + GameSystem(id: .n3ds, displayName: "Nintendo 3DS", shortName: "3DS", fileExtensions: ["3ds", "cci", "cia"]), + GameSystem(id: .switchConsole, displayName: "Nintendo Switch", shortName: "Switch", fileExtensions: ["nsp", "xci"]), + GameSystem(id: .gba, displayName: "Game Boy Advance", shortName: "GBA", fileExtensions: ["gba"]), + GameSystem(id: .snes, displayName: "Super Nintendo", shortName: "SNES", fileExtensions: ["sfc", "smc"]), + GameSystem(id: .n64, displayName: "Nintendo 64", shortName: "N64", fileExtensions: ["n64", "z64", "v64"]), + ] public static func system(_ id: GameSystemID) -> GameSystem? { all.first { $0.id == id } diff --git a/Tests/RetroXCoreTests/ThemeTests.swift b/Tests/RetroXCoreTests/ThemeTests.swift new file mode 100644 index 0000000..cfaf150 --- /dev/null +++ b/Tests/RetroXCoreTests/ThemeTests.swift @@ -0,0 +1,42 @@ +import Testing +@testable import RetroXCore + +private let allPalettes: [(String, ThemePalette)] = ThemeID.allCases.flatMap { theme in + [false, true].flatMap { dark in + let accents: [Palette.Accent] = theme == .retrox ? Palette.Accent.allCases : [.coral] + return accents.map { accent in + ("\(theme.title) \(theme.variantName(dark: dark)) \(theme == .retrox ? accent.rawValue : "")", theme.palette(dark: dark, retroXAccent: accent)) + } + } +} + +struct ThemeTests { + @Test("Há pelo menos 10 temas, cada um com claro e escuro") + func count() { + #expect(ThemeID.allCases.count >= 10) + } + + @Test("Contraste AA em todos os temas e modos", arguments: allPalettes) + func contrast(name: String, palette: ThemePalette) { + for background in [palette.background, palette.surface, palette.raised] { + #expect(HexColor.contrast(palette.textPrimary, background) >= 4.5, "\(name): texto") + #expect(HexColor.contrast(palette.textSecondary, background) >= 4.5, "\(name): texto secundário") + } + #expect(HexColor.contrast(palette.onAccent, palette.accent) >= 4.5, "\(name): texto sobre o acento") + #expect(HexColor.contrast(palette.accent, palette.background) >= 3, "\(name): anel sobre o fundo") + #expect(HexColor.contrast(palette.accent, palette.surface) >= 3, "\(name): anel sobre a superfície") + } + + @Test("Texto principal se destaca mais que o secundário", arguments: allPalettes) + func hierarchy(name: String, palette: ThemePalette) { + #expect( + HexColor.contrast(palette.textPrimary, palette.background) > HexColor.contrast(palette.textSecondary, palette.background), + "\(name)" + ) + } + + @Test("Capas geradas legíveis para todos os sistemas do catálogo", arguments: SystemCatalog.all.map(\.id)) + func coverTones(system: GameSystemID) { + #expect(HexColor.contrast(Palette.onCover.light, Palette.coverTone(for: system).light) >= 4.5) + } +} From 7ab9042fb954f9f90e4392a08d991e68ad1c5c09 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 00:52:20 -0300 Subject: [PATCH 18/56] =?UTF-8?q?feat(core):=20perfis,=20capas=20pr=C3=B3p?= =?UTF-8?q?rias=20e=20metadados=20da=20Wikipedia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Profile (nome, foto, tema, aparência, usuário do RetroAchievements) e ProfileStorage com histórico por perfil; o history.json antigo migra para o primeiro perfil e fica guardado como legacy. - ImageImporter copia fotos e capas como PNG reduzido, sem tocar no original; ArtworkStorage guarda capa própria e metadados por jogo. - WikipediaMetadataProvider: busca (pt, depois en) e resumo da Wikipedia, completados pelo Wikidata (ano, desenvolvedora, editora, gênero) quando ele responde. Sem chave nem conta. Co-Authored-By: Claude Opus 5.5 --- .../Library/GameCustomization.swift | 47 ++++ .../Metadata/WikipediaMetadataProvider.swift | 247 ++++++++++++++++++ Sources/RetroXCore/Profiles/Profile.swift | 102 ++++++++ .../RetroXCore/Support/ImageImporter.swift | 29 ++ 4 files changed, 425 insertions(+) create mode 100644 Sources/RetroXCore/Library/GameCustomization.swift create mode 100644 Sources/RetroXCore/Metadata/WikipediaMetadataProvider.swift create mode 100644 Sources/RetroXCore/Profiles/Profile.swift create mode 100644 Sources/RetroXCore/Support/ImageImporter.swift diff --git a/Sources/RetroXCore/Library/GameCustomization.swift b/Sources/RetroXCore/Library/GameCustomization.swift new file mode 100644 index 0000000..b3545f9 --- /dev/null +++ b/Sources/RetroXCore/Library/GameCustomization.swift @@ -0,0 +1,47 @@ +import CryptoKit +import Foundation + +/// O que o usuário mudou num jogo, compartilhado entre perfis: capa própria e informações buscadas. +public struct GameCustomization: Codable, Sendable, Equatable { + /// Nome do arquivo da capa dentro de `Artwork/`. + public var coverFile: String? + public var metadata: GameMetadata? + + public init(coverFile: String? = nil, metadata: GameMetadata? = nil) { + self.coverFile = coverFile + self.metadata = metadata + } +} + +public struct ArtworkStorage: Sendable { + public let root: URL + + public init(root: URL = RetroXDirectories.applicationSupport) { + self.root = root + } + + public var customizations: JSONFileStore<[String: GameCustomization]> { + JSONFileStore(url: root.appending(path: "games.json")) + } + + public var artworkDirectory: URL { + root.appending(path: "Artwork", directoryHint: .isDirectory) + } + + public func coverURL(for customization: GameCustomization?) -> URL? { + customization?.coverFile.map { artworkDirectory.appending(path: $0) } + } + + /// Nome estável e sem caracteres problemáticos para a capa de um jogo. + public static func coverFileName(for gameID: String) -> String { + let digest = SHA256.hash(data: Data(gameID.utf8)).prefix(12).map { String(format: "%02x", $0) }.joined() + return "\(digest).png" + } + + /// Copia a imagem escolhida como capa do jogo e devolve o nome do arquivo. + public func importCover(from source: URL, for gameID: String) throws -> String { + let name = Self.coverFileName(for: gameID) + try ImageImporter.importPNG(from: source, to: artworkDirectory.appending(path: name), maxPixelSize: 1200) + return name + } +} diff --git a/Sources/RetroXCore/Metadata/WikipediaMetadataProvider.swift b/Sources/RetroXCore/Metadata/WikipediaMetadataProvider.swift new file mode 100644 index 0000000..6184019 --- /dev/null +++ b/Sources/RetroXCore/Metadata/WikipediaMetadataProvider.swift @@ -0,0 +1,247 @@ +import Foundation + +/// Informações de um jogo vindas de uma fonte pública, guardadas com a origem (ADR-0014). +public struct GameMetadata: Codable, Sendable, Equatable { + public var title: String + public var summary: String + public var shortDescription: String? + public var releaseYear: Int? + public var developers: [String] + public var publishers: [String] + public var genres: [String] + public var sourceName: String + public var sourceURL: URL? + public var fetchedAt: Date + + public init( + title: String, summary: String, shortDescription: String? = nil, releaseYear: Int? = nil, + developers: [String] = [], publishers: [String] = [], genres: [String] = [], + sourceName: String, sourceURL: URL? = nil, fetchedAt: Date = .now + ) { + self.title = title + self.summary = summary + self.shortDescription = shortDescription + self.releaseYear = releaseYear + self.developers = developers + self.publishers = publishers + self.genres = genres + self.sourceName = sourceName + self.sourceURL = sourceURL + self.fetchedAt = fetchedAt + } +} + +/// Um resultado de busca para o usuário escolher. Nada é salvo sem a escolha dele. +public struct MetadataCandidate: Identifiable, Sendable, Hashable { + public let title: String + public let snippet: String + public let language: String + + public var id: String { "\(language):\(title)" } +} + +public enum MetadataError: Error, Equatable { + case http(Int) + case network(String) + case invalidResponse +} + +public protocol HTTPFetching: Sendable { + func data(from url: URL) async throws -> Data +} + +/// URLSession com identificação, como pede a política da Wikimedia. +public struct URLSessionHTTP: HTTPFetching { + public static let userAgent = "RetroX/0.1 (launcher de emuladores para macOS)" + + public init() {} + + public func data(from url: URL) async throws -> Data { + var request = URLRequest(url: url, timeoutInterval: 15) + request.setValue(Self.userAgent, forHTTPHeaderField: "User-Agent") + let data: Data + let response: URLResponse + do { + (data, response) = try await URLSession.shared.data(for: request) + } catch { + throw MetadataError.network(error.localizedDescription) + } + guard let http = response as? HTTPURLResponse else { throw MetadataError.invalidResponse } + guard (200..<300).contains(http.statusCode) else { throw MetadataError.http(http.statusCode) } + return data + } +} + +/// Busca na Wikipedia (português, depois inglês) e completa com dados estruturados do Wikidata quando +/// disponíveis. Não precisa de conta nem de chave. Texto da Wikipedia: CC BY-SA, com link para a origem. +public struct WikipediaMetadataProvider: Sendable { + private let http: any HTTPFetching + private let languages: [String] + + public init(http: any HTTPFetching = URLSessionHTTP(), languages: [String] = ["pt", "en"]) { + self.http = http + self.languages = languages + } + + public func search(_ query: String) async throws -> [MetadataCandidate] { + var lastError: Error? + for language in languages { + do { + let results = try await search(query, language: language) + if !results.isEmpty { return results } + } catch { + lastError = error + } + } + if let lastError { throw lastError } + return [] + } + + public func metadata(for candidate: MetadataCandidate) async throws -> GameMetadata { + let encodedTitle = candidate.title.replacingOccurrences(of: " ", with: "_") + .addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/?#"))) + ?? candidate.title + let url = URL(string: "https://\(candidate.language).wikipedia.org/api/rest_v1/page/summary/\(encodedTitle)")! + let summary = try await JSONDecoder().decode(Summary.self, from: http.data(from: url)) + var metadata = GameMetadata( + title: summary.title, + summary: summary.extract ?? "", + shortDescription: summary.description, + sourceName: "Wikipedia (\(candidate.language))", + sourceURL: summary.contentURLs?.desktop?.page.flatMap(URL.init(string:)) + ) + // O Wikidata é um complemento: se estiver fora do ar, fica só o resumo. + if let item = summary.wikibaseItem { + try? await enrich(&metadata, item: item, language: candidate.language) + } + return metadata + } + + // MARK: Wikipedia + + private func search(_ query: String, language: String) async throws -> [MetadataCandidate] { + var components = URLComponents(string: "https://\(language).wikipedia.org/w/api.php")! + let hint = language == "pt" ? "jogo eletrônico" : "video game" + components.queryItems = [ + URLQueryItem(name: "action", value: "query"), + URLQueryItem(name: "list", value: "search"), + URLQueryItem(name: "srsearch", value: "\(query) \(hint)"), + URLQueryItem(name: "srlimit", value: "6"), + URLQueryItem(name: "srprop", value: "snippet"), + URLQueryItem(name: "format", value: "json"), + URLQueryItem(name: "formatversion", value: "2"), + ] + let response = try await JSONDecoder().decode(SearchResponse.self, from: http.data(from: components.url!)) + return response.query.search.map { + MetadataCandidate(title: $0.title, snippet: Self.plainText($0.snippet), language: language) + } + } + + /// "Test Drive" → "Test Drive". + static func plainText(_ html: String) -> String { + var text = html.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression) + for (entity, character) in [""": "\"", "&": "&", "'": "'", "<": "<", ">": ">", " ": " "] { + text = text.replacingOccurrences(of: entity, with: character) + } + return text.trimmingCharacters(in: .whitespacesAndNewlines) + } + + // MARK: Wikidata + + private func enrich(_ metadata: inout GameMetadata, item: String, language: String) async throws { + let claims = try await JSONDecoder().decode(EntitiesResponse.self, from: http.data(from: wikidataURL(ids: [item], props: "claims", language: language))) + .entities[item]?.claims ?? [:] + metadata.releaseYear = claims["P577"]?.compactMap(\.mainsnak.datavalue?.value.year).min() + let developers = claims["P178"]?.compactMap(\.mainsnak.datavalue?.value.id) ?? [] + let publishers = claims["P123"]?.compactMap(\.mainsnak.datavalue?.value.id) ?? [] + let genres = claims["P136"]?.compactMap(\.mainsnak.datavalue?.value.id) ?? [] + let ids = Array(Set(developers + publishers + genres)).sorted() + guard !ids.isEmpty else { return } + let labels = try await JSONDecoder().decode(EntitiesResponse.self, from: http.data(from: wikidataURL(ids: ids, props: "labels", language: language))) + .entities.compactMapValues { $0.labels?[language]?.value ?? $0.labels?["en"]?.value } + metadata.developers = developers.compactMap { labels[$0] } + metadata.publishers = publishers.compactMap { labels[$0] } + metadata.genres = genres.compactMap { labels[$0] } + } + + private func wikidataURL(ids: [String], props: String, language: String) -> URL { + var components = URLComponents(string: "https://www.wikidata.org/w/api.php")! + components.queryItems = [ + URLQueryItem(name: "action", value: "wbgetentities"), + URLQueryItem(name: "ids", value: ids.joined(separator: "|")), + URLQueryItem(name: "props", value: props), + URLQueryItem(name: "languages", value: Array(Set([language, "en"])).sorted().joined(separator: "|")), + URLQueryItem(name: "format", value: "json"), + ] + return components.url! + } +} + +// MARK: Formatos das respostas + +private struct SearchResponse: Decodable { + struct Query: Decodable { let search: [Hit] } + struct Hit: Decodable { + let title: String + let snippet: String + } + + let query: Query +} + +private struct Summary: Decodable { + struct ContentURLs: Decodable { + struct Desktop: Decodable { let page: String? } + let desktop: Desktop? + } + + let title: String + let extract: String? + let description: String? + let wikibaseItem: String? + let contentURLs: ContentURLs? + + enum CodingKeys: String, CodingKey { + case title, extract, description + case wikibaseItem = "wikibase_item" + case contentURLs = "content_urls" + } +} + +private struct EntitiesResponse: Decodable { + struct Entity: Decodable { + let claims: [String: [Claim]]? + let labels: [String: Label]? + } + + struct Label: Decodable { let value: String } + + struct Claim: Decodable { + struct Snak: Decodable { let datavalue: DataValue? } + let mainsnak: Snak + } + + /// `value` é um id de entidade ({"id": "Q123"}) ou uma data ({"time": "+2006-09-05T00:00:00Z"}). + struct DataValue: Decodable { + struct Value: Decodable { + let id: String? + let time: String? + + var year: Int? { + guard let time else { return nil } + return Int(time.drop(while: { $0 == "+" }).prefix(4)) + } + } + + let value: Value + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + value = (try? container.decode(Value.self, forKey: .value)) ?? Value(id: nil, time: nil) + } + + enum CodingKeys: String, CodingKey { case value } + } + + let entities: [String: Entity] +} diff --git a/Sources/RetroXCore/Profiles/Profile.swift b/Sources/RetroXCore/Profiles/Profile.swift new file mode 100644 index 0000000..bcce675 --- /dev/null +++ b/Sources/RetroXCore/Profiles/Profile.swift @@ -0,0 +1,102 @@ +import Foundation + +/// Um perfil de jogador: nome, foto, tema e o próprio histórico de favoritos e partidas. +public struct Profile: Codable, Identifiable, Sendable, Equatable, Hashable { + public var id: UUID + public var name: String + /// Nome do arquivo da foto dentro de `Avatars/`. + public var avatarFile: String? + public var theme: ThemeID + /// Acento do tema RetroX; os outros temas têm acento próprio. + public var accent: Palette.Accent + public var appearance: AppearancePreference + /// Usuário do RetroAchievements que este jogador usa (só para conferir com o emulador). + public var retroAchievementsUsername: String? + + public init( + id: UUID = UUID(), + name: String, + avatarFile: String? = nil, + theme: ThemeID = .retrox, + accent: Palette.Accent = .coral, + appearance: AppearancePreference = .system, + retroAchievementsUsername: String? = nil + ) { + self.id = id + self.name = name + self.avatarFile = avatarFile + self.theme = theme + self.accent = accent + self.appearance = appearance + self.retroAchievementsUsername = retroAchievementsUsername + } + + /// Campos novos entram com valor padrão, para arquivos de versões anteriores continuarem abrindo. + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + id = try container.decode(UUID.self, forKey: .id) + name = try container.decode(String.self, forKey: .name) + avatarFile = try container.decodeIfPresent(String.self, forKey: .avatarFile) + theme = (try? container.decodeIfPresent(ThemeID.self, forKey: .theme)) ?? .retrox + accent = (try? container.decodeIfPresent(Palette.Accent.self, forKey: .accent)) ?? .coral + appearance = (try? container.decodeIfPresent(AppearancePreference.self, forKey: .appearance)) ?? .system + retroAchievementsUsername = try container.decodeIfPresent(String.self, forKey: .retroAchievementsUsername) + } + + /// Iniciais para o avatar sem foto: "Ana Souza" → "AS", "Jogador 1" → "J1", "léo" → "L". + public var initials: String { + let words = name.split(whereSeparator: \.isWhitespace) + let letters = words.prefix(2).compactMap(\.first).map { String($0).uppercased() } + return letters.isEmpty ? "?" : letters.joined() + } +} + +public struct ProfilesState: Codable, Sendable, Equatable { + public var profiles: [Profile] + public var lastUsedID: UUID? + + public init(profiles: [Profile] = [], lastUsedID: UUID? = nil) { + self.profiles = profiles + self.lastUsedID = lastUsedID + } +} + +/// Arquivos dos perfis em `Application Support/RetroX`: `profiles.json`, `Avatars/` e `History/.json`. +public struct ProfileStorage: Sendable { + public let root: URL + + public init(root: URL = RetroXDirectories.applicationSupport) { + self.root = root + } + + public var state: JSONFileStore { + JSONFileStore(url: root.appending(path: "profiles.json")) + } + + public var avatarsDirectory: URL { + root.appending(path: "Avatars", directoryHint: .isDirectory) + } + + public func avatarURL(for profile: Profile) -> URL? { + profile.avatarFile.map { avatarsDirectory.appending(path: $0) } + } + + public func history(for profileID: UUID) -> JSONFileStore<[String: GameHistory]> { + JSONFileStore(url: root.appending(path: "History/\(profileID.uuidString).json")) + } + + /// Antes dos perfis, o histórico era um arquivo só (`history.json`). Na primeira vez, ele passa a + /// pertencer ao primeiro perfil, e o arquivo antigo fica guardado como `history.legacy.json`. + public func migrateLegacyHistory(into profileID: UUID) throws { + let legacy = root.appending(path: "history.json") + let destination = history(for: profileID) + guard FileManager.default.fileExists(atPath: legacy.path(percentEncoded: false)), + destination.load() == nil + else { return } + let entries = JSONFileStore<[String: GameHistory]>(url: legacy).load() ?? [:] + try destination.save(entries) + let backup = root.appending(path: "history.legacy.json") + try? FileManager.default.removeItem(at: backup) + try FileManager.default.moveItem(at: legacy, to: backup) + } +} diff --git a/Sources/RetroXCore/Support/ImageImporter.swift b/Sources/RetroXCore/Support/ImageImporter.swift new file mode 100644 index 0000000..283678e --- /dev/null +++ b/Sources/RetroXCore/Support/ImageImporter.swift @@ -0,0 +1,29 @@ +import Foundation +import ImageIO + +public enum ImageImporterError: Error, Equatable { + case unreadableImage + case writeFailed +} + +/// Copia uma imagem escolhida pelo usuário (foto de perfil, capa) como PNG reduzido para dentro do RetroX. +/// O arquivo original nunca é alterado nem movido. +public enum ImageImporter { + public static func importPNG(from source: URL, to destination: URL, maxPixelSize: Int) throws { + guard let image = CoverThumbnailer.thumbnail(of: source, maxPixelSize: maxPixelSize) else { + throw ImageImporterError.unreadableImage + } + try FileManager.default.createDirectory(at: destination.deletingLastPathComponent(), withIntermediateDirectories: true) + let temporary = destination.deletingLastPathComponent().appending(path: ".\(UUID().uuidString).png") + guard let output = CGImageDestinationCreateWithURL(temporary as CFURL, "public.png" as CFString, 1, nil) else { + throw ImageImporterError.writeFailed + } + CGImageDestinationAddImage(output, image, nil) + guard CGImageDestinationFinalize(output) else { throw ImageImporterError.writeFailed } + // Grava num temporário e só então troca: uma falha no meio não deixa uma imagem pela metade. + if FileManager.default.fileExists(atPath: destination.path(percentEncoded: false)) { + try FileManager.default.removeItem(at: destination) + } + try FileManager.default.moveItem(at: temporary, to: destination) + } +} From ba605c923084b0f46e29c23abf622e97e09595af Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 00:52:20 -0300 Subject: [PATCH 19/56] =?UTF-8?q?feat(core):=20=C3=ADndice=20de=20jogos,?= =?UTF-8?q?=20RetroAchievements=20e=20controle=20do=20PCSX2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PCSX2GameIndex lê o GameIndex.yaml do app (serial → nome oficial, região e compatibilidade), só para os seriais da biblioteca. - A descoberta do plugin lê do PCSX2.ini o estado do RetroAchievements (ativado, hardcore, usuário; o token nunca é consultado) e o mapeamento do controle da porta 1. - TitleParser.searchTitle limpa região, tags e versão para buscas. - Testes de perfis, importação de imagem, índice, conquistas, controle e metadados com HTTP falso. Co-Authored-By: Claude Opus 5.5 --- Sources/RetroXCore/Domain/TitleParser.swift | 10 + Sources/RetroXCore/Library/Game.swift | 18 +- Sources/RetroXCore/Library/GameScanner.swift | 13 +- .../RetroXCore/Plugins/EmulatorPlugin.swift | 26 ++ .../RetroXCore/Plugins/PCSX2GameIndex.swift | 55 ++++ Sources/RetroXCore/Plugins/PCSX2Plugin.swift | 28 ++ .../ProfileAndMetadataTests.swift | 256 ++++++++++++++++++ 7 files changed, 400 insertions(+), 6 deletions(-) create mode 100644 Sources/RetroXCore/Plugins/PCSX2GameIndex.swift create mode 100644 Tests/RetroXCoreTests/ProfileAndMetadataTests.swift diff --git a/Sources/RetroXCore/Domain/TitleParser.swift b/Sources/RetroXCore/Domain/TitleParser.swift index f523bae..9224fff 100644 --- a/Sources/RetroXCore/Domain/TitleParser.swift +++ b/Sources/RetroXCore/Domain/TitleParser.swift @@ -10,6 +10,16 @@ public enum TitleParser { return title.isEmpty ? filename.precomposedStringWithCanonicalMapping : title } + /// Título para buscar em fontes externas: sem região, tags e versões. "GT 4 Spec II v1.08" → "GT 4 Spec II". + public static func searchTitle(_ title: String) -> String { + let withoutGroups = title + .replacingOccurrences(of: "\\([^)]*\\)|\\[[^\\]]*\\]", with: " ", options: .regularExpression) + let words = withoutGroups.split(whereSeparator: \.isWhitespace).filter { + $0.range(of: "^v\\d+(\\.\\d+)*$", options: [.regularExpression, .caseInsensitive]) == nil + } + return words.joined(separator: " ") + } + /// Chave de busca que ignora caixa, acentos e largura: "Ação" e "acao" geram a mesma chave. public static func searchKey(_ text: String) -> String { text.folding(options: [.caseInsensitive, .diacriticInsensitive, .widthInsensitive], locale: nil) diff --git a/Sources/RetroXCore/Library/Game.swift b/Sources/RetroXCore/Library/Game.swift index 98ef4f4..3cc9bb2 100644 --- a/Sources/RetroXCore/Library/Game.swift +++ b/Sources/RetroXCore/Library/Game.swift @@ -11,10 +11,15 @@ public struct Game: Identifiable, Hashable, Sendable { public let fileSize: Int64 /// Serial do disco ("SLUS-21490"), quando o formato permite ler. public let serial: String? + /// O que o banco de dados do emulador sabe pelo serial (nome oficial, região, compatibilidade). + public let info: GameIndexEntry? public let coverURL: URL? public let searchKey: String - public init(romURL: URL, systemID: GameSystemID, pluginID: EmulatorPluginID, fileSize: Int64, serial: String? = nil, coverURL: URL?) { + public init( + romURL: URL, systemID: GameSystemID, pluginID: EmulatorPluginID, fileSize: Int64, + serial: String? = nil, info: GameIndexEntry? = nil, coverURL: URL? + ) { let title = TitleParser.displayTitle(fromFilename: romURL.lastPathComponent) self.id = romURL.standardizedFileURL.path(percentEncoded: false) self.title = title @@ -23,11 +28,22 @@ public struct Game: Identifiable, Hashable, Sendable { self.romURL = romURL self.fileSize = fileSize self.serial = serial + self.info = info self.coverURL = coverURL self.searchKey = TitleParser.searchKey(title) } public var fileExtension: String { romURL.pathExtension.uppercased() } + + /// O mesmo jogo com outra capa (por exemplo, a escolhida pelo usuário). + public func withCover(_ url: URL?) -> Game { + Game(romURL: romURL, systemID: systemID, pluginID: pluginID, fileSize: fileSize, serial: serial, info: info, coverURL: url) + } + + /// Título para buscar informações: o nome oficial do emulador, se houver; senão, o do arquivo sem marcas. + public var searchTitle: String { + info?.name ?? TitleParser.searchTitle(title) + } } /// O que o usuário fez com um jogo: favorito e histórico de partidas. diff --git a/Sources/RetroXCore/Library/GameScanner.swift b/Sources/RetroXCore/Library/GameScanner.swift index cbe937f..64e400c 100644 --- a/Sources/RetroXCore/Library/GameScanner.swift +++ b/Sources/RetroXCore/Library/GameScanner.swift @@ -43,16 +43,19 @@ public enum LibraryBuilder { let covers = discovery.coverDirectories .flatMap { fileSystem.contentsOfDirectory(at: $0) } .filter { CoverMatcher.imageExtensions.contains($0.pathExtension.lowercased()) } - return GameScanner.scan(discovery.romDirectories, extensions: extensions) - .map { rom in - // O PCSX2 nomeia as capas que baixa pelo serial do disco. - let serial = system == .ps2 ? PS2DiscReader.serial(of: rom.url) : nil - return Game( + // O PCSX2 nomeia as capas que baixa pelo serial do disco, e o banco de dados dele também usa o serial. + let roms = GameScanner.scan(discovery.romDirectories, extensions: extensions) + .map { rom in (rom, system == .ps2 ? PS2DiscReader.serial(of: rom.url) : nil) } + let index = discovery.gameIndexFile.map { PCSX2GameIndex.entries(for: Set(roms.compactMap(\.1)), in: $0) } ?? [:] + return roms + .map { rom, serial in + Game( romURL: rom.url, systemID: system, pluginID: plugin.id, fileSize: rom.fileSize, serial: serial, + info: serial.flatMap { index[$0] }, coverURL: CoverMatcher.match(romFilename: rom.url.lastPathComponent, serial: serial, covers: covers) ) } diff --git a/Sources/RetroXCore/Plugins/EmulatorPlugin.swift b/Sources/RetroXCore/Plugins/EmulatorPlugin.swift index 5f06b4f..3a3a46c 100644 --- a/Sources/RetroXCore/Plugins/EmulatorPlugin.swift +++ b/Sources/RetroXCore/Plugins/EmulatorPlugin.swift @@ -66,6 +66,28 @@ public enum PluginIssue: Sendable, Equatable { } } +/// Estado do RetroAchievements no emulador. Só o que serve para conferir; o token de login nunca é lido. +public struct AchievementsStatus: Sendable, Equatable { + public var isEnabled: Bool + public var isHardcore: Bool + public var username: String? + + public var isLoggedIn: Bool { username != nil } +} + +/// Como o controle está configurado no emulador (primeira porta). +public struct ControllerSummary: Sendable, Equatable { + public struct Binding: Sendable, Equatable, Hashable { + public let button: String + public let input: String + } + + public var type: String + /// Dispositivo das associações, por exemplo "SDL-0". + public var device: String? + public var bindings: [Binding] +} + public struct PluginDiscovery: Sendable, Equatable { public enum BIOSStatus: Sendable, Equatable { case configured(String) @@ -81,6 +103,10 @@ public struct PluginDiscovery: Sendable, Equatable { public var coverDirectories: [URL] = [] public var settingsFile: URL? public var bios: BIOSStatus = .unknown + public var achievements: AchievementsStatus? + public var controller: ControllerSummary? + /// Banco de dados de jogos do emulador (no PCSX2, `GameIndex.yaml` dentro do app). + public var gameIndexFile: URL? public var issues: [PluginIssue] = [] public init(root: URL) { diff --git a/Sources/RetroXCore/Plugins/PCSX2GameIndex.swift b/Sources/RetroXCore/Plugins/PCSX2GameIndex.swift new file mode 100644 index 0000000..fb6fd7a --- /dev/null +++ b/Sources/RetroXCore/Plugins/PCSX2GameIndex.swift @@ -0,0 +1,55 @@ +import Foundation + +/// O que o banco de dados de jogos do emulador sabe sobre um disco. +public struct GameIndexEntry: Codable, Sendable, Equatable, Hashable { + public let name: String + public let region: String? + /// Nota de compatibilidade do PCSX2, de 1 (não abre) a 5 (perfeito). + public let compatibility: Int? +} + +/// Lê o `GameIndex.yaml` que vem dentro do app do PCSX2 (serial → nome, região, compatibilidade). +/// Offline e sem alterar nada. Só os seriais pedidos são guardados; o resto do arquivo é ignorado. +public enum PCSX2GameIndex { + public static func entries(for serials: Set, in url: URL) -> [String: GameIndexEntry] { + guard !serials.isEmpty, let text = try? String(contentsOf: url, encoding: .utf8) else { return [:] } + return parse(text, serials: serials) + } + + static func parse(_ text: String, serials: Set) -> [String: GameIndexEntry] { + var result: [String: GameIndexEntry] = [:] + var current: String? + var fields: [String: String] = [:] + + func flush() { + if let current, let name = fields["name"] { + result[current] = GameIndexEntry(name: name, region: fields["region"], compatibility: fields["compat"].flatMap { Int($0) }) + } + fields = [:] + } + + for line in text.split(separator: "\n", omittingEmptySubsequences: true) { + if let first = line.first, !first.isWhitespace, first != "#" { + // Nova entrada de nível superior ("SLUS-21490:"). + flush() + let key = line.split(separator: ":", maxSplits: 1).first.map { String($0).trimmingCharacters(in: .whitespaces) } + current = key.flatMap { serials.contains($0) ? $0 : nil } + continue + } + guard current != nil else { continue } + let trimmed = line.trimmingCharacters(in: .whitespaces) + // Só os campos diretos da entrada (dois espaços de recuo), não os aninhados. + guard line.hasPrefix(" "), !line.hasPrefix(" "), + let colon = trimmed.firstIndex(of: ":") + else { continue } + let key = String(trimmed[..= 2 { + value = String(value.dropFirst().dropLast()).replacingOccurrences(of: "\\\"", with: "\"") + } + if ["name", "region", "compat"].contains(key) { fields[key] = value } + } + flush() + return result + } +} diff --git a/Sources/RetroXCore/Plugins/PCSX2Plugin.swift b/Sources/RetroXCore/Plugins/PCSX2Plugin.swift index 0ceafca..cb92adf 100644 --- a/Sources/RetroXCore/Plugins/PCSX2Plugin.swift +++ b/Sources/RetroXCore/Plugins/PCSX2Plugin.swift @@ -71,6 +71,12 @@ public struct PCSX2Plugin: EmulatorPlugin { let coversURL = resolve(settings.value("Covers", in: "Folders") ?? "covers", relativeTo: dataDirectory) if fileSystem.kind(of: coversURL) == .directory { discovery.coverDirectories.append(coversURL) } discovery.bios = biosStatus(settings: settings, dataDirectory: dataDirectory) + discovery.achievements = Self.achievements(settings) + discovery.controller = Self.controller(settings) + } + if let app = discovery.app { + let index = app.bundleURL.appending(path: "Contents/Resources/GameIndex.yaml", directoryHint: .notDirectory) + if fileSystem.kind(of: index) == .regularFile { discovery.gameIndexFile = index } } discovery.romDirectories = Self.merged(romDirectories) @@ -100,6 +106,28 @@ public struct PCSX2Plugin: EmulatorPlugin { return markers.contains(where: { fileSystem.kind(of: $0) == .regularFile }) ? folder : nil } + /// `[Achievements]` do PCSX2.ini. O token de login (`Token`) não é consultado. + static func achievements(_ settings: INIFile) -> AchievementsStatus { + AchievementsStatus( + isEnabled: settings.value("Enabled", in: "Achievements") == "true", + isHardcore: settings.value("ChallengeMode", in: "Achievements") == "true", + username: settings.value("Username", in: "Achievements") + ) + } + + static let padButtons = ["Cross", "Circle", "Square", "Triangle", "Up", "Down", "Left", "Right", + "L1", "R1", "L2", "R2", "L3", "R3", "Select", "Start"] + + /// `[Pad1]` do PCSX2.ini: tipo de controle e a que entrada cada botão do PS2 está ligado. + static func controller(_ settings: INIFile) -> ControllerSummary? { + guard let type = settings.value("Type", in: "Pad1"), type != "None" else { return nil } + let bindings = padButtons.compactMap { button in + settings.value(button, in: "Pad1").map { ControllerSummary.Binding(button: button, input: $0) } + } + let device = bindings.first?.input.split(separator: "/").first.map(String.init) + return ControllerSummary(type: type, device: device, bindings: bindings) + } + private func biosStatus(settings: INIFile, dataDirectory: URL) -> PluginDiscovery.BIOSStatus { guard let name = settings.value("BIOS", in: "Filenames") else { return .notConfigured } let folder = resolve(settings.value("Bios", in: "Folders") ?? "bios", relativeTo: dataDirectory) diff --git a/Tests/RetroXCoreTests/ProfileAndMetadataTests.swift b/Tests/RetroXCoreTests/ProfileAndMetadataTests.swift new file mode 100644 index 0000000..22007f7 --- /dev/null +++ b/Tests/RetroXCoreTests/ProfileAndMetadataTests.swift @@ -0,0 +1,256 @@ +import CoreGraphics +import Foundation +import ImageIO +import Testing +@testable import RetroXCore + +struct ProfileTests { + @Test("Iniciais do avatar sem foto", arguments: [ + ("Ana Souza", "AS"), ("Jogador 1", "J1"), ("léo", "L"), (" ", "?"), ("Maria da Silva", "MD"), + ]) + func initials(name: String, expected: String) { + #expect(Profile(name: name).initials == expected) + } + + @Test("Perfil de versão anterior (sem tema e aparência) abre com os padrões") + func decodesOlderFiles() throws { + let json = #"{"id":"6F9619FF-8B86-D011-B42D-00C04FC964FF","name":"Ana"}"# + let profile = try JSONDecoder().decode(Profile.self, from: Data(json.utf8)) + #expect(profile.theme == .retrox) + #expect(profile.appearance == .system) + #expect(profile.accent == .coral) + } + + @Test("Histórico antigo passa para o primeiro perfil e o arquivo antigo é guardado") + func migratesLegacyHistory() throws { + let folder = try TemporaryFolder() + let storage = ProfileStorage(root: folder.url) + let legacy = ["/jogos/a.iso": GameHistory(isFavorite: true, playCount: 3)] + try JSONFileStore<[String: GameHistory]>(url: folder.url.appending(path: "history.json")).save(legacy) + let profile = Profile(name: "Jogador 1") + + try storage.migrateLegacyHistory(into: profile.id) + #expect(storage.history(for: profile.id).load() == legacy) + #expect(FileManager.default.fileExists(atPath: folder.url.appending(path: "history.legacy.json").path(percentEncoded: false))) + #expect(!FileManager.default.fileExists(atPath: folder.url.appending(path: "history.json").path(percentEncoded: false))) + + // Rodar de novo não apaga nem sobrescreve nada. + try storage.migrateLegacyHistory(into: profile.id) + #expect(storage.history(for: profile.id).load() == legacy) + } +} + +struct ImageImporterTests { + private func writePNG(width: Int, height: Int, to url: URL) throws { + let context = CGContext( + data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: 0, + space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue + )! + context.setFillColor(red: 0.8, green: 0.3, blue: 0.2, alpha: 1) + context.fill(CGRect(x: 0, y: 0, width: width, height: height)) + let destination = CGImageDestinationCreateWithURL(url as CFURL, "public.png" as CFString, 1, nil)! + CGImageDestinationAddImage(destination, context.makeImage()!, nil) + #expect(CGImageDestinationFinalize(destination)) + } + + @Test("Copia reduzido, sem tocar no original") + func importsDownsampled() throws { + let folder = try TemporaryFolder() + let source = folder.url.appending(path: "foto.png") + try writePNG(width: 2000, height: 1000, to: source) + let before = try Data(contentsOf: source) + + let destination = folder.url.appending(path: "Avatars/eu.png") + try ImageImporter.importPNG(from: source, to: destination, maxPixelSize: 512) + let image = CGImageSourceCreateImageAtIndex(CGImageSourceCreateWithURL(destination as CFURL, nil)!, 0, nil)! + #expect(max(image.width, image.height) == 512) + #expect(try Data(contentsOf: source) == before) + + // Importar de novo substitui a cópia anterior. + try ImageImporter.importPNG(from: source, to: destination, maxPixelSize: 256) + let replaced = CGImageSourceCreateImageAtIndex(CGImageSourceCreateWithURL(destination as CFURL, nil)!, 0, nil)! + #expect(max(replaced.width, replaced.height) == 256) + } + + @Test("Arquivo que não é imagem") + func rejectsNonImages() throws { + let folder = try TemporaryFolder() + let source = try folder.file("nota.txt", bytes: 10) + #expect(throws: ImageImporterError.unreadableImage) { + try ImageImporter.importPNG(from: source, to: folder.url.appending(path: "x.png"), maxPixelSize: 100) + } + } + + @Test("Nome da capa é estável e só tem caracteres seguros") + func coverFileName() { + let name = ArtworkStorage.coverFileName(for: "/Volumes/Jogos Ação/Jogo (USA).iso") + #expect(name == ArtworkStorage.coverFileName(for: "/Volumes/Jogos Ação/Jogo (USA).iso")) + #expect(name.range(of: "^[0-9a-f]{24}\\.png$", options: .regularExpression) != nil) + } +} + +struct GameIndexTests { + let yaml = """ + # comentário + SCUS-97436: + name: "Gran Turismo 4 [Online Public Beta]" + region: "NTSC-U" + clampModes: *gran-turismo-4-clamp-modes + SLUS-21490: + name: "Test Drive Unlimited" + region: "NTSC-U" + compat: 5 + gameFixes: + - SoftwareRendererFMVHack + patches: + default: + name: "não é o nome do jogo" + SLUS-99999: + name: "Outro jogo" + compat: 3 + """ + + @Test("Lê nome, região e compatibilidade só dos seriais pedidos") + func parses() { + let entries = PCSX2GameIndex.parse(yaml, serials: ["SLUS-21490", "SCUS-97436"]) + #expect(entries.count == 2) + #expect(entries["SLUS-21490"] == GameIndexEntry(name: "Test Drive Unlimited", region: "NTSC-U", compatibility: 5)) + #expect(entries["SCUS-97436"]?.name == "Gran Turismo 4 [Online Public Beta]") + #expect(entries["SCUS-97436"]?.compatibility == nil) + } +} + +struct PluginEmulatorSettingsTests { + @Test("RetroAchievements e controle vêm do PCSX2.ini; o token não aparece em nenhum lugar") + func achievementsAndController() { + let scenario = PluginScenario(settings: """ + [Achievements] + Enabled = true + ChallengeMode = true + Username = jogadora + Token = SEGREDO-NAO-PODE-VAZAR + [Pad1] + Type = DualShock2 + Cross = SDL-0/FaceSouth + Circle = SDL-0/FaceEast + Start = SDL-0/Start + """) + let discovery = scenario.discover() + #expect(discovery.achievements == AchievementsStatus(isEnabled: true, isHardcore: true, username: "jogadora")) + #expect(discovery.controller?.type == "DualShock2") + #expect(discovery.controller?.device == "SDL-0") + #expect(discovery.controller?.bindings.first == ControllerSummary.Binding(button: "Cross", input: "SDL-0/FaceSouth")) + #expect(!String(describing: discovery).contains("SEGREDO")) + } + + @Test("Conquistas desligadas e sem login") + func achievementsOff() { + let discovery = PluginScenario(settings: "[Achievements]\nEnabled = false\n").discover() + #expect(discovery.achievements == AchievementsStatus(isEnabled: false, isHardcore: false, username: nil)) + #expect(discovery.achievements?.isLoggedIn == false) + #expect(discovery.controller == nil) + } + + @Test("Aponta o GameIndex.yaml de dentro do app, quando existe") + func gameIndexFile() { + var scenario = PluginScenario() + scenario.disk["/Emuladores/ps2/PCSX2-v2.9.144.app/Contents/Resources"] = .directory + scenario.disk["/Emuladores/ps2/PCSX2-v2.9.144.app/Contents/Resources/GameIndex.yaml"] = .file() + #expect(scenario.discover().gameIndexFile?.lastPathComponent == "GameIndex.yaml") + #expect(PluginScenario().discover().gameIndexFile == nil) + } +} + +/// Responde por trecho de URL; o que não estiver mapeado falha como servidor fora do ar. +struct FakeHTTP: HTTPFetching { + var responses: [String: String] + + func data(from url: URL) async throws -> Data { + let address = url.absoluteString.removingPercentEncoding ?? url.absoluteString + guard let match = responses.first(where: { address.contains($0.key) }) else { throw MetadataError.http(503) } + return Data(match.value.utf8) + } +} + +struct WikipediaMetadataProviderTests { + static let ptSearch = #""" + {"query":{"search":[{"title":"Test Drive Unlimited","snippet":"Test Drive Unlimited é um jogo eletrônico de corrida & mundo aberto"}]}} + """# + static let ptSummary = #""" + {"title":"Test Drive Unlimited","extract":"Test Drive Unlimited é um jogo eletrônico de corrida de 2006.","description":"videojogo de 2006","wikibase_item":"Q853941","content_urls":{"desktop":{"page":"https://pt.wikipedia.org/wiki/Test_Drive_Unlimited"}}} + """# + static let claims = #""" + {"entities":{"Q853941":{"claims":{ + "P577":[{"mainsnak":{"datavalue":{"value":{"time":"+2007-03-16T00:00:00Z"}}}},{"mainsnak":{"datavalue":{"value":{"time":"+2006-09-05T00:00:00Z"}}}}], + "P178":[{"mainsnak":{"datavalue":{"value":{"id":"Q1"}}}}], + "P123":[{"mainsnak":{"datavalue":{"value":{"id":"Q2"}}}}], + "P136":[{"mainsnak":{"datavalue":{"value":{"id":"Q3"}}}},{"mainsnak":{"snaktype":"novalue"}}] + }}}} + """# + static let labels = #""" + {"entities":{"Q1":{"labels":{"en":{"value":"Eden Games"}}},"Q2":{"labels":{"pt":{"value":"Atari"}}},"Q3":{"labels":{"pt":{"value":"jogo eletrônico de corrida"}}}}} + """# + + @Test("Busca em português e limpa o HTML do trecho") + func searchesPortuguese() async throws { + let provider = WikipediaMetadataProvider(http: FakeHTTP(responses: ["pt.wikipedia.org/w/api.php": Self.ptSearch])) + let results = try await provider.search("Test Drive Unlimited") + #expect(results == [MetadataCandidate( + title: "Test Drive Unlimited", snippet: "Test Drive Unlimited é um jogo eletrônico de corrida & mundo aberto", language: "pt" + )]) + } + + @Test("Sem resultado em português, tenta em inglês") + func fallsBackToEnglish() async throws { + let provider = WikipediaMetadataProvider(http: FakeHTTP(responses: [ + "pt.wikipedia.org/w/api.php": #"{"query":{"search":[]}}"#, + "en.wikipedia.org/w/api.php": #"{"query":{"search":[{"title":"Raro","snippet":"a video game"}]}}"#, + ])) + #expect(try await provider.search("Raro").map(\.language) == ["en"]) + } + + @Test("Resumo da Wikipedia completado pelo Wikidata") + func metadataWithWikidata() async throws { + let provider = WikipediaMetadataProvider(http: FakeHTTP(responses: [ + "rest_v1/page/summary/Test_Drive_Unlimited": Self.ptSummary, + "props=claims": Self.claims, + "props=labels": Self.labels, + ])) + let candidate = MetadataCandidate(title: "Test Drive Unlimited", snippet: "", language: "pt") + let metadata = try await provider.metadata(for: candidate) + #expect(metadata.summary == "Test Drive Unlimited é um jogo eletrônico de corrida de 2006.") + #expect(metadata.releaseYear == 2006) + #expect(metadata.developers == ["Eden Games"]) + #expect(metadata.publishers == ["Atari"]) + #expect(metadata.genres == ["jogo eletrônico de corrida"]) + #expect(metadata.sourceName == "Wikipedia (pt)") + #expect(metadata.sourceURL?.absoluteString == "https://pt.wikipedia.org/wiki/Test_Drive_Unlimited") + } + + @Test("Wikidata fora do ar: fica só o resumo, sem erro") + func wikidataDown() async throws { + let provider = WikipediaMetadataProvider(http: FakeHTTP(responses: ["rest_v1/page/summary/": Self.ptSummary])) + let metadata = try await provider.metadata(for: MetadataCandidate(title: "Test Drive Unlimited", snippet: "", language: "pt")) + #expect(metadata.releaseYear == nil) + #expect(metadata.developers.isEmpty) + #expect(!metadata.summary.isEmpty) + } + + @Test("Wikipedia fora do ar: o erro chega a quem chamou") + func wikipediaDown() async { + let provider = WikipediaMetadataProvider(http: FakeHTTP(responses: [:])) + await #expect(throws: MetadataError.http(503)) { try await provider.search("x") } + } +} + +struct SearchTitleTests { + @Test("Título para busca", arguments: [ + ("GT 4 Spec II v1.08", "GT 4 Spec II"), + ("Test Drive Unlimited (USA)", "Test Drive Unlimited"), + ("PES 2014 - Pro Evolution Soccer (Europe) (En,Nl,Sv,Ru,Tr)", "PES 2014 - Pro Evolution Soccer"), + ("Jogo [!] [T-Por]", "Jogo"), + ]) + func cleans(title: String, expected: String) { + #expect(TitleParser.searchTitle(title) == expected) + } +} From 053436e77afd1853a3cc296a97778978d1cd7dfe Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 01:03:34 -0300 Subject: [PATCH 20/56] =?UTF-8?q?feat(app):=20perfis,=20biblioteca=20em=20?= =?UTF-8?q?grade,=2011=20temas=20e=20capas=20pr=C3=B3prias?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Tela "Quem vai jogar?" ao abrir, como num console: avatares com foco por teclado, controle e hover; criar, editar e excluir perfis com foto, nome, tema, aparência e usuário do RetroAchievements. Favoritos, recentes e tema são de cada perfil. - Biblioteca em grade com busca (nome, nome oficial ou serial), chips e menu por console (catálogo inteiro, sem jogos desativado), favoritos, ordenação e quatro layouts: Capas, Capas grandes, Capas e nomes, Lista. Navegação 2D por teclado e controle. - Temas aplicados por perfil (galeria com claro e escuro lado a lado), inclusive na janela de Ajustes. - Detalhes: trocar/restaurar capa, nome oficial, região e compatibilidade do PCSX2, informações da Wikipedia com escolha do resultado e atribuição da fonte. - Emuladores: estado do RetroAchievements e mapeamento do controle do PCSX2 (só leitura). Ajustes > Controle: botão de confirmar estilo Nintendo e teste ao vivo dos botões. - Acabamento com a swiftui-design-skill: cantos contínuos, hover com leve elevação, animações snappy/smooth, abas com matchedGeometry. - Argumentos de revisão visual: -RetroXTheme e -RetroXAppearance. Co-Authored-By: Claude Opus 5.5 --- Sources/RetroXApp/App/AppModel.swift | 262 ++++++++++- Sources/RetroXApp/App/FilePanel.swift | 21 +- Sources/RetroXApp/App/LibraryBrowser.swift | 152 +++++++ Sources/RetroXApp/App/LibraryModel.swift | 148 ++++-- Sources/RetroXApp/App/ProfilesModel.swift | 102 +++++ .../RetroXApp/DesignSystem/Components.swift | 122 ++++- .../RetroXApp/DesignSystem/CoverArtView.swift | 4 +- .../DesignSystem/CoverImageStore.swift | 5 + Sources/RetroXApp/DesignSystem/Theme.swift | 90 ++-- Sources/RetroXApp/DesignSystem/TopBar.swift | 115 +++++ .../Features/Details/GameDetailsView.swift | 311 ++++++++++--- .../Features/Emulators/EmulatorsView.swift | 90 +++- .../RetroXApp/Features/Home/HomeView.swift | 147 +++--- .../RetroXApp/Features/Home/ShelfView.swift | 42 +- .../Features/Library/LibraryView.swift | 430 ++++++++++++++++++ .../Features/Profiles/ProfileEditorView.swift | 251 ++++++++++ .../Features/Profiles/ProfilePickerView.swift | 131 ++++++ .../Features/Session/SessionOverlay.swift | 2 +- .../Features/Settings/SettingsView.swift | 142 ++++-- .../RetroXApp/Input/InputCoordinator.swift | 17 +- Sources/RetroXApp/RetroXApp.swift | 51 ++- 21 files changed, 2310 insertions(+), 325 deletions(-) create mode 100644 Sources/RetroXApp/App/LibraryBrowser.swift create mode 100644 Sources/RetroXApp/App/ProfilesModel.swift create mode 100644 Sources/RetroXApp/DesignSystem/TopBar.swift create mode 100644 Sources/RetroXApp/Features/Library/LibraryView.swift create mode 100644 Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift create mode 100644 Sources/RetroXApp/Features/Profiles/ProfilePickerView.swift diff --git a/Sources/RetroXApp/App/AppModel.swift b/Sources/RetroXApp/App/AppModel.swift index 41d643d..a024760 100644 --- a/Sources/RetroXApp/App/AppModel.swift +++ b/Sources/RetroXApp/App/AppModel.swift @@ -2,27 +2,48 @@ import AppKit import Observation import RetroXCore -/// Raiz do estado do app: navegação, plugins, biblioteca, partida e entrada. +/// Raiz do estado do app: navegação, perfis, plugins, biblioteca, partida e entrada. @MainActor @Observable final class AppModel { - enum Screen { - case home, emulators + enum Screen: Hashable { + case profiles, home, library, emulators } - var screen: Screen = .home + var screen: Screen = .profiles var detailsGame: Game? + var editingProfile: ProfileDraft? + /// Na tela de perfis: índice do perfil em foco (o último é "Adicionar perfil"). + var profilePickerIndex = 0 + /// Mensagem de erro curta para ações pontuais (importar imagem, por exemplo). + var notice: String? + /// Tema e aparência do perfil atual. O tema serve de identidade da árvore de views. + private(set) var themeSelection = ThemeSelection() + private(set) var appearance: AppearancePreference = .system + + let profiles = ProfilesModel() let plugins = PluginsModel() let library = LibraryModel() + let browser: LibraryBrowser let session = SessionModel() let covers = CoverImageStore() let input = InputCoordinator() + let metadata = MetadataSearchModel() init() { - // Para revisão visual sem clicar: `open RetroX.app --args -RetroXInitialScreen emulators`. - if UserDefaults.standard.string(forKey: "RetroXInitialScreen") == "emulators" { - screen = .emulators + browser = LibraryBrowser(library: library) + profilePickerIndex = profiles.profiles.firstIndex { $0.id == profiles.lastUsed?.id } ?? 0 + applyTheme(of: profiles.lastUsed) + // Para revisão visual sem clicar: `RetroX -RetroXInitialScreen home|library|emulators`. + if let initial = UserDefaults.standard.string(forKey: "RetroXInitialScreen"), initial != "profiles", + let profile = profiles.lastUsed { + enter(profile) + screen = switch initial { + case "library": .library + case "emulators": .emulators + default: .home + } } input.onAction = { [weak self] action in self?.handle(action) } session.onLaunched = { [weak self] game, date in self?.library.recordPlay(game, at: date) } @@ -37,6 +58,84 @@ final class AppModel { await library.reload(from: plugins.readyPlugins) } + // MARK: Perfis + + func enter(_ profile: Profile) { + profiles.select(profile) + library.use(profile, storage: profiles.storage) + browser.clearFilters() + applyTheme(of: profile) + screen = .home + } + + func showProfiles() { + detailsGame = nil + profilePickerIndex = profiles.profiles.firstIndex { $0.id == profiles.current?.id } ?? 0 + screen = .profiles + } + + func newProfile() { + editingProfile = ProfileDraft(profile: Profile(name: ""), isNew: true) + } + + func edit(_ profile: Profile) { + editingProfile = ProfileDraft(profile: profile, isNew: false) + } + + func save(_ draft: ProfileDraft) { + var profile = draft.profile + profile.name = profile.name.trimmingCharacters(in: .whitespaces) + if profile.name.isEmpty { profile.name = String(localized: "Jogador \(profiles.profiles.count + (draft.isNew ? 1 : 0))") } + if let username = profile.retroAchievementsUsername?.trimmingCharacters(in: .whitespaces) { + profile.retroAchievementsUsername = username.isEmpty ? nil : username + } + if draft.isNew { + let created = profiles.create(name: profile.name) + profile.id = created.id + } + profiles.update(profile) + if draft.removeAvatar { profiles.removeAvatar(for: profile) } + if let source = draft.avatarSource, let saved = profiles.profiles.first(where: { $0.id == profile.id }) { + do { + try profiles.setAvatar(for: saved, from: source) + } catch { + notice = String(localized: "Não foi possível usar essa imagem como foto.") + } + } + if profiles.current?.id == profile.id { applyTheme(of: profiles.current) } + if draft.isNew { profilePickerIndex = profiles.profiles.count - 1 } + editingProfile = nil + } + + func delete(_ draft: ProfileDraft) { + profiles.delete(draft.profile) + editingProfile = nil + profilePickerIndex = min(profilePickerIndex, profiles.profiles.count - 1) + if profiles.current == nil { showProfiles() } + } + + /// Muda o tema do perfil atual (Ajustes), aplicando na hora. + func setTheme(_ theme: ThemeID? = nil, accent: Palette.Accent? = nil, appearance: AppearancePreference? = nil) { + guard var profile = profiles.current else { return } + if let theme { profile.theme = theme } + if let accent { profile.accent = accent } + if let appearance { profile.appearance = appearance } + profiles.update(profile) + applyTheme(of: profile) + } + + private func applyTheme(of profile: Profile?) { + var selection = ThemeSelection(theme: profile?.theme ?? .retrox, accent: profile?.accent ?? .coral) + var appearance = profile?.appearance ?? .system + // Só para revisão visual, sem gravar no perfil: `-RetroXTheme gruvbox -RetroXAppearance light`. + let defaults = UserDefaults.standard + if let theme = defaults.string(forKey: "RetroXTheme").flatMap(ThemeID.init(rawValue:)) { selection.theme = theme } + if let forced = defaults.string(forKey: "RetroXAppearance").flatMap(AppearancePreference.init(rawValue:)) { appearance = forced } + Theme.current = selection + themeSelection = selection + self.appearance = appearance + } + // MARK: Plugins func setPlugin(_ id: EmulatorPluginID, enabled: Bool) async { @@ -62,6 +161,11 @@ final class AppModel { Task { await session.play(game, plugin: entry.plugin, app: entry.discovery?.app) } } + func showDetails(_ game: Game?) { + metadata.cancel() + detailsGame = game + } + func plan(for game: Game) -> Result { guard let entry = plugins.entry(game.pluginID), let app = entry.discovery?.app else { return .failure(.emulatorNotConfigured(game.systemID)) @@ -73,6 +177,24 @@ final class AppModel { } } + func chooseCustomCover(for game: Game) async { + let message = String(localized: "Escolha uma imagem para a capa de \(game.title). Uma cópia reduzida é guardada no RetroX.") + guard let source = await FilePanel.chooseImage(message: message) else { return } + do { + let cover = try library.setCustomCover(for: game, from: source) + covers.invalidate(cover) + detailsGame = library.game(withID: game.id) + } catch { + notice = String(localized: "Não foi possível usar essa imagem como capa.") + } + } + + func restoreOriginalCover(for game: Game) { + if let cover = game.coverURL { covers.invalidate(cover) } + library.removeCustomCover(for: game) + detailsGame = library.game(withID: game.id) + } + func perform(_ action: RecoveryAction, for game: Game) { switch action { case .chooseEmulator, .openSettings: @@ -95,19 +217,36 @@ final class AppModel { /// Um só roteador para teclado e controle: a mesma ação faz a mesma coisa em qualquer dispositivo. func handle(_ action: InputAction) { + if editingProfile != nil { return } if session.isPresenting { handleSession(action) } else if let game = detailsGame { switch action { case .confirm: play(game) - case .back, .details: detailsGame = nil + case .back, .details: showDetails(nil) case .favorite: library.toggleFavorite(game) default: break } - } else if screen == .emulators { - if action == .back || action == .menu { screen = .home } } else { - handleHome(action) + switch screen { + case .profiles: handleProfiles(action) + case .home: handleHome(action) + case .library: handleLibrary(action) + case .emulators: if action == .back || action == .menu { screen = .home } + } + } + } + + private func handleProfiles(_ action: InputAction) { + let count = profiles.profiles.count + switch action { + case .left: profilePickerIndex = max(profilePickerIndex - 1, 0) + case .right: profilePickerIndex = min(profilePickerIndex + 1, count) + case .confirm: + if profilePickerIndex < count { enter(profiles.profiles[profilePickerIndex]) } else { newProfile() } + case .details: + if profilePickerIndex < count { edit(profiles.profiles[profilePickerIndex]) } + default: break } } @@ -118,13 +257,30 @@ final class AppModel { case .up, .previousShelf: library.cycleShelf(by: -1) case .down, .nextShelf: library.cycleShelf(by: 1) case .confirm: library.focusedGame.map(play) - case .details: detailsGame = library.focusedGame + case .details: showDetails(library.focusedGame) case .favorite: library.focusedGame.map(library.toggleFavorite) case .menu: screen = .emulators case .back: break } } + private func handleLibrary(_ action: InputAction) { + switch action { + case .left: browser.moveFocus(by: -1) + case .right: browser.moveFocus(by: 1) + case .up: browser.moveFocus(by: -browser.columns) + case .down: browser.moveFocus(by: browser.columns) + case .previousShelf: browser.cycleSystem(by: -1) + case .nextShelf: browser.cycleSystem(by: 1) + case .confirm: browser.focusedGame.map(play) + case .details: showDetails(browser.focusedGame) + case .favorite: browser.focusedGame.map(library.toggleFavorite) + case .menu: screen = .emulators + case .back: + if browser.isFiltering { browser.clearFilters() } else { screen = .home } + } + } + private func handleSession(_ action: InputAction) { switch session.phase { case .running: @@ -139,3 +295,85 @@ final class AppModel { } } } + +/// Cópia de um perfil sendo editado; só vale ao salvar. +@MainActor +@Observable +final class ProfileDraft: Identifiable { + let id = UUID() + var profile: Profile + let isNew: Bool + /// Foto nova escolhida (copiada ao salvar). + var avatarSource: URL? + var removeAvatar = false + + init(profile: Profile, isNew: Bool) { + self.profile = profile + self.isNew = isNew + } +} + +/// Busca de informações de um jogo numa fonte pública, com escolha do usuário (ADR-0014). +@MainActor +@Observable +final class MetadataSearchModel { + enum Phase: Equatable { + case idle + case searching + case results([MetadataCandidate]) + case loading(MetadataCandidate) + case failed(String) + } + + private(set) var phase: Phase = .idle + private(set) var gameID: Game.ID? + var query = "" + + @ObservationIgnored private let provider = WikipediaMetadataProvider() + + var isActive: Bool { gameID != nil } + + func start(for game: Game) { + gameID = game.id + query = game.searchTitle + Task { await search() } + } + + func search() async { + guard !query.trimmingCharacters(in: .whitespaces).isEmpty else { return } + phase = .searching + do { + phase = .results(try await provider.search(query)) + } catch { + phase = .failed(Self.message(for: error)) + } + } + + func choose(_ candidate: MetadataCandidate, for game: Game, library: LibraryModel) async { + phase = .loading(candidate) + do { + library.setMetadata(try await provider.metadata(for: candidate), for: game) + cancel() + } catch { + phase = .failed(Self.message(for: error)) + } + } + + func cancel() { + phase = .idle + gameID = nil + } + + private static func message(for error: Error) -> String { + switch error as? MetadataError { + case .http(let status) where status >= 500: + String(localized: "A Wikipedia não respondeu agora (erro \(status)). Tente de novo em alguns minutos.") + case .http(let status): + String(localized: "A Wikipedia recusou a busca (erro \(status)).") + case .network: + String(localized: "Sem conexão com a internet. O RetroX continua funcionando; só a busca precisa de rede.") + default: + String(localized: "A resposta da Wikipedia veio num formato inesperado.") + } + } +} diff --git a/Sources/RetroXApp/App/FilePanel.swift b/Sources/RetroXApp/App/FilePanel.swift index 2fa7c9a..ebbcaf8 100644 --- a/Sources/RetroXApp/App/FilePanel.swift +++ b/Sources/RetroXApp/App/FilePanel.swift @@ -1,4 +1,5 @@ import AppKit +import UniformTypeIdentifiers /// Seletor nativo de pasta. Usa `NSOpenPanel` diretamente: o `fileImporter` do SwiftUI fechava o seletor /// antes de entregar a escolha, e a escolha se perdia. @@ -13,13 +14,29 @@ enum FilePanel { panel.allowsMultipleSelection = false panel.canCreateDirectories = false panel.directoryURL = directory - let response = await withCheckedContinuation { continuation in + let response = await present(panel) + return response == .OK ? panel.url : nil + } + + static func chooseImage(message: String) async -> URL? { + let panel = NSOpenPanel() + panel.message = message + panel.prompt = String(localized: "Usar imagem") + panel.canChooseDirectories = false + panel.canChooseFiles = true + panel.allowsMultipleSelection = false + panel.allowedContentTypes = [.image] + let response = await present(panel) + return response == .OK ? panel.url : nil + } + + private static func present(_ panel: NSOpenPanel) async -> NSApplication.ModalResponse { + await withCheckedContinuation { continuation in if let window = NSApp.keyWindow { panel.beginSheetModal(for: window) { continuation.resume(returning: $0) } } else { panel.begin { continuation.resume(returning: $0) } } } - return response == .OK ? panel.url : nil } } diff --git a/Sources/RetroXApp/App/LibraryBrowser.swift b/Sources/RetroXApp/App/LibraryBrowser.swift new file mode 100644 index 0000000..b31e0c1 --- /dev/null +++ b/Sources/RetroXApp/App/LibraryBrowser.swift @@ -0,0 +1,152 @@ +import Foundation +import Observation +import RetroXCore + +/// Estado da grade da biblioteca: busca, filtros, ordem, forma de exibir e jogo em foco. +@MainActor +@Observable +final class LibraryBrowser { + enum Layout: String, CaseIterable, Identifiable { + case covers, largeCovers, titledCovers, list + + var id: Self { self } + + var title: String { + switch self { + case .covers: String(localized: "Capas") + case .largeCovers: String(localized: "Capas grandes") + case .titledCovers: String(localized: "Capas e nomes") + case .list: String(localized: "Lista") + } + } + + var symbol: String { + switch self { + case .covers: "square.grid.3x3" + case .largeCovers: "square.grid.2x2" + case .titledCovers: "rectangle.grid.2x2" + case .list: "list.bullet" + } + } + + /// Largura da capa em cada forma de exibir (a lista usa uma miniatura). + var tileWidth: CGFloat { + switch self { + case .covers: 128 + case .largeCovers: 184 + case .titledCovers: 148 + case .list: 40 + } + } + } + + enum Sort: String, CaseIterable, Identifiable { + case title, recent, size, system + + var id: Self { self } + + var title: String { + switch self { + case .title: String(localized: "Nome") + case .recent: String(localized: "Jogados recentemente") + case .size: String(localized: "Tamanho") + case .system: String(localized: "Console") + } + } + } + + var searchText = "" + var system: GameSystemID? + var onlyFavorites = false + private(set) var layout: Layout + private(set) var sort: Sort + /// Quantas colunas cabem na grade (informado pela view), para mover o foco para cima e para baixo. + var columns = 1 + private(set) var focusedGameID: Game.ID? + /// Jogo sob o ponteiro do mouse, para o realce de hover. + var hoveredGameID: Game.ID? + + @ObservationIgnored private let library: LibraryModel + @ObservationIgnored private let defaults: UserDefaults + + init(library: LibraryModel, defaults: UserDefaults = .standard) { + self.library = library + self.defaults = defaults + layout = defaults.string(forKey: "library.layout").flatMap(Layout.init(rawValue:)) ?? .titledCovers + sort = defaults.string(forKey: "library.sort").flatMap(Sort.init(rawValue:)) ?? .title + } + + func setLayout(_ layout: Layout) { + self.layout = layout + defaults.set(layout.rawValue, forKey: "library.layout") + } + + func setSort(_ sort: Sort) { + self.sort = sort + defaults.set(sort.rawValue, forKey: "library.sort") + } + + var isFiltering: Bool { + !searchText.isEmpty || system != nil || onlyFavorites + } + + func clearFilters() { + searchText = "" + system = nil + onlyFavorites = false + } + + /// Jogos por console, para o filtro: todos os sistemas do catálogo, com a contagem (zero fica desativado). + var systemCounts: [(GameSystem, Int)] { + let counts = Dictionary(grouping: library.games, by: \.systemID).mapValues(\.count) + return SystemCatalog.all.map { ($0, counts[$0.id] ?? 0) } + } + + var results: [Game] { + let query = TitleParser.searchKey(searchText.trimmingCharacters(in: .whitespaces)) + let filtered = library.games.filter { game in + (system == nil || game.systemID == system) + && (!onlyFavorites || library.isFavorite(game)) + && (query.isEmpty || game.searchKey.contains(query) + || game.info.map { TitleParser.searchKey($0.name).contains(query) } == true + || game.serial.map { TitleParser.searchKey($0).contains(query) } == true) + } + switch sort { + case .title: + return filtered + case .recent: + return filtered.sorted { + (library.history[$0.id]?.lastPlayedAt ?? .distantPast) > (library.history[$1.id]?.lastPlayedAt ?? .distantPast) + } + case .size: + return filtered.sorted { $0.fileSize > $1.fileSize } + case .system: + let order = Dictionary(uniqueKeysWithValues: SystemCatalog.all.enumerated().map { ($1.id, $0) }) + return filtered.sorted { (order[$0.systemID] ?? .max, $0.title) < (order[$1.systemID] ?? .max, $1.title) } + } + } + + var focusedGame: Game? { + let all = results + return all.first { $0.id == focusedGameID } ?? all.first + } + + func focus(_ game: Game) { + focusedGameID = game.id + } + + /// Esquerda/direita andam um; cima/baixo andam uma linha inteira da grade. + func moveFocus(by offset: Int) { + let all = results + guard !all.isEmpty else { return } + let index = all.firstIndex { $0.id == focusedGame?.id } ?? 0 + focusedGameID = all[min(max(index + offset, 0), all.count - 1)].id + } + + /// LB/RB passam pelos consoles que têm jogos (e por "Todos"). + func cycleSystem(by offset: Int) { + let options: [GameSystemID?] = [nil] + systemCounts.filter { $0.1 > 0 }.map { Optional($0.0.id) } + let index = options.firstIndex(of: system) ?? 0 + system = options[(index + offset + options.count) % options.count] + } +} diff --git a/Sources/RetroXApp/App/LibraryModel.swift b/Sources/RetroXApp/App/LibraryModel.swift index 26f2510..8c6ca36 100644 --- a/Sources/RetroXApp/App/LibraryModel.swift +++ b/Sources/RetroXApp/App/LibraryModel.swift @@ -2,7 +2,7 @@ import Foundation import Observation import RetroXCore -/// Os jogos dos plugins prontos, organizados em prateleiras, com o jogo em foco. +/// Os jogos dos plugins prontos, com o histórico do perfil atual e as personalizações (capa, informações). @MainActor @Observable final class LibraryModel { @@ -22,20 +22,35 @@ final class LibraryModel { } } + /// Jogos já com a capa escolhida pelo usuário, quando houver. private(set) var games: [Game] = [] - private(set) var history: [String: GameHistory] + private(set) var history: [String: GameHistory] = [:] + private(set) var customizations: [String: GameCustomization] private(set) var isScanning = false private(set) var hasLoaded = false private(set) var shelf: Shelf = .all private(set) var focusedGameID: Game.ID? - @ObservationIgnored private let store: JSONFileStore<[String: GameHistory]> + @ObservationIgnored private var scanned: [Game] = [] + @ObservationIgnored private var historyStore: JSONFileStore<[String: GameHistory]>? + @ObservationIgnored let artwork: ArtworkStorage - init(store: JSONFileStore<[String: GameHistory]> = JSONFileStore(url: RetroXDirectories.applicationSupport.appending(path: "history.json"))) { - self.store = store - history = store.load() ?? [:] + init(artwork: ArtworkStorage = ArtworkStorage()) { + self.artwork = artwork + customizations = artwork.customizations.load() ?? [:] } + // MARK: Perfil + + func use(_ profile: Profile, storage: ProfileStorage) { + historyStore = storage.history(for: profile.id) + history = historyStore?.load() ?? [:] + shelf = shelves.contains(.recent) ? .recent : .all + focusedGameID = visibleGames.first?.id + } + + // MARK: Prateleiras (tela inicial) + var shelves: [Shelf] { var result: [Shelf] = [] if games.contains(where: { history[$0.id]?.lastPlayedAt != nil }) { result.append(.recent) } @@ -49,19 +64,19 @@ final class LibraryModel { var visibleGames: [Game] { switch shelf { - case .all: - games - case .favorites: - games.filter { history[$0.id]?.isFavorite == true } - case .recent: - games - .filter { history[$0.id]?.lastPlayedAt != nil } - .sorted { (history[$0.id]?.lastPlayedAt ?? .distantPast) > (history[$1.id]?.lastPlayedAt ?? .distantPast) } - case .system(let id): - games.filter { $0.systemID == id } + case .all: games + case .favorites: games.filter { isFavorite($0) } + case .recent: recentGames + case .system(let id): games.filter { $0.systemID == id } } } + var recentGames: [Game] { + games + .filter { history[$0.id]?.lastPlayedAt != nil } + .sorted { (history[$0.id]?.lastPlayedAt ?? .distantPast) > (history[$1.id]?.lastPlayedAt ?? .distantPast) } + } + var focusedIndex: Int? { let visible = visibleGames return visible.firstIndex { $0.id == focusedGameID } ?? (visible.isEmpty ? nil : 0) @@ -71,8 +86,34 @@ final class LibraryModel { focusedIndex.map { visibleGames[$0] } } - func history(for game: Game) -> GameHistory { - history[game.id] ?? GameHistory() + func focus(_ game: Game) { + focusedGameID = game.id + } + + func moveFocus(by offset: Int) { + let visible = visibleGames + guard let index = focusedIndex, !visible.isEmpty else { return } + focusedGameID = visible[min(max(index + offset, 0), visible.count - 1)].id + } + + func select(_ shelf: Shelf) { + guard shelf != self.shelf else { return } + let previous = focusedGameID + self.shelf = shelf + // Mantém o mesmo jogo em foco se ele também está na nova prateleira. + focusedGameID = visibleGames.contains { $0.id == previous } ? previous : visibleGames.first?.id + } + + func cycleShelf(by offset: Int) { + let all = shelves + guard let index = all.firstIndex(of: shelf) else { return select(.all) } + select(all[(index + offset + all.count) % all.count]) + } + + // MARK: Jogos + + func game(withID id: Game.ID) -> Game? { + games.first { $0.id == id } } func gameCount(for plugin: EmulatorPluginID) -> Int { @@ -81,11 +122,11 @@ final class LibraryModel { func reload(from ready: [(any EmulatorPlugin, PluginDiscovery)]) async { isScanning = true - let scanned = await Task.detached(priority: .userInitiated) { + scanned = await Task.detached(priority: .userInitiated) { ready.flatMap { plugin, discovery in LibraryBuilder.games(for: plugin, discovery: discovery) } }.value + decorate() let isFirstLoad = !hasLoaded - games = scanned hasLoaded = true isScanning = false if isFirstLoad, shelves.contains(.recent) { @@ -98,28 +139,14 @@ final class LibraryModel { } } - func focus(_ game: Game) { - focusedGameID = game.id - } + // MARK: Histórico do perfil - func moveFocus(by offset: Int) { - let visible = visibleGames - guard let index = focusedIndex, !visible.isEmpty else { return } - focusedGameID = visible[min(max(index + offset, 0), visible.count - 1)].id - } - - func select(_ shelf: Shelf) { - guard shelf != self.shelf else { return } - let previous = focusedGameID - self.shelf = shelf - // Mantém o mesmo jogo em foco se ele também está na nova prateleira. - focusedGameID = visibleGames.contains { $0.id == previous } ? previous : visibleGames.first?.id + func history(for game: Game) -> GameHistory { + history[game.id] ?? GameHistory() } - func cycleShelf(by offset: Int) { - let all = shelves - guard let index = all.firstIndex(of: shelf) else { return select(.all) } - select(all[(index + offset + all.count) % all.count]) + func isFavorite(_ game: Game) -> Bool { + history[game.id]?.isFavorite == true } func toggleFavorite(_ game: Game) { @@ -137,6 +164,47 @@ final class LibraryModel { var entry = history[game.id] ?? GameHistory() change(&entry) history[game.id] = entry - try? store.save(history) + try? historyStore?.save(history) + } + + // MARK: Personalização (compartilhada entre perfis) + + func customization(for game: Game) -> GameCustomization? { + customizations[game.id] + } + + func hasCustomCover(_ game: Game) -> Bool { + customizations[game.id]?.coverFile != nil + } + + /// Copia a imagem escolhida como capa e devolve o endereço dela. + @discardableResult + func setCustomCover(for game: Game, from source: URL) throws -> URL { + let name = try artwork.importCover(from: source, for: game.id) + customize(game) { $0.coverFile = name } + return artwork.artworkDirectory.appending(path: name) + } + + func removeCustomCover(for game: Game) { + if let url = artwork.coverURL(for: customizations[game.id]) { try? FileManager.default.removeItem(at: url) } + customize(game) { $0.coverFile = nil } + } + + func setMetadata(_ metadata: GameMetadata?, for game: Game) { + customize(game) { $0.metadata = metadata } + } + + private func customize(_ game: Game, _ change: (inout GameCustomization) -> Void) { + var entry = customizations[game.id] ?? GameCustomization() + change(&entry) + customizations[game.id] = entry == GameCustomization() ? nil : entry + try? artwork.customizations.save(customizations) + decorate() + } + + private func decorate() { + games = scanned.map { game in + artwork.coverURL(for: customizations[game.id]).map(game.withCover) ?? game + } } } diff --git a/Sources/RetroXApp/App/ProfilesModel.swift b/Sources/RetroXApp/App/ProfilesModel.swift new file mode 100644 index 0000000..14c96b9 --- /dev/null +++ b/Sources/RetroXApp/App/ProfilesModel.swift @@ -0,0 +1,102 @@ +import AppKit +import Observation +import RetroXCore + +/// Perfis de jogador: quem está jogando, a foto, o tema e o histórico de cada um. +@MainActor +@Observable +final class ProfilesModel { + private(set) var profiles: [Profile] + private(set) var current: Profile? + /// Muda quando uma foto é trocada, para as views recarregarem a imagem do mesmo caminho. + private(set) var avatarRevision = 0 + + @ObservationIgnored let storage: ProfileStorage + @ObservationIgnored private var lastUsedID: UUID? + + init(storage: ProfileStorage = ProfileStorage()) { + self.storage = storage + let state = storage.state.load() ?? ProfilesState() + profiles = state.profiles + lastUsedID = state.lastUsedID + if profiles.isEmpty { createFirstProfile() } + } + + var lastUsed: Profile? { + profiles.first { $0.id == lastUsedID } ?? profiles.first + } + + func avatarURL(for profile: Profile) -> URL? { + storage.avatarURL(for: profile) + } + + func select(_ profile: Profile) { + current = profile + lastUsedID = profile.id + save() + } + + @discardableResult + func create(name: String) -> Profile { + let profile = Profile(name: name.isEmpty ? String(localized: "Jogador \(profiles.count + 1)") : name) + profiles.append(profile) + save() + return profile + } + + func update(_ profile: Profile) { + guard let index = profiles.firstIndex(where: { $0.id == profile.id }) else { return } + profiles[index] = profile + if current?.id == profile.id { current = profile } + save() + } + + /// Apaga o perfil e o histórico dele. Os jogos e as pastas dos emuladores não são tocados. + func delete(_ profile: Profile) { + guard profiles.count > 1 else { return } + profiles.removeAll { $0.id == profile.id } + try? FileManager.default.removeItem(at: storage.history(for: profile.id).url) + if let avatar = storage.avatarURL(for: profile) { try? FileManager.default.removeItem(at: avatar) } + if current?.id == profile.id { current = nil } + if lastUsedID == profile.id { lastUsedID = profiles.first?.id } + save() + } + + /// Copia a foto escolhida (reduzida) para dentro do RetroX. + func setAvatar(for profile: Profile, from source: URL) throws { + var updated = profile + let name = "\(profile.id.uuidString).png" + try ImageImporter.importPNG(from: source, to: storage.avatarsDirectory.appending(path: name), maxPixelSize: 512) + updated.avatarFile = name + update(updated) + avatarRevision += 1 + } + + func removeAvatar(for profile: Profile) { + guard let url = storage.avatarURL(for: profile) else { return } + try? FileManager.default.removeItem(at: url) + var updated = profile + updated.avatarFile = nil + update(updated) + avatarRevision += 1 + } + + /// Primeiro uso dos perfis: aproveita o tema escolhido antes nos Ajustes e o histórico que já existia. + private func createFirstProfile() { + let defaults = UserDefaults.standard + let fullName = NSFullUserName().split(separator: " ").first.map(String.init) + var profile = Profile(name: fullName ?? String(localized: "Jogador 1")) + if let accent = defaults.string(forKey: "accent").flatMap(Palette.Accent.init(rawValue:)) { profile.accent = accent } + if let appearance = defaults.string(forKey: "appearance").flatMap(AppearancePreference.init(rawValue:)) { + profile.appearance = appearance + } + profiles = [profile] + lastUsedID = profile.id + try? storage.migrateLegacyHistory(into: profile.id) + save() + } + + private func save() { + try? storage.state.save(ProfilesState(profiles: profiles, lastUsedID: lastUsedID)) + } +} diff --git a/Sources/RetroXApp/DesignSystem/Components.swift b/Sources/RetroXApp/DesignSystem/Components.swift index ba50068..1435be1 100644 --- a/Sources/RetroXApp/DesignSystem/Components.swift +++ b/Sources/RetroXApp/DesignSystem/Components.swift @@ -1,52 +1,75 @@ +import AppKit import RetroXCore import SwiftUI /// Ação principal: preenchida com a cor de tema. struct PrimaryButtonStyle: ButtonStyle { - @Environment(\.accent) private var accent @Environment(\.isEnabled) private var isEnabled func makeBody(configuration: Configuration) -> some View { configuration.label .font(Typography.bodyEmphasis) - .foregroundStyle(Color(accent.onFill)) + .foregroundStyle(Theme.onAccent) .padding(.horizontal, Spacing.l) .frame(minHeight: 44) - .background(Color(accent.fill).opacity(configuration.isPressed ? 0.85 : 1), in: Capsule()) - .opacity(isEnabled ? 1 : 0.45) + .background(Theme.accent, in: Capsule()) + .scaleEffect(configuration.isPressed ? 0.97 : 1) + .opacity(isEnabled ? (configuration.isPressed ? 0.9 : 1) : 0.45) .contentShape(Capsule()) + .animation(Motion.hover, value: configuration.isPressed) } } /// Ação secundária: superfície neutra, sem cor de tema. struct SecondaryButtonStyle: ButtonStyle { + var isCompact = false @Environment(\.isEnabled) private var isEnabled func makeBody(configuration: Configuration) -> some View { configuration.label - .font(Typography.bodyEmphasis) + .font(isCompact ? Typography.caption : Typography.bodyEmphasis) .foregroundStyle(Theme.textPrimary) - .padding(.horizontal, Spacing.m) - .frame(minHeight: 44) - .background(Theme.raised.opacity(configuration.isPressed ? 0.7 : 1), in: Capsule()) - .opacity(isEnabled ? 1 : 0.45) + .padding(.horizontal, isCompact ? Spacing.s + Spacing.xs : Spacing.m) + .frame(minHeight: isCompact ? 32 : 44) + .background(Theme.raised, in: Capsule()) + .scaleEffect(configuration.isPressed ? 0.97 : 1) + .opacity(isEnabled ? (configuration.isPressed ? 0.8 : 1) : 0.45) .contentShape(Capsule()) + .animation(Motion.hover, value: configuration.isPressed) } } /// Botão redondo só com ícone (favoritar, detalhes). Sempre com rótulo para VoiceOver. struct IconButtonStyle: ButtonStyle { var isActive = false - @Environment(\.accent) private var accent func makeBody(configuration: Configuration) -> some View { configuration.label .font(.system(size: 17, weight: .semibold)) - .foregroundStyle(isActive ? Color(accent.onFill) : Theme.textPrimary) + .foregroundStyle(isActive ? Theme.onAccent : Theme.textPrimary) .frame(width: 44, height: 44) - .background(isActive ? Color(accent.fill) : Theme.raised, in: Circle()) - .opacity(configuration.isPressed ? 0.8 : 1) + .background(isActive ? Theme.accent : Theme.raised, in: Circle()) + .scaleEffect(configuration.isPressed ? 0.94 : 1) .contentShape(Circle()) + .animation(Motion.hover, value: configuration.isPressed) + } +} + +/// Chip de filtro: selecionado ganha a cor de tema. +struct ChipButtonStyle: ButtonStyle { + let isSelected: Bool + @Environment(\.isEnabled) private var isEnabled + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .font(Typography.caption) + .foregroundStyle(isSelected ? Theme.onAccent : Theme.textPrimary) + .padding(.horizontal, Spacing.s + Spacing.xs) + .frame(minHeight: 32) + .background(isSelected ? Theme.accent : Theme.raised, in: Capsule()) + .opacity(isEnabled ? (configuration.isPressed ? 0.8 : 1) : 0.4) + .contentShape(Capsule()) + .animation(Motion.hover, value: isSelected) } } @@ -71,7 +94,7 @@ struct CommandHint: View { .font(.system(size: 11, weight: .semibold, design: .rounded)) .padding(.horizontal, Spacing.s) .frame(minWidth: 24, minHeight: 22) - .background(Theme.raised, in: RoundedRectangle(cornerRadius: 6, style: .continuous)) + .background(Theme.raised, in: RoundedRectangle.rx(6)) } Text(label) .font(Typography.caption) @@ -82,7 +105,7 @@ struct CommandHint: View { } } -/// Linha de verificação na tela de emuladores: ícone de estado + texto. +/// Linha de verificação: ícone de estado + texto. struct StatusLine: View { enum Kind { case ok, warning, info @@ -98,7 +121,6 @@ struct StatusLine: View { let kind: Kind let text: String - @Environment(\.accent) private var accent var body: some View { Label { @@ -108,7 +130,7 @@ struct StatusLine: View { .fixedSize(horizontal: false, vertical: true) } icon: { Image(systemName: kind.symbol) - .foregroundStyle(kind == .ok ? Color(accent.fill) : Theme.textSecondary) + .foregroundStyle(kind == .ok ? Theme.accent : Theme.textSecondary) } } } @@ -123,7 +145,71 @@ struct SystemBadge: View { .font(.system(size: size * 0.3, weight: .heavy, design: .rounded)) .foregroundStyle(Theme.onCover) .frame(width: size, height: size) - .background(Theme.coverTone(system), in: RoundedRectangle(cornerRadius: Radius.m, style: .continuous)) + .background(Theme.coverTone(system), in: RoundedRectangle.rx(Radius.m)) .accessibilityHidden(true) } } + +/// Foto do perfil, ou as iniciais sobre a cor de tema quando não há foto. +struct AvatarView: View { + let profile: Profile + var size: CGFloat = 32 + @Environment(AppModel.self) private var model + + var body: some View { + ZStack { + if let url = model.profiles.avatarURL(for: profile), + let image = NSImage(contentsOf: url) { + Image(nsImage: image) + .resizable() + .aspectRatio(contentMode: .fill) + } else { + Theme.accent + Text(profile.initials) + .font(.system(size: size * 0.38, weight: .bold, design: .rounded)) + .foregroundStyle(Theme.onAccent) + } + } + .frame(width: size, height: size) + .clipShape(Circle()) + .id(model.profiles.avatarRevision) + .accessibilityHidden(true) + } +} + +/// Campo de busca arredondado, no lugar do campo padrão do sistema. +struct SearchField: View { + @Binding var text: String + var prompt: String + var isFocused: FocusState.Binding + + var body: some View { + HStack(spacing: Spacing.s) { + Image(systemName: "magnifyingglass") + .foregroundStyle(Theme.textSecondary) + .accessibilityHidden(true) + TextField(prompt, text: $text) + .textFieldStyle(.plain) + .font(Typography.body) + .foregroundStyle(Theme.textPrimary) + .focused(isFocused) + if !text.isEmpty { + Button { + text = "" + } label: { + Image(systemName: "xmark.circle.fill") + .foregroundStyle(Theme.textSecondary) + } + .buttonStyle(.plain) + .accessibilityLabel("Limpar busca") + } + } + .padding(.horizontal, Spacing.m) + .frame(height: 40) + .background(Theme.raised, in: Capsule()) + .overlay { + Capsule().strokeBorder(Theme.accent.opacity(isFocused.wrappedValue ? 1 : 0), lineWidth: 2) + } + .animation(Motion.hover, value: isFocused.wrappedValue) + } +} diff --git a/Sources/RetroXApp/DesignSystem/CoverArtView.swift b/Sources/RetroXApp/DesignSystem/CoverArtView.swift index ae66b54..6735987 100644 --- a/Sources/RetroXApp/DesignSystem/CoverArtView.swift +++ b/Sources/RetroXApp/DesignSystem/CoverArtView.swift @@ -22,9 +22,9 @@ struct CoverArtView: View { } } .frame(width: width, height: width * Self.aspectRatio) - .clipShape(RoundedRectangle(cornerRadius: Radius.m, style: .continuous)) + .clipShape(RoundedRectangle.rx(Radius.m)) .overlay { - RoundedRectangle(cornerRadius: Radius.m, style: .continuous) + RoundedRectangle.rx(Radius.m) .strokeBorder(.white.opacity(0.06), lineWidth: 1) } .task(id: game.coverURL) { diff --git a/Sources/RetroXApp/DesignSystem/CoverImageStore.swift b/Sources/RetroXApp/DesignSystem/CoverImageStore.swift index f509735..14db0fd 100644 --- a/Sources/RetroXApp/DesignSystem/CoverImageStore.swift +++ b/Sources/RetroXApp/DesignSystem/CoverImageStore.swift @@ -15,6 +15,11 @@ final class CoverImageStore { url.flatMap { images[$0] } } + /// Esquece a imagem guardada (a capa foi trocada no mesmo endereço). + func invalidate(_ url: URL) { + images[url] = nil + } + func load(_ url: URL) async { guard images[url] == nil, inFlight.insert(url).inserted else { return } let cgImage = await Task.detached(priority: .utility) { diff --git a/Sources/RetroXApp/DesignSystem/Theme.swift b/Sources/RetroXApp/DesignSystem/Theme.swift index 7704bba..f43637d 100644 --- a/Sources/RetroXApp/DesignSystem/Theme.swift +++ b/Sources/RetroXApp/DesignSystem/Theme.swift @@ -3,33 +3,58 @@ import RetroXCore import SwiftUI extension Color { - /// Cor que acompanha o modo claro/escuro, a partir de um token da paleta. - init(_ tone: Tone) { + /// Cor que acompanha o modo claro/escuro, a partir de um par de cores. + init(light: HexColor, dark: HexColor) { self.init(nsColor: NSColor(name: nil) { appearance in let isDark = appearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua - let color = isDark ? tone.dark : tone.light + let color = isDark ? dark : light return NSColor(srgbRed: color.red, green: color.green, blue: color.blue, alpha: 1) }) } + + init(_ tone: Tone) { + self.init(light: tone.light, dark: tone.dark) + } +} + +/// Tema escolhido no perfil: esquema de cores e, no tema RetroX, o acento. +struct ThemeSelection: Equatable, Hashable { + var theme: ThemeID = .retrox + var accent: Palette.Accent = .coral } -/// Tokens da direção "Portátil quente" (docs/design/brand-spec.md). +/// Tokens de cor do tema ativo (docs/design/brand-spec.md). Trocar de tema reconstrói a árvore de views +/// (`RootView` usa o tema como identidade), então ler daqui no `body` é seguro. +@MainActor enum Theme { - static let background = Color(Palette.background) - static let surface = Color(Palette.surface) - static let raised = Color(Palette.raised) - static let textPrimary = Color(Palette.textPrimary) - static let textSecondary = Color(Palette.textSecondary) - static let divider = Color(Palette.divider) + static var current = ThemeSelection() + + static var background: Color { color(\.background) } + static var surface: Color { color(\.surface) } + static var raised: Color { color(\.raised) } + static var textPrimary: Color { color(\.textPrimary) } + static var textSecondary: Color { color(\.textSecondary) } + static var divider: Color { color(\.divider) } + static var accent: Color { color(\.accent) } + static var onAccent: Color { color(\.onAccent) } static let onCover = Color(Palette.onCover) static func coverTone(_ system: GameSystemID) -> Color { Color(Palette.coverTone(for: system)) } + + private static func color(_ key: KeyPath) -> Color { + let selection = current + return Color( + light: selection.theme.palette(dark: false, retroXAccent: selection.accent)[keyPath: key], + dark: selection.theme.palette(dark: true, retroXAccent: selection.accent)[keyPath: key] + ) + } } /// Grade de 8 pt. enum Spacing { + static let xxs: CGFloat = 2 static let xs: CGFloat = 4 static let s: CGFloat = 8 static let m: CGFloat = 16 @@ -38,10 +63,12 @@ enum Spacing { static let xxl: CGFloat = 48 } +/// Cantos sempre contínuos (`style: .continuous`), que leem mais suaves que arcos circulares. enum Radius { static let s: CGFloat = 8 static let m: CGFloat = 12 static let l: CGFloat = 16 + static let xl: CGFloat = 24 } /// No máximo quatro tamanhos por tela: título, seção, corpo e legenda. @@ -54,12 +81,15 @@ enum Typography { } enum Motion { - static let standard = Animation.spring(response: 0.32, dampingFraction: 0.82) - static let fade = Animation.easeOut(duration: 0.15) + /// Foco e seleção: rápido e sem quicar demais. + static let focus = Animation.snappy(duration: 0.28, extraBounce: 0.04) + /// Passar o mouse: um pouco mais suave que o foco. + static let hover = Animation.smooth(duration: 0.22) + static let fade = Animation.easeOut(duration: 0.18) /// Com Reduce Motion, só esmaece; nada se desloca ou cresce. static func animation(reduceMotion: Bool) -> Animation { - reduceMotion ? fade : standard + reduceMotion ? fade : focus } } @@ -68,32 +98,7 @@ enum AppLocale { static let current = Locale(identifier: "pt_BR") } -// MARK: Acento escolhido pelo usuário - -private struct AccentKey: EnvironmentKey { - static let defaultValue = Palette.Accent.coral -} - -extension EnvironmentValues { - var accent: Palette.Accent { - get { self[AccentKey.self] } - set { self[AccentKey.self] = newValue } - } -} - -enum Appearance: String, CaseIterable, Identifiable { - case system, light, dark - - var id: Self { self } - - var title: String { - switch self { - case .system: String(localized: "Sistema") - case .light: String(localized: "Claro") - case .dark: String(localized: "Escuro") - } - } - +extension AppearancePreference { var colorScheme: ColorScheme? { switch self { case .system: nil @@ -102,3 +107,10 @@ enum Appearance: String, CaseIterable, Identifiable { } } } + +extension RoundedRectangle { + /// Retângulo arredondado com cantos contínuos, o padrão do RetroX. + static func rx(_ radius: CGFloat) -> RoundedRectangle { + RoundedRectangle(cornerRadius: radius, style: .continuous) + } +} diff --git a/Sources/RetroXApp/DesignSystem/TopBar.swift b/Sources/RetroXApp/DesignSystem/TopBar.swift new file mode 100644 index 0000000..30f51f6 --- /dev/null +++ b/Sources/RetroXApp/DesignSystem/TopBar.swift @@ -0,0 +1,115 @@ +import RetroXCore +import SwiftUI + +/// Barra superior compartilhada por Início e Biblioteca: abas, estado, relógio, emuladores e perfil. +struct TopBar: View { + @Environment(AppModel.self) private var model + + var body: some View { + HStack(spacing: Spacing.m) { + Text("RetroX") + .font(.system(size: 20, weight: .heavy, design: .rounded)) + .foregroundStyle(Theme.textPrimary) + ScreenTabs() + .padding(.leading, Spacing.s) + Spacer() + if model.library.isScanning || model.plugins.entries.contains(where: \.isDiscovering) { + HStack(spacing: Spacing.s) { + ProgressView().controlSize(.small) + Text("Atualizando…") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + .transition(.opacity) + } + if let controller = model.input.controllerName { + Image(systemName: "gamecontroller.fill") + .foregroundStyle(Theme.textSecondary) + .help(controller) + .accessibilityLabel("Controle conectado: \(controller)") + } + TimelineView(.everyMinute) { context in + Text(context.date, format: .dateTime.hour().minute().locale(AppLocale.current)) + .font(Typography.bodyEmphasis) + .monospacedDigit() + .foregroundStyle(Theme.textPrimary) + } + Button { + model.screen = .emulators + } label: { + Image(systemName: "puzzlepiece.extension") + } + .buttonStyle(IconButtonStyle()) + .help("Emuladores") + .accessibilityLabel("Emuladores") + ProfileMenu() + } + // Espaço para os botões da janela (a barra de título fica escondida). + .padding(.leading, 88) + .padding(.trailing, Spacing.xl) + .padding(.top, Spacing.m) + .frame(height: 72) + .animation(Motion.fade, value: model.library.isScanning) + } +} + +/// Início | Biblioteca, como abas em pílula. +private struct ScreenTabs: View { + @Environment(AppModel.self) private var model + @Namespace private var selection + + var body: some View { + HStack(spacing: Spacing.xs) { + tab(.home, String(localized: "Início"), "house") + tab(.library, String(localized: "Biblioteca"), "square.grid.2x2") + } + .padding(Spacing.xs) + .background(Theme.raised, in: Capsule()) + } + + private func tab(_ screen: AppModel.Screen, _ title: String, _ symbol: String) -> some View { + let isSelected = model.screen == screen + return Button { + withAnimation(Motion.focus) { model.screen = screen } + } label: { + Label(title, systemImage: symbol) + .font(Typography.caption) + .foregroundStyle(isSelected ? Theme.onAccent : Theme.textPrimary) + .padding(.horizontal, Spacing.m) + .frame(height: 32) + .background { + if isSelected { + Capsule().fill(Theme.accent).matchedGeometryEffect(id: "tab", in: selection) + } + } + .contentShape(Capsule()) + } + .buttonStyle(.plain) + .accessibilityAddTraits(isSelected ? .isSelected : []) + } +} + +private struct ProfileMenu: View { + @Environment(AppModel.self) private var model + + var body: some View { + if let profile = model.profiles.current { + Menu { + Text(profile.name) + Button("Editar perfil…") { model.edit(profile) } + Button("Trocar de perfil") { model.showProfiles() } + Divider() + SettingsLink { Text("Ajustes…") } + } label: { + AvatarView(profile: profile, size: 36) + .overlay(Circle().strokeBorder(Theme.divider, lineWidth: 1)) + } + .menuStyle(.button) + .buttonStyle(.plain) + .menuIndicator(.hidden) + .fixedSize() + .help(profile.name) + .accessibilityLabel("Perfil: \(profile.name)") + } + } +} diff --git a/Sources/RetroXApp/Features/Details/GameDetailsView.swift b/Sources/RetroXApp/Features/Details/GameDetailsView.swift index 77b0209..25526ad 100644 --- a/Sources/RetroXApp/Features/Details/GameDetailsView.swift +++ b/Sources/RetroXApp/Features/Details/GameDetailsView.swift @@ -8,73 +8,126 @@ struct GameDetailsView: View { var body: some View { let history = model.library.history(for: game) - HStack(alignment: .top, spacing: Spacing.xl) { - CoverArtView(game: game, width: 200) - .shadow(color: .black.opacity(0.2), radius: 16, y: 8) - VStack(alignment: .leading, spacing: Spacing.m) { - Text((SystemCatalog.system(game.systemID)?.displayName ?? "").uppercased()) - .font(Typography.caption) - .tracking(1.4) - .foregroundStyle(Theme.textSecondary) - Text(game.title) - .font(Typography.heading) - .foregroundStyle(Theme.textPrimary) - .fixedSize(horizontal: false, vertical: true) - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: Spacing.m, verticalSpacing: Spacing.s) { - row(String(localized: "Arquivo"), game.romURL.lastPathComponent) - row(String(localized: "Pasta"), (game.romURL.deletingLastPathComponent().path(percentEncoded: false) as NSString).abbreviatingWithTildeInPath) - row(String(localized: "Tamanho"), game.fileSize.formatted(.byteCount(style: .file).locale(AppLocale.current))) - if let serial = game.serial { - row(String(localized: "Serial"), serial) + VStack(spacing: 0) { + HStack(alignment: .top, spacing: Spacing.xl) { + VStack(spacing: Spacing.s) { + CoverArtView(game: game, width: 220) + .shadow(color: .black.opacity(0.2), radius: 16, y: 8) + HStack(spacing: Spacing.s) { + Button("Trocar capa…") { Task { await model.chooseCustomCover(for: game) } } + if model.library.hasCustomCover(game) { + Button("Original") { model.restoreOriginalCover(for: game) } + .help("Voltar para a capa encontrada nas pastas") + } } - row(String(localized: "Emulador"), emulatorDescription) - row(String(localized: "Partidas"), playsDescription(history)) - } - DisclosureGroup("Comando de abertura") { - commandPlan - .padding(.top, Spacing.s) + .buttonStyle(SecondaryButtonStyle(isCompact: true)) } - .font(Typography.body) - Spacer(minLength: 0) - HStack(spacing: Spacing.s) { - Button { - model.play(game) - } label: { - Label("Jogar", systemImage: "play.fill") - } - .buttonStyle(PrimaryButtonStyle()) - .keyboardShortcut(.defaultAction) - Button { - model.library.toggleFavorite(game) - } label: { - Label(history.isFavorite ? "Favorito" : "Favoritar", systemImage: history.isFavorite ? "star.fill" : "star") - } - .buttonStyle(SecondaryButtonStyle()) - Button { - NSWorkspace.shared.activateFileViewerSelecting([game.romURL]) - } label: { - Label("Mostrar no Finder", systemImage: "folder") - } - .buttonStyle(SecondaryButtonStyle()) - Spacer() - Button("Fechar") { - model.detailsGame = nil + ScrollView { + VStack(alignment: .leading, spacing: Spacing.l) { + header + facts(history) + MetadataSection(game: game) + DisclosureGroup("Comando de abertura") { + commandPlan + .padding(.top, Spacing.s) + } + .font(Typography.body) + .foregroundStyle(Theme.textPrimary) } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.trailing, Spacing.s) + } + .scrollIndicators(.automatic) + } + .padding(Spacing.xl) + + HStack(spacing: Spacing.s) { + Button { + model.play(game) + } label: { + Label("Jogar", systemImage: "play.fill") + } + .buttonStyle(PrimaryButtonStyle()) + .keyboardShortcut(.defaultAction) + Button { + model.library.toggleFavorite(game) + } label: { + Label(history.isFavorite ? "Favorito" : "Favoritar", systemImage: history.isFavorite ? "star.fill" : "star") + } + .buttonStyle(SecondaryButtonStyle()) + Button { + NSWorkspace.shared.activateFileViewerSelecting([game.romURL]) + } label: { + Label("Mostrar no Finder", systemImage: "folder") + } + .buttonStyle(SecondaryButtonStyle()) + Spacer() + Button("Fechar") { model.showDetails(nil) } .buttonStyle(SecondaryButtonStyle()) .keyboardShortcut(.cancelAction) - } } + .padding(.horizontal, Spacing.xl) + .padding(.vertical, Spacing.m) + .background(Theme.background) + .overlay(alignment: .top) { Theme.divider.frame(height: 1) } } - .padding(Spacing.xl) - .frame(width: 760, height: 460) + .frame(width: 880, height: 620) .background(Theme.surface) } - private func row(_ label: String, _ value: String) -> some View { - GridRow { - Text(label) + private var header: some View { + VStack(alignment: .leading, spacing: Spacing.s) { + Text(GameText.overline(game, emulator: model.plugins.entry(game.pluginID)?.plugin.displayName)) .font(Typography.caption) + .tracking(1.4) .foregroundStyle(Theme.textSecondary) + Text(game.title) + .font(Typography.display) + .foregroundStyle(Theme.textPrimary) + .fixedSize(horizontal: false, vertical: true) + if let official = game.info?.name, TitleParser.searchKey(official) != TitleParser.searchKey(TitleParser.searchTitle(game.title)) { + Text("Nome no \(model.plugins.entry(game.pluginID)?.plugin.displayName ?? "emulador"): \(official)") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + } + } + + private func facts(_ history: GameHistory) -> some View { + Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: Spacing.m, verticalSpacing: Spacing.s) { + row(String(localized: "Arquivo"), game.romURL.lastPathComponent) + row(String(localized: "Pasta"), (game.romURL.deletingLastPathComponent().path(percentEncoded: false) as NSString).abbreviatingWithTildeInPath) + row(String(localized: "Tamanho"), GameText.size(game)) + if let serial = game.serial { row(String(localized: "Serial"), serial) } + if let region = game.info?.region { row(String(localized: "Região"), region) } + if let compatibility = game.info?.compatibility { + GridRow { + label(String(localized: "Compatibilidade")) + HStack(spacing: Spacing.xxs) { + ForEach(1...5, id: \.self) { star in + Image(systemName: star <= compatibility ? "star.fill" : "star") + .font(.system(size: 11)) + .foregroundStyle(star <= compatibility ? Theme.accent : Theme.textSecondary) + } + } + .accessibilityElement(children: .ignore) + .accessibilityLabel("\(compatibility) de 5 no \(model.plugins.entry(game.pluginID)?.plugin.displayName ?? "emulador")") + } + } + row(String(localized: "Emulador"), emulatorDescription) + row(String(localized: "Partidas"), playsDescription(history)) + } + } + + private func label(_ text: String) -> some View { + Text(text) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + + private func row(_ title: String, _ value: String) -> some View { + GridRow { + label(title) Text(value) .font(Typography.body) .foregroundStyle(Theme.textPrimary) @@ -115,3 +168,151 @@ struct GameDetailsView: View { } } } + +/// Informações de uma fonte pública: só com a ação do usuário, que escolhe o resultado certo (ADR-0014). +private struct MetadataSection: View { + let game: Game + @Environment(AppModel.self) private var model + + var body: some View { + let search = model.metadata + VStack(alignment: .leading, spacing: Spacing.m) { + HStack { + Text("Sobre o jogo") + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + Spacer() + if !search.isActive { + Button(model.library.customization(for: game)?.metadata == nil ? "Buscar na Wikipedia" : "Buscar de novo") { + search.start(for: game) + } + .buttonStyle(SecondaryButtonStyle(isCompact: true)) + } + } + if search.isActive && search.gameID == game.id { + SearchPanel(game: game) + } else if let metadata = model.library.customization(for: game)?.metadata { + SavedMetadata(game: game, metadata: metadata) + } else { + Text("Sem informações extras. A busca usa a Wikipedia (sem conta) e você escolhe o resultado certo.") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + .fixedSize(horizontal: false, vertical: true) + } + } + .padding(Spacing.m) + .background(Theme.background.opacity(0.6), in: RoundedRectangle.rx(Radius.l)) + } +} + +private struct SearchPanel: View { + let game: Game + @Environment(AppModel.self) private var model + @FocusState private var isQueryFocused: Bool + + var body: some View { + @Bindable var search = model.metadata + VStack(alignment: .leading, spacing: Spacing.s) { + HStack(spacing: Spacing.s) { + SearchField(text: $search.query, prompt: String(localized: "Nome do jogo"), isFocused: $isQueryFocused) + .onSubmit { Task { await search.search() } } + Button("Buscar") { Task { await search.search() } } + .buttonStyle(SecondaryButtonStyle(isCompact: true)) + Button("Cancelar") { search.cancel() } + .buttonStyle(SecondaryButtonStyle(isCompact: true)) + } + switch search.phase { + case .idle: + EmptyView() + case .searching: + HStack(spacing: Spacing.s) { + ProgressView().controlSize(.small) + Text("Buscando na Wikipedia…").font(Typography.body).foregroundStyle(Theme.textSecondary) + } + case .results(let candidates) where candidates.isEmpty: + Text("Nenhum resultado. Tente o nome sem número de versão ou em inglês.") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + case .results(let candidates): + Text("Qual destes é o jogo?") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + ForEach(candidates) { candidate in + Button { + Task { await search.choose(candidate, for: game, library: model.library) } + } label: { + VStack(alignment: .leading, spacing: Spacing.xxs) { + Text("\(candidate.title) · \(candidate.language.uppercased())") + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.textPrimary) + Text(candidate.snippet) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + .lineLimit(2) + } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(Spacing.s + Spacing.xs) + .background(Theme.raised, in: RoundedRectangle.rx(Radius.m)) + .contentShape(RoundedRectangle.rx(Radius.m)) + } + .buttonStyle(.plain) + } + case .loading(let candidate): + HStack(spacing: Spacing.s) { + ProgressView().controlSize(.small) + Text("Lendo “\(candidate.title)”…").font(Typography.body).foregroundStyle(Theme.textSecondary) + } + case .failed(let message): + StatusLine(kind: .warning, text: message) + } + } + .onAppear { isQueryFocused = false } + } +} + +private struct SavedMetadata: View { + let game: Game + let metadata: GameMetadata + @Environment(AppModel.self) private var model + + var body: some View { + VStack(alignment: .leading, spacing: Spacing.s) { + if let description = metadata.shortDescription { + Text(description.prefix(1).uppercased() + description.dropFirst()) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + Text(metadata.summary) + .font(Typography.body) + .foregroundStyle(Theme.textPrimary) + .lineSpacing(3) + .fixedSize(horizontal: false, vertical: true) + .textSelection(.enabled) + Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: Spacing.m, verticalSpacing: Spacing.xs) { + if let year = metadata.releaseYear { fact(String(localized: "Lançamento"), String(year)) } + if !metadata.developers.isEmpty { fact(String(localized: "Desenvolvedora"), metadata.developers.joined(separator: ", ")) } + if !metadata.publishers.isEmpty { fact(String(localized: "Editora"), metadata.publishers.joined(separator: ", ")) } + if !metadata.genres.isEmpty { fact(String(localized: "Gênero"), metadata.genres.joined(separator: ", ")) } + } + .padding(.top, Spacing.xs) + HStack(spacing: Spacing.s) { + if let url = metadata.sourceURL { + Link("Fonte: \(metadata.sourceName) · CC BY-SA", destination: url) + .font(Typography.caption) + } else { + Text("Fonte: \(metadata.sourceName)").font(Typography.caption).foregroundStyle(Theme.textSecondary) + } + Spacer() + Button("Remover") { model.library.setMetadata(nil, for: game) } + .buttonStyle(SecondaryButtonStyle(isCompact: true)) + } + } + } + + private func fact(_ title: String, _ value: String) -> some View { + GridRow { + Text(title).font(Typography.caption).foregroundStyle(Theme.textSecondary) + Text(value).font(Typography.body).foregroundStyle(Theme.textPrimary) + } + } +} diff --git a/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift b/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift index 3a831f4..5cb4d53 100644 --- a/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift +++ b/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift @@ -94,7 +94,7 @@ private struct PluginCard: View { } } .padding(Spacing.l) - .background(Theme.surface, in: RoundedRectangle(cornerRadius: Radius.l, style: .continuous)) + .background(Theme.surface, in: RoundedRectangle.rx(Radius.l)) } private var rootFolder: some View { @@ -135,6 +135,10 @@ private struct DiscoveryReport: View { gamesLines coversLine biosLine + achievementsLine + if let controller = discovery.controller { + ControllerMapping(controller: controller, emulator: entry.plugin.displayName) + } ForEach(Array(otherIssues.enumerated()), id: \.offset) { _, issue in StatusLine(kind: .warning, text: issue.message) } @@ -218,6 +222,21 @@ private struct DiscoveryReport: View { } } + /// Estado do RetroAchievements no emulador. A conta é escolhida e conectada no próprio emulador. + @ViewBuilder + private var achievementsLine: some View { + if let status = discovery.achievements { + switch (status.isEnabled, status.username) { + case (false, _): + StatusLine(kind: .info, text: String(localized: "RetroAchievements desligado no \(entry.plugin.displayName).")) + case (true, nil): + StatusLine(kind: .warning, text: String(localized: "RetroAchievements ligado, mas sem conta conectada no \(entry.plugin.displayName).")) + case (true, let username?): + StatusLine(kind: .ok, text: String(localized: "RetroAchievements: conectado como \(username)\(status.isHardcore ? String(localized: " · hardcore") : "")")) + } + } + } + private var otherIssues: [PluginIssue] { discovery.issues.filter { switch $0 { @@ -244,7 +263,7 @@ private struct UpcomingCard: View { .font(.system(size: 20, weight: .semibold)) .foregroundStyle(Theme.textSecondary) .frame(width: 48, height: 48) - .background(Theme.raised, in: RoundedRectangle(cornerRadius: Radius.m, style: .continuous)) + .background(Theme.raised, in: RoundedRectangle.rx(Radius.m)) .accessibilityHidden(true) VStack(alignment: .leading, spacing: Spacing.xs) { Text(upcoming.name) @@ -263,7 +282,7 @@ private struct UpcomingCard: View { .background(Theme.raised, in: Capsule()) } .padding(Spacing.l) - .background(Theme.surface.opacity(0.6), in: RoundedRectangle(cornerRadius: Radius.l, style: .continuous)) + .background(Theme.surface.opacity(0.6), in: RoundedRectangle.rx(Radius.l)) .accessibilityElement(children: .combine) } } @@ -272,3 +291,68 @@ private func abbreviated(_ url: URL) -> String { (url.path(percentEncoded: false).trimmingCharacters(in: CharacterSet(charactersIn: "/")).isEmpty ? "/" : (url.path(percentEncoded: false) as NSString).abbreviatingWithTildeInPath) } + +/// O mapeamento do controle configurado no emulador, só para conferir (não é alterado aqui). +private struct ControllerMapping: View { + let controller: ControllerSummary + let emulator: String + + var body: some View { + DisclosureGroup { + Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: Spacing.m, verticalSpacing: Spacing.xs) { + ForEach(controller.bindings, id: \.self) { binding in + GridRow { + Text(Self.ps2Name(binding.button)) + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.textPrimary) + Text(Self.inputName(binding.input)) + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + } + } + } + .padding(.top, Spacing.s) + .padding(.leading, Spacing.l) + } label: { + StatusLine(kind: .ok, text: String(localized: "Controle no \(emulator): \(controller.type)\(controller.device.map { " · \($0)" } ?? "")")) + } + } + + static func ps2Name(_ button: String) -> String { + switch button { + case "Cross": "×" + case "Circle": "○" + case "Square": "□" + case "Triangle": "△" + case "Up": "↑" + case "Down": "↓" + case "Left": "←" + case "Right": "→" + default: button + } + } + + /// "SDL-0/FaceSouth" → "botão de baixo (A / ×)". + static func inputName(_ input: String) -> String { + let name = input.split(separator: "/").last.map(String.init) ?? input + let names: [String: String] = [ + "FaceSouth": String(localized: "botão de baixo (A / ×)"), + "FaceEast": String(localized: "botão da direita (B / ○)"), + "FaceWest": String(localized: "botão da esquerda (X / □)"), + "FaceNorth": String(localized: "botão de cima (Y / △)"), + "DPadUp": String(localized: "direcional ↑"), + "DPadDown": String(localized: "direcional ↓"), + "DPadLeft": String(localized: "direcional ←"), + "DPadRight": String(localized: "direcional →"), + "LeftShoulder": "LB / L1", + "RightShoulder": "RB / R1", + "+LeftTrigger": "LT / L2", + "+RightTrigger": "RT / R2", + "LeftStick": String(localized: "clique do analógico esquerdo"), + "RightStick": String(localized: "clique do analógico direito"), + "Back": "Select / View", + "Start": "Start / Menu", + ] + return names[name] ?? input + } +} diff --git a/Sources/RetroXApp/Features/Home/HomeView.swift b/Sources/RetroXApp/Features/Home/HomeView.swift index c805edd..c09ea7c 100644 --- a/Sources/RetroXApp/Features/Home/HomeView.swift +++ b/Sources/RetroXApp/Features/Home/HomeView.swift @@ -11,7 +11,12 @@ struct HomeView: View { VStack(spacing: 0) { TopBar() content - HintBar() + HintBar(items: [ + .init(action: .confirm, key: "↩", label: String(localized: "Jogar")), + .init(action: .details, key: "Espaço", label: String(localized: "Detalhes")), + .init(action: .favorite, key: "F", label: String(localized: "Favoritar")), + .init(actions: [.previousShelf, .nextShelf], key: "Q E", label: String(localized: "Prateleira")), + ]) } .focusable() .focusEffectDisabled() @@ -21,7 +26,7 @@ struct HomeView: View { if game == nil { isFocused = true } } .onKeyPress(phases: [.down, .repeat]) { press in - guard !press.modifiers.contains(.command), let action = Self.action(for: press) else { return .ignored } + guard !press.modifiers.contains(.command), let action = KeyMapping.action(for: press) else { return .ignored } model.handle(action) return .handled } @@ -42,7 +47,10 @@ struct HomeView: View { ShelfView() } } +} +/// Teclas → ações, iguais em todas as telas. +enum KeyMapping { static func action(for press: KeyPress) -> InputAction? { switch press.key { case .leftArrow: return .left @@ -64,55 +72,6 @@ struct HomeView: View { } } -private struct TopBar: View { - @Environment(AppModel.self) private var model - - var body: some View { - HStack(spacing: Spacing.m) { - Text("RetroX") - .font(.system(size: 20, weight: .heavy, design: .rounded)) - .foregroundStyle(Theme.textPrimary) - Spacer() - if model.library.isScanning || model.plugins.entries.contains(where: \.isDiscovering) { - HStack(spacing: Spacing.s) { - ProgressView().controlSize(.small) - Text("Atualizando biblioteca…") - .font(Typography.caption) - .foregroundStyle(Theme.textSecondary) - } - } - if let controller = model.input.controllerName { - Image(systemName: "gamecontroller.fill") - .foregroundStyle(Theme.textSecondary) - .help(controller) - .accessibilityLabel("Controle conectado: \(controller)") - } - TimelineView(.everyMinute) { context in - Text(context.date, format: .dateTime.hour().minute().locale(AppLocale.current)) - .font(Typography.bodyEmphasis) - .monospacedDigit() - .foregroundStyle(Theme.textPrimary) - } - Button { - model.screen = .emulators - } label: { - Label("Emuladores", systemImage: "puzzlepiece.extension") - } - .buttonStyle(SecondaryButtonStyle()) - SettingsLink { - Image(systemName: "gearshape") - } - .buttonStyle(IconButtonStyle()) - .accessibilityLabel("Ajustes") - } - // Espaço para os botões da janela (a barra de título fica escondida). - .padding(.leading, 88) - .padding(.trailing, Spacing.xl) - .padding(.top, Spacing.m) - .frame(height: 72) - } -} - private struct StageView: View { @Environment(AppModel.self) private var model @Environment(\.accessibilityReduceMotion) private var reduceMotion @@ -133,7 +92,7 @@ private struct StageView: View { } .padding(.horizontal, Spacing.xxl) .id(game.id) - .transition(.opacity) + .transition(.opacity.combined(with: .offset(x: reduceMotion ? 0 : 12))) } else { EmptyShelfMessage(shelf: model.library.shelf) .padding(.horizontal, Spacing.xxl) @@ -153,7 +112,7 @@ private struct StageDetails: View { var body: some View { let history = model.library.history(for: game) VStack(alignment: .leading, spacing: Spacing.m) { - Text(overline) + Text(GameText.overline(game, emulator: model.plugins.entry(game.pluginID)?.plugin.displayName)) .font(Typography.caption) .tracking(1.4) .foregroundStyle(Theme.textSecondary) @@ -162,7 +121,7 @@ private struct StageDetails: View { .foregroundStyle(Theme.textPrimary) .lineLimit(2) .fixedSize(horizontal: false, vertical: true) - Text(Self.metadata(game: game, history: history)) + Text(GameText.metadata(game: game, history: history)) .font(Typography.body) .foregroundStyle(Theme.textSecondary) HStack(spacing: Spacing.s) { @@ -180,7 +139,7 @@ private struct StageDetails: View { .buttonStyle(IconButtonStyle(isActive: history.isFavorite)) .accessibilityLabel(history.isFavorite ? "Remover dos favoritos" : "Favoritar") Button { - model.detailsGame = game + model.showDetails(game) } label: { Image(systemName: "info") } @@ -191,26 +150,29 @@ private struct StageDetails: View { } .frame(maxWidth: 520, alignment: .leading) } +} - private var overline: String { +/// Textos de jogo repetidos em várias telas. +enum GameText { + static func overline(_ game: Game, emulator: String?) -> String { let system = SystemCatalog.system(game.systemID)?.displayName ?? game.systemID.rawValue - let emulator = model.plugins.entry(game.pluginID)?.plugin.displayName ?? "" - return "\(system) · \(emulator)".uppercased() + return [system, emulator].compactMap { $0 }.joined(separator: " · ").uppercased() + } + + static func lastPlayed(_ history: GameHistory) -> String { + guard let last = history.lastPlayedAt else { return String(localized: "Ainda não jogado") } + let relative = RelativeDateTimeFormatter() + relative.locale = AppLocale.current + relative.unitsStyle = .full + return String(localized: "Jogado \(relative.localizedString(for: last, relativeTo: .now))") + } + + static func size(_ game: Game) -> String { + game.fileSize.formatted(.byteCount(style: .file).locale(AppLocale.current)) } static func metadata(game: Game, history: GameHistory) -> String { - var parts: [String] = [] - if let last = history.lastPlayedAt { - let relative = RelativeDateTimeFormatter() - relative.locale = AppLocale.current - relative.unitsStyle = .full - parts.append(String(localized: "Jogado \(relative.localizedString(for: last, relativeTo: .now))")) - } else { - parts.append(String(localized: "Ainda não jogado")) - } - parts.append(game.fileSize.formatted(.byteCount(style: .file).locale(AppLocale.current))) - parts.append(game.fileExtension) - return parts.joined(separator: " · ") + [lastPlayed(history), size(game), game.fileExtension].joined(separator: " · ") } } @@ -233,14 +195,13 @@ private struct EmptyShelfMessage: View { } /// Estados de tela inteira: sem emulador, procurando jogos, nenhum jogo encontrado. -private struct EmptyHome: View { +struct EmptyHome: View { enum Kind { case noEmulator, loading, noGames } let kind: Kind @Environment(AppModel.self) private var model - @Environment(\.accent) private var accent var body: some View { VStack(alignment: .leading, spacing: Spacing.m) { @@ -250,7 +211,7 @@ private struct EmptyHome: View { } else { Image(systemName: kind == .noEmulator ? "puzzlepiece.extension" : "tray") .font(.system(size: 34, weight: .semibold)) - .foregroundStyle(Color(accent.fill)) + .foregroundStyle(Theme.accent) .accessibilityHidden(true) } Text(title) @@ -293,23 +254,41 @@ private struct EmptyHome: View { } } -private struct HintBar: View { +/// Barra de comandos no rodapé: mostra os glifos do controle conectado ou as teclas. +struct HintBar: View { + struct Item { + let actions: [InputAction] + let key: String + let label: String + + init(action: InputAction, key: String, label: String) { + self.init(actions: [action], key: key, label: label) + } + + init(actions: [InputAction], key: String, label: String) { + self.actions = actions + self.key = key + self.label = label + } + } + + let items: [Item] + var showsMenu = true @Environment(AppModel.self) private var model var body: some View { let glyphs = model.input.glyphs HStack(spacing: Spacing.l) { - CommandHint(glyphs: glyphs[.confirm].map { [$0] }, key: "↩", label: String(localized: "Jogar")) - CommandHint(glyphs: glyphs[.details].map { [$0] }, key: "Espaço", label: String(localized: "Detalhes")) - CommandHint(glyphs: glyphs[.favorite].map { [$0] }, key: "F", label: String(localized: "Favoritar")) - CommandHint( - glyphs: [glyphs[.previousShelf], glyphs[.nextShelf]].allSatisfy { $0 != nil } - ? [glyphs[.previousShelf]!, glyphs[.nextShelf]!] : nil, - key: "Q E", - label: String(localized: "Prateleira") - ) + ForEach(items, id: \.label) { item in + // Atalho só de teclado (sem ação) ou controle sem glifo para todas as ações: mostra a tecla. + let symbols = item.actions.compactMap { glyphs[$0] } + let hasGlyphs = !item.actions.isEmpty && symbols.count == item.actions.count + CommandHint(glyphs: hasGlyphs ? symbols : nil, key: item.key, label: item.label) + } Spacer() - CommandHint(glyphs: glyphs[.menu].map { [$0] }, key: "M", label: String(localized: "Emuladores")) + if showsMenu { + CommandHint(glyphs: glyphs[.menu].map { [$0] }, key: "M", label: String(localized: "Emuladores")) + } } .padding(.horizontal, Spacing.xxl) .frame(height: 48) diff --git a/Sources/RetroXApp/Features/Home/ShelfView.swift b/Sources/RetroXApp/Features/Home/ShelfView.swift index dc10f57..5a64700 100644 --- a/Sources/RetroXApp/Features/Home/ShelfView.swift +++ b/Sources/RetroXApp/Features/Home/ShelfView.swift @@ -42,7 +42,7 @@ struct ShelfView: View { private struct ShelfTabs: View { @Environment(AppModel.self) private var model - @Environment(\.accent) private var accent + @Namespace private var underline var body: some View { let library = model.library @@ -50,15 +50,21 @@ private struct ShelfTabs: View { ForEach(library.shelves) { shelf in let isSelected = shelf == library.shelf Button { - library.select(shelf) + withAnimation(Motion.focus) { library.select(shelf) } } label: { VStack(spacing: Spacing.xs) { Text(shelf.title) .font(Typography.bodyEmphasis) .foregroundStyle(isSelected ? Theme.textPrimary : Theme.textSecondary) - Capsule() - .fill(isSelected ? Color(accent.fill) : .clear) - .frame(width: 20, height: 3) + ZStack { + Capsule().fill(.clear).frame(width: 20, height: 3) + if isSelected { + Capsule() + .fill(Theme.accent) + .frame(width: 20, height: 3) + .matchedGeometryEffect(id: "underline", in: underline) + } + } } .contentShape(Rectangle()) } @@ -82,32 +88,36 @@ private struct ShelfTile: View { let game: Game let isFocused: Bool @Environment(AppModel.self) private var model - @Environment(\.accent) private var accent @Environment(\.accessibilityReduceMotion) private var reduceMotion var body: some View { - let lifts = isFocused && !reduceMotion + let isHovered = model.browser.hoveredGameID == game.id && !isFocused + let lifts = !reduceMotion && (isFocused || isHovered) VStack(spacing: 0) { CoverArtView(game: game, width: ShelfView.tileWidth) .overlay { - RoundedRectangle(cornerRadius: Radius.m + 5, style: .continuous) - .strokeBorder(Color(accent.fill), lineWidth: 3) + RoundedRectangle.rx(Radius.m + 5) + .strokeBorder(Theme.accent, lineWidth: 3) .padding(-6) .opacity(isFocused ? 1 : 0) } .shadow( - color: isFocused ? Color(accent.fill).opacity(0.45) : .black.opacity(0.16), - radius: isFocused ? 22 : 6, - y: isFocused ? 10 : 3 + color: isFocused ? Theme.accent.opacity(0.45) : .black.opacity(isHovered ? 0.24 : 0.14), + radius: isFocused ? 22 : (isHovered ? 12 : 6), + y: isFocused ? 10 : 4 ) - .scaleEffect(lifts ? 1.1 : 1, anchor: .bottom) - .offset(y: lifts ? -6 : 0) + .scaleEffect(lifts ? (isFocused ? 1.1 : 1.04) : 1, anchor: .bottom) + .offset(y: lifts ? (isFocused ? -6 : -2) : 0) Reflection(game: game) .opacity(isFocused ? 1 : 0) } .animation(Motion.animation(reduceMotion: reduceMotion), value: isFocused) + .animation(Motion.hover, value: isHovered) .contentShape(Rectangle()) - .onTapGesture { model.library.focus(game) } + .onHover { inside in + model.browser.hoveredGameID = inside ? game.id : (model.browser.hoveredGameID == game.id ? nil : model.browser.hoveredGameID) + } + .onTapGesture { withAnimation(Motion.focus) { model.library.focus(game) } } .simultaneousGesture(TapGesture(count: 2).onEnded { model.play(game) }) .accessibilityElement(children: .ignore) .accessibilityLabel(accessibilityLabel) @@ -119,7 +129,7 @@ private struct ShelfTile: View { private var accessibilityLabel: String { let system = SystemCatalog.system(game.systemID)?.shortName ?? "" - let favorite = model.library.history(for: game).isFavorite ? String(localized: ", favorito") : "" + let favorite = model.library.isFavorite(game) ? String(localized: ", favorito") : "" return "\(game.title), \(system)\(favorite)" } } diff --git a/Sources/RetroXApp/Features/Library/LibraryView.swift b/Sources/RetroXApp/Features/Library/LibraryView.swift new file mode 100644 index 0000000..720318f --- /dev/null +++ b/Sources/RetroXApp/Features/Library/LibraryView.swift @@ -0,0 +1,430 @@ +import AppKit +import RetroXCore +import SwiftUI + +/// Todos os jogos em grade ou lista, com busca, filtro por console e favoritos. +struct LibraryView: View { + @Environment(AppModel.self) private var model + @FocusState private var isGridFocused: Bool + @FocusState private var isSearchFocused: Bool + + var body: some View { + VStack(spacing: 0) { + TopBar() + LibraryToolbar(isSearchFocused: $isSearchFocused) + content + HintBar(items: [ + .init(action: .confirm, key: "↩", label: String(localized: "Jogar")), + .init(action: .details, key: "Espaço", label: String(localized: "Detalhes")), + .init(action: .favorite, key: "F", label: String(localized: "Favoritar")), + .init(actions: [.previousShelf, .nextShelf], key: "Q E", label: String(localized: "Console")), + .init(actions: [], key: "/", label: String(localized: "Buscar")), + ]) + } + .focusable() + .focusEffectDisabled() + .focused($isGridFocused) + .onAppear { isGridFocused = true } + .onChange(of: model.detailsGame) { _, game in + if game == nil { isGridFocused = true } + } + .onKeyPress(phases: [.down, .repeat]) { press in + if isSearchFocused { + // Na busca, Esc e as setas para baixo voltam para a grade; o resto é texto. + guard press.key == .escape || press.key == .downArrow || press.key == .return else { return .ignored } + isSearchFocused = false + isGridFocused = true + return .handled + } + if press.characters == "/" || (press.modifiers.contains(.command) && press.characters == "f") { + isSearchFocused = true + return .handled + } + guard !press.modifiers.contains(.command), let action = KeyMapping.action(for: press) else { return .ignored } + model.handle(action) + return .handled + } + } + + @ViewBuilder + private var content: some View { + let library = model.library + if !model.plugins.hasEnabledPlugin { + EmptyHome(kind: .noEmulator) + } else if !library.hasLoaded { + EmptyHome(kind: .loading) + } else if library.games.isEmpty { + EmptyHome(kind: .noGames) + } else if model.browser.results.isEmpty { + NoResults() + } else { + LibraryGrid() + } + } +} + +private struct LibraryToolbar: View { + var isSearchFocused: FocusState.Binding + @Environment(AppModel.self) private var model + + var body: some View { + @Bindable var browser = model.browser + VStack(alignment: .leading, spacing: Spacing.m) { + HStack(alignment: .firstTextBaseline, spacing: Spacing.m) { + Text("Biblioteca") + .font(Typography.display) + .foregroundStyle(Theme.textPrimary) + Text(countLabel) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + Spacer() + SearchField(text: $browser.searchText, prompt: String(localized: "Buscar por nome ou serial"), isFocused: isSearchFocused) + .frame(width: 320) + } + HStack(spacing: Spacing.s) { + SystemChips() + Button { + withAnimation(Motion.hover) { browser.onlyFavorites.toggle() } + } label: { + Label("Favoritos", systemImage: browser.onlyFavorites ? "star.fill" : "star") + } + .buttonStyle(ChipButtonStyle(isSelected: browser.onlyFavorites)) + .accessibilityAddTraits(browser.onlyFavorites ? .isSelected : []) + if browser.isFiltering { + Button("Limpar filtros") { withAnimation(Motion.hover) { browser.clearFilters() } } + .buttonStyle(SecondaryButtonStyle(isCompact: true)) + .transition(.opacity) + } + Spacer() + Menu { + Picker("Ordenar por", selection: Binding(get: { browser.sort }, set: { browser.setSort($0) })) { + ForEach(LibraryBrowser.Sort.allCases) { Text($0.title).tag($0) } + } + .pickerStyle(.inline) + } label: { + Label(browser.sort.title, systemImage: "arrow.up.arrow.down") + .font(Typography.caption) + .foregroundStyle(Theme.textPrimary) + .padding(.horizontal, Spacing.s + Spacing.xs) + .frame(minHeight: 32) + .background(Theme.raised, in: Capsule()) + } + .menuStyle(.button) + .buttonStyle(.plain) + .menuIndicator(.hidden) + .fixedSize() + .help("Ordenar") + LayoutPicker() + } + } + .padding(.horizontal, Spacing.xxl) + .padding(.bottom, Spacing.m) + .animation(Motion.hover, value: browser.isFiltering) + } + + private var countLabel: String { + let shown = model.browser.results.count + let total = model.library.games.count + return shown == total ? String(localized: "\(total) jogos") : String(localized: "\(shown) de \(total) jogos") + } +} + +/// "Todos" + os consoles que têm jogos, e um menu com o catálogo inteiro (os sem jogos ficam desativados). +private struct SystemChips: View { + @Environment(AppModel.self) private var model + + var body: some View { + let browser = model.browser + let counts = browser.systemCounts + HStack(spacing: Spacing.s) { + chip(String(localized: "Todos"), isSelected: browser.system == nil) { browser.system = nil } + ForEach(counts.filter { $0.1 > 0 }, id: \.0.id) { system, count in + chip("\(system.shortName) · \(count)", isSelected: browser.system == system.id) { browser.system = system.id } + } + Menu { + ForEach(counts, id: \.0.id) { system, count in + Button("\(system.displayName) (\(count))") { browser.system = system.id } + .disabled(count == 0) + } + } label: { + Label("Consoles", systemImage: "line.3.horizontal.decrease") + .font(Typography.caption) + .foregroundStyle(Theme.textPrimary) + .padding(.horizontal, Spacing.s + Spacing.xs) + .frame(minHeight: 32) + .background(Theme.raised, in: Capsule()) + } + .menuStyle(.button) + .buttonStyle(.plain) + .menuIndicator(.hidden) + .fixedSize() + .help("Filtrar por console") + } + } + + private func chip(_ title: String, isSelected: Bool, action: @escaping () -> Void) -> some View { + Button(title) { withAnimation(Motion.hover) { action() } } + .buttonStyle(ChipButtonStyle(isSelected: isSelected)) + .accessibilityAddTraits(isSelected ? .isSelected : []) + } +} + +private struct LayoutPicker: View { + @Environment(AppModel.self) private var model + @Namespace private var selection + + var body: some View { + let browser = model.browser + HStack(spacing: Spacing.xxs) { + ForEach(LibraryBrowser.Layout.allCases) { layout in + let isSelected = browser.layout == layout + Button { + withAnimation(Motion.focus) { browser.setLayout(layout) } + } label: { + Image(systemName: layout.symbol) + .font(.system(size: 13, weight: .semibold)) + .foregroundStyle(isSelected ? Theme.onAccent : Theme.textPrimary) + .frame(width: 36, height: 28) + .background { + if isSelected { + Capsule().fill(Theme.accent).matchedGeometryEffect(id: "layout", in: selection) + } + } + .contentShape(Capsule()) + } + .buttonStyle(.plain) + .help(layout.title) + .accessibilityLabel(layout.title) + .accessibilityAddTraits(isSelected ? .isSelected : []) + } + } + .padding(Spacing.xxs + 1) + .background(Theme.raised, in: Capsule()) + } +} + +private struct LibraryGrid: View { + @Environment(AppModel.self) private var model + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + var body: some View { + let browser = model.browser + let layout = browser.layout + let results = browser.results + let focusedID = browser.focusedGame?.id + GeometryReader { proxy in + let spacing = layout == .largeCovers ? Spacing.l : Spacing.m + Spacing.xs + let available = proxy.size.width - 2 * Spacing.xxl + let columns = layout == .list ? 1 : max(1, Int((available + spacing) / (layout.tileWidth + spacing))) + ScrollViewReader { scroll in + ScrollView { + Group { + if layout == .list { + LazyVStack(spacing: Spacing.xs) { + ForEach(results) { game in + GameRow(game: game, isFocused: game.id == focusedID).id(game.id) + } + } + } else { + LazyVGrid( + columns: Array(repeating: GridItem(.fixed(layout.tileWidth), spacing: spacing, alignment: .top), count: columns), + alignment: .leading, + spacing: layout == .titledCovers ? Spacing.l : spacing + ) { + ForEach(results) { game in + GridTile(game: game, layout: layout, isFocused: game.id == focusedID).id(game.id) + } + } + } + } + .padding(.horizontal, Spacing.xxl) + .padding(.vertical, Spacing.m) + } + .onChange(of: columns, initial: true) { _, value in browser.columns = value } + .onChange(of: browser.focusedGameID) { _, id in + guard let id else { return } + withAnimation(Motion.animation(reduceMotion: reduceMotion)) { scroll.scrollTo(id) } + } + } + } + .animation(Motion.focus, value: layout) + } +} + +/// Uma capa da grade. Em "Capas e nomes", com título e console embaixo. +private struct GridTile: View { + let game: Game + let layout: LibraryBrowser.Layout + let isFocused: Bool + @Environment(AppModel.self) private var model + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + var body: some View { + let isHovered = model.browser.hoveredGameID == game.id + let isFavorite = model.library.isFavorite(game) + VStack(alignment: .leading, spacing: Spacing.s) { + CoverArtView(game: game, width: layout.tileWidth) + .overlay(alignment: .topTrailing) { + if isFavorite { + Image(systemName: "star.fill") + .font(.system(size: 11, weight: .bold)) + .foregroundStyle(Theme.onAccent) + .frame(width: 24, height: 24) + .background(Theme.accent, in: Circle()) + .padding(Spacing.s) + .accessibilityHidden(true) + } + } + .overlay { + RoundedRectangle.rx(Radius.m + 4) + .strokeBorder(Theme.accent, lineWidth: 3) + .padding(-5) + .opacity(isFocused ? 1 : 0) + } + .shadow( + color: isFocused ? Theme.accent.opacity(0.35) : .black.opacity(isHovered ? 0.22 : 0.12), + radius: isFocused ? 16 : (isHovered ? 12 : 5), + y: isFocused || isHovered ? 8 : 3 + ) + .scaleEffect(!reduceMotion && (isFocused || isHovered) ? 1.03 : 1) + if layout == .titledCovers { + VStack(alignment: .leading, spacing: Spacing.xxs) { + Text(game.title) + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.textPrimary) + .lineLimit(2) + Text("\(SystemCatalog.system(game.systemID)?.shortName ?? "") · \(GameText.size(game))") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + .frame(width: layout.tileWidth, alignment: .leading) + } + } + .animation(Motion.animation(reduceMotion: reduceMotion), value: isFocused) + .animation(Motion.hover, value: isHovered) + .contentShape(Rectangle()) + .onHover { inside in + model.browser.hoveredGameID = inside ? game.id : (model.browser.hoveredGameID == game.id ? nil : model.browser.hoveredGameID) + } + .onTapGesture { withAnimation(Motion.focus) { model.browser.focus(game) } } + .simultaneousGesture(TapGesture(count: 2).onEnded { model.play(game) }) + .contextMenu { GameContextMenu(game: game) } + .accessibilityElement(children: .ignore) + .accessibilityLabel(GameAccessibility.label(game, isFavorite: isFavorite)) + .accessibilityAddTraits(isFocused ? [.isButton, .isSelected] : .isButton) + .accessibilityAction { model.browser.focus(game) } + .accessibilityAction(named: "Jogar") { model.play(game) } + .accessibilityAction(named: "Detalhes") { model.showDetails(game) } + .accessibilityAction(named: "Favoritar") { model.library.toggleFavorite(game) } + } +} + +/// Uma linha da lista: miniatura, nome, console, tamanho e última partida. +private struct GameRow: View { + let game: Game + let isFocused: Bool + @Environment(AppModel.self) private var model + + var body: some View { + let isHovered = model.browser.hoveredGameID == game.id + let history = model.library.history(for: game) + HStack(spacing: Spacing.m) { + CoverArtView(game: game, width: LibraryBrowser.Layout.list.tileWidth) + VStack(alignment: .leading, spacing: Spacing.xxs) { + Text(game.title) + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.textPrimary) + .lineLimit(1) + Text(game.info?.name ?? game.romURL.lastPathComponent) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + .lineLimit(1) + } + Spacer(minLength: Spacing.m) + Text(SystemCatalog.system(game.systemID)?.shortName ?? "") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + .frame(width: 56, alignment: .leading) + Text(GameText.size(game)) + .font(Typography.caption) + .monospacedDigit() + .foregroundStyle(Theme.textSecondary) + .frame(width: 72, alignment: .trailing) + Text(GameText.lastPlayed(history)) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + .frame(width: 160, alignment: .trailing) + Button { + model.library.toggleFavorite(game) + } label: { + Image(systemName: history.isFavorite ? "star.fill" : "star") + .foregroundStyle(history.isFavorite ? Theme.accent : Theme.textSecondary) + .frame(width: 32, height: 32) + .contentShape(Rectangle()) + } + .buttonStyle(.plain) + .accessibilityLabel(history.isFavorite ? "Remover dos favoritos" : "Favoritar") + } + .padding(.horizontal, Spacing.m) + .padding(.vertical, Spacing.s) + .background(isFocused || isHovered ? Theme.raised : .clear, in: RoundedRectangle.rx(Radius.m)) + .overlay { + RoundedRectangle.rx(Radius.m) + .strokeBorder(Theme.accent, lineWidth: 2) + .opacity(isFocused ? 1 : 0) + } + .animation(Motion.hover, value: isHovered) + .animation(Motion.focus, value: isFocused) + .contentShape(Rectangle()) + .onHover { inside in + model.browser.hoveredGameID = inside ? game.id : (model.browser.hoveredGameID == game.id ? nil : model.browser.hoveredGameID) + } + .onTapGesture { model.browser.focus(game) } + .simultaneousGesture(TapGesture(count: 2).onEnded { model.play(game) }) + .contextMenu { GameContextMenu(game: game) } + .accessibilityElement(children: .combine) + .accessibilityAddTraits(isFocused ? [.isButton, .isSelected] : .isButton) + .accessibilityAction(named: "Jogar") { model.play(game) } + } +} + +struct GameContextMenu: View { + let game: Game + @Environment(AppModel.self) private var model + + var body: some View { + Button("Jogar") { model.play(game) } + Button("Detalhes") { model.showDetails(game) } + Button(model.library.isFavorite(game) ? "Remover dos favoritos" : "Favoritar") { model.library.toggleFavorite(game) } + Divider() + Button("Trocar capa…") { Task { await model.chooseCustomCover(for: game) } } + Button("Mostrar no Finder") { NSWorkspace.shared.activateFileViewerSelecting([game.romURL]) } + } +} + +enum GameAccessibility { + static func label(_ game: Game, isFavorite: Bool) -> String { + let system = SystemCatalog.system(game.systemID)?.shortName ?? "" + return "\(game.title), \(system)\(isFavorite ? String(localized: ", favorito") : "")" + } +} + +private struct NoResults: View { + @Environment(AppModel.self) private var model + + var body: some View { + VStack(alignment: .leading, spacing: Spacing.m) { + Text("Nenhum jogo com esses filtros") + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + Text("Tente outro nome, outro console ou desligue o filtro de favoritos.") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + Button("Limpar filtros") { model.browser.clearFilters() } + .buttonStyle(SecondaryButtonStyle()) + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + .padding(.horizontal, Spacing.xxl) + .padding(.top, Spacing.xl) + } +} diff --git a/Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift b/Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift new file mode 100644 index 0000000..b3bc7ff --- /dev/null +++ b/Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift @@ -0,0 +1,251 @@ +import AppKit +import RetroXCore +import SwiftUI + +struct ProfileEditorView: View { + @Bindable var draft: ProfileDraft + @Environment(AppModel.self) private var model + + var body: some View { + VStack(alignment: .leading, spacing: Spacing.l) { + Text(draft.isNew ? "Novo perfil" : "Editar perfil") + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + + HStack(alignment: .top, spacing: Spacing.l) { + VStack(spacing: Spacing.s) { + DraftAvatar(draft: draft, size: 112) + Button("Escolher foto…") { + Task { + if let url = await FilePanel.chooseImage(message: String(localized: "Escolha uma foto para o perfil.")) { + draft.avatarSource = url + draft.removeAvatar = false + } + } + } + .buttonStyle(SecondaryButtonStyle(isCompact: true)) + if draft.avatarSource != nil || (draft.profile.avatarFile != nil && !draft.removeAvatar) { + Button("Remover foto") { + draft.avatarSource = nil + draft.removeAvatar = true + } + .buttonStyle(SecondaryButtonStyle(isCompact: true)) + } + } + VStack(alignment: .leading, spacing: Spacing.m) { + field(String(localized: "Nome")) { + TextField("Jogador", text: $draft.profile.name) + .textFieldStyle(.roundedBorder) + } + field(String(localized: "Usuário do RetroAchievements (opcional)")) { + TextField("usuário", text: Binding( + get: { draft.profile.retroAchievementsUsername ?? "" }, + set: { draft.profile.retroAchievementsUsername = $0 } + )) + .textFieldStyle(.roundedBorder) + AchievementsCheck(username: draft.profile.retroAchievementsUsername) + } + } + } + + VStack(alignment: .leading, spacing: Spacing.s) { + Text("Tema") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + ThemeGallery( + selection: $draft.profile.theme, + accent: $draft.profile.accent, + columns: 4 + ) + Picker("Aparência", selection: $draft.profile.appearance) { + ForEach(AppearancePreference.allCases) { Text($0.title).tag($0) } + } + .pickerStyle(.segmented) + .frame(maxWidth: 320) + .padding(.top, Spacing.s) + } + + HStack(spacing: Spacing.s) { + if !draft.isNew, model.profiles.profiles.count > 1 { + Button("Excluir perfil", role: .destructive) { model.delete(draft) } + .buttonStyle(SecondaryButtonStyle()) + } + Spacer() + Button("Cancelar") { model.editingProfile = nil } + .buttonStyle(SecondaryButtonStyle()) + .keyboardShortcut(.cancelAction) + Button(draft.isNew ? "Criar perfil" : "Salvar") { model.save(draft) } + .buttonStyle(PrimaryButtonStyle()) + .keyboardShortcut(.defaultAction) + } + } + .padding(Spacing.xl) + .frame(width: 720) + .background(Theme.surface) + } + + private func field(_ label: String, @ViewBuilder content: () -> Content) -> some View { + VStack(alignment: .leading, spacing: Spacing.xs) { + Text(label) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + content() + } + } +} + +/// Foto do perfil em edição: a nova escolhida, a atual, ou as iniciais. +private struct DraftAvatar: View { + let draft: ProfileDraft + let size: CGFloat + @Environment(AppModel.self) private var model + + var body: some View { + ZStack { + if let image = image { + Image(nsImage: image) + .resizable() + .aspectRatio(contentMode: .fill) + } else { + Theme.accent + Text(draft.profile.initials) + .font(.system(size: size * 0.38, weight: .bold, design: .rounded)) + .foregroundStyle(Theme.onAccent) + } + } + .frame(width: size, height: size) + .clipShape(Circle()) + .accessibilityHidden(true) + } + + private var image: NSImage? { + if let source = draft.avatarSource { return NSImage(contentsOf: source) } + if draft.removeAvatar { return nil } + return model.profiles.avatarURL(for: draft.profile).flatMap(NSImage.init(contentsOf:)) + } +} + +/// Confere o usuário do perfil com a conta em que o PCSX2 está conectado. Não troca a conta do emulador. +struct AchievementsCheck: View { + let username: String? + @Environment(AppModel.self) private var model + + var body: some View { + if let status = model.plugins.entries.compactMap(\.discovery?.achievements).first { + let wanted = username?.trimmingCharacters(in: .whitespaces).nilIfEmpty + switch (status.isEnabled, status.username, wanted) { + case (false, _, _): + StatusLine(kind: .info, text: String(localized: "As conquistas estão desligadas no PCSX2. Ative e entre na sua conta em Configurações > Conquistas, no próprio PCSX2.")) + case (true, nil, _): + StatusLine(kind: .warning, text: String(localized: "As conquistas estão ligadas no PCSX2, mas sem conta conectada.")) + case (true, let connected?, let wanted?) where connected.caseInsensitiveCompare(wanted) != .orderedSame: + StatusLine(kind: .warning, text: String(localized: "O PCSX2 está conectado como \(connected), não como \(wanted). Troque a conta no próprio PCSX2.")) + case (true, let connected?, _): + StatusLine(kind: .ok, text: String(localized: "O PCSX2 está conectado como \(connected)\(status.isHardcore ? String(localized: " (modo hardcore)") : "").")) + } + } + } +} + +extension String { + var nilIfEmpty: String? { isEmpty ? nil : self } +} + +/// Galeria de temas: cada cartão mostra a variante clara e a escura lado a lado. +struct ThemeGallery: View { + @Binding var selection: ThemeID + @Binding var accent: Palette.Accent + var columns = 4 + + var body: some View { + VStack(alignment: .leading, spacing: Spacing.m) { + LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: Spacing.s), count: columns), spacing: Spacing.s) { + ForEach(ThemeID.allCases) { theme in + ThemeCard(theme: theme, accent: accent, isSelected: theme == selection) + .onTapGesture { withAnimation(Motion.focus) { selection = theme } } + } + } + if selection == .retrox { + HStack(spacing: Spacing.m) { + Text("Acento") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + ForEach(Palette.Accent.allCases, id: \.self) { option in + Button { + accent = option + } label: { + Circle() + .fill(Color(option.fill)) + .frame(width: 22, height: 22) + .overlay { + Circle().strokeBorder(Theme.textPrimary, lineWidth: 2).padding(-5) + .opacity(option == accent ? 1 : 0) + } + .frame(width: 36, height: 36) + .contentShape(Circle()) + } + .buttonStyle(.plain) + .help(option.title) + .accessibilityLabel(option.title) + .accessibilityAddTraits(option == accent ? .isSelected : []) + } + } + } + } + } +} + +private struct ThemeCard: View { + let theme: ThemeID + let accent: Palette.Accent + let isSelected: Bool + + var body: some View { + VStack(alignment: .leading, spacing: Spacing.xs) { + HStack(spacing: 0) { + preview(dark: false) + preview(dark: true) + } + .frame(height: 56) + .clipShape(RoundedRectangle.rx(Radius.s)) + .overlay { + RoundedRectangle.rx(Radius.s + 4) + .strokeBorder(Theme.accent, lineWidth: 3) + .padding(-4) + .opacity(isSelected ? 1 : 0) + } + Text(theme.title) + .font(Typography.caption) + .foregroundStyle(isSelected ? Theme.textPrimary : Theme.textSecondary) + } + .padding(Spacing.xs) + .contentShape(Rectangle()) + .accessibilityElement(children: .ignore) + .accessibilityLabel("Tema \(theme.title)") + .accessibilityAddTraits(isSelected ? [.isButton, .isSelected] : .isButton) + } + + /// Miniatura: fundo, um cartão com duas linhas de texto e o acento. + private func preview(dark: Bool) -> some View { + let palette = theme.palette(dark: dark, retroXAccent: accent) + return ZStack(alignment: .topLeading) { + Color(palette.background) + VStack(alignment: .leading, spacing: 3) { + Capsule().fill(Color(palette.textPrimary)).frame(width: 26, height: 4) + Capsule().fill(Color(palette.textSecondary)).frame(width: 18, height: 4) + Capsule().fill(Color(palette.accent)).frame(width: 22, height: 8) + .padding(.top, 3) + } + .padding(6) + .background(Color(palette.surface), in: RoundedRectangle.rx(5)) + .padding(6) + } + } +} + +extension Color { + /// Cor fixa (sem acompanhar o modo), para miniaturas que mostram claro e escuro ao mesmo tempo. + init(_ hex: HexColor) { + self.init(.sRGB, red: hex.red, green: hex.green, blue: hex.blue, opacity: 1) + } +} diff --git a/Sources/RetroXApp/Features/Profiles/ProfilePickerView.swift b/Sources/RetroXApp/Features/Profiles/ProfilePickerView.swift new file mode 100644 index 0000000..ba337cb --- /dev/null +++ b/Sources/RetroXApp/Features/Profiles/ProfilePickerView.swift @@ -0,0 +1,131 @@ +import RetroXCore +import SwiftUI + +/// "Quem vai jogar?": a primeira tela, como num console. Cada perfil tem seus favoritos, recentes e tema. +struct ProfilePickerView: View { + @Environment(AppModel.self) private var model + @FocusState private var isFocused: Bool + + var body: some View { + VStack(spacing: 0) { + Spacer() + VStack(spacing: Spacing.s) { + Text("Quem vai jogar?") + .font(Typography.display) + .foregroundStyle(Theme.textPrimary) + Text("Cada perfil tem os próprios favoritos, recentes e tema.") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + } + .padding(.bottom, Spacing.xxl) + HStack(alignment: .top, spacing: Spacing.xl) { + ForEach(Array(model.profiles.profiles.enumerated()), id: \.element.id) { index, profile in + ProfileTile(profile: profile, index: index) + } + AddProfileTile(index: model.profiles.profiles.count) + } + .padding(.horizontal, Spacing.xxl) + Spacer() + HintBar(items: [ + .init(actions: [.left, .right], key: "← →", label: String(localized: "Escolher")), + .init(action: .confirm, key: "↩", label: String(localized: "Entrar")), + .init(action: .details, key: "Espaço", label: String(localized: "Editar perfil")), + ], showsMenu: false) + } + .focusable() + .focusEffectDisabled() + .focused($isFocused) + .onAppear { isFocused = true } + .onChange(of: model.editingProfile == nil) { _, closed in + if closed { isFocused = true } + } + .onKeyPress(phases: [.down, .repeat]) { press in + guard !press.modifiers.contains(.command), let action = KeyMapping.action(for: press) else { return .ignored } + model.handle(action) + return .handled + } + } +} + +private struct ProfileTile: View { + let profile: Profile + let index: Int + @Environment(AppModel.self) private var model + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + static let avatarSize: CGFloat = 128 + + var body: some View { + let isFocused = model.profilePickerIndex == index + VStack(spacing: Spacing.m) { + AvatarView(profile: profile, size: Self.avatarSize) + .overlay { + Circle() + .strokeBorder(Theme.accent, lineWidth: 4) + .padding(-8) + .opacity(isFocused ? 1 : 0) + } + .shadow(color: isFocused ? Theme.accent.opacity(0.4) : .black.opacity(0.12), radius: isFocused ? 24 : 8, y: isFocused ? 10 : 4) + .scaleEffect(isFocused && !reduceMotion ? 1.08 : 1) + Text(profile.name) + .font(Typography.heading) + .foregroundStyle(isFocused ? Theme.textPrimary : Theme.textSecondary) + .lineLimit(1) + .frame(maxWidth: Self.avatarSize + Spacing.l) + } + .padding(Spacing.s) + .contentShape(Rectangle()) + .animation(Motion.animation(reduceMotion: reduceMotion), value: isFocused) + .onHover { inside in + if inside { model.profilePickerIndex = index } + } + .onTapGesture { model.enter(profile) } + .contextMenu { + Button("Entrar") { model.enter(profile) } + Button("Editar perfil…") { model.edit(profile) } + } + .accessibilityElement(children: .ignore) + .accessibilityLabel(profile.name) + .accessibilityAddTraits(isFocused ? [.isButton, .isSelected] : .isButton) + .accessibilityAction { model.enter(profile) } + .accessibilityAction(named: "Editar perfil") { model.edit(profile) } + } +} + +private struct AddProfileTile: View { + let index: Int + @Environment(AppModel.self) private var model + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + var body: some View { + let isFocused = model.profilePickerIndex == index + VStack(spacing: Spacing.m) { + Image(systemName: "plus") + .font(.system(size: 36, weight: .semibold)) + .foregroundStyle(isFocused ? Theme.textPrimary : Theme.textSecondary) + .frame(width: ProfileTile.avatarSize, height: ProfileTile.avatarSize) + .background(Theme.raised, in: Circle()) + .overlay { + Circle() + .strokeBorder(Theme.accent, lineWidth: 4) + .padding(-8) + .opacity(isFocused ? 1 : 0) + } + .scaleEffect(isFocused && !reduceMotion ? 1.08 : 1) + Text("Adicionar") + .font(Typography.heading) + .foregroundStyle(isFocused ? Theme.textPrimary : Theme.textSecondary) + } + .padding(Spacing.s) + .contentShape(Rectangle()) + .animation(Motion.animation(reduceMotion: reduceMotion), value: isFocused) + .onHover { inside in + if inside { model.profilePickerIndex = index } + } + .onTapGesture { model.newProfile() } + .accessibilityElement(children: .ignore) + .accessibilityLabel("Adicionar perfil") + .accessibilityAddTraits(.isButton) + .accessibilityAction { model.newProfile() } + } +} diff --git a/Sources/RetroXApp/Features/Session/SessionOverlay.swift b/Sources/RetroXApp/Features/Session/SessionOverlay.swift index 2adc5d8..ba48e6c 100644 --- a/Sources/RetroXApp/Features/Session/SessionOverlay.swift +++ b/Sources/RetroXApp/Features/Session/SessionOverlay.swift @@ -27,7 +27,7 @@ struct SessionOverlay: View { .frame(maxWidth: 420, alignment: .leading) } .padding(Spacing.xl) - .background(Theme.surface, in: RoundedRectangle(cornerRadius: Radius.l, style: .continuous)) + .background(Theme.surface, in: RoundedRectangle.rx(Radius.l)) .accessibilityElement(children: .contain) } } diff --git a/Sources/RetroXApp/Features/Settings/SettingsView.swift b/Sources/RetroXApp/Features/Settings/SettingsView.swift index 737c5f4..e696eec 100644 --- a/Sources/RetroXApp/Features/Settings/SettingsView.swift +++ b/Sources/RetroXApp/Features/Settings/SettingsView.swift @@ -2,53 +2,123 @@ import RetroXCore import SwiftUI struct SettingsView: View { - @AppStorage("appearance") private var appearance = Appearance.system - @AppStorage("accent") private var accent = Palette.Accent.coral + var body: some View { + TabView { + AppearanceSettings() + .tabItem { Label("Aparência", systemImage: "paintpalette") } + ControllerSettings() + .tabItem { Label("Controle", systemImage: "gamecontroller") } + } + .frame(width: 600) + } +} + +/// Tema e aparência do perfil atual. Cada perfil guarda os seus. +private struct AppearanceSettings: View { + @Environment(AppModel.self) private var model var body: some View { - Form { - Picker("Aparência", selection: $appearance) { - ForEach(Appearance.allCases) { option in - Text(option.title).tag(option) + VStack(alignment: .leading, spacing: Spacing.l) { + if let profile = model.profiles.current { + HStack(spacing: Spacing.s) { + AvatarView(profile: profile, size: 28) + Text("Tema do perfil \(profile.name)") + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.textPrimary) + } + ThemeGallery( + selection: Binding(get: { profile.theme }, set: { model.setTheme($0) }), + accent: Binding(get: { profile.accent }, set: { model.setTheme(accent: $0) }), + columns: 4 + ) + Picker("Aparência", selection: Binding(get: { profile.appearance }, set: { model.setTheme(appearance: $0) })) { + ForEach(AppearancePreference.allCases) { Text($0.title).tag($0) } } + .pickerStyle(.segmented) + .frame(maxWidth: 320) + } else { + Text("Escolha um perfil para mudar o tema.") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) } - .pickerStyle(.segmented) + Text("O RetroX segue os ajustes de Reduzir Movimento, Reduzir Transparência e Aumentar Contraste do macOS.") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + .padding(Spacing.l) + .frame(maxWidth: .infinity, alignment: .leading) + .background(Theme.surface) + } +} - LabeledContent("Cor do tema") { - HStack(spacing: Spacing.m) { - ForEach(Palette.Accent.allCases, id: \.self) { option in - Button { - accent = option - } label: { - Circle() - .fill(Color(option.fill)) - .frame(width: 24, height: 24) - .overlay { - Circle() - .strokeBorder(Theme.textPrimary, lineWidth: 2) - .padding(-5) - .opacity(option == accent ? 1 : 0) - } - .frame(width: 36, height: 36) - .contentShape(Circle()) - } - .buttonStyle(.plain) - .help(option.title) - .accessibilityLabel(option.title) - .accessibilityAddTraits(option == accent ? .isSelected : []) - } +/// Mini configurador: layout dos botões no RetroX e teste ao vivo. O mapeamento dentro do emulador +/// é mostrado em Emuladores e continua sendo mudado no próprio emulador (docs/spikes/0002). +private struct ControllerSettings: View { + @Environment(AppModel.self) private var model + + var body: some View { + let input = model.input + VStack(alignment: .leading, spacing: Spacing.l) { + if let name = input.controllerName { + StatusLine(kind: .ok, text: String(localized: "Controle conectado: \(name)")) + } else { + StatusLine(kind: .info, text: String(localized: "Nenhum controle conectado. Teclado e mouse funcionam em tudo.")) + } + + VStack(alignment: .leading, spacing: Spacing.s) { + Text("Botão de confirmar") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + Picker("Botão de confirmar", selection: Binding(get: { input.swapsConfirmAndBack }, set: { input.setSwapsConfirmAndBack($0) })) { + Text("Botão de baixo (A / ×)").tag(false) + Text("Botão da direita (estilo Nintendo)").tag(true) } + .pickerStyle(.radioGroup) + .labelsHidden() } - Section { - Text("O RetroX segue os ajustes de Reduzir Movimento, Reduzir Transparência e Aumentar Contraste do macOS.") + VStack(alignment: .leading, spacing: Spacing.s) { + Text("Teste") .font(Typography.caption) .foregroundStyle(Theme.textSecondary) + HStack(spacing: Spacing.m) { + Image(systemName: input.lastAction.flatMap { input.glyphs[$0] } ?? "gamecontroller") + .font(.system(size: 28, weight: .semibold)) + .foregroundStyle(input.lastAction == nil ? Theme.textSecondary : Theme.accent) + .frame(width: 56, height: 56) + .background(Theme.raised, in: RoundedRectangle.rx(Radius.m)) + .id(input.actionCount) + .transition(.scale(scale: 0.85).combined(with: .opacity)) + Text(input.lastAction.map(Self.describe) ?? String(localized: "Aperte um botão do controle para ver a ação no RetroX.")) + .font(Typography.body) + .foregroundStyle(Theme.textPrimary) + } + .animation(Motion.focus, value: input.actionCount) } + + Text("O mapeamento dos botões dentro do jogo é do emulador. Você pode conferir o do PCSX2 em Emuladores; para mudar, use Configurações > Controles no próprio PCSX2.") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + .fixedSize(horizontal: false, vertical: true) + } + .padding(Spacing.l) + .frame(maxWidth: .infinity, alignment: .leading) + .background(Theme.surface) + } + + static func describe(_ action: InputAction) -> String { + switch action { + case .up: String(localized: "Para cima") + case .down: String(localized: "Para baixo") + case .left: String(localized: "Para a esquerda") + case .right: String(localized: "Para a direita") + case .confirm: String(localized: "Confirmar (jogar)") + case .back: String(localized: "Voltar") + case .details: String(localized: "Detalhes") + case .favorite: String(localized: "Favoritar") + case .previousShelf: String(localized: "Prateleira anterior") + case .nextShelf: String(localized: "Próxima prateleira") + case .menu: String(localized: "Emuladores") } - .formStyle(.grouped) - .frame(width: 460) - .preferredColorScheme(appearance.colorScheme) - .tint(Color(accent.fill)) } } diff --git a/Sources/RetroXApp/Input/InputCoordinator.swift b/Sources/RetroXApp/Input/InputCoordinator.swift index d848771..10aa25f 100644 --- a/Sources/RetroXApp/Input/InputCoordinator.swift +++ b/Sources/RetroXApp/Input/InputCoordinator.swift @@ -17,6 +17,11 @@ final class InputCoordinator { private(set) var controllerName: String? /// Símbolos SF do controle conectado para cada ação (ex.: "xmark.circle" num controle PlayStation). private(set) var glyphs: [InputAction: String] = [:] + /// Layout estilo Nintendo: o botão da direita confirma e o de baixo volta. + private(set) var swapsConfirmAndBack: Bool + /// Última ação recebida do controle e um contador, para o teste nos Ajustes. + private(set) var lastAction: InputAction? + private(set) var actionCount = 0 @ObservationIgnored var onAction: ((InputAction) -> Void)? @ObservationIgnored private var heldDirection: InputAction? @@ -27,6 +32,7 @@ final class InputCoordinator { static let repeatInterval: Duration = .milliseconds(90) init() { + swapsConfirmAndBack = UserDefaults.standard.bool(forKey: "input.swapConfirmBack") // Com o emulador na frente, o RetroX não deve receber nada do controle (é o default; fica explícito). GCController.shouldMonitorBackgroundEvents = false let center = NotificationCenter.default @@ -49,8 +55,9 @@ final class InputCoordinator { pad.leftThumbstick.valueChangedHandler = { [weak self] _, x, y in MainActor.assumeIsolated { self?.hold(Self.direction(x: x, y: y, threshold: 0.6)) } } + let (south, east): (InputAction, InputAction) = swapsConfirmAndBack ? (.back, .confirm) : (.confirm, .back) let buttons: [(GCControllerButtonInput?, InputAction)] = [ - (pad.buttonA, .confirm), (pad.buttonB, .back), (pad.buttonX, .details), (pad.buttonY, .favorite), + (pad.buttonA, south), (pad.buttonB, east), (pad.buttonX, .details), (pad.buttonY, .favorite), (pad.leftShoulder, .previousShelf), (pad.rightShoulder, .nextShelf), (pad.buttonMenu, .menu), ] for (button, action) in buttons { @@ -75,7 +82,15 @@ final class InputCoordinator { } } + func setSwapsConfirmAndBack(_ swaps: Bool) { + swapsConfirmAndBack = swaps + UserDefaults.standard.set(swaps, forKey: "input.swapConfirmBack") + refreshCurrentController() + } + private func send(_ action: InputAction) { + lastAction = action + actionCount += 1 onAction?(action) } diff --git a/Sources/RetroXApp/RetroXApp.swift b/Sources/RetroXApp/RetroXApp.swift index 1961461..21b7f63 100644 --- a/Sources/RetroXApp/RetroXApp.swift +++ b/Sources/RetroXApp/RetroXApp.swift @@ -6,8 +6,6 @@ import SwiftUI struct RetroXApp: App { // Constante em vez de `@State`: no SDK 27 `@State` é uma macro que as Command Line Tools não trazem (ADR-0010). private let model = AppModel() - @AppStorage("appearance") private var appearance = Appearance.system - @AppStorage("accent") private var accent = Palette.Accent.coral init() { // Rodando fora de um .app (swift run), o processo nasceria sem ícone no Dock nem foco. @@ -19,49 +17,58 @@ struct RetroXApp: App { RootView() .environment(model) .environment(model.covers) - .environment(\.accent, accent) - .tint(Color(accent.fill)) - .preferredColorScheme(appearance.colorScheme) } .windowStyle(.hiddenTitleBar) .defaultSize(width: 1240, height: 800) Settings { - SettingsView() - .environment(\.accent, accent) + SettingsRoot() + .environment(model) + .environment(model.covers) } } } struct RootView: View { @Environment(AppModel.self) private var model - @Environment(\.accent) private var accent var body: some View { @Bindable var model = model ZStack { Theme.background .ignoresSafeArea() - switch model.screen { - case .home: - HomeView() - .transition(.opacity) - case .emulators: - EmulatorsView() - .transition(.opacity) + Group { + switch model.screen { + case .profiles: ProfilePickerView() + case .home: HomeView() + case .library: LibraryView() + case .emulators: EmulatorsView() + } } + .transition(.opacity) if model.session.isPresenting { SessionOverlay() .transition(.opacity) } } + // O tema é a identidade da árvore: trocar de tema redesenha tudo com as cores novas. + .id(model.themeSelection) + .tint(Theme.accent) + .preferredColorScheme(model.appearance.colorScheme) .animation(Motion.fade, value: model.screen) .animation(Motion.fade, value: model.session.isPresenting) .sheet(item: $model.detailsGame) { game in GameDetailsView(game: game) .environment(model) .environment(model.covers) - .environment(\.accent, accent) + } + .sheet(item: $model.editingProfile) { draft in + ProfileEditorView(draft: draft) + .environment(model) + .environment(model.covers) + } + .alert(model.notice ?? "", isPresented: Binding(get: { model.notice != nil }, set: { if !$0 { model.notice = nil } })) { + Button("OK", role: .cancel) { model.notice = nil } } .frame(minWidth: 1024, minHeight: 680) .task { await model.start() } @@ -83,3 +90,15 @@ struct RootView: View { } } } + +/// Janela de Ajustes, com o mesmo tema e aparência do perfil atual. +private struct SettingsRoot: View { + @Environment(AppModel.self) private var model + + var body: some View { + SettingsView() + .id(model.themeSelection) + .tint(Theme.accent) + .preferredColorScheme(model.appearance.colorScheme) + } +} From 75da2295a3db8a76728bcba7ab6c042d7f75b71a Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 01:04:23 -0300 Subject: [PATCH 21/56] test(core): teste opt-in da busca real na Wikipedia MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RX_NETWORK=1 scripts/test.sh --filter MetadataNetworkTests consulta a Wikipedia de verdade (busca + resumo). Fora da suíte normal, que continua sem rede. Co-Authored-By: Claude Opus 5.5 --- .../RetroXCoreTests/MetadataNetworkTests.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Tests/RetroXCoreTests/MetadataNetworkTests.swift diff --git a/Tests/RetroXCoreTests/MetadataNetworkTests.swift b/Tests/RetroXCoreTests/MetadataNetworkTests.swift new file mode 100644 index 0000000..17dbdfc --- /dev/null +++ b/Tests/RetroXCoreTests/MetadataNetworkTests.swift @@ -0,0 +1,18 @@ +import Foundation +import Testing +@testable import RetroXCore + +/// Consulta a Wikipedia de verdade. Opt-in: `RX_NETWORK=1 scripts/test.sh --filter MetadataNetworkTests`. +@Suite(.enabled(if: ProcessInfo.processInfo.environment["RX_NETWORK"] == "1")) +struct MetadataNetworkTests { + @Test("Busca e resumo reais na Wikipedia") + func liveWikipedia() async throws { + let provider = WikipediaMetadataProvider() + let results = try await provider.search("Test Drive Unlimited") + let first = try #require(results.first) + #expect(first.title.contains("Test Drive")) + let metadata = try await provider.metadata(for: first) + #expect(!metadata.summary.isEmpty) + #expect(metadata.sourceURL != nil) + } +} From 401d39b8b75d0fb48d15111818f60e06b5730d86 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 01:04:48 -0300 Subject: [PATCH 22/56] docs: ADR-0014 (metadados), spike 0002 (conquistas e controle) e temas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ADR-0014: banco do PCSX2 offline + Wikipedia/Wikidata sob demanda, com escolha do resultado e atribuição; sem download de capas. - Spike 0002: RetroAchievements e controle do PCSX2 validados em leitura; conta por perfil e gravação de perfil de entrada pendentes de consentimento e teste com controle. - Brand spec com os 11 temas, movimento e telas; decisões D8-D11; README com perfis, biblioteca e atalhos. Co-Authored-By: Claude Opus 5.5 --- README.md | 10 +++-- docs/DECISOES.md | 5 +++ docs/adr/0014-metadados-wikipedia.md | 27 ++++++++++++ docs/design/brand-spec.md | 16 ++++++- .../0002-retroachievements-e-controle.md | 42 +++++++++++++++++++ 5 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 docs/adr/0014-metadados-wikipedia.md create mode 100644 docs/spikes/0002-retroachievements-e-controle.md diff --git a/README.md b/README.md index dcd2e47..c188f95 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,12 @@ Launcher nativo para macOS que reúne numa biblioteca visual os jogos de vários ## Como usar -1. Abra o RetroX e vá em **Emuladores**. -2. Ative o **PCSX2** e escolha a pasta dele: a que tem o `PCSX2.app` e as pastas de jogos (por exemplo `~/Emulators/ps2`, com `roms/` e `covers/`). O RetroX também usa as pastas de jogos, as capas e a BIOS que o próprio PCSX2 já conhece. -3. Na tela inicial, navegue com as setas ou com o controle e pressione **Return** (ou o botão de confirmar) para jogar. Quando o PCSX2 fecha, o RetroX volta para a frente. +1. Escolha (ou crie) um perfil em **Quem vai jogar?**. Cada perfil tem foto, tema, favoritos e recentes próprios. +2. Vá em **Emuladores**, ative o **PCSX2** e escolha a pasta dele: a que tem o `PCSX2.app` e as pastas de jogos (por exemplo `~/Emulators/ps2`, com `roms/` e `covers/`). O RetroX também usa as pastas de jogos, as capas (inclusive as que o PCSX2 baixa) e a BIOS que o próprio PCSX2 já conhece. +3. Em **Início**, navegue pela prateleira; em **Biblioteca**, veja todos os jogos em grade ou lista, com busca e filtro por console. Pressione **Return** (ou o botão de confirmar) para jogar. Quando o PCSX2 fecha, o RetroX volta para a frente. +4. Em **Detalhes**, troque a capa de um jogo ou busque informações na Wikipedia. -Teclado: ←/→ escolhe o jogo, ↑/↓ ou Q/E troca de prateleira, Espaço abre os detalhes, F favorita, M abre Emuladores. Nada nas pastas dos jogos é copiado, movido ou alterado. +Teclado: setas navegam, Q/E troca de prateleira ou de console, Espaço abre os detalhes, F favorita, / busca na Biblioteca, M abre Emuladores, Esc volta. Nada nas pastas dos jogos é copiado, movido ou alterado. ## Requisitos @@ -25,6 +26,7 @@ scripts/check-toolchain.sh # o que o toolchain atual consegue (Xcode, Swi swift build # app, ferramentas e núcleo scripts/test.sh # testes unitários (Swift Testing) scripts/integration-launch.sh # abre um emulador falso de verdade e confere o argv +RX_NETWORK=1 scripts/test.sh --filter MetadataNetworkTests # busca real na Wikipedia (opt-in) scripts/bundle-app.sh debug # monta .build/RetroX.app (assinatura ad hoc) open .build/RetroX.app ``` diff --git a/docs/DECISOES.md b/docs/DECISOES.md index fe36d39..ef182dd 100644 --- a/docs/DECISOES.md +++ b/docs/DECISOES.md @@ -18,6 +18,10 @@ Decisões do usuário e suposições de trabalho que não cabem num ADR. Decisõ | D5 | A "pasta raiz" de um emulador é a pasta que guarda o app dele junto com ROMs, capas e BIOS (ex.: `~/Emulators/ps2`). | | D6 | Direção visual **"Portátil quente"** (docs/design/brand-spec.md), com a usabilidade de launcher de portátil inspirada no iiSU e identidade própria. | | D7 | A skill `swiftui-design-skill` faz parte do projeto (`.claude/skills/`); os passos dela de baixar assets de marca não se aplicam. | +| D8 | Perfis de jogador com tela de seleção ao abrir (estilo console). Favoritos, recentes e tema são por perfil; capa própria e informações dos jogos são compartilhadas. | +| D9 | 11 temas de cor (RetroX + 10 esquemas conhecidos), cada um claro e escuro, escolhidos por perfil. | +| D10 | Informações de jogos: banco do PCSX2 offline e Wikipedia/Wikidata sob demanda, com escolha do resultado (ADR-0014). Capas não são baixadas da internet. | +| D11 | RetroAchievements e controle do PCSX2: só leitura por enquanto. Gravar perfil de entrada para o PCSX2 depende de consentimento e teste com controle (spike 0002). | ## Suposições de trabalho @@ -35,4 +39,5 @@ Decisões do usuário e suposições de trabalho que não cabem num ADR. Decisõ - Instalar o Xcode e rodar `sudo xcode-select -s /Applications/Xcode.app/Contents/Developer` (Fase 1). - Instalar o Dolphin para validar a Fase 4. +- Autorizar (ou não) o RetroX a criar um perfil de entrada próprio na pasta do PCSX2 e testar com um controle físico (spike 0002). - Escolher o bundle ID definitivo e ter conta Apple Developer para assinatura e notarização (Fase 7). diff --git a/docs/adr/0014-metadados-wikipedia.md b/docs/adr/0014-metadados-wikipedia.md new file mode 100644 index 0000000..b0bdcae --- /dev/null +++ b/docs/adr/0014-metadados-wikipedia.md @@ -0,0 +1,27 @@ +# ADR-0014 — Informações de jogos: banco do emulador offline e Wikipedia sob demanda + +**Status:** Aceito | **Data:** 2026-10-28 + +## Contexto +O usuário pediu para puxar informações dos jogos de uma fonte pública, como o Playnite faz. O ADR-0006 exige offline-first, fonte opcional, cache, escolha manual do resultado e atenção a termos e licenças. + +Opções avaliadas: +- **IGDB** (o padrão do Playnite): bom para jogos, mas exige credenciais de desenvolvedor da Twitch (client ID e secret) de cada usuário. +- **TheGamesDB, ScreenScraper, RAWG**: exigem chave ou conta. +- **Wikipedia e Wikidata**: públicos, sem chave. Texto da Wikipedia em CC BY-SA (exige atribuição); dados do Wikidata em CC0. +- **Banco do próprio emulador**: o PCSX2 traz `GameIndex.yaml` no app (serial → nome oficial, região, compatibilidade). Offline e local. + +## Decisão +1. **Offline e automático:** o plugin do PCSX2 lê o `GameIndex.yaml` do app para os seriais da biblioteca. O nome oficial aparece como subtítulo, e região e compatibilidade nos detalhes. O título exibido continua sendo o do arquivo, porque mods e traduções não batem com o nome oficial (ex.: "GT 4 Spec II" tem o serial de "Gran Turismo 4 [Online Public Beta]"). +2. **Online, só por ação do usuário:** em Detalhes, "Buscar na Wikipedia" pesquisa (português, depois inglês) e lista resultados. O usuário escolhe o certo, e só então o resumo é baixado e guardado em `games.json`. O Wikidata completa ano, desenvolvedora, editora e gênero quando responde; se estiver fora do ar, fica só o resumo. +3. A fonte e a licença ficam visíveis ("Fonte: Wikipedia (pt) · CC BY-SA", com link). As requisições usam um User-Agent identificado, como pede a política da Wikimedia. +4. **Capas não são baixadas da internet.** Capas de jogos em geral não são livres. O RetroX usa as capas que o usuário tem (pastas do emulador, capas que o PCSX2 baixa, ou uma imagem escolhida em "Trocar capa"). +5. O contrato fica aberto para outros provedores. O IGDB pode entrar depois, como opção para quem fornecer as próprias credenciais. + +## Consequências +- Funciona sem conta e sem chave. Sem rede, tudo continua funcionando, menos a busca, que avisa. +- Jogos obscuros podem não ter página na Wikipedia; a busca aceita editar o termo. +- Em 2026-10-28 o Wikidata estava fora do ar (503) durante o desenvolvimento. O desenho já trata isso, e o teste `wikidataDown` cobre o caso. + +## Alternativas +IGDB por padrão (exige credenciais por usuário); scraping de sites de capas (licenças e termos); buscar automaticamente para a biblioteca inteira (viola a escolha manual do ADR-0006 e gera associações erradas). diff --git a/docs/design/brand-spec.md b/docs/design/brand-spec.md index a84a29a..dc7382c 100644 --- a/docs/design/brand-spec.md +++ b/docs/design/brand-spec.md @@ -4,7 +4,12 @@ Direção escolhida em 2026-10-28 entre três propostas (Portátil quente, Edito Os valores abaixo são a fonte da verdade em `Sources/RetroXCore/Design/Palette.swift`, e o contraste é verificado por teste (`PaletteTests`). -## Cores +## Temas +O RetroX tem 11 temas, escolhidos por perfil, cada um com variante clara e escura: **RetroX** (a paleta abaixo, com 4 acentos), Gruvbox, Catppuccin (Latte/Mocha), Tokyo Night (Day/Night), Nord, Solarized, Dracula (Alucard/Dracula), Rosé Pine (Dawn/Main), Everforest, Kanagawa (Lotus/Wave) e One. Os esquemas conhecidos usam as cores oficiais de cada projeto, com ajustes mínimos onde a cor original não atingia AA. Quase sempre o ajuste foi no texto secundário; em Catppuccin Latte, Tokyo Night Day, Solarized e Everforest claros, o texto principal ficou um pouco mais escuro para manter a hierarquia. Os valores estão em `Sources/RetroXCore/Design/Themes.swift`, e `ThemeTests` confere contraste e hierarquia de todos. + +Cada tema define oito tokens: fundo, superfície, elevado, texto, texto secundário, divisória, acento e texto sobre o acento. + +## Cores (tema RetroX) ### Neutros (quentes, nunca preto ou branco puros) | Token | Claro | Escuro | Uso | @@ -51,7 +56,14 @@ SF Pro Rounded para títulos (tom de console), SF Pro para o resto. No máximo q Na prateleira, a capa em foco sobe 10%, ganha um halo na cor de tema e se reflete no "chão" da prateleira. Com Reduzir Movimento, fica só o anel de foco: nada cresce nem se desloca. ## Movimento -Mola curta (0,32 s) para foco; esmaecimento de 0,15 s para trocas de tela e, com Reduzir Movimento, para tudo. +- Foco: `snappy` (0,28 s, pouco quique). +- Hover: `smooth` (0,22 s), com elevação leve (escala 1,03–1,04). +- Trocas de tela: esmaecimento de 0,18 s. +- Abas e seletor de layout deslizam a pílula selecionada (`matchedGeometryEffect`). +- Com Reduzir Movimento, só esmaece: nada cresce nem se desloca. + +## Telas +Perfis ("Quem vai jogar?", avatares de 128 pt com anel de foco), Início (palco + prateleira), Biblioteca (grade com quatro layouts: Capas 128 pt, Capas grandes 184 pt, Capas e nomes 148 pt, Lista), Emuladores, Detalhes (folha de 880 × 620) e Ajustes (Aparência e Controle). ## Voz Português do Brasil, direto e calmo. Mensagens de erro dizem o que aconteceu e oferecem a ação que resolve. diff --git a/docs/spikes/0002-retroachievements-e-controle.md b/docs/spikes/0002-retroachievements-e-controle.md new file mode 100644 index 0000000..bd51fc5 --- /dev/null +++ b/docs/spikes/0002-retroachievements-e-controle.md @@ -0,0 +1,42 @@ +# Spike 0002 — RetroAchievements e controle integrados ao PCSX2 + +**Data:** 2026-10-28 · **Status:** validado (leitura implementada; escrita pendente de consentimento e teste com controle) + +## Perguntas +1. Dá para validar a configuração do RetroAchievements do emulador junto com o RetroX, inclusive por perfil? +2. Dá para ter um mini configurador de controle no RetroX que reflita no emulador? + +Tudo abaixo foi verificado só lendo arquivos (PCSX2 2.9.147, `PCSX2.ini` do usuário e texto do binário), sem alterar nada. + +## RetroAchievements +**O que o PCSX2 guarda:** a seção `[Achievements]` do `PCSX2.ini`, com `Enabled`, `ChallengeMode` (hardcore), `EncoreMode`, opções de notificação e, quando há login, `Username` e `Token`. Na máquina do usuário: `Enabled = false` e sem `Username` nem `Token`, ou seja, desligado e sem conta. + +**Implementado (só leitura):** +- A descoberta do plugin lê `Enabled`, `ChallengeMode` e `Username`. **O token nunca é consultado nem exibido**; o teste `achievementsAndController` garante que ele não aparece na descoberta. +- Emuladores mostra "desligado", "ligado sem conta" ou "conectado como X (hardcore)". +- Cada perfil pode guardar o usuário do RetroAchievements. O editor de perfil compara com a conta conectada no PCSX2 e avisa se for outra. + +**Por perfil, de verdade, não foi feito:** trocar a conta do emulador ao trocar de perfil exigiria gravar `Username` e `Token` no `PCSX2.ini`. Isso significa guardar o token de cada jogador e alterar a configuração do emulador, o que a suposição S3 proíbe sem consentimento explícito. O PCSX2 tem um login global. + +**Possível depois (RF-18):** mostrar progresso e conquistas no RetroX pela Web API do RetroAchievements, com a chave de API que cada usuário gera no site. Não exige mexer no emulador. + +## Controle +**O que o PCSX2 guarda:** `[Pad1]` no `PCSX2.ini`, com `Type = DualShock2` e cada botão ligado a uma entrada SDL (`Cross = SDL-0/FaceSouth`, `L2 = SDL-0/+LeftTrigger`…). Ele também aceita perfis de entrada (`inputprofiles/*.ini`, referenciados por `InputProfileName`) e configurações por jogo passadas na linha de comando (`-gamecfg `, presente no texto de ajuda do binário). + +**Implementado:** +- Emuladores mostra o tipo de controle e o mapeamento da porta 1 com nomes amigáveis (por exemplo, "× → botão de baixo (A / ×)"). +- Ajustes > Controle: escolher o botão de confirmar do RetroX (baixo, ou direita no estilo Nintendo) e um teste ao vivo que mostra a ação de cada botão. Vale só para navegar no RetroX. + +**Caminho validado para "refletir no emulador", ainda não implementado:** +1. O RetroX grava um perfil de entrada próprio, `inputprofiles/RetroX.ini`, na pasta de dados do PCSX2. É um arquivo novo; nenhum arquivo existente é alterado. +2. Ao abrir um jogo, passa `-gamecfg ` com `InputProfileName = RetroX`, sem tocar no `PCSX2.ini`. + +Pendências antes de implementar: +- **Consentimento** para criar arquivos na pasta do PCSX2. +- Confirmar no código-fonte do PCSX2 em que seção do arquivo de jogo o `InputProfileName` é lido. +- Testar com um controle físico conectado. O teste do spike 0001 não teve controle. + +## Conclusão +- Validação do RetroAchievements: **possível e feita** (leitura). +- Conta por perfil: **não**, sem alterar a configuração do emulador. +- Configurador que reflete no emulador: **possível** pelo caminho `-gamecfg` + perfil de entrada próprio, aguardando consentimento e teste com controle. From 96e60992cfa9cd4d151f622b7746c9e73f32b3df Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 01:11:20 -0300 Subject: [PATCH 23/56] =?UTF-8?q?refactor:=20remove=20a=20integra=C3=A7?= =?UTF-8?q?=C3=A3o=20com=20o=20RetroAchievements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pedido do usuário, o RetroX deixa de ler e mostrar o estado do RetroAchievements do emulador e o campo de usuário do perfil. Perfis antigos com o campo continuam abrindo (chave ignorada). Um teste garante que a seção [Achievements] do PCSX2.ini, inclusive o token, não é lida. Decisão D12; spike 0002 atualizado. Co-Authored-By: Claude Opus 5.5 --- Sources/RetroXApp/App/AppModel.swift | 3 -- .../Features/Emulators/EmulatorsView.swift | 16 ---------- .../Features/Profiles/ProfileEditorView.swift | 30 ------------------- .../RetroXCore/Plugins/EmulatorPlugin.swift | 10 ------- Sources/RetroXCore/Plugins/PCSX2Plugin.swift | 10 ------- Sources/RetroXCore/Profiles/Profile.swift | 7 +---- .../ProfileAndMetadataTests.swift | 15 ++++------ docs/DECISOES.md | 3 +- .../0002-retroachievements-e-controle.md | 4 +-- 9 files changed, 11 insertions(+), 87 deletions(-) diff --git a/Sources/RetroXApp/App/AppModel.swift b/Sources/RetroXApp/App/AppModel.swift index a024760..7417464 100644 --- a/Sources/RetroXApp/App/AppModel.swift +++ b/Sources/RetroXApp/App/AppModel.swift @@ -86,9 +86,6 @@ final class AppModel { var profile = draft.profile profile.name = profile.name.trimmingCharacters(in: .whitespaces) if profile.name.isEmpty { profile.name = String(localized: "Jogador \(profiles.profiles.count + (draft.isNew ? 1 : 0))") } - if let username = profile.retroAchievementsUsername?.trimmingCharacters(in: .whitespaces) { - profile.retroAchievementsUsername = username.isEmpty ? nil : username - } if draft.isNew { let created = profiles.create(name: profile.name) profile.id = created.id diff --git a/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift b/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift index 5cb4d53..d5a68e5 100644 --- a/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift +++ b/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift @@ -135,7 +135,6 @@ private struct DiscoveryReport: View { gamesLines coversLine biosLine - achievementsLine if let controller = discovery.controller { ControllerMapping(controller: controller, emulator: entry.plugin.displayName) } @@ -222,21 +221,6 @@ private struct DiscoveryReport: View { } } - /// Estado do RetroAchievements no emulador. A conta é escolhida e conectada no próprio emulador. - @ViewBuilder - private var achievementsLine: some View { - if let status = discovery.achievements { - switch (status.isEnabled, status.username) { - case (false, _): - StatusLine(kind: .info, text: String(localized: "RetroAchievements desligado no \(entry.plugin.displayName).")) - case (true, nil): - StatusLine(kind: .warning, text: String(localized: "RetroAchievements ligado, mas sem conta conectada no \(entry.plugin.displayName).")) - case (true, let username?): - StatusLine(kind: .ok, text: String(localized: "RetroAchievements: conectado como \(username)\(status.isHardcore ? String(localized: " · hardcore") : "")")) - } - } - } - private var otherIssues: [PluginIssue] { discovery.issues.filter { switch $0 { diff --git a/Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift b/Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift index b3bc7ff..5f46d04 100644 --- a/Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift +++ b/Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift @@ -37,14 +37,6 @@ struct ProfileEditorView: View { TextField("Jogador", text: $draft.profile.name) .textFieldStyle(.roundedBorder) } - field(String(localized: "Usuário do RetroAchievements (opcional)")) { - TextField("usuário", text: Binding( - get: { draft.profile.retroAchievementsUsername ?? "" }, - set: { draft.profile.retroAchievementsUsername = $0 } - )) - .textFieldStyle(.roundedBorder) - AchievementsCheck(username: draft.profile.retroAchievementsUsername) - } } } @@ -125,28 +117,6 @@ private struct DraftAvatar: View { } } -/// Confere o usuário do perfil com a conta em que o PCSX2 está conectado. Não troca a conta do emulador. -struct AchievementsCheck: View { - let username: String? - @Environment(AppModel.self) private var model - - var body: some View { - if let status = model.plugins.entries.compactMap(\.discovery?.achievements).first { - let wanted = username?.trimmingCharacters(in: .whitespaces).nilIfEmpty - switch (status.isEnabled, status.username, wanted) { - case (false, _, _): - StatusLine(kind: .info, text: String(localized: "As conquistas estão desligadas no PCSX2. Ative e entre na sua conta em Configurações > Conquistas, no próprio PCSX2.")) - case (true, nil, _): - StatusLine(kind: .warning, text: String(localized: "As conquistas estão ligadas no PCSX2, mas sem conta conectada.")) - case (true, let connected?, let wanted?) where connected.caseInsensitiveCompare(wanted) != .orderedSame: - StatusLine(kind: .warning, text: String(localized: "O PCSX2 está conectado como \(connected), não como \(wanted). Troque a conta no próprio PCSX2.")) - case (true, let connected?, _): - StatusLine(kind: .ok, text: String(localized: "O PCSX2 está conectado como \(connected)\(status.isHardcore ? String(localized: " (modo hardcore)") : "").")) - } - } - } -} - extension String { var nilIfEmpty: String? { isEmpty ? nil : self } } diff --git a/Sources/RetroXCore/Plugins/EmulatorPlugin.swift b/Sources/RetroXCore/Plugins/EmulatorPlugin.swift index 3a3a46c..6ee458b 100644 --- a/Sources/RetroXCore/Plugins/EmulatorPlugin.swift +++ b/Sources/RetroXCore/Plugins/EmulatorPlugin.swift @@ -66,15 +66,6 @@ public enum PluginIssue: Sendable, Equatable { } } -/// Estado do RetroAchievements no emulador. Só o que serve para conferir; o token de login nunca é lido. -public struct AchievementsStatus: Sendable, Equatable { - public var isEnabled: Bool - public var isHardcore: Bool - public var username: String? - - public var isLoggedIn: Bool { username != nil } -} - /// Como o controle está configurado no emulador (primeira porta). public struct ControllerSummary: Sendable, Equatable { public struct Binding: Sendable, Equatable, Hashable { @@ -103,7 +94,6 @@ public struct PluginDiscovery: Sendable, Equatable { public var coverDirectories: [URL] = [] public var settingsFile: URL? public var bios: BIOSStatus = .unknown - public var achievements: AchievementsStatus? public var controller: ControllerSummary? /// Banco de dados de jogos do emulador (no PCSX2, `GameIndex.yaml` dentro do app). public var gameIndexFile: URL? diff --git a/Sources/RetroXCore/Plugins/PCSX2Plugin.swift b/Sources/RetroXCore/Plugins/PCSX2Plugin.swift index cb92adf..3dd6176 100644 --- a/Sources/RetroXCore/Plugins/PCSX2Plugin.swift +++ b/Sources/RetroXCore/Plugins/PCSX2Plugin.swift @@ -71,7 +71,6 @@ public struct PCSX2Plugin: EmulatorPlugin { let coversURL = resolve(settings.value("Covers", in: "Folders") ?? "covers", relativeTo: dataDirectory) if fileSystem.kind(of: coversURL) == .directory { discovery.coverDirectories.append(coversURL) } discovery.bios = biosStatus(settings: settings, dataDirectory: dataDirectory) - discovery.achievements = Self.achievements(settings) discovery.controller = Self.controller(settings) } if let app = discovery.app { @@ -106,15 +105,6 @@ public struct PCSX2Plugin: EmulatorPlugin { return markers.contains(where: { fileSystem.kind(of: $0) == .regularFile }) ? folder : nil } - /// `[Achievements]` do PCSX2.ini. O token de login (`Token`) não é consultado. - static func achievements(_ settings: INIFile) -> AchievementsStatus { - AchievementsStatus( - isEnabled: settings.value("Enabled", in: "Achievements") == "true", - isHardcore: settings.value("ChallengeMode", in: "Achievements") == "true", - username: settings.value("Username", in: "Achievements") - ) - } - static let padButtons = ["Cross", "Circle", "Square", "Triangle", "Up", "Down", "Left", "Right", "L1", "R1", "L2", "R2", "L3", "R3", "Select", "Start"] diff --git a/Sources/RetroXCore/Profiles/Profile.swift b/Sources/RetroXCore/Profiles/Profile.swift index bcce675..7833689 100644 --- a/Sources/RetroXCore/Profiles/Profile.swift +++ b/Sources/RetroXCore/Profiles/Profile.swift @@ -10,8 +10,6 @@ public struct Profile: Codable, Identifiable, Sendable, Equatable, Hashable { /// Acento do tema RetroX; os outros temas têm acento próprio. public var accent: Palette.Accent public var appearance: AppearancePreference - /// Usuário do RetroAchievements que este jogador usa (só para conferir com o emulador). - public var retroAchievementsUsername: String? public init( id: UUID = UUID(), @@ -19,8 +17,7 @@ public struct Profile: Codable, Identifiable, Sendable, Equatable, Hashable { avatarFile: String? = nil, theme: ThemeID = .retrox, accent: Palette.Accent = .coral, - appearance: AppearancePreference = .system, - retroAchievementsUsername: String? = nil + appearance: AppearancePreference = .system ) { self.id = id self.name = name @@ -28,7 +25,6 @@ public struct Profile: Codable, Identifiable, Sendable, Equatable, Hashable { self.theme = theme self.accent = accent self.appearance = appearance - self.retroAchievementsUsername = retroAchievementsUsername } /// Campos novos entram com valor padrão, para arquivos de versões anteriores continuarem abrindo. @@ -40,7 +36,6 @@ public struct Profile: Codable, Identifiable, Sendable, Equatable, Hashable { theme = (try? container.decodeIfPresent(ThemeID.self, forKey: .theme)) ?? .retrox accent = (try? container.decodeIfPresent(Palette.Accent.self, forKey: .accent)) ?? .coral appearance = (try? container.decodeIfPresent(AppearancePreference.self, forKey: .appearance)) ?? .system - retroAchievementsUsername = try container.decodeIfPresent(String.self, forKey: .retroAchievementsUsername) } /// Iniciais para o avatar sem foto: "Ana Souza" → "AS", "Jogador 1" → "J1", "léo" → "L". diff --git a/Tests/RetroXCoreTests/ProfileAndMetadataTests.swift b/Tests/RetroXCoreTests/ProfileAndMetadataTests.swift index 22007f7..92e9fa5 100644 --- a/Tests/RetroXCoreTests/ProfileAndMetadataTests.swift +++ b/Tests/RetroXCoreTests/ProfileAndMetadataTests.swift @@ -121,8 +121,8 @@ struct GameIndexTests { } struct PluginEmulatorSettingsTests { - @Test("RetroAchievements e controle vêm do PCSX2.ini; o token não aparece em nenhum lugar") - func achievementsAndController() { + @Test("Controle vem do PCSX2.ini; nada da seção de conquistas (nem o token) é lido") + func controllerOnly() { let scenario = PluginScenario(settings: """ [Achievements] Enabled = true @@ -136,19 +136,16 @@ struct PluginEmulatorSettingsTests { Start = SDL-0/Start """) let discovery = scenario.discover() - #expect(discovery.achievements == AchievementsStatus(isEnabled: true, isHardcore: true, username: "jogadora")) #expect(discovery.controller?.type == "DualShock2") #expect(discovery.controller?.device == "SDL-0") #expect(discovery.controller?.bindings.first == ControllerSummary.Binding(button: "Cross", input: "SDL-0/FaceSouth")) #expect(!String(describing: discovery).contains("SEGREDO")) + #expect(!String(describing: discovery).contains("jogadora")) } - @Test("Conquistas desligadas e sem login") - func achievementsOff() { - let discovery = PluginScenario(settings: "[Achievements]\nEnabled = false\n").discover() - #expect(discovery.achievements == AchievementsStatus(isEnabled: false, isHardcore: false, username: nil)) - #expect(discovery.achievements?.isLoggedIn == false) - #expect(discovery.controller == nil) + @Test("Sem [Pad1], sem resumo de controle") + func noController() { + #expect(PluginScenario(settings: "[UI]\nStartFullscreen = true\n").discover().controller == nil) } @Test("Aponta o GameIndex.yaml de dentro do app, quando existe") diff --git a/docs/DECISOES.md b/docs/DECISOES.md index ef182dd..2e520cb 100644 --- a/docs/DECISOES.md +++ b/docs/DECISOES.md @@ -21,7 +21,8 @@ Decisões do usuário e suposições de trabalho que não cabem num ADR. Decisõ | D8 | Perfis de jogador com tela de seleção ao abrir (estilo console). Favoritos, recentes e tema são por perfil; capa própria e informações dos jogos são compartilhadas. | | D9 | 11 temas de cor (RetroX + 10 esquemas conhecidos), cada um claro e escuro, escolhidos por perfil. | | D10 | Informações de jogos: banco do PCSX2 offline e Wikipedia/Wikidata sob demanda, com escolha do resultado (ADR-0014). Capas não são baixadas da internet. | -| D11 | RetroAchievements e controle do PCSX2: só leitura por enquanto. Gravar perfil de entrada para o PCSX2 depende de consentimento e teste com controle (spike 0002). | +| D11 | ~~RetroAchievements e controle do PCSX2 em leitura.~~ Revisto em D12. | +| D12 | RetroAchievements fica fora do RetroX (pedido do usuário em 2026-10-28): nada é lido nem mostrado. O controle do PCSX2 continua só em leitura; gravar perfil de entrada depende de consentimento e teste com controle (spike 0002). | ## Suposições de trabalho diff --git a/docs/spikes/0002-retroachievements-e-controle.md b/docs/spikes/0002-retroachievements-e-controle.md index bd51fc5..9b84cbe 100644 --- a/docs/spikes/0002-retroachievements-e-controle.md +++ b/docs/spikes/0002-retroachievements-e-controle.md @@ -1,6 +1,6 @@ # Spike 0002 — RetroAchievements e controle integrados ao PCSX2 -**Data:** 2026-10-28 · **Status:** validado (leitura implementada; escrita pendente de consentimento e teste com controle) +**Data:** 2026-10-28 · **Status:** validado. A parte de RetroAchievements foi removida do app a pedido do usuário (D12); a de controle segue em leitura. ## Perguntas 1. Dá para validar a configuração do RetroAchievements do emulador junto com o RetroX, inclusive por perfil? @@ -11,7 +11,7 @@ Tudo abaixo foi verificado só lendo arquivos (PCSX2 2.9.147, `PCSX2.ini` do usu ## RetroAchievements **O que o PCSX2 guarda:** a seção `[Achievements]` do `PCSX2.ini`, com `Enabled`, `ChallengeMode` (hardcore), `EncoreMode`, opções de notificação e, quando há login, `Username` e `Token`. Na máquina do usuário: `Enabled = false` e sem `Username` nem `Token`, ou seja, desligado e sem conta. -**Implementado (só leitura):** +**Implementado e depois removido (D12):** - A descoberta do plugin lê `Enabled`, `ChallengeMode` e `Username`. **O token nunca é consultado nem exibido**; o teste `achievementsAndController` garante que ele não aparece na descoberta. - Emuladores mostra "desligado", "ligado sem conta" ou "conectado como X (hardcore)". - Cada perfil pode guardar o usuário do RetroAchievements. O editor de perfil compara com a conta conectada no PCSX2 e avisa se for outra. From aefe0f8987799f6cb72041f4985719ecc684b795 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 01:12:29 -0300 Subject: [PATCH 24/56] =?UTF-8?q?feat(core):=20prefer=C3=AAncias=20de=20pe?= =?UTF-8?q?rfil=20e=20presets=20de=20controle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ProfilePreferences: estilo da tela inicial (prateleira, carrossel, grade), tamanho das capas, prateleira inicial, fonte, tamanho do texto, fundo ambiente, nível e velocidade das animações, abertura animada, selo de favorito e relógio. Decodificação tolerante. - ControllerPreset: Automático, Xbox, PlayStation (DualSense) e Nintendo Switch, com glifos SF por posição de botão, confirmação à direita no layout Nintendo e detecção pela categoria do controle. Co-Authored-By: Claude Opus 5.5 --- .../RetroXCore/Input/ControllerPreset.swift | 76 ++++++++ Sources/RetroXCore/Profiles/Profile.swift | 6 +- .../Profiles/ProfilePreferences.swift | 177 ++++++++++++++++++ Tests/RetroXCoreTests/PreferencesTests.swift | 59 ++++++ 4 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 Sources/RetroXCore/Input/ControllerPreset.swift create mode 100644 Sources/RetroXCore/Profiles/ProfilePreferences.swift create mode 100644 Tests/RetroXCoreTests/PreferencesTests.swift diff --git a/Sources/RetroXCore/Input/ControllerPreset.swift b/Sources/RetroXCore/Input/ControllerPreset.swift new file mode 100644 index 0000000..874b001 --- /dev/null +++ b/Sources/RetroXCore/Input/ControllerPreset.swift @@ -0,0 +1,76 @@ +import Foundation + +/// Controles físicos, por posição (o GameController nomeia os botões pela posição do layout Xbox). +public enum ControllerControl: String, CaseIterable, Sendable { + case south, east, west, north + case leftShoulder, rightShoulder, leftTrigger, rightTrigger + case menu, options +} + +/// Como mostrar e interpretar os botões: glifos de cada família de controle e qual botão confirma. +public enum ControllerPreset: String, Codable, CaseIterable, Sendable, Identifiable { + /// Usa os glifos do próprio controle conectado; confirma com o botão de baixo. + case automatic + case xbox + /// DualSense e DualShock. + case playStation + /// Switch Pro e Joy-Con: confirma com o botão da direita (A). + case nintendo + + public var id: Self { self } + + public var title: String { + switch self { + case .automatic: String(localized: "Automático") + case .xbox: "Xbox" + case .playStation: "PlayStation (DualSense)" + case .nintendo: "Nintendo Switch" + } + } + + /// No layout Nintendo, A fica à direita e é o botão de confirmar. + public var confirmsWithEastButton: Bool { + self == .nintendo + } + + /// Símbolo SF do botão nesta família; `nil` no automático (usa o do controle conectado). + public func glyph(for control: ControllerControl) -> String? { + switch self { + case .automatic: + return nil + case .xbox: + return [ + .south: "a.circle", .east: "b.circle", .west: "x.circle", .north: "y.circle", + .leftShoulder: "lb.rectangle.roundedbottom", .rightShoulder: "rb.rectangle.roundedbottom", + .leftTrigger: "lt.rectangle.roundedtop", .rightTrigger: "rt.rectangle.roundedtop", + .menu: "line.3.horizontal.circle", .options: "rectangle.on.rectangle.circle", + ][control] + case .playStation: + return [ + .south: "xmark.circle", .east: "circle.circle", .west: "square.circle", .north: "triangle.circle", + .leftShoulder: "l1.rectangle.roundedbottom", .rightShoulder: "r1.rectangle.roundedbottom", + .leftTrigger: "l2.rectangle.roundedtop", .rightTrigger: "r2.rectangle.roundedtop", + .menu: "line.3.horizontal.circle", .options: "rectangle.on.rectangle.circle", + ][control] + case .nintendo: + return [ + .south: "b.circle", .east: "a.circle", .west: "y.circle", .north: "x.circle", + .leftShoulder: "l.rectangle.roundedbottom", .rightShoulder: "r.rectangle.roundedbottom", + .leftTrigger: "zl.rectangle.roundedtop", .rightTrigger: "zr.rectangle.roundedtop", + .menu: "plus.circle", .options: "minus.circle", + ][control] + } + } + + /// Família do controle conectado, pela categoria que o GameController informa ("DualSense", "Xbox One"…). + public static func detect(productCategory: String) -> ControllerPreset { + let category = productCategory.lowercased() + if category.contains("dualsense") || category.contains("dualshock") || category.contains("playstation") { + return .playStation + } + if category.contains("switch") || category.contains("joy-con") || category.contains("nintendo") { + return .nintendo + } + return .xbox + } +} diff --git a/Sources/RetroXCore/Profiles/Profile.swift b/Sources/RetroXCore/Profiles/Profile.swift index 7833689..30b4146 100644 --- a/Sources/RetroXCore/Profiles/Profile.swift +++ b/Sources/RetroXCore/Profiles/Profile.swift @@ -10,6 +10,7 @@ public struct Profile: Codable, Identifiable, Sendable, Equatable, Hashable { /// Acento do tema RetroX; os outros temas têm acento próprio. public var accent: Palette.Accent public var appearance: AppearancePreference + public var preferences: ProfilePreferences public init( id: UUID = UUID(), @@ -17,7 +18,8 @@ public struct Profile: Codable, Identifiable, Sendable, Equatable, Hashable { avatarFile: String? = nil, theme: ThemeID = .retrox, accent: Palette.Accent = .coral, - appearance: AppearancePreference = .system + appearance: AppearancePreference = .system, + preferences: ProfilePreferences = ProfilePreferences() ) { self.id = id self.name = name @@ -25,6 +27,7 @@ public struct Profile: Codable, Identifiable, Sendable, Equatable, Hashable { self.theme = theme self.accent = accent self.appearance = appearance + self.preferences = preferences } /// Campos novos entram com valor padrão, para arquivos de versões anteriores continuarem abrindo. @@ -36,6 +39,7 @@ public struct Profile: Codable, Identifiable, Sendable, Equatable, Hashable { theme = (try? container.decodeIfPresent(ThemeID.self, forKey: .theme)) ?? .retrox accent = (try? container.decodeIfPresent(Palette.Accent.self, forKey: .accent)) ?? .coral appearance = (try? container.decodeIfPresent(AppearancePreference.self, forKey: .appearance)) ?? .system + preferences = (try? container.decodeIfPresent(ProfilePreferences.self, forKey: .preferences)) ?? ProfilePreferences() } /// Iniciais para o avatar sem foto: "Ana Souza" → "AS", "Jogador 1" → "J1", "léo" → "L". diff --git a/Sources/RetroXCore/Profiles/ProfilePreferences.swift b/Sources/RetroXCore/Profiles/ProfilePreferences.swift new file mode 100644 index 0000000..b58911b --- /dev/null +++ b/Sources/RetroXCore/Profiles/ProfilePreferences.swift @@ -0,0 +1,177 @@ +import Foundation + +/// O que cada perfil personaliza além do tema: tela inicial, texto e movimento. +/// Campos novos entram com valor padrão, para arquivos antigos continuarem abrindo. +public struct ProfilePreferences: Codable, Sendable, Equatable, Hashable { + public enum HomeStyle: String, Codable, CaseIterable, Sendable, Identifiable { + /// Palco com o jogo em foco e prateleira embaixo. + case shelf + /// Capas grandes no centro, vizinhas inclinadas dos lados. + case carousel + /// Grade de capas com o jogo em foco no topo. + case grid + + public var id: Self { self } + + public var title: String { + switch self { + case .shelf: String(localized: "Prateleira") + case .carousel: String(localized: "Carrossel") + case .grid: String(localized: "Grade") + } + } + } + + public enum TileSize: String, Codable, CaseIterable, Sendable, Identifiable { + case small, medium, large + + public var id: Self { self } + + public var title: String { + switch self { + case .small: String(localized: "Pequenas") + case .medium: String(localized: "Médias") + case .large: String(localized: "Grandes") + } + } + + public var scale: Double { + switch self { + case .small: 0.8 + case .medium: 1 + case .large: 1.25 + } + } + } + + public enum StartShelf: String, Codable, CaseIterable, Sendable, Identifiable { + /// Recentes quando houver; senão, Todos. + case automatic, recent, all, favorites + + public var id: Self { self } + + public var title: String { + switch self { + case .automatic: String(localized: "Automática") + case .recent: String(localized: "Recentes") + case .all: String(localized: "Todos") + case .favorites: String(localized: "Favoritos") + } + } + } + + public enum FontStyle: String, Codable, CaseIterable, Sendable, Identifiable { + case rounded, standard, serif, mono + + public var id: Self { self } + + public var title: String { + switch self { + case .rounded: String(localized: "Arredondada") + case .standard: String(localized: "Padrão") + case .serif: String(localized: "Serifada") + case .mono: String(localized: "Monoespaçada") + } + } + } + + public enum TextSize: String, Codable, CaseIterable, Sendable, Identifiable { + case small, standard, large, extraLarge + + public var id: Self { self } + + public var title: String { + switch self { + case .small: String(localized: "Pequeno") + case .standard: String(localized: "Padrão") + case .large: String(localized: "Grande") + case .extraLarge: String(localized: "Extra grande") + } + } + + public var scale: Double { + switch self { + case .small: 0.9 + case .standard: 1 + case .large: 1.12 + case .extraLarge: 1.25 + } + } + } + + public enum AnimationLevel: String, Codable, CaseIterable, Sendable, Identifiable { + /// Tudo: elevação, deslizes, carrossel inclinado, fundo ambiente se movendo. + case full + /// Só esmaecimentos e trocas curtas (como o Reduzir Movimento do macOS). + case reduced + /// Sem animação. + case off + + public var id: Self { self } + + public var title: String { + switch self { + case .full: String(localized: "Completas") + case .reduced: String(localized: "Reduzidas") + case .off: String(localized: "Desligadas") + } + } + } + + public enum AnimationSpeed: String, Codable, CaseIterable, Sendable, Identifiable { + case calm, normal, fast + + public var id: Self { self } + + public var title: String { + switch self { + case .calm: String(localized: "Calma") + case .normal: String(localized: "Normal") + case .fast: String(localized: "Rápida") + } + } + + /// Multiplica as durações: maior é mais lento. + public var durationFactor: Double { + switch self { + case .calm: 1.35 + case .normal: 1 + case .fast: 0.7 + } + } + } + + public var homeStyle: HomeStyle = .shelf + public var tileSize: TileSize = .medium + public var startShelf: StartShelf = .automatic + public var fontStyle: FontStyle = .rounded + public var textSize: TextSize = .standard + /// Capa do jogo em foco, desfocada, atrás da tela. + public var ambientBackground = true + public var animationLevel: AnimationLevel = .full + public var animationSpeed: AnimationSpeed = .normal + public var startupAnimation = true + public var showsFavoriteBadge = true + public var showsClock = true + + public init() {} + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let defaults = ProfilePreferences() + func value(_ key: CodingKeys, _ fallback: T) -> T { + (try? container.decodeIfPresent(T.self, forKey: key)) ?? fallback + } + homeStyle = value(.homeStyle, defaults.homeStyle) + tileSize = value(.tileSize, defaults.tileSize) + startShelf = value(.startShelf, defaults.startShelf) + fontStyle = value(.fontStyle, defaults.fontStyle) + textSize = value(.textSize, defaults.textSize) + ambientBackground = value(.ambientBackground, defaults.ambientBackground) + animationLevel = value(.animationLevel, defaults.animationLevel) + animationSpeed = value(.animationSpeed, defaults.animationSpeed) + startupAnimation = value(.startupAnimation, defaults.startupAnimation) + showsFavoriteBadge = value(.showsFavoriteBadge, defaults.showsFavoriteBadge) + showsClock = value(.showsClock, defaults.showsClock) + } +} diff --git a/Tests/RetroXCoreTests/PreferencesTests.swift b/Tests/RetroXCoreTests/PreferencesTests.swift new file mode 100644 index 0000000..498b809 --- /dev/null +++ b/Tests/RetroXCoreTests/PreferencesTests.swift @@ -0,0 +1,59 @@ +import Foundation +import Testing +@testable import RetroXCore + +struct PreferencesTests { + @Test("Perfil antigo (sem preferências) abre com os padrões") + func olderProfileDecodes() throws { + let json = #"{"id":"6F9619FF-8B86-D011-B42D-00C04FC964FF","name":"Ana","theme":"nord","retroAchievementsUsername":"x"}"# + let profile = try JSONDecoder().decode(Profile.self, from: Data(json.utf8)) + #expect(profile.theme == .nord) + #expect(profile.preferences == ProfilePreferences()) + } + + @Test("Preferências parciais mantêm o resto no padrão") + func partialPreferences() throws { + let json = #"{"homeStyle":"carousel","textSize":"large","valorDesconhecido":true}"# + let preferences = try JSONDecoder().decode(ProfilePreferences.self, from: Data(json.utf8)) + #expect(preferences.homeStyle == .carousel) + #expect(preferences.textSize == .large) + #expect(preferences.fontStyle == .rounded) + #expect(preferences.ambientBackground) + } + + @Test("Ida e volta em JSON") + func roundTrip() throws { + var profile = Profile(name: "Bia") + profile.preferences.fontStyle = .serif + profile.preferences.animationLevel = .reduced + let decoded = try JSONDecoder().decode(Profile.self, from: JSONEncoder().encode(profile)) + #expect(decoded == profile) + } +} + +struct ControllerPresetTests { + @Test("Presets fixos têm glifo para todos os botões", arguments: [ControllerPreset.xbox, .playStation, .nintendo]) + func glyphs(preset: ControllerPreset) { + for control in ControllerControl.allCases { + #expect(preset.glyph(for: control) != nil, "\(preset) \(control)") + } + } + + @Test("Só o layout Nintendo confirma com o botão da direita") + func confirmButton() { + #expect(ControllerPreset.nintendo.confirmsWithEastButton) + #expect(!ControllerPreset.xbox.confirmsWithEastButton) + #expect(!ControllerPreset.playStation.confirmsWithEastButton) + #expect(ControllerPreset.nintendo.glyph(for: .east) == "a.circle") + #expect(ControllerPreset.playStation.glyph(for: .south) == "xmark.circle") + } + + @Test("Detecta a família pelo nome da categoria", arguments: [ + ("DualSense", ControllerPreset.playStation), ("DualShock 4", .playStation), + ("Xbox One", .xbox), ("Xbox Series X", .xbox), ("Switch Pro Controller", .nintendo), + ("Nintendo Switch Joy-Con (L/R)", .nintendo), ("8BitDo", .xbox), + ]) + func detects(category: String, expected: ControllerPreset) { + #expect(ControllerPreset.detect(productCategory: category) == expected) + } +} From 7b1706a73e54bac3a6ab43a239a8f499643468dc Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 01:26:43 -0300 Subject: [PATCH 25/56] =?UTF-8?q?feat(app):=20anima=C3=A7=C3=B5es=20suaves?= =?UTF-8?q?,=20ajustes=20por=20controle=20e=20novas=20visualiza=C3=A7?= =?UTF-8?q?=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Navegação: quatro abas fixas (Início, Biblioteca, Emuladores, Ajustes); o conteúdo desliza para o lado da aba escolhida. Detalhes e edição de perfil viram cartões na janela, com mola suave e fundo escurecendo. - Abertura animada (símbolo com anel se desenhando e nome letra a letra), desligável no perfil. - Fundo ambiente: a capa do jogo em foco desfocada atrás da tela, a partir de uma miniatura minúscula (sem filtro caro, sem esticar o layout). Some com Reduzir Transparência. - Tela inicial com três visualizações: Prateleira, Carrossel (capas vizinhas inclinadas em 3D) e Grade; Biblioteca ganha "Capas pequenas". - Ajustes dentro da janela, no estilo console, navegáveis por controle e teclado: aparência, tela inicial, biblioteca, texto (fonte e tamanho), controle, animações (nível e velocidade) e sobre. - Controle no app inteiro, com presets Xbox, PlayStation (DualSense), Nintendo Switch e automático; gatilhos trocam de aba, Start abre Ajustes, View abre Emuladores; inverter confirmar/voltar, velocidade de repetição e modo das dicas. - Emuladores: ícone real do app instalado, selo de estado, blocos de resumo, detalhes recolhíveis e outros emuladores detectados no Mac. - Menu "Ir" (⌘1-⌘4, ⌘, para Ajustes, ⇧⌘P para trocar de perfil). - Modo de captura (-RetroXSnapshot) inerte: ignora entradas e nunca abre jogo. Co-Authored-By: Claude Opus 5.5 --- Sources/RetroXApp/App/AppModel.swift | 294 +++++++++-- Sources/RetroXApp/App/DebugSnapshot.swift | 6 +- Sources/RetroXApp/App/LibraryBrowser.swift | 5 +- Sources/RetroXApp/App/LibraryModel.swift | 20 +- Sources/RetroXApp/App/PluginsModel.swift | 8 +- .../RetroXApp/DesignSystem/Atmosphere.swift | 151 ++++++ .../DesignSystem/CoverImageStore.swift | 17 + Sources/RetroXApp/DesignSystem/Theme.swift | 103 +++- Sources/RetroXApp/DesignSystem/TopBar.swift | 45 +- .../Features/Emulators/EmulatorsView.swift | 476 ++++++++++++------ .../RetroXApp/Features/Home/HomeStyles.swift | 218 ++++++++ .../RetroXApp/Features/Home/HomeView.swift | 22 +- .../RetroXApp/Features/Home/ShelfView.swift | 21 +- .../Features/Library/LibraryView.swift | 5 +- .../Features/Profiles/ProfileEditorView.swift | 3 +- .../Features/Profiles/ProfilePickerView.swift | 4 +- .../Features/Settings/SettingsCatalog.swift | 177 +++++++ .../Features/Settings/SettingsView.swift | 339 ++++++++++--- .../RetroXApp/Input/InputCoordinator.swift | 182 ++++++- Sources/RetroXApp/RetroXApp.swift | 112 +++-- .../RetroXCore/Plugins/EmulatorPlugin.swift | 19 +- 21 files changed, 1810 insertions(+), 417 deletions(-) create mode 100644 Sources/RetroXApp/DesignSystem/Atmosphere.swift create mode 100644 Sources/RetroXApp/Features/Home/HomeStyles.swift create mode 100644 Sources/RetroXApp/Features/Settings/SettingsCatalog.swift diff --git a/Sources/RetroXApp/App/AppModel.swift b/Sources/RetroXApp/App/AppModel.swift index 7417464..a819c3d 100644 --- a/Sources/RetroXApp/App/AppModel.swift +++ b/Sources/RetroXApp/App/AppModel.swift @@ -1,16 +1,54 @@ import AppKit import Observation import RetroXCore +import SwiftUI -/// Raiz do estado do app: navegação, perfis, plugins, biblioteca, partida e entrada. +/// Raiz do estado do app: navegação, perfis, plugins, biblioteca, partida, ajustes e entrada. @MainActor @Observable final class AppModel { enum Screen: Hashable { - case profiles, home, library, emulators + case profiles, home, library, emulators, settings + + /// Abas da barra superior, na ordem em que os gatilhos do controle passam por elas. + static let tabs: [Screen] = [.home, .library, .emulators, .settings] + + var title: String { + switch self { + case .profiles: String(localized: "Perfis") + case .home: String(localized: "Início") + case .library: String(localized: "Biblioteca") + case .emulators: String(localized: "Emuladores") + case .settings: String(localized: "Ajustes") + } + } + + var symbol: String { + switch self { + case .profiles: "person.2" + case .home: "house" + case .library: "square.grid.2x2" + case .emulators: "puzzlepiece.extension" + case .settings: "slider.horizontal.3" + } + } + } + + enum SplashPhase { + case intro, revealed, done + } + + /// Tudo o que, ao mudar, pede para redesenhar a árvore inteira com os tokens novos. + struct StyleIdentity: Hashable { + var theme = ThemeSelection() + var text = TextSettings() + var motion = MotionSettings() } - var screen: Screen = .profiles + private(set) var screen: Screen = .profiles + /// +1 indo para uma aba à direita, -1 para a esquerda: define o lado do deslize. + private(set) var navigationDirection = 1 + private(set) var splash: SplashPhase = .done var detailsGame: Game? var editingProfile: ProfileDraft? /// Na tela de perfis: índice do perfil em foco (o último é "Adicionar perfil"). @@ -18,8 +56,18 @@ final class AppModel { /// Mensagem de erro curta para ações pontuais (importar imagem, por exemplo). var notice: String? - /// Tema e aparência do perfil atual. O tema serve de identidade da árvore de views. - private(set) var themeSelection = ThemeSelection() + // Ajustes e Emuladores navegáveis por controle e teclado. + var settingsSection: SettingsSection = .appearance + /// `nil`: o foco está na lista de seções; senão, na linha de opções. + var settingsRow: Int? + var emulatorsFocus = 0 + /// O anel de foco de listas aparece depois do primeiro comando de teclado ou controle. + private(set) var showsListFocus = false + + private(set) var styleIdentity = StyleIdentity() + /// Rodando só para capturar a janela (`-RetroXSnapshot`): ignora entradas e nunca abre jogo, para uma + /// tecla digitada em outro app não disparar nada. + let isReviewMode = UserDefaults.standard.string(forKey: "RetroXSnapshot") != nil private(set) var appearance: AppearancePreference = .system let profiles = ProfilesModel() @@ -34,14 +82,20 @@ final class AppModel { init() { browser = LibraryBrowser(library: library) profilePickerIndex = profiles.profiles.firstIndex { $0.id == profiles.lastUsed?.id } ?? 0 - applyTheme(of: profiles.lastUsed) - // Para revisão visual sem clicar: `RetroX -RetroXInitialScreen home|library|emulators`. + applyStyle(of: profiles.lastUsed) + let isSnapshot = UserDefaults.standard.string(forKey: "RetroXSnapshot") != nil + let forcesSplash = UserDefaults.standard.bool(forKey: "RetroXSplash") + if forcesSplash || (!isSnapshot && preferences.startupAnimation && Motion.settings.level != .off) { + splash = .intro + } + // Para revisão visual sem clicar: `RetroX -RetroXInitialScreen home|library|emulators|settings`. if let initial = UserDefaults.standard.string(forKey: "RetroXInitialScreen"), initial != "profiles", let profile = profiles.lastUsed { enter(profile) screen = switch initial { case "library": .library case "emulators": .emulators + case "settings": .settings default: .home } } @@ -58,28 +112,59 @@ final class AppModel { await library.reload(from: plugins.readyPlugins) } + /// Abertura: o símbolo e o nome entram, ficam um instante e a tela de perfis aparece por baixo. + func runSplash() async { + guard splash == .intro else { return } + try? await Task.sleep(for: .milliseconds(60)) + withAnimation(Motion.screen) { splash = .revealed } + try? await Task.sleep(for: .milliseconds(Int(1500 * Motion.settings.factor))) + withAnimation(Motion.screen) { splash = .done } + } + + // MARK: Navegação + + func navigate(to target: Screen) { + guard target != screen else { return } + let from = Screen.tabs.firstIndex(of: screen) ?? -1 + let to = Screen.tabs.firstIndex(of: target) ?? -1 + navigationDirection = to >= from ? 1 : -1 + showsListFocus = false + if target == .settings { settingsRow = nil } + withAnimation(Motion.screen) { screen = target } + } + + func cycleTab(by offset: Int) { + guard let index = Screen.tabs.firstIndex(of: screen) else { return } + let count = Screen.tabs.count + navigate(to: Screen.tabs[(index + offset + count) % count]) + } + // MARK: Perfis func enter(_ profile: Profile) { profiles.select(profile) library.use(profile, storage: profiles.storage) browser.clearFilters() - applyTheme(of: profile) - screen = .home + applyStyle(of: profile) + navigate(to: .home) } func showProfiles() { detailsGame = nil profilePickerIndex = profiles.profiles.firstIndex { $0.id == profiles.current?.id } ?? 0 - screen = .profiles + navigate(to: .profiles) } func newProfile() { - editingProfile = ProfileDraft(profile: Profile(name: ""), isNew: true) + withAnimation(Motion.screen) { editingProfile = ProfileDraft(profile: Profile(name: ""), isNew: true) } } func edit(_ profile: Profile) { - editingProfile = ProfileDraft(profile: profile, isNew: false) + withAnimation(Motion.screen) { editingProfile = ProfileDraft(profile: profile, isNew: false) } + } + + func closeEditor() { + withAnimation(Motion.screen) { editingProfile = nil } } func save(_ draft: ProfileDraft) { @@ -99,37 +184,58 @@ final class AppModel { notice = String(localized: "Não foi possível usar essa imagem como foto.") } } - if profiles.current?.id == profile.id { applyTheme(of: profiles.current) } + if profiles.current?.id == profile.id { applyStyle(of: profiles.current) } if draft.isNew { profilePickerIndex = profiles.profiles.count - 1 } - editingProfile = nil + closeEditor() } func delete(_ draft: ProfileDraft) { profiles.delete(draft.profile) - editingProfile = nil + closeEditor() profilePickerIndex = min(profilePickerIndex, profiles.profiles.count - 1) if profiles.current == nil { showProfiles() } } - /// Muda o tema do perfil atual (Ajustes), aplicando na hora. + // MARK: Estilo do perfil + + var preferences: ProfilePreferences { + var preferences = (profiles.current ?? profiles.lastUsed)?.preferences ?? ProfilePreferences() + // Só para revisão visual, sem gravar no perfil: `-RetroXHomeStyle carousel|grid`. + if let style = UserDefaults.standard.string(forKey: "RetroXHomeStyle").flatMap(ProfilePreferences.HomeStyle.init(rawValue:)) { + preferences.homeStyle = style + } + return preferences + } + + /// Muda o tema do perfil atual, aplicando na hora. func setTheme(_ theme: ThemeID? = nil, accent: Palette.Accent? = nil, appearance: AppearancePreference? = nil) { guard var profile = profiles.current else { return } if let theme { profile.theme = theme } if let accent { profile.accent = accent } if let appearance { profile.appearance = appearance } profiles.update(profile) - applyTheme(of: profile) + applyStyle(of: profile) + } + + func updatePreferences(_ change: (inout ProfilePreferences) -> Void) { + guard var profile = profiles.current else { return } + change(&profile.preferences) + profiles.update(profile) + applyStyle(of: profile) } - private func applyTheme(of profile: Profile?) { + private func applyStyle(of profile: Profile?) { var selection = ThemeSelection(theme: profile?.theme ?? .retrox, accent: profile?.accent ?? .coral) var appearance = profile?.appearance ?? .system // Só para revisão visual, sem gravar no perfil: `-RetroXTheme gruvbox -RetroXAppearance light`. let defaults = UserDefaults.standard if let theme = defaults.string(forKey: "RetroXTheme").flatMap(ThemeID.init(rawValue:)) { selection.theme = theme } if let forced = defaults.string(forKey: "RetroXAppearance").flatMap(AppearancePreference.init(rawValue:)) { appearance = forced } + let preferences = profile?.preferences ?? ProfilePreferences() Theme.current = selection - themeSelection = selection + Typography.settings = TextSettings(fontStyle: preferences.fontStyle, scale: preferences.textSize.scale) + Motion.settings = MotionSettings(level: preferences.animationLevel, factor: preferences.animationSpeed.durationFactor) + styleIdentity = StyleIdentity(theme: selection, text: Typography.settings, motion: Motion.settings) self.appearance = appearance } @@ -150,17 +256,40 @@ final class AppModel { await reloadLibrary() } + /// Controles focáveis da tela de Emuladores, na ordem em que o controle passa por eles. + var emulatorControls: [FocusableControl] { + plugins.entries.flatMap { entry -> [FocusableControl] in + let id = entry.id + var controls = [FocusableControl(id: "\(id).toggle") { [weak self] in + Task { await self?.setPlugin(id, enabled: !entry.config.isEnabled) } + }] + if entry.config.isEnabled { + controls.append(FocusableControl(id: "\(id).root") { [weak self] in Task { await self?.chooseRoot(for: id) } }) + if let root = entry.discovery?.root { + controls.append(FocusableControl(id: "\(id).rediscover") { [weak self] in Task { await self?.rediscover(id) } }) + controls.append(FocusableControl(id: "\(id).reveal") { NSWorkspace.shared.activateFileViewerSelecting([root]) }) + } + } + return controls + } + } + + func isFocused(emulatorControl id: String) -> Bool { + showsListFocus && emulatorControls.indices.contains(emulatorsFocus) && emulatorControls[emulatorsFocus].id == id + } + // MARK: Jogos func play(_ game: Game) { - detailsGame = nil + guard !isReviewMode else { return } + withAnimation(Motion.screen) { detailsGame = nil } guard let entry = plugins.entry(game.pluginID) else { return } Task { await session.play(game, plugin: entry.plugin, app: entry.discovery?.app) } } func showDetails(_ game: Game?) { metadata.cancel() - detailsGame = game + withAnimation(Motion.screen) { detailsGame = game } } func plan(for game: Game) -> Result { @@ -180,7 +309,7 @@ final class AppModel { do { let cover = try library.setCustomCover(for: game, from: source) covers.invalidate(cover) - detailsGame = library.game(withID: game.id) + if detailsGame != nil { detailsGame = library.game(withID: game.id) } } catch { notice = String(localized: "Não foi possível usar essa imagem como capa.") } @@ -196,7 +325,7 @@ final class AppModel { switch action { case .chooseEmulator, .openSettings: session.dismiss() - screen = .emulators + navigate(to: .emulators) case .locateROM: session.dismiss() Task { await reloadLibrary() } @@ -210,54 +339,80 @@ final class AppModel { } } + /// O jogo em foco na tela atual (para o fundo ambiente). + var ambientGame: Game? { + switch screen { + case .home: library.focusedGame + case .library: browser.focusedGame + default: nil + } + } + // MARK: Entrada /// Um só roteador para teclado e controle: a mesma ação faz a mesma coisa em qualquer dispositivo. func handle(_ action: InputAction) { - if editingProfile != nil { return } - if session.isPresenting { - handleSession(action) - } else if let game = detailsGame { + guard splash == .done, !isReviewMode else { return } + if editingProfile != nil { + if action == .back { closeEditor() } + return + } + if session.isPresenting { return handleSession(action) } + if let game = detailsGame { switch action { case .confirm: play(game) case .back, .details: showDetails(nil) case .favorite: library.toggleFavorite(game) default: break } - } else { - switch screen { - case .profiles: handleProfiles(action) - case .home: handleHome(action) - case .library: handleLibrary(action) - case .emulators: if action == .back || action == .menu { screen = .home } + return + } + if screen != .profiles { + switch action { + case .previousTab: return cycleTab(by: -1) + case .nextTab: return cycleTab(by: 1) + case .menu: return navigate(to: screen == .settings ? .home : .settings) + case .options: return navigate(to: screen == .emulators ? .home : .emulators) + default: break } } + switch screen { + case .profiles: handleProfiles(action) + case .home: handleHome(action) + case .library: handleLibrary(action) + case .emulators: handleEmulators(action) + case .settings: handleSettings(action) + } } private func handleProfiles(_ action: InputAction) { let count = profiles.profiles.count - switch action { - case .left: profilePickerIndex = max(profilePickerIndex - 1, 0) - case .right: profilePickerIndex = min(profilePickerIndex + 1, count) - case .confirm: - if profilePickerIndex < count { enter(profiles.profiles[profilePickerIndex]) } else { newProfile() } - case .details: - if profilePickerIndex < count { edit(profiles.profiles[profilePickerIndex]) } - default: break + withAnimation(Motion.focus) { + switch action { + case .left: profilePickerIndex = max(profilePickerIndex - 1, 0) + case .right: profilePickerIndex = min(profilePickerIndex + 1, count) + case .confirm: + if profilePickerIndex < count { enter(profiles.profiles[profilePickerIndex]) } else { newProfile() } + case .details: + if profilePickerIndex < count { edit(profiles.profiles[profilePickerIndex]) } + default: break + } } } private func handleHome(_ action: InputAction) { + let isGrid = preferences.homeStyle == .grid switch action { case .left: library.moveFocus(by: -1) case .right: library.moveFocus(by: 1) - case .up, .previousShelf: library.cycleShelf(by: -1) - case .down, .nextShelf: library.cycleShelf(by: 1) + case .up: isGrid ? library.moveFocus(by: -library.homeColumns) : library.cycleShelf(by: -1) + case .down: isGrid ? library.moveFocus(by: library.homeColumns) : library.cycleShelf(by: 1) + case .previousShelf: library.cycleShelf(by: -1) + case .nextShelf: library.cycleShelf(by: 1) case .confirm: library.focusedGame.map(play) case .details: showDetails(library.focusedGame) case .favorite: library.focusedGame.map(library.toggleFavorite) - case .menu: screen = .emulators - case .back: break + default: break } } @@ -272,9 +427,48 @@ final class AppModel { case .confirm: browser.focusedGame.map(play) case .details: showDetails(browser.focusedGame) case .favorite: browser.focusedGame.map(library.toggleFavorite) - case .menu: screen = .emulators case .back: - if browser.isFiltering { browser.clearFilters() } else { screen = .home } + if browser.isFiltering { browser.clearFilters() } else { navigate(to: .home) } + default: break + } + } + + private func handleEmulators(_ action: InputAction) { + let controls = emulatorControls + showsListFocus = true + switch action { + case .up, .left: emulatorsFocus = max(emulatorsFocus - 1, 0) + case .down, .right: emulatorsFocus = min(emulatorsFocus + 1, max(controls.count - 1, 0)) + case .confirm: if controls.indices.contains(emulatorsFocus) { controls[emulatorsFocus].run() } + case .back: navigate(to: .home) + default: break + } + } + + private func handleSettings(_ action: InputAction) { + showsListFocus = true + let sections = SettingsSection.allCases + guard let row = settingsRow else { + let index = sections.firstIndex(of: settingsSection) ?? 0 + switch action { + case .up: settingsSection = sections[max(index - 1, 0)] + case .down: settingsSection = sections[min(index + 1, sections.count - 1)] + case .right, .confirm: if !settingsRows.isEmpty { settingsRow = 0 } + case .back: navigate(to: .home) + default: break + } + return + } + let rows = settingsRows + guard rows.indices.contains(row) else { settingsRow = rows.isEmpty ? nil : rows.count - 1; return } + switch action { + case .up: settingsRow = max(row - 1, 0) + case .down: settingsRow = min(row + 1, rows.count - 1) + case .left: rows[row].step(by: -1) + case .right: rows[row].step(by: 1) + case .confirm: rows[row].activate() + case .back: settingsRow = nil + default: break } } @@ -293,6 +487,12 @@ final class AppModel { } } +/// Um controle que teclado e controle de jogo alcançam com as setas. +struct FocusableControl: Identifiable { + let id: String + let run: () -> Void +} + /// Cópia de um perfil sendo editado; só vale ao salvar. @MainActor @Observable diff --git a/Sources/RetroXApp/App/DebugSnapshot.swift b/Sources/RetroXApp/App/DebugSnapshot.swift index 41112be..e9e4044 100644 --- a/Sources/RetroXApp/App/DebugSnapshot.swift +++ b/Sources/RetroXApp/App/DebugSnapshot.swift @@ -1,12 +1,14 @@ import AppKit /// Revisão visual sem permissão de Gravação de Tela: o app grava a própria janela em PNG. -/// `open RetroX.app --args -RetroXSnapshot /caminho/tela.png [-RetroXInitialScreen emulators]` +/// `RetroX -RetroXSnapshot /caminho/tela.png [-RetroXInitialScreen emulators] [-RetroXSnapshotDelay 0.8]` @MainActor enum DebugSnapshot { static func captureIfRequested() async { guard let path = UserDefaults.standard.string(forKey: "RetroXSnapshot") else { return } - try? await Task.sleep(for: .seconds(3)) + let delay = UserDefaults.standard.object(forKey: "RetroXSnapshotDelay") == nil + ? 3 : UserDefaults.standard.double(forKey: "RetroXSnapshotDelay") + try? await Task.sleep(for: .seconds(delay)) guard let window = NSApp.windows.first(where: { $0.isVisible && $0.contentView != nil }), let view = window.contentView, let representation = view.bitmapImageRepForCachingDisplay(in: view.bounds) diff --git a/Sources/RetroXApp/App/LibraryBrowser.swift b/Sources/RetroXApp/App/LibraryBrowser.swift index b31e0c1..f8dd003 100644 --- a/Sources/RetroXApp/App/LibraryBrowser.swift +++ b/Sources/RetroXApp/App/LibraryBrowser.swift @@ -7,12 +7,13 @@ import RetroXCore @Observable final class LibraryBrowser { enum Layout: String, CaseIterable, Identifiable { - case covers, largeCovers, titledCovers, list + case compact, covers, largeCovers, titledCovers, list var id: Self { self } var title: String { switch self { + case .compact: String(localized: "Capas pequenas") case .covers: String(localized: "Capas") case .largeCovers: String(localized: "Capas grandes") case .titledCovers: String(localized: "Capas e nomes") @@ -22,6 +23,7 @@ final class LibraryBrowser { var symbol: String { switch self { + case .compact: "square.grid.4x3.fill" case .covers: "square.grid.3x3" case .largeCovers: "square.grid.2x2" case .titledCovers: "rectangle.grid.2x2" @@ -32,6 +34,7 @@ final class LibraryBrowser { /// Largura da capa em cada forma de exibir (a lista usa uma miniatura). var tileWidth: CGFloat { switch self { + case .compact: 96 case .covers: 128 case .largeCovers: 184 case .titledCovers: 148 diff --git a/Sources/RetroXApp/App/LibraryModel.swift b/Sources/RetroXApp/App/LibraryModel.swift index 8c6ca36..9661fec 100644 --- a/Sources/RetroXApp/App/LibraryModel.swift +++ b/Sources/RetroXApp/App/LibraryModel.swift @@ -30,8 +30,11 @@ final class LibraryModel { private(set) var hasLoaded = false private(set) var shelf: Shelf = .all private(set) var focusedGameID: Game.ID? + /// Colunas da grade da tela inicial (estilo Grade), para mover o foco para cima e para baixo. + var homeColumns = 1 @ObservationIgnored private var scanned: [Game] = [] + @ObservationIgnored private var startShelf: ProfilePreferences.StartShelf = .automatic @ObservationIgnored private var historyStore: JSONFileStore<[String: GameHistory]>? @ObservationIgnored let artwork: ArtworkStorage @@ -45,10 +48,21 @@ final class LibraryModel { func use(_ profile: Profile, storage: ProfileStorage) { historyStore = storage.history(for: profile.id) history = historyStore?.load() ?? [:] - shelf = shelves.contains(.recent) ? .recent : .all + startShelf = profile.preferences.startShelf + shelf = initialShelf focusedGameID = visibleGames.first?.id } + /// A prateleira escolhida nas preferências; Recentes só se houver algo jogado. + private var initialShelf: Shelf { + let hasRecent = shelves.contains(.recent) + switch startShelf { + case .automatic, .recent: return hasRecent ? .recent : .all + case .all: return .all + case .favorites: return .favorites + } + } + // MARK: Prateleiras (tela inicial) var shelves: [Shelf] { @@ -129,8 +143,8 @@ final class LibraryModel { let isFirstLoad = !hasLoaded hasLoaded = true isScanning = false - if isFirstLoad, shelves.contains(.recent) { - shelf = .recent + if isFirstLoad { + shelf = initialShelf } else if !shelves.contains(shelf) { shelf = .all } diff --git a/Sources/RetroXApp/App/PluginsModel.swift b/Sources/RetroXApp/App/PluginsModel.swift index dda2370..4fbb72d 100644 --- a/Sources/RetroXApp/App/PluginsModel.swift +++ b/Sources/RetroXApp/App/PluginsModel.swift @@ -1,4 +1,4 @@ -import Foundation +import AppKit import Observation import RetroXCore @@ -18,6 +18,8 @@ final class PluginsModel { } private(set) var entries: [Entry] + /// Emuladores conhecidos ainda sem plugin, com o app encontrado neste Mac (se houver). + private(set) var otherEmulators: [(PluginCatalog.KnownEmulator, URL?)] = [] @ObservationIgnored private let store: JSONFileStore<[String: PluginConfig]> init( @@ -77,6 +79,10 @@ final class PluginsModel { } func discoverAll() async { + otherEmulators = PluginCatalog.known.compactMap { emulator in + let app = emulator.bundleIdentifiers.lazy.compactMap { NSWorkspace.shared.urlsForApplications(withBundleIdentifier: $0).first }.first + return emulator.isPlanned || app != nil ? (emulator, app) : nil + } for entry in entries where entry.config.isEnabled { await discover(entry.id) } diff --git a/Sources/RetroXApp/DesignSystem/Atmosphere.swift b/Sources/RetroXApp/DesignSystem/Atmosphere.swift new file mode 100644 index 0000000..b2191b4 --- /dev/null +++ b/Sources/RetroXApp/DesignSystem/Atmosphere.swift @@ -0,0 +1,151 @@ +import AppKit +import RetroXCore +import SwiftUI + +/// Abertura do app: o símbolo surge com um anel se desenhando em volta, o nome entra letra a letra, +/// e tudo se dissolve revelando a tela de perfis. +struct SplashView: View { + @Environment(AppModel.self) private var model + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + private static let word = Array("RetroX") + + var body: some View { + let revealed = model.splash == .revealed + let moves = Motion.allowsMovement(reduceMotion: reduceMotion) + ZStack { + Theme.background + .ignoresSafeArea() + VStack(spacing: Spacing.l) { + ZStack { + Circle() + .trim(from: 0, to: revealed ? 1 : 0.001) + .stroke(Theme.accent, style: StrokeStyle(lineWidth: 4, lineCap: .round)) + .rotationEffect(.degrees(-90)) + .frame(width: 132, height: 132) + .animation(moves ? .easeInOut(duration: 0.9 * Motion.settings.factor) : nil, value: revealed) + RoundedRectangle.rx(28) + .fill(Theme.accent) + .frame(width: 96, height: 96) + .overlay { + Text("R") + .font(.system(size: 56, weight: .heavy, design: .rounded)) + .foregroundStyle(Theme.onAccent) + } + .scaleEffect(revealed || !moves ? 1 : 0.6) + .rotationEffect(.degrees(revealed || !moves ? 0 : -12)) + .opacity(revealed ? 1 : 0) + .animation(moves ? .spring(response: 0.6, dampingFraction: 0.68) : Motion.fade, value: revealed) + } + HStack(spacing: 0) { + ForEach(Array(Self.word.enumerated()), id: \.offset) { index, letter in + Text(String(letter)) + .font(.system(size: 44, weight: .heavy, design: .rounded)) + .foregroundStyle(Theme.textPrimary) + .opacity(revealed ? 1 : 0) + .offset(y: revealed || !moves ? 0 : 18) + .animation( + (moves ? Animation.smooth(duration: 0.5) : .easeOut(duration: 0.3)).delay(0.25 + Double(index) * 0.06), + value: revealed + ) + } + } + Text("Seus jogos, num lugar só.") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + .opacity(revealed ? 1 : 0) + .animation(.easeOut(duration: 0.4).delay(0.7), value: revealed) + } + } + .accessibilityElement(children: .ignore) + .accessibilityLabel("RetroX") + } +} + +/// Fundo ambiente: a capa do jogo em foco, bem desfocada, atrás da tela. Troca devagar. +/// Ocupa exatamente o tamanho da janela (a imagem fica num overlay de um `Color.clear`, para não esticar o +/// layout). Some com Reduzir Transparência ou se o perfil desligar. +struct AmbientBackdrop: View { + @Environment(AppModel.self) private var model + @Environment(\.accessibilityReduceTransparency) private var reduceTransparency + @Environment(\.colorScheme) private var colorScheme + + var body: some View { + Color.clear + .overlay { + if !reduceTransparency, model.preferences.ambientBackground, let game = model.ambientGame { + Group { + if let image = model.covers.ambientImage(for: game.coverURL) { + Image(nsImage: image) + .resizable() + .interpolation(.medium) + .scaledToFill() + .blur(radius: 24) + } else { + Theme.coverTone(game.systemID) + } + } + .opacity(colorScheme == .dark ? 0.45 : 0.32) + .id(game.coverURL?.absoluteString ?? game.id) + .transition(.opacity) + .task(id: game.coverURL) { + if let url = game.coverURL { await model.covers.loadAmbient(url) } + } + } + } + .overlay { + // Mantém o texto legível sobre qualquer capa. + LinearGradient( + colors: [Theme.background.opacity(0.5), Theme.background.opacity(0.82), Theme.background], + startPoint: .top, endPoint: .bottom + ) + } + .clipped() + .ignoresSafeArea() + .animation(Motion.ambient, value: model.ambientGame?.id) + .allowsHitTesting(false) + .accessibilityHidden(true) + } +} + +/// Fundo escurecido atrás de um cartão (detalhes, edição de perfil); clicar fora fecha. +struct ModalDim: View { + let onDismiss: () -> Void + + var body: some View { + Color.black.opacity(0.42) + .ignoresSafeArea() + .contentShape(Rectangle()) + .onTapGesture(perform: onDismiss) + .accessibilityHidden(true) + } +} + +extension View { + /// Aparência de cartão flutuante. + func modalCard() -> some View { + clipShape(RoundedRectangle.rx(Radius.xl)) + .overlay(RoundedRectangle.rx(Radius.xl).strokeBorder(Theme.divider, lineWidth: 1)) + .shadow(color: .black.opacity(0.35), radius: 40, y: 20) + } +} + +extension AnyTransition { + /// O cartão cresce de leve e sobe enquanto aparece. + static var modalCard: AnyTransition { + .scale(scale: 0.94).combined(with: .opacity).combined(with: .offset(y: 16)) + } + + /// Troca entre abas: o conteúdo novo entra pelo lado da aba escolhida. + static func screen(direction: Int) -> AnyTransition { + .asymmetric( + insertion: .offset(x: CGFloat(direction) * 48).combined(with: .opacity), + removal: .offset(x: CGFloat(-direction) * 48).combined(with: .opacity) + ) + } + + /// Entrar no perfil: a tela inicial aproxima. + static var zoom: AnyTransition { + .asymmetric(insertion: .scale(scale: 1.04).combined(with: .opacity), removal: .scale(scale: 0.96).combined(with: .opacity)) + } +} diff --git a/Sources/RetroXApp/DesignSystem/CoverImageStore.swift b/Sources/RetroXApp/DesignSystem/CoverImageStore.swift index 14db0fd..121bd13 100644 --- a/Sources/RetroXApp/DesignSystem/CoverImageStore.swift +++ b/Sources/RetroXApp/DesignSystem/CoverImageStore.swift @@ -7,6 +7,8 @@ import RetroXCore @Observable final class CoverImageStore { private var images: [URL: NSImage] = [:] + /// Versões minúsculas para o fundo ambiente: ampliadas, já ficam desfocadas sem filtro caro. + private var ambientImages: [URL: NSImage] = [:] @ObservationIgnored private var inFlight: Set = [] nonisolated static let maxPixelSize = 900 @@ -15,9 +17,24 @@ final class CoverImageStore { url.flatMap { images[$0] } } + func ambientImage(for url: URL?) -> NSImage? { + url.flatMap { ambientImages[$0] } + } + + func loadAmbient(_ url: URL) async { + guard ambientImages[url] == nil else { return } + let cgImage = await Task.detached(priority: .utility) { + CoverThumbnailer.thumbnail(of: url, maxPixelSize: 36) + }.value + if let cgImage { + ambientImages[url] = NSImage(cgImage: cgImage, size: NSSize(width: cgImage.width, height: cgImage.height)) + } + } + /// Esquece a imagem guardada (a capa foi trocada no mesmo endereço). func invalidate(_ url: URL) { images[url] = nil + ambientImages[url] = nil } func load(_ url: URL) async { diff --git a/Sources/RetroXApp/DesignSystem/Theme.swift b/Sources/RetroXApp/DesignSystem/Theme.swift index f43637d..2085919 100644 --- a/Sources/RetroXApp/DesignSystem/Theme.swift +++ b/Sources/RetroXApp/DesignSystem/Theme.swift @@ -71,26 +71,101 @@ enum Radius { static let xl: CGFloat = 24 } -/// No máximo quatro tamanhos por tela: título, seção, corpo e legenda. +/// Fonte e tamanho escolhidos no perfil. +struct TextSettings: Equatable, Hashable { + var fontStyle: ProfilePreferences.FontStyle = .rounded + var scale: Double = 1 +} + +/// No máximo quatro tamanhos por tela: título, seção, corpo e legenda. A fonte e o tamanho vêm do perfil; +/// trocar reconstrói a árvore de views (ver `AppModel.styleIdentity`). +@MainActor enum Typography { - static let display = Font.system(size: 34, weight: .bold, design: .rounded) - static let heading = Font.system(size: 20, weight: .semibold, design: .rounded) - static let body = Font.system(size: 15) - static let bodyEmphasis = Font.system(size: 15, weight: .semibold) - static let caption = Font.system(size: 12, weight: .medium) + static var settings = TextSettings() + + static var display: Font { title(34, .bold) } + static var heading: Font { title(20, .semibold) } + static var body: Font { text(15, .regular) } + static var bodyEmphasis: Font { text(15, .semibold) } + static var caption: Font { text(12, .medium) } + + /// Títulos usam o estilo escolhido. + static func title(_ size: CGFloat, _ weight: Font.Weight) -> Font { + .system(size: size * settings.scale, weight: weight, design: design) + } + + /// No estilo arredondado, o corpo continua na fonte padrão, que lê melhor em tamanhos pequenos. + static func text(_ size: CGFloat, _ weight: Font.Weight) -> Font { + .system(size: size * settings.scale, weight: weight, design: settings.fontStyle == .rounded ? .default : design) + } + + private static var design: Font.Design { + switch settings.fontStyle { + case .rounded: .rounded + case .standard: .default + case .serif: .serif + case .mono: .monospaced + } + } +} + +/// Nível e velocidade das animações escolhidos no perfil, somados ao Reduzir Movimento do macOS. +struct MotionSettings: Equatable, Hashable { + var level: ProfilePreferences.AnimationLevel = .full + var factor: Double = 1 } +@MainActor enum Motion { - /// Foco e seleção: rápido e sem quicar demais. - static let focus = Animation.snappy(duration: 0.28, extraBounce: 0.04) - /// Passar o mouse: um pouco mais suave que o foco. - static let hover = Animation.smooth(duration: 0.22) - static let fade = Animation.easeOut(duration: 0.18) - - /// Com Reduce Motion, só esmaece; nada se desloca ou cresce. - static func animation(reduceMotion: Bool) -> Animation { + static var settings = MotionSettings() + + private static var factor: Double { settings.factor } + + /// Foco e seleção: rápido, com um quique quase imperceptível. + static var focus: Animation? { + switch settings.level { + case .full: .snappy(duration: 0.32 * factor, extraBounce: 0.05) + case .reduced: .easeOut(duration: 0.15 * factor) + case .off: nil + } + } + + /// Passar o mouse e apertar botões. + static var hover: Animation? { + switch settings.level { + case .full: .smooth(duration: 0.24 * factor) + case .reduced: .easeOut(duration: 0.12 * factor) + case .off: nil + } + } + + static var fade: Animation? { + settings.level == .off ? nil : .easeOut(duration: 0.2 * factor) + } + + /// Troca de tela e cartões que surgem: mola longa e macia, sem quique. + static var screen: Animation? { + switch settings.level { + case .full: .smooth(duration: 0.45 * factor) + case .reduced: .easeOut(duration: 0.2 * factor) + case .off: nil + } + } + + /// Fundo ambiente: troca lenta. + static var ambient: Animation? { + settings.level == .off ? nil : .easeInOut(duration: 0.7 * factor) + } + + /// Com Reduzir Movimento do macOS, só esmaece. + static func animation(reduceMotion: Bool) -> Animation? { reduceMotion ? fade : focus } + + /// Escala, deslocamento e inclinação só com animações completas e sem Reduzir Movimento. + static func allowsMovement(reduceMotion: Bool) -> Bool { + !reduceMotion && settings.level == .full + } } /// O português é o idioma da interface; datas e tamanhos seguem a mesma língua. diff --git a/Sources/RetroXApp/DesignSystem/TopBar.swift b/Sources/RetroXApp/DesignSystem/TopBar.swift index 30f51f6..6ec2fcb 100644 --- a/Sources/RetroXApp/DesignSystem/TopBar.swift +++ b/Sources/RetroXApp/DesignSystem/TopBar.swift @@ -1,7 +1,7 @@ import RetroXCore import SwiftUI -/// Barra superior compartilhada por Início e Biblioteca: abas, estado, relógio, emuladores e perfil. +/// Barra superior fixa: abas (o conteúdo desliza por baixo dela), estado, relógio e perfil. struct TopBar: View { @Environment(AppModel.self) private var model @@ -28,20 +28,14 @@ struct TopBar: View { .help(controller) .accessibilityLabel("Controle conectado: \(controller)") } - TimelineView(.everyMinute) { context in - Text(context.date, format: .dateTime.hour().minute().locale(AppLocale.current)) - .font(Typography.bodyEmphasis) - .monospacedDigit() - .foregroundStyle(Theme.textPrimary) - } - Button { - model.screen = .emulators - } label: { - Image(systemName: "puzzlepiece.extension") + if model.preferences.showsClock { + TimelineView(.everyMinute) { context in + Text(context.date, format: .dateTime.hour().minute().locale(AppLocale.current)) + .font(Typography.bodyEmphasis) + .monospacedDigit() + .foregroundStyle(Theme.textPrimary) + } } - .buttonStyle(IconButtonStyle()) - .help("Emuladores") - .accessibilityLabel("Emuladores") ProfileMenu() } // Espaço para os botões da janela (a barra de título fica escondida). @@ -53,26 +47,33 @@ struct TopBar: View { } } -/// Início | Biblioteca, como abas em pílula. +/// As quatro abas, como pílulas; a selecionada desliza (LT/RT ou `[` `]` no teclado). private struct ScreenTabs: View { @Environment(AppModel.self) private var model @Namespace private var selection var body: some View { - HStack(spacing: Spacing.xs) { - tab(.home, String(localized: "Início"), "house") - tab(.library, String(localized: "Biblioteca"), "square.grid.2x2") + HStack(spacing: Spacing.xxs) { + if model.input.showsControllerGlyphs, let glyph = model.input.glyphs[.previousTab] { + Image(systemName: glyph).foregroundStyle(Theme.textSecondary).padding(.horizontal, Spacing.xs) + } + ForEach(AppModel.Screen.tabs, id: \.self) { screen in + tab(screen) + } + if model.input.showsControllerGlyphs, let glyph = model.input.glyphs[.nextTab] { + Image(systemName: glyph).foregroundStyle(Theme.textSecondary).padding(.horizontal, Spacing.xs) + } } .padding(Spacing.xs) .background(Theme.raised, in: Capsule()) } - private func tab(_ screen: AppModel.Screen, _ title: String, _ symbol: String) -> some View { + private func tab(_ screen: AppModel.Screen) -> some View { let isSelected = model.screen == screen return Button { - withAnimation(Motion.focus) { model.screen = screen } + model.navigate(to: screen) } label: { - Label(title, systemImage: symbol) + Label(screen.title, systemImage: screen.symbol) .font(Typography.caption) .foregroundStyle(isSelected ? Theme.onAccent : Theme.textPrimary) .padding(.horizontal, Spacing.m) @@ -99,7 +100,7 @@ private struct ProfileMenu: View { Button("Editar perfil…") { model.edit(profile) } Button("Trocar de perfil") { model.showProfiles() } Divider() - SettingsLink { Text("Ajustes…") } + Button("Ajustes…") { model.navigate(to: .settings) } } label: { AvatarView(profile: profile, size: 36) .overlay(Circle().strokeBorder(Theme.divider, lineWidth: 1)) diff --git a/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift b/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift index d5a68e5..dd6c817 100644 --- a/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift +++ b/Sources/RetroXApp/Features/Emulators/EmulatorsView.swift @@ -3,53 +3,102 @@ import RetroXCore import SwiftUI /// Os emuladores como plugins: ativar, escolher a pasta raiz e ver o que foi encontrado nela. +/// Tudo alcançável pelo controle (↑ ↓ passa pelos botões, A ativa). struct EmulatorsView: View { @Environment(AppModel.self) private var model + @FocusState private var isFocused: Bool var body: some View { - VStack(alignment: .leading, spacing: 0) { - header - ScrollView { - VStack(alignment: .leading, spacing: Spacing.l) { - ForEach(model.plugins.entries) { entry in - PluginCard(entry: entry) - } - ForEach(PluginCatalog.upcoming) { upcoming in - UpcomingCard(upcoming: upcoming) + VStack(spacing: 0) { + ScrollViewReader { scroll in + ScrollView { + VStack(alignment: .leading, spacing: Spacing.l) { + VStack(alignment: .leading, spacing: Spacing.s) { + Text("Emuladores") + .font(Typography.display) + .foregroundStyle(Theme.textPrimary) + Text("Ative os emuladores instalados neste Mac e diga onde eles estão. O RetroX só lê essas pastas: nada é copiado, movido ou alterado.") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + .frame(maxWidth: 600, alignment: .leading) + .fixedSize(horizontal: false, vertical: true) + } + ForEach(model.plugins.entries) { entry in + PluginCard(entry: entry) + } + if !model.plugins.otherEmulators.isEmpty { + OtherEmulators() + } } + .frame(maxWidth: 880, alignment: .leading) + .padding(.horizontal, Spacing.xxl) + .padding(.top, Spacing.m) + .padding(.bottom, Spacing.xxl) + .frame(maxWidth: .infinity, alignment: .leading) + } + .onChange(of: model.emulatorsFocus) { _, index in + let controls = model.emulatorControls + guard controls.indices.contains(index) else { return } + withAnimation(Motion.focus) { scroll.scrollTo(controls[index].id, anchor: .center) } } - .frame(maxWidth: 760, alignment: .leading) - .padding(.horizontal, Spacing.xxl) - .padding(.bottom, Spacing.xxl) - // Mesma margem esquerda da tela inicial, em vez de uma coluna centralizada. - .frame(maxWidth: .infinity, alignment: .leading) } + HintBar(items: [ + .init(actions: [.up, .down], key: "↑ ↓", label: String(localized: "Navegar")), + .init(action: .confirm, key: "↩", label: String(localized: "Escolher")), + .init(action: .back, key: "Esc", label: String(localized: "Voltar")), + ], showsMenu: false) + } + .focusable() + .focusEffectDisabled() + .focused($isFocused) + .onAppear { isFocused = true } + .onKeyPress(phases: [.down, .repeat]) { press in + guard !press.modifiers.contains(.command), let action = KeyMapping.action(for: press) else { return .ignored } + model.handle(action) + return .handled } - .frame(maxWidth: .infinity, alignment: .leading) } +} - private var header: some View { - VStack(alignment: .leading, spacing: Spacing.s) { - Button { - model.screen = .home - } label: { - Label("Início", systemImage: "chevron.left") +extension View { + /// Anel de foco para controles alcançados pelo teclado ou controle de jogo. + func controllerFocus(_ isFocused: Bool, radius: CGFloat = 26) -> some View { + overlay { + RoundedRectangle.rx(radius) + .strokeBorder(Theme.accent, lineWidth: 2.5) + .padding(-5) + .opacity(isFocused ? 1 : 0) + } + .scaleEffect(isFocused && Motion.settings.level == .full ? 1.03 : 1) + .animation(Motion.focus, value: isFocused) + } +} + +/// Ícone do app instalado (o mesmo que o Finder mostra), ou um selo genérico. +struct EmulatorIcon: View { + let appURL: URL? + var fallbackSystem: GameSystemID? + var size: CGFloat = 64 + + var body: some View { + Group { + if let appURL { + Image(nsImage: NSWorkspace.shared.icon(forFile: appURL.path(percentEncoded: false))) + .resizable() + .interpolation(.high) + .aspectRatio(contentMode: .fit) + } else if let fallbackSystem { + SystemBadge(system: fallbackSystem, size: size * 0.86) + } else { + Image(systemName: "puzzlepiece.extension") + .font(.system(size: size * 0.36, weight: .semibold)) + .foregroundStyle(Theme.textSecondary) + .frame(width: size * 0.86, height: size * 0.86) + .background(Theme.raised, in: RoundedRectangle.rx(Radius.l)) } - .buttonStyle(SecondaryButtonStyle()) - .keyboardShortcut(.cancelAction) - Text("Emuladores") - .font(Typography.display) - .foregroundStyle(Theme.textPrimary) - .padding(.top, Spacing.m) - Text("Ative os emuladores instalados neste Mac e diga onde eles estão. O RetroX só lê essas pastas: nada é copiado, movido ou alterado.") - .font(Typography.body) - .foregroundStyle(Theme.textSecondary) - .frame(maxWidth: 560, alignment: .leading) - .fixedSize(horizontal: false, vertical: true) } - .padding(.leading, Spacing.xxl) - .padding(.top, 56) - .padding(.bottom, Spacing.l) + .frame(width: size, height: size) + .accessibilityHidden(true) } } @@ -58,16 +107,28 @@ private struct PluginCard: View { @Environment(AppModel.self) private var model var body: some View { - VStack(alignment: .leading, spacing: Spacing.m) { + let id = entry.id.rawValue + VStack(alignment: .leading, spacing: Spacing.l) { HStack(alignment: .center, spacing: Spacing.m) { - SystemBadge(system: entry.plugin.systems.first ?? .ps2) + EmulatorIcon(appURL: entry.discovery?.app?.bundleURL, fallbackSystem: entry.plugin.systems.first, size: 72) VStack(alignment: .leading, spacing: Spacing.xs) { - Text(entry.plugin.displayName) - .font(Typography.heading) - .foregroundStyle(Theme.textPrimary) + HStack(spacing: Spacing.s) { + Text(entry.plugin.displayName) + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + if let version = entry.discovery?.app?.version { + Text(version) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + .padding(.horizontal, Spacing.s) + .padding(.vertical, Spacing.xxs) + .background(Theme.raised, in: Capsule()) + } + } Text(entry.plugin.summary) .font(Typography.caption) .foregroundStyle(Theme.textSecondary) + StatusPill(entry: entry) } Spacer() Toggle("Ativado", isOn: Binding( @@ -75,12 +136,16 @@ private struct PluginCard: View { set: { isEnabled in Task { await model.setPlugin(entry.id, enabled: isEnabled) } } )) .toggleStyle(.switch) - .font(Typography.body) + .labelsHidden() + .tint(Theme.accent) + .padding(Spacing.xs) + .controllerFocus(model.isFocused(emulatorControl: "\(id).toggle")) + .id("\(id).toggle") + .accessibilityLabel("Ativar \(entry.plugin.displayName)") } if entry.config.isEnabled { - Theme.divider.frame(height: 1) - rootFolder + RootFolderRow(entry: entry) if entry.isDiscovering { HStack(spacing: Spacing.s) { ProgressView().controlSize(.small) @@ -88,18 +153,54 @@ private struct PluginCard: View { .font(Typography.body) .foregroundStyle(Theme.textSecondary) } + .transition(.opacity) } else if let discovery = entry.discovery { - DiscoveryReport(entry: entry, discovery: discovery) + DiscoverySummary(entry: entry, discovery: discovery) + .transition(.opacity.combined(with: .offset(y: 8))) } } } .padding(Spacing.l) - .background(Theme.surface, in: RoundedRectangle.rx(Radius.l)) + .background(Theme.surface, in: RoundedRectangle.rx(Radius.xl)) + .animation(Motion.screen, value: entry.config.isEnabled) + .animation(Motion.screen, value: entry.isDiscovering) } +} + +private struct StatusPill: View { + let entry: PluginsModel.Entry + + var body: some View { + let (text, symbol, isGood): (String, String, Bool) = { + if !entry.config.isEnabled { return (String(localized: "Desativado"), "pause.circle", false) } + if entry.config.rootPath == nil { return (String(localized: "Escolha a pasta"), "folder.badge.questionmark", false) } + if entry.isDiscovering { return (String(localized: "Procurando…"), "magnifyingglass", false) } + if entry.isReady { return (String(localized: "Pronto"), "checkmark.circle.fill", true) } + return (String(localized: "Precisa de atenção"), "exclamationmark.triangle.fill", false) + }() + Label(text, systemImage: symbol) + .font(Typography.caption) + .foregroundStyle(isGood ? Theme.onAccent : Theme.textPrimary) + .padding(.horizontal, Spacing.s + Spacing.xxs) + .padding(.vertical, Spacing.xs) + .background(isGood ? Theme.accent : Theme.raised, in: Capsule()) + .contentTransition(.opacity) + } +} - private var rootFolder: some View { +private struct RootFolderRow: View { + let entry: PluginsModel.Entry + @Environment(AppModel.self) private var model + + var body: some View { + let id = entry.id.rawValue HStack(alignment: .center, spacing: Spacing.m) { - VStack(alignment: .leading, spacing: Spacing.xs) { + Image(systemName: "folder.fill") + .font(.system(size: 20)) + .foregroundStyle(Theme.accent) + .frame(width: 40, height: 40) + .background(Theme.raised, in: RoundedRectangle.rx(Radius.m)) + VStack(alignment: .leading, spacing: Spacing.xxs) { Text("Pasta do emulador") .font(Typography.caption) .foregroundStyle(Theme.textSecondary) @@ -115,190 +216,231 @@ private struct PluginCard: View { Task { await model.chooseRoot(for: entry.id) } } .buttonStyle(SecondaryButtonStyle()) + .controllerFocus(model.isFocused(emulatorControl: "\(id).root")) + .id("\(id).root") } + .padding(Spacing.m) + .background(Theme.background.opacity(0.5), in: RoundedRectangle.rx(Radius.l)) } } -private struct DiscoveryReport: View { +/// Resumo em blocos (app, jogos, capas, BIOS), avisos, ações e os detalhes recolhíveis. +private struct DiscoverySummary: View { let entry: PluginsModel.Entry let discovery: PluginDiscovery @Environment(AppModel.self) private var model - private static let host = HostEnvironment.current() - var body: some View { - VStack(alignment: .leading, spacing: Spacing.s) { + let id = entry.id.rawValue + VStack(alignment: .leading, spacing: Spacing.m) { if discovery.issues.contains(.rootNotFound) { StatusLine(kind: .warning, text: PluginIssue.rootNotFound.message) } else { - appLine - gamesLines - coversLine - biosLine - if let controller = discovery.controller { - ControllerMapping(controller: controller, emulator: entry.plugin.displayName) - } - ForEach(Array(otherIssues.enumerated()), id: \.offset) { _, issue in - StatusLine(kind: .warning, text: issue.message) + HStack(spacing: Spacing.s) { + StatTile(symbol: "app.badge.checkmark", value: discovery.app == nil ? "—" : String(localized: "Encontrado"), + label: discovery.app.map(appDetail) ?? String(localized: "App não encontrado"), isGood: discovery.app != nil) + StatTile(symbol: "gamecontroller", value: "\(gameCount)", label: String(localized: "jogos"), isGood: gameCount > 0) + StatTile(symbol: "photo.on.rectangle", value: "\(coverCount)/\(gameCount)", label: String(localized: "com capa"), isGood: coverCount > 0) + StatTile(symbol: "cpu", value: biosValue, label: String(localized: "BIOS"), isGood: biosIsGood) } - if discovery.settingsFile != nil { - StatusLine(kind: .info, text: String(localized: "Lendo a configuração do \(entry.plugin.displayName) (só leitura).")) + ForEach(Array(warnings.enumerated()), id: \.offset) { _, warning in + StatusLine(kind: .warning, text: warning) } - } - HStack(spacing: Spacing.s) { - Button { - Task { await model.rediscover(entry.id) } - } label: { - Label("Procurar de novo", systemImage: "arrow.clockwise") + HStack(spacing: Spacing.s) { + Button { + Task { await model.rediscover(entry.id) } + } label: { + Label("Procurar de novo", systemImage: "arrow.clockwise") + } + .controllerFocus(model.isFocused(emulatorControl: "\(id).rediscover")) + .id("\(id).rediscover") + Button { + NSWorkspace.shared.activateFileViewerSelecting([discovery.root]) + } label: { + Label("Mostrar no Finder", systemImage: "folder") + } + .controllerFocus(model.isFocused(emulatorControl: "\(id).reveal")) + .id("\(id).reveal") } - Button { - NSWorkspace.shared.activateFileViewerSelecting([discovery.root]) + .buttonStyle(SecondaryButtonStyle()) + DisclosureGroup { + DetailsList(entry: entry, discovery: discovery) + .padding(.top, Spacing.s) } label: { - Label("Mostrar no Finder", systemImage: "folder") + Text("Pastas, BIOS e controle") + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.textPrimary) } } - .buttonStyle(SecondaryButtonStyle()) - .padding(.top, Spacing.s) } } - @ViewBuilder - private var appLine: some View { - if let app = discovery.app { - let architectures = app.architectures.map(\.description).sorted().joined(separator: ", ") - let viaRosetta = Self.host.compatibility(with: app.architectures) == .rosetta - StatusLine(kind: .ok, text: [ - "\(entry.plugin.displayName) \(app.version ?? "")", - architectures, - viaRosetta ? String(localized: "roda via Rosetta") : nil, - ].compactMap { $0?.isEmpty == false ? $0 : nil }.joined(separator: " · ")) - } else { - StatusLine(kind: .warning, text: String(localized: "O app do \(entry.plugin.displayName) não está nesta pasta nem numa subpasta dela.")) - } + private var gameCount: Int { model.library.gameCount(for: entry.id) } + + private var coverCount: Int { + model.library.games.filter { $0.pluginID == entry.id && $0.coverURL != nil }.count } - @ViewBuilder - private var gamesLines: some View { - if discovery.romDirectories.isEmpty { - StatusLine(kind: .warning, text: String(localized: "Nenhuma pasta de jogos. Crie uma pasta “roms” aqui ou configure a lista de jogos no próprio emulador.")) - } else { - let count = model.library.gameCount(for: entry.id) - StatusLine(kind: .ok, text: count == 1 ? String(localized: "1 jogo encontrado") : String(localized: "\(count) jogos encontrados")) - ForEach(discovery.romDirectories, id: \.self) { directory in - StatusLine(kind: .info, text: "\(abbreviated(directory.url)) · \(origin(directory.origin))") - .padding(.leading, Spacing.l) - } - } + private func appDetail(_ app: AppBundleInfo) -> String { + let architectures = app.architectures.map(\.description).sorted().joined(separator: ", ") + let viaRosetta = HostEnvironment.current().compatibility(with: app.architectures) == .rosetta + return viaRosetta ? String(localized: "\(architectures) · via Rosetta") : architectures } - @ViewBuilder - private var coversLine: some View { - if discovery.coverDirectories.isEmpty { - StatusLine(kind: .info, text: String(localized: "Capas são opcionais: crie uma pasta “covers” com imagens nomeadas como os jogos ou pelo serial do disco.")) - } else { - let withCover = model.library.games.filter { $0.pluginID == entry.id && $0.coverURL != nil }.count - StatusLine(kind: .ok, text: String(localized: "Capas para \(withCover) de \(model.library.gameCount(for: entry.id)) jogos")) - ForEach(discovery.coverDirectories, id: \.self) { directory in - let isInRoot = directory.standardizedFileURL.path(percentEncoded: false) - .hasPrefix(discovery.root.standardizedFileURL.path(percentEncoded: false)) - StatusLine(kind: .info, text: "\(abbreviated(directory)) · \(isInRoot ? String(localized: "na pasta do emulador") : String(localized: "capas do \(entry.plugin.displayName)"))") - .padding(.leading, Spacing.l) - } + private var biosValue: String { + switch discovery.bios { + case .configured: String(localized: "Configurada") + case .fileMissing: String(localized: "Ausente") + case .notConfigured: String(localized: "Falta") + case .unknown: "—" } } - @ViewBuilder - private var biosLine: some View { + private var biosIsGood: Bool { + if case .configured = discovery.bios { return true } + return false + } + + private var warnings: [String] { + var result: [String] = [] + if discovery.romDirectories.isEmpty { + result.append(String(localized: "Nenhuma pasta de jogos. Crie uma pasta “roms” aqui ou configure a lista de jogos no próprio emulador.")) + } switch discovery.bios { - case .configured(let name): - StatusLine(kind: .ok, text: String(localized: "BIOS configurada no emulador: \(name)")) - case .fileMissing(let name): - StatusLine(kind: .warning, text: String(localized: "A BIOS configurada no emulador (\(name)) não foi encontrada.")) - case .notConfigured: - StatusLine(kind: .warning, text: String(localized: "BIOS não configurada: abra o emulador e conclua a configuração inicial.")) - case .unknown: - StatusLine(kind: .info, text: String(localized: "Configuração do emulador não encontrada: ele pedirá a BIOS na primeira vez.")) + case .fileMissing(let name): result.append(String(localized: "A BIOS configurada no emulador (\(name)) não foi encontrada.")) + case .notConfigured: result.append(String(localized: "BIOS não configurada: abra o emulador e conclua a configuração inicial.")) + default: break + } + for issue in discovery.issues { + if case .settingsFolderMissing = issue { result.append(issue.message) } + } + return result + } +} + +private struct StatTile: View { + let symbol: String + let value: String + let label: String + let isGood: Bool + + var body: some View { + VStack(alignment: .leading, spacing: Spacing.xs) { + Image(systemName: symbol) + .font(.system(size: 16, weight: .semibold)) + .foregroundStyle(isGood ? Theme.accent : Theme.textSecondary) + Text(value) + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + .lineLimit(1) + .minimumScaleFactor(0.7) + Text(label) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + .lineLimit(2) } + .padding(Spacing.m) + .frame(maxWidth: .infinity, minHeight: 112, alignment: .topLeading) + .background(Theme.background.opacity(0.5), in: RoundedRectangle.rx(Radius.l)) + .accessibilityElement(children: .combine) } +} + +private struct DetailsList: View { + let entry: PluginsModel.Entry + let discovery: PluginDiscovery - private var otherIssues: [PluginIssue] { - discovery.issues.filter { - switch $0 { - case .settingsFolderMissing: true - default: false + var body: some View { + VStack(alignment: .leading, spacing: Spacing.s) { + ForEach(discovery.romDirectories, id: \.self) { directory in + StatusLine(kind: .info, text: "\(abbreviated(directory.url)) · \(origin(directory.origin))") + } + ForEach(discovery.coverDirectories, id: \.self) { directory in + let isInRoot = directory.standardizedFileURL.path(percentEncoded: false) + .hasPrefix(discovery.root.standardizedFileURL.path(percentEncoded: false)) + StatusLine(kind: .info, text: "\(abbreviated(directory)) · \(isInRoot ? String(localized: "capas na pasta do emulador") : String(localized: "capas do \(entry.plugin.displayName)"))") + } + if case .configured(let name) = discovery.bios { + StatusLine(kind: .ok, text: String(localized: "BIOS: \(name)")) + } + if discovery.settingsFile != nil { + StatusLine(kind: .info, text: String(localized: "Lendo a configuração do \(entry.plugin.displayName) (só leitura).")) + } + if let controller = discovery.controller { + ControllerMapping(controller: controller, emulator: entry.plugin.displayName) + .padding(.top, Spacing.s) } } } private func origin(_ origin: ROMDirectory.Origin) -> String { switch origin { - case .rootFolder: String(localized: "na pasta do emulador") + case .rootFolder: String(localized: "jogos na pasta do emulador") case .emulatorSettings: String(localized: "da lista de jogos do \(entry.plugin.displayName)") } } } -private struct UpcomingCard: View { - let upcoming: PluginCatalog.Upcoming +/// Emuladores reconhecidos sem plugin: o planejado (Dolphin) e os que já estão instalados neste Mac. +private struct OtherEmulators: View { + @Environment(AppModel.self) private var model var body: some View { - HStack(spacing: Spacing.m) { - Image(systemName: "puzzlepiece.extension") - .font(.system(size: 20, weight: .semibold)) - .foregroundStyle(Theme.textSecondary) - .frame(width: 48, height: 48) - .background(Theme.raised, in: RoundedRectangle.rx(Radius.m)) - .accessibilityHidden(true) - VStack(alignment: .leading, spacing: Spacing.xs) { - Text(upcoming.name) - .font(Typography.heading) - .foregroundStyle(Theme.textPrimary) - Text(upcoming.systems) - .font(Typography.caption) - .foregroundStyle(Theme.textSecondary) + VStack(alignment: .leading, spacing: Spacing.m) { + Text("Outros emuladores") + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + .padding(.top, Spacing.s) + LazyVGrid(columns: [GridItem(.flexible(), spacing: Spacing.m), GridItem(.flexible(), spacing: Spacing.m)], spacing: Spacing.m) { + ForEach(model.plugins.otherEmulators, id: \.0.id) { emulator, app in + HStack(spacing: Spacing.m) { + EmulatorIcon(appURL: app, size: 48) + .saturation(app == nil ? 0 : 1) + VStack(alignment: .leading, spacing: Spacing.xxs) { + Text(emulator.name) + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.textPrimary) + Text(emulator.systems) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + Spacer() + Text(app == nil ? String(localized: "Em breve") : String(localized: "Instalado · plugin em breve")) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + .multilineTextAlignment(.trailing) + } + .padding(Spacing.m) + .background(Theme.surface.opacity(0.7), in: RoundedRectangle.rx(Radius.l)) + .accessibilityElement(children: .combine) + } } - Spacer() - Text("Em breve") - .font(Typography.caption) - .foregroundStyle(Theme.textSecondary) - .padding(.horizontal, Spacing.s) - .padding(.vertical, Spacing.xs) - .background(Theme.raised, in: Capsule()) } - .padding(Spacing.l) - .background(Theme.surface.opacity(0.6), in: RoundedRectangle.rx(Radius.l)) - .accessibilityElement(children: .combine) } } -private func abbreviated(_ url: URL) -> String { - (url.path(percentEncoded: false).trimmingCharacters(in: CharacterSet(charactersIn: "/")).isEmpty - ? "/" : (url.path(percentEncoded: false) as NSString).abbreviatingWithTildeInPath) -} - /// O mapeamento do controle configurado no emulador, só para conferir (não é alterado aqui). private struct ControllerMapping: View { let controller: ControllerSummary let emulator: String var body: some View { - DisclosureGroup { - Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: Spacing.m, verticalSpacing: Spacing.xs) { + VStack(alignment: .leading, spacing: Spacing.s) { + StatusLine(kind: .ok, text: String(localized: "Controle no \(emulator): \(controller.type)\(controller.device.map { " · \($0)" } ?? "")")) + LazyVGrid(columns: [GridItem(.flexible(), spacing: Spacing.s), GridItem(.flexible(), spacing: Spacing.s)], alignment: .leading, spacing: Spacing.xs) { ForEach(controller.bindings, id: \.self) { binding in - GridRow { + HStack(spacing: Spacing.s) { Text(Self.ps2Name(binding.button)) .font(Typography.bodyEmphasis) .foregroundStyle(Theme.textPrimary) + .frame(width: 44, alignment: .leading) Text(Self.inputName(binding.input)) - .font(Typography.body) + .font(Typography.caption) .foregroundStyle(Theme.textSecondary) } } } - .padding(.top, Spacing.s) .padding(.leading, Spacing.l) - } label: { - StatusLine(kind: .ok, text: String(localized: "Controle no \(emulator): \(controller.type)\(controller.device.map { " · \($0)" } ?? "")")) } } @@ -340,3 +482,7 @@ private struct ControllerMapping: View { return names[name] ?? input } } + +private func abbreviated(_ url: URL) -> String { + (url.path(percentEncoded: false) as NSString).abbreviatingWithTildeInPath +} diff --git a/Sources/RetroXApp/Features/Home/HomeStyles.swift b/Sources/RetroXApp/Features/Home/HomeStyles.swift new file mode 100644 index 0000000..87cb511 --- /dev/null +++ b/Sources/RetroXApp/Features/Home/HomeStyles.swift @@ -0,0 +1,218 @@ +import RetroXCore +import SwiftUI + +/// Carrossel: a capa em foco grande no centro, as vizinhas menores e inclinadas, deslizando com mola. +/// O jogo em foco tem título e ações embaixo. Com animações reduzidas, as vizinhas não inclinam. +struct CarouselHome: View { + @Environment(AppModel.self) private var model + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + /// Quantas capas de cada lado do foco ficam visíveis. + static let reach = 4 + + var body: some View { + let library = model.library + let games = library.visibleGames + let focused = library.focusedIndex ?? 0 + let moves = Motion.allowsMovement(reduceMotion: reduceMotion) + VStack(spacing: Spacing.m) { + ShelfTabs() + .padding(.top, Spacing.s) + GeometryReader { proxy in + let coverWidth = min(260 * model.preferences.tileSize.scale, (proxy.size.height - Spacing.xxl) / CoverArtView.aspectRatio) + ZStack { + ForEach(Array(games.enumerated()), id: \.element.id) { index, game in + let distance = Double(index - focused) + if abs(distance) <= Double(Self.reach) { + CarouselCover(game: game, width: coverWidth, distance: distance, moves: moves) + .onTapGesture { + if index == focused { model.play(game) } else { withAnimation(Motion.focus) { library.focus(game) } } + } + .transition(.opacity) + } + } + } + .frame(width: proxy.size.width, height: proxy.size.height) + .animation(Motion.focus, value: focused) + .animation(Motion.focus, value: library.shelf) + } + if let game = library.focusedGame { + FocusedGameCaption(game: game, centered: true) + .id(game.id) + .transition(.opacity) + .animation(Motion.fade, value: game.id) + } + } + .padding(.bottom, Spacing.l) + .gesture(DragGesture(minimumDistance: 24).onEnded { value in + let steps = Int((-value.translation.width / 120).rounded()) + if steps != 0 { withAnimation(Motion.focus) { library.moveFocus(by: steps) } } + }) + } +} + +private struct CarouselCover: View { + let game: Game + let width: CGFloat + let distance: Double + let moves: Bool + @Environment(AppModel.self) private var model + + var body: some View { + let magnitude = min(abs(distance), 3) + let side: Double = distance == 0 ? 0 : (distance > 0 ? 1 : -1) + let isFocused = distance == 0 + VStack(spacing: 0) { + CoverArtView(game: game, width: width) + .overlay { + RoundedRectangle.rx(Radius.m + 6) + .strokeBorder(Theme.accent, lineWidth: 3) + .padding(-7) + .opacity(isFocused ? 1 : 0) + } + .shadow(color: isFocused ? Theme.accent.opacity(0.4) : .black.opacity(0.25), radius: isFocused ? 30 : 12, y: 14) + Reflection(game: game, width: width) + .opacity(isFocused ? 1 : 0.4) + } + .scaleEffect(1 - magnitude * 0.16) + .rotation3DEffect(.degrees(moves ? -side * 38 : 0), axis: (x: 0, y: 1, z: 0), perspective: 0.55) + .offset(x: distance * width * 0.58 + side * width * 0.24) + .opacity(abs(distance) >= Double(CarouselHome.reach) ? 0 : 1 - magnitude * 0.18) + .zIndex(-abs(distance)) + .accessibilityElement(children: .ignore) + .accessibilityLabel(GameAccessibility.label(game, isFavorite: model.library.isFavorite(game))) + .accessibilityAddTraits(isFocused ? [.isButton, .isSelected] : .isButton) + .accessibilityAction(named: "Jogar") { model.play(game) } + } +} + +/// Grade: o jogo em foco numa faixa no topo e todas as capas da prateleira embaixo. +struct GridHome: View { + @Environment(AppModel.self) private var model + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + var body: some View { + let library = model.library + let tileWidth = 120 * model.preferences.tileSize.scale + let focusedID = library.focusedGame?.id + VStack(alignment: .leading, spacing: Spacing.m) { + if let game = library.focusedGame { + FocusedGameCaption(game: game, centered: false) + .padding(.horizontal, Spacing.xxl) + .id(game.id) + .transition(.opacity) + .animation(Motion.fade, value: game.id) + } + ShelfTabs() + GeometryReader { proxy in + let spacing = Spacing.m + Spacing.xs + let columns = max(1, Int((proxy.size.width - 2 * Spacing.xxl + spacing) / (tileWidth + spacing))) + ScrollViewReader { scroll in + ScrollView { + LazyVGrid( + columns: Array(repeating: GridItem(.fixed(tileWidth), spacing: spacing), count: columns), + alignment: .leading, + spacing: spacing + ) { + ForEach(library.visibleGames) { game in + HomeGridTile(game: game, width: tileWidth, isFocused: game.id == focusedID) + .id(game.id) + } + } + .padding(.horizontal, Spacing.xxl) + .padding(.vertical, Spacing.m) + } + .onChange(of: columns, initial: true) { _, value in library.homeColumns = value } + .onChange(of: library.focusedGameID) { _, id in + guard let id else { return } + withAnimation(Motion.animation(reduceMotion: reduceMotion)) { scroll.scrollTo(id) } + } + } + } + } + .padding(.top, Spacing.s) + } +} + +private struct HomeGridTile: View { + let game: Game + let width: CGFloat + let isFocused: Bool + @Environment(AppModel.self) private var model + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + var body: some View { + let isHovered = model.browser.hoveredGameID == game.id + let lifts = Motion.allowsMovement(reduceMotion: reduceMotion) && (isFocused || isHovered) + CoverArtView(game: game, width: width) + .overlay { + RoundedRectangle.rx(Radius.m + 4) + .strokeBorder(Theme.accent, lineWidth: 3) + .padding(-5) + .opacity(isFocused ? 1 : 0) + } + .shadow(color: isFocused ? Theme.accent.opacity(0.35) : .black.opacity(isHovered ? 0.22 : 0.12), + radius: isFocused ? 16 : 6, y: 6) + .scaleEffect(lifts ? 1.04 : 1) + .animation(Motion.focus, value: isFocused) + .animation(Motion.hover, value: isHovered) + .onHover { inside in + model.browser.hoveredGameID = inside ? game.id : (model.browser.hoveredGameID == game.id ? nil : model.browser.hoveredGameID) + } + .onTapGesture { withAnimation(Motion.focus) { model.library.focus(game) } } + .simultaneousGesture(TapGesture(count: 2).onEnded { model.play(game) }) + .contextMenu { GameContextMenu(game: game) } + .accessibilityElement(children: .ignore) + .accessibilityLabel(GameAccessibility.label(game, isFavorite: model.library.isFavorite(game))) + .accessibilityAddTraits(isFocused ? [.isButton, .isSelected] : .isButton) + .accessibilityAction(named: "Jogar") { model.play(game) } + } +} + +/// Título, metadados e ações do jogo em foco (carrossel e grade). +private struct FocusedGameCaption: View { + let game: Game + let centered: Bool + @Environment(AppModel.self) private var model + + var body: some View { + let history = model.library.history(for: game) + let stack = VStack(alignment: centered ? .center : .leading, spacing: Spacing.s) { + Text(game.title) + .font(Typography.heading) + .foregroundStyle(Theme.textPrimary) + .lineLimit(1) + Text(GameText.metadata(game: game, history: history)) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + } + HStack(spacing: Spacing.m) { + if centered { Spacer() } + stack + if !centered { Spacer() } + HStack(spacing: Spacing.s) { + Button { + model.play(game) + } label: { + Label("Jogar", systemImage: "play.fill") + } + .buttonStyle(PrimaryButtonStyle()) + Button { + model.library.toggleFavorite(game) + } label: { + Image(systemName: history.isFavorite ? "star.fill" : "star") + } + .buttonStyle(IconButtonStyle(isActive: history.isFavorite)) + .accessibilityLabel(history.isFavorite ? "Remover dos favoritos" : "Favoritar") + Button { + model.showDetails(game) + } label: { + Image(systemName: "info") + } + .buttonStyle(IconButtonStyle()) + .accessibilityLabel("Detalhes") + } + if centered { Spacer() } + } + } +} diff --git a/Sources/RetroXApp/Features/Home/HomeView.swift b/Sources/RetroXApp/Features/Home/HomeView.swift index c09ea7c..d0ce5c4 100644 --- a/Sources/RetroXApp/Features/Home/HomeView.swift +++ b/Sources/RetroXApp/Features/Home/HomeView.swift @@ -9,7 +9,6 @@ struct HomeView: View { var body: some View { VStack(spacing: 0) { - TopBar() content HintBar(items: [ .init(action: .confirm, key: "↩", label: String(localized: "Jogar")), @@ -42,9 +41,16 @@ struct HomeView: View { } else if library.games.isEmpty { EmptyHome(kind: .noGames) } else { - StageView() - .frame(maxWidth: .infinity, maxHeight: .infinity) - ShelfView() + switch model.preferences.homeStyle { + case .shelf: + StageView() + .frame(maxWidth: .infinity, maxHeight: .infinity) + ShelfView() + case .carousel: + CarouselHome() + case .grid: + GridHome() + } } } } @@ -63,6 +69,8 @@ enum KeyMapping { default: break } switch press.characters.lowercased() { + case "[": return .previousTab + case "]": return .nextTab case "f": return .favorite case "q": return .previousShelf case "e": return .nextShelf @@ -92,7 +100,7 @@ private struct StageView: View { } .padding(.horizontal, Spacing.xxl) .id(game.id) - .transition(.opacity.combined(with: .offset(x: reduceMotion ? 0 : 12))) + .transition(.opacity.combined(with: .offset(x: Motion.allowsMovement(reduceMotion: reduceMotion) ? 12 : 0))) } else { EmptyShelfMessage(shelf: model.library.shelf) .padding(.horizontal, Spacing.xxl) @@ -224,7 +232,7 @@ struct EmptyHome: View { .fixedSize(horizontal: false, vertical: true) if kind != .loading { Button(kind == .noEmulator ? "Ativar emuladores" : "Abrir Emuladores") { - model.screen = .emulators + model.navigate(to: .emulators) } .buttonStyle(PrimaryButtonStyle()) .padding(.top, Spacing.s) @@ -287,7 +295,7 @@ struct HintBar: View { } Spacer() if showsMenu { - CommandHint(glyphs: glyphs[.menu].map { [$0] }, key: "M", label: String(localized: "Emuladores")) + CommandHint(glyphs: glyphs[.menu].map { [$0] }, key: "M", label: String(localized: "Ajustes")) } } .padding(.horizontal, Spacing.xxl) diff --git a/Sources/RetroXApp/Features/Home/ShelfView.swift b/Sources/RetroXApp/Features/Home/ShelfView.swift index 5a64700..1cb6fef 100644 --- a/Sources/RetroXApp/Features/Home/ShelfView.swift +++ b/Sources/RetroXApp/Features/Home/ShelfView.swift @@ -7,18 +7,19 @@ struct ShelfView: View { @Environment(AppModel.self) private var model @Environment(\.accessibilityReduceMotion) private var reduceMotion - static let tileWidth: CGFloat = 128 + static let baseTileWidth: CGFloat = 128 static let reflectionHeight: CGFloat = 32 var body: some View { let library = model.library + let tileWidth = Self.baseTileWidth * model.preferences.tileSize.scale VStack(alignment: .leading, spacing: Spacing.s) { ShelfTabs() ScrollViewReader { proxy in ScrollView(.horizontal, showsIndicators: false) { LazyHStack(alignment: .bottom, spacing: Spacing.l) { ForEach(library.visibleGames) { game in - ShelfTile(game: game, isFocused: game.id == library.focusedGame?.id) + ShelfTile(game: game, width: tileWidth, isFocused: game.id == library.focusedGame?.id) .id(game.id) } } @@ -26,7 +27,7 @@ struct ShelfView: View { .padding(.top, Spacing.xl) } .scrollClipDisabled() - .frame(height: Self.tileWidth * CoverArtView.aspectRatio + Self.reflectionHeight + Spacing.xl + Spacing.s) + .frame(height: tileWidth * CoverArtView.aspectRatio + Self.reflectionHeight + Spacing.xl + Spacing.s) .background(alignment: .bottom) { ShelfFloor() } .onChange(of: library.focusedGameID) { _, id in guard let id else { return } @@ -40,7 +41,7 @@ struct ShelfView: View { } } -private struct ShelfTabs: View { +struct ShelfTabs: View { @Environment(AppModel.self) private var model @Namespace private var underline @@ -86,15 +87,16 @@ private struct ShelfTabs: View { private struct ShelfTile: View { let game: Game + let width: CGFloat let isFocused: Bool @Environment(AppModel.self) private var model @Environment(\.accessibilityReduceMotion) private var reduceMotion var body: some View { let isHovered = model.browser.hoveredGameID == game.id && !isFocused - let lifts = !reduceMotion && (isFocused || isHovered) + let lifts = Motion.allowsMovement(reduceMotion: reduceMotion) && (isFocused || isHovered) VStack(spacing: 0) { - CoverArtView(game: game, width: ShelfView.tileWidth) + CoverArtView(game: game, width: width) .overlay { RoundedRectangle.rx(Radius.m + 5) .strokeBorder(Theme.accent, lineWidth: 3) @@ -108,7 +110,7 @@ private struct ShelfTile: View { ) .scaleEffect(lifts ? (isFocused ? 1.1 : 1.04) : 1, anchor: .bottom) .offset(y: lifts ? (isFocused ? -6 : -2) : 0) - Reflection(game: game) + Reflection(game: game, width: width) .opacity(isFocused ? 1 : 0) } .animation(Motion.animation(reduceMotion: reduceMotion), value: isFocused) @@ -135,11 +137,12 @@ private struct ShelfTile: View { } /// O pé da capa espelhado e esmaecido, como num piso brilhante. -private struct Reflection: View { +struct Reflection: View { let game: Game + var width: CGFloat = ShelfView.baseTileWidth var body: some View { - CoverArtView(game: game, width: ShelfView.tileWidth) + CoverArtView(game: game, width: width) .scaleEffect(x: 1, y: -1) .frame(height: ShelfView.reflectionHeight, alignment: .top) .clipped() diff --git a/Sources/RetroXApp/Features/Library/LibraryView.swift b/Sources/RetroXApp/Features/Library/LibraryView.swift index 720318f..e679495 100644 --- a/Sources/RetroXApp/Features/Library/LibraryView.swift +++ b/Sources/RetroXApp/Features/Library/LibraryView.swift @@ -10,7 +10,6 @@ struct LibraryView: View { var body: some View { VStack(spacing: 0) { - TopBar() LibraryToolbar(isSearchFocused: $isSearchFocused) content HintBar(items: [ @@ -265,7 +264,7 @@ private struct GridTile: View { VStack(alignment: .leading, spacing: Spacing.s) { CoverArtView(game: game, width: layout.tileWidth) .overlay(alignment: .topTrailing) { - if isFavorite { + if isFavorite && model.preferences.showsFavoriteBadge { Image(systemName: "star.fill") .font(.system(size: 11, weight: .bold)) .foregroundStyle(Theme.onAccent) @@ -286,7 +285,7 @@ private struct GridTile: View { radius: isFocused ? 16 : (isHovered ? 12 : 5), y: isFocused || isHovered ? 8 : 3 ) - .scaleEffect(!reduceMotion && (isFocused || isHovered) ? 1.03 : 1) + .scaleEffect(Motion.allowsMovement(reduceMotion: reduceMotion) && (isFocused || isHovered) ? 1.03 : 1) if layout == .titledCovers { VStack(alignment: .leading, spacing: Spacing.xxs) { Text(game.title) diff --git a/Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift b/Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift index 5f46d04..39ef9ad 100644 --- a/Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift +++ b/Sources/RetroXApp/Features/Profiles/ProfileEditorView.swift @@ -126,6 +126,7 @@ struct ThemeGallery: View { @Binding var selection: ThemeID @Binding var accent: Palette.Accent var columns = 4 + var showsAccents = true var body: some View { VStack(alignment: .leading, spacing: Spacing.m) { @@ -135,7 +136,7 @@ struct ThemeGallery: View { .onTapGesture { withAnimation(Motion.focus) { selection = theme } } } } - if selection == .retrox { + if selection == .retrox && showsAccents { HStack(spacing: Spacing.m) { Text("Acento") .font(Typography.caption) diff --git a/Sources/RetroXApp/Features/Profiles/ProfilePickerView.swift b/Sources/RetroXApp/Features/Profiles/ProfilePickerView.swift index ba337cb..55e10a2 100644 --- a/Sources/RetroXApp/Features/Profiles/ProfilePickerView.swift +++ b/Sources/RetroXApp/Features/Profiles/ProfilePickerView.swift @@ -66,7 +66,7 @@ private struct ProfileTile: View { .opacity(isFocused ? 1 : 0) } .shadow(color: isFocused ? Theme.accent.opacity(0.4) : .black.opacity(0.12), radius: isFocused ? 24 : 8, y: isFocused ? 10 : 4) - .scaleEffect(isFocused && !reduceMotion ? 1.08 : 1) + .scaleEffect(isFocused && Motion.allowsMovement(reduceMotion: reduceMotion) ? 1.08 : 1) Text(profile.name) .font(Typography.heading) .foregroundStyle(isFocused ? Theme.textPrimary : Theme.textSecondary) @@ -111,7 +111,7 @@ private struct AddProfileTile: View { .padding(-8) .opacity(isFocused ? 1 : 0) } - .scaleEffect(isFocused && !reduceMotion ? 1.08 : 1) + .scaleEffect(isFocused && Motion.allowsMovement(reduceMotion: reduceMotion) ? 1.08 : 1) Text("Adicionar") .font(Typography.heading) .foregroundStyle(isFocused ? Theme.textPrimary : Theme.textSecondary) diff --git a/Sources/RetroXApp/Features/Settings/SettingsCatalog.swift b/Sources/RetroXApp/Features/Settings/SettingsCatalog.swift new file mode 100644 index 0000000..16c55ab --- /dev/null +++ b/Sources/RetroXApp/Features/Settings/SettingsCatalog.swift @@ -0,0 +1,177 @@ +import AppKit +import RetroXCore + +enum SettingsSection: String, CaseIterable, Identifiable { + case appearance, home, library, text, controller, animations, about + + var id: Self { self } + + var title: String { + switch self { + case .appearance: String(localized: "Aparência") + case .home: String(localized: "Tela inicial") + case .library: String(localized: "Biblioteca") + case .text: String(localized: "Texto") + case .controller: String(localized: "Controle") + case .animations: String(localized: "Animações") + case .about: String(localized: "Sobre") + } + } + + var symbol: String { + switch self { + case .appearance: "paintpalette" + case .home: "house" + case .library: "square.grid.2x2" + case .text: "textformat.size" + case .controller: "gamecontroller" + case .animations: "wand.and.stars" + case .about: "info.circle" + } + } +} + +/// Uma linha de ajuste. A mesma lista desenha a tela e responde ao controle (← → muda, A ativa). +struct SettingsRow: Identifiable { + enum Control { + case choice(options: [String], selected: Int, select: @MainActor (Int) -> Void) + case toggle(isOn: Bool, set: @MainActor (Bool) -> Void) + case action(label: String, run: @MainActor () -> Void) + case info(String) + } + + let id: String + let title: String + var detail: String? + let control: Control + + @MainActor + func step(by offset: Int) { + switch control { + case .choice(let options, let selected, let select): + select((selected + offset + options.count) % options.count) + case .toggle(let isOn, let set): + set(!isOn) + case .action, .info: + break + } + } + + @MainActor + func activate() { + switch control { + case .choice: step(by: 1) + case .toggle(let isOn, let set): set(!isOn) + case .action(_, let run): run() + case .info: break + } + } +} + +extension AppModel { + var settingsRows: [SettingsRow] { rows(for: settingsSection) } + + func rows(for section: SettingsSection) -> [SettingsRow] { + let preferences = self.preferences + switch section { + case .appearance: + guard let profile = profiles.current else { return [] } + var rows = [ + choice("theme", String(localized: "Tema"), ThemeID.allCases, profile.theme, \.title) { self.setTheme($0) }, + ] + if profile.theme == .retrox { + rows.append(choice("accent", String(localized: "Acento"), Palette.Accent.allCases, profile.accent, \.title) { self.setTheme(accent: $0) }) + } + rows.append(choice("appearance", String(localized: "Modo"), AppearancePreference.allCases, profile.appearance, \.title) { + self.setTheme(appearance: $0) + }) + rows.append(toggle("ambient", String(localized: "Fundo ambiente"), + detail: String(localized: "A capa do jogo em foco, desfocada, atrás da tela."), + preferences.ambientBackground) { value in self.updatePreferences { $0.ambientBackground = value } }) + return rows + case .home: + return [ + choice("homeStyle", String(localized: "Visualização"), ProfilePreferences.HomeStyle.allCases, preferences.homeStyle, \.title) { value in + self.updatePreferences { $0.homeStyle = value } + }, + choice("tileSize", String(localized: "Tamanho das capas"), ProfilePreferences.TileSize.allCases, preferences.tileSize, \.title) { value in + self.updatePreferences { $0.tileSize = value } + }, + choice("startShelf", String(localized: "Prateleira ao abrir"), ProfilePreferences.StartShelf.allCases, preferences.startShelf, \.title) { value in + self.updatePreferences { $0.startShelf = value } + }, + toggle("clock", String(localized: "Relógio na barra"), preferences.showsClock) { value in self.updatePreferences { $0.showsClock = value } }, + toggle("favoriteBadge", String(localized: "Estrela nos favoritos"), preferences.showsFavoriteBadge) { value in + self.updatePreferences { $0.showsFavoriteBadge = value } + }, + ] + case .library: + return [ + choice("libraryLayout", String(localized: "Visualização padrão"), LibraryBrowser.Layout.allCases, browser.layout, \.title) { + self.browser.setLayout($0) + }, + choice("librarySort", String(localized: "Ordem padrão"), LibraryBrowser.Sort.allCases, browser.sort, \.title) { + self.browser.setSort($0) + }, + ] + case .text: + return [ + choice("font", String(localized: "Fonte"), ProfilePreferences.FontStyle.allCases, preferences.fontStyle, \.title) { value in + self.updatePreferences { $0.fontStyle = value } + }, + choice("textSize", String(localized: "Tamanho do texto"), ProfilePreferences.TextSize.allCases, preferences.textSize, \.title) { value in + self.updatePreferences { $0.textSize = value } + }, + ] + case .controller: + return [ + choice("preset", String(localized: "Tipo de controle"), ControllerPreset.allCases, input.preset, \.title) { self.input.setPreset($0) }, + toggle("swap", String(localized: "Inverter confirmar e voltar"), + detail: String(localized: input.confirmsWithEastButton ? "Agora: confirma com o botão da direita." : "Agora: confirma com o botão de baixo."), + input.swapsConfirmAndBack) { self.input.setSwapsConfirmAndBack($0) }, + choice("repeat", String(localized: "Repetição ao segurar"), RepeatSpeed.allCases, input.repeatSpeed, \.title) { self.input.setRepeatSpeed($0) }, + choice("hints", String(localized: "Dicas de botões"), HintsMode.allCases, input.hintsMode, \.title) { self.input.setHintsMode($0) }, + ] + case .animations: + return [ + choice("animationLevel", String(localized: "Animações"), ProfilePreferences.AnimationLevel.allCases, preferences.animationLevel, \.title) { value in + self.updatePreferences { $0.animationLevel = value } + }, + choice("animationSpeed", String(localized: "Velocidade"), ProfilePreferences.AnimationSpeed.allCases, preferences.animationSpeed, \.title) { value in + self.updatePreferences { $0.animationSpeed = value } + }, + toggle("startup", String(localized: "Animação de abertura"), preferences.startupAnimation) { value in + self.updatePreferences { $0.startupAnimation = value } + }, + ] + case .about: + let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "dev" + return [ + SettingsRow(id: "version", title: String(localized: "Versão"), control: .info("RetroX \(version)")), + SettingsRow(id: "emulators", title: String(localized: "Emuladores ativos"), + control: .info(plugins.entries.filter(\.config.isEnabled).map(\.plugin.displayName).joined(separator: ", ").nilIfEmpty + ?? String(localized: "Nenhum"))), + SettingsRow(id: "data", title: String(localized: "Dados do RetroX"), detail: String(localized: "Perfis, favoritos, capas próprias e configuração dos emuladores."), + control: .action(label: String(localized: "Mostrar no Finder")) { + NSWorkspace.shared.activateFileViewerSelecting([RetroXDirectories.applicationSupport]) + }), + SettingsRow(id: "profiles", title: String(localized: "Perfis"), control: .action(label: String(localized: "Trocar de perfil")) { self.showProfiles() }), + ] + } + } + + private func choice( + _ id: String, _ title: String, _ options: [Value], _ selected: Value, _ name: KeyPath, + select: @escaping @MainActor (Value) -> Void + ) -> SettingsRow { + SettingsRow(id: id, title: title, control: .choice( + options: options.map { $0[keyPath: name] }, + selected: options.firstIndex(of: selected) ?? 0, + select: { select(options[$0]) } + )) + } + + private func toggle(_ id: String, _ title: String, detail: String? = nil, _ isOn: Bool, set: @escaping @MainActor (Bool) -> Void) -> SettingsRow { + SettingsRow(id: id, title: title, detail: detail, control: .toggle(isOn: isOn, set: set)) + } +} diff --git a/Sources/RetroXApp/Features/Settings/SettingsView.swift b/Sources/RetroXApp/Features/Settings/SettingsView.swift index e696eec..fb42302 100644 --- a/Sources/RetroXApp/Features/Settings/SettingsView.swift +++ b/Sources/RetroXApp/Features/Settings/SettingsView.swift @@ -1,124 +1,311 @@ import RetroXCore import SwiftUI -struct SettingsView: View { +/// Ajustes dentro da janela, como num console: seções à esquerda, opções à direita, tudo pelo controle. +struct SettingsScreen: View { + @Environment(AppModel.self) private var model + @FocusState private var isFocused: Bool + var body: some View { - TabView { - AppearanceSettings() - .tabItem { Label("Aparência", systemImage: "paintpalette") } - ControllerSettings() - .tabItem { Label("Controle", systemImage: "gamecontroller") } + VStack(spacing: 0) { + HStack(alignment: .top, spacing: Spacing.xl) { + SectionList() + .frame(width: 232) + ScrollView { + VStack(alignment: .leading, spacing: Spacing.s) { + Text(model.settingsSection.title) + .font(Typography.display) + .foregroundStyle(Theme.textPrimary) + .padding(.bottom, Spacing.s) + ForEach(Array(model.settingsRows.enumerated()), id: \.element.id) { index, row in + SettingsRowView(row: row, isFocused: model.showsListFocus && model.settingsRow == index) + .onTapGesture { model.settingsRow = index } + } + SectionExtras(section: model.settingsSection) + .padding(.top, Spacing.m) + } + .frame(maxWidth: 720, alignment: .leading) + .padding(.bottom, Spacing.xl) + .id(model.settingsSection) + .transition(.opacity.combined(with: .offset(y: 8))) + } + .scrollIndicators(.never) + } + .padding(.horizontal, Spacing.xxl) + .padding(.top, Spacing.m) + .animation(Motion.screen, value: model.settingsSection) + HintBar(items: [ + .init(actions: [.up, .down], key: "↑ ↓", label: String(localized: "Navegar")), + .init(actions: [.left, .right], key: "← →", label: String(localized: "Mudar")), + .init(action: .confirm, key: "↩", label: String(localized: "Escolher")), + .init(action: .back, key: "Esc", label: String(localized: "Voltar")), + ], showsMenu: false) + } + .focusable() + .focusEffectDisabled() + .focused($isFocused) + .onAppear { isFocused = true } + .onKeyPress(phases: [.down, .repeat]) { press in + guard !press.modifiers.contains(.command), let action = KeyMapping.action(for: press) else { return .ignored } + model.handle(action) + return .handled } - .frame(width: 600) } } -/// Tema e aparência do perfil atual. Cada perfil guarda os seus. -private struct AppearanceSettings: View { +private struct SectionList: View { @Environment(AppModel.self) private var model + @Namespace private var selection var body: some View { - VStack(alignment: .leading, spacing: Spacing.l) { - if let profile = model.profiles.current { - HStack(spacing: Spacing.s) { - AvatarView(profile: profile, size: 28) - Text("Tema do perfil \(profile.name)") + VStack(alignment: .leading, spacing: Spacing.xs) { + ForEach(SettingsSection.allCases) { section in + let isSelected = model.settingsSection == section + let isFocused = isSelected && model.settingsRow == nil && model.showsListFocus + Button { + withAnimation(Motion.focus) { + model.settingsSection = section + model.settingsRow = nil + } + } label: { + Label(section.title, systemImage: section.symbol) .font(Typography.bodyEmphasis) - .foregroundStyle(Theme.textPrimary) + .foregroundStyle(isSelected ? Theme.onAccent : Theme.textPrimary) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, Spacing.m) + .frame(height: 44) + .background { + if isSelected { + RoundedRectangle.rx(Radius.m).fill(Theme.accent) + .matchedGeometryEffect(id: "section", in: selection) + } + } + .overlay { + RoundedRectangle.rx(Radius.m + 4) + .strokeBorder(Theme.accent, lineWidth: 2) + .padding(-4) + .opacity(isFocused ? 1 : 0) + } + .contentShape(RoundedRectangle.rx(Radius.m)) } - ThemeGallery( - selection: Binding(get: { profile.theme }, set: { model.setTheme($0) }), - accent: Binding(get: { profile.accent }, set: { model.setTheme(accent: $0) }), - columns: 4 - ) - Picker("Aparência", selection: Binding(get: { profile.appearance }, set: { model.setTheme(appearance: $0) })) { - ForEach(AppearancePreference.allCases) { Text($0.title).tag($0) } + .buttonStyle(.plain) + .accessibilityAddTraits(isSelected ? .isSelected : []) + } + } + .padding(Spacing.s) + .background(Theme.surface, in: RoundedRectangle.rx(Radius.l)) + } +} + +struct SettingsRowView: View { + let row: SettingsRow + let isFocused: Bool + + var body: some View { + HStack(spacing: Spacing.m) { + VStack(alignment: .leading, spacing: Spacing.xxs) { + Text(row.title) + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.textPrimary) + if let detail = row.detail { + Text(detail) + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + .fixedSize(horizontal: false, vertical: true) } - .pickerStyle(.segmented) - .frame(maxWidth: 320) - } else { - Text("Escolha um perfil para mudar o tema.") - .font(Typography.body) - .foregroundStyle(Theme.textSecondary) } - Text("O RetroX segue os ajustes de Reduzir Movimento, Reduzir Transparência e Aumentar Contraste do macOS.") - .font(Typography.caption) + Spacer(minLength: Spacing.m) + control + } + .padding(.horizontal, Spacing.m) + .padding(.vertical, Spacing.s + Spacing.xs) + .frame(minHeight: 60) + .background(isFocused ? Theme.raised : Theme.surface, in: RoundedRectangle.rx(Radius.l)) + .overlay { + RoundedRectangle.rx(Radius.l) + .strokeBorder(Theme.accent, lineWidth: 2) + .opacity(isFocused ? 1 : 0) + } + .scaleEffect(isFocused && Motion.allowsMovement(reduceMotion: false) ? 1.01 : 1) + .animation(Motion.focus, value: isFocused) + .contentShape(RoundedRectangle.rx(Radius.l)) + } + + @ViewBuilder + private var control: some View { + switch row.control { + case .choice(let options, let selected, let select): + HStack(spacing: Spacing.xs) { + stepButton("chevron.left") { select((selected - 1 + options.count) % options.count) } + Text(options[selected]) + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.textPrimary) + .frame(minWidth: 168) + .contentTransition(.opacity) + .id(options[selected]) + .transition(.opacity) + stepButton("chevron.right") { select((selected + 1) % options.count) } + } + .padding(Spacing.xs) + .background(Theme.raised, in: Capsule()) + .animation(Motion.hover, value: selected) + .accessibilityElement(children: .ignore) + .accessibilityLabel("\(row.title): \(options[selected])") + .accessibilityAdjustableAction { direction in + switch direction { + case .increment: select((selected + 1) % options.count) + case .decrement: select((selected - 1 + options.count) % options.count) + @unknown default: break + } + } + case .toggle(let isOn, let set): + Toggle(row.title, isOn: Binding(get: { isOn }, set: set)) + .toggleStyle(.switch) + .labelsHidden() + .tint(Theme.accent) + case .action(let label, let run): + Button(label, action: run) + .buttonStyle(SecondaryButtonStyle(isCompact: true)) + case .info(let text): + Text(text) + .font(Typography.body) .foregroundStyle(Theme.textSecondary) + .textSelection(.enabled) } - .padding(Spacing.l) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.surface) + } + + private func stepButton(_ symbol: String, action: @escaping () -> Void) -> some View { + Button(action: action) { + Image(systemName: symbol) + .font(.system(size: 12, weight: .bold)) + .foregroundStyle(Theme.textSecondary) + .frame(width: 32, height: 32) + .background(Theme.surface, in: Circle()) + .contentShape(Circle()) + } + .buttonStyle(.plain) } } -/// Mini configurador: layout dos botões no RetroX e teste ao vivo. O mapeamento dentro do emulador -/// é mostrado em Emuladores e continua sendo mudado no próprio emulador (docs/spikes/0002). -private struct ControllerSettings: View { +/// Conteúdo visual de cada seção, além das linhas: galeria de temas, prévia do texto, mapa do controle. +private struct SectionExtras: View { + let section: SettingsSection @Environment(AppModel.self) private var model var body: some View { - let input = model.input - VStack(alignment: .leading, spacing: Spacing.l) { - if let name = input.controllerName { - StatusLine(kind: .ok, text: String(localized: "Controle conectado: \(name)")) - } else { - StatusLine(kind: .info, text: String(localized: "Nenhum controle conectado. Teclado e mouse funcionam em tudo.")) + switch section { + case .appearance: + if let profile = model.profiles.current { + VStack(alignment: .leading, spacing: Spacing.s) { + Text("Todos os temas") + .font(Typography.caption) + .foregroundStyle(Theme.textSecondary) + ThemeGallery( + selection: Binding(get: { profile.theme }, set: { model.setTheme($0) }), + accent: Binding(get: { profile.accent }, set: { model.setTheme(accent: $0) }), + columns: 4, + showsAccents: false + ) + } } - + case .text: VStack(alignment: .leading, spacing: Spacing.s) { - Text("Botão de confirmar") + Text("Prévia") .font(Typography.caption) .foregroundStyle(Theme.textSecondary) - Picker("Botão de confirmar", selection: Binding(get: { input.swapsConfirmAndBack }, set: { input.setSwapsConfirmAndBack($0) })) { - Text("Botão de baixo (A / ×)").tag(false) - Text("Botão da direita (estilo Nintendo)").tag(true) + VStack(alignment: .leading, spacing: Spacing.s) { + Text("Test Drive Unlimited") + .font(Typography.display) + Text("Corrida em mundo aberto · Jogado ontem · 4 GB") + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) } - .pickerStyle(.radioGroup) - .labelsHidden() + .foregroundStyle(Theme.textPrimary) + .padding(Spacing.l) + .frame(maxWidth: .infinity, alignment: .leading) + .background(Theme.surface, in: RoundedRectangle.rx(Radius.l)) } + case .controller: + ControllerMap() + default: + EmptyView() + } + } +} - VStack(alignment: .leading, spacing: Spacing.s) { - Text("Teste") +/// Mapa dos botões no RetroX conforme o tipo de controle, e o último botão apertado. +private struct ControllerMap: View { + @Environment(AppModel.self) private var model + + var body: some View { + let input = model.input + let preset = input.effectivePreset + let confirm: ControllerControl = input.confirmsWithEastButton ? .east : .south + let back: ControllerControl = input.confirmsWithEastButton ? .south : .east + let entries: [(ControllerControl, String)] = [ + (confirm, String(localized: "Confirmar / jogar")), (back, String(localized: "Voltar")), + (.west, String(localized: "Detalhes")), (.north, String(localized: "Favoritar")), + (.leftShoulder, String(localized: "Prateleira ou console anterior")), (.rightShoulder, String(localized: "Próxima prateleira ou console")), + (.leftTrigger, String(localized: "Aba anterior")), (.rightTrigger, String(localized: "Próxima aba")), + (.menu, String(localized: "Ajustes")), (.options, String(localized: "Emuladores")), + ] + VStack(alignment: .leading, spacing: Spacing.m) { + HStack(spacing: Spacing.s) { + Image(systemName: "gamecontroller.fill") + .foregroundStyle(input.controllerName == nil ? Theme.textSecondary : Theme.accent) + Text(input.controllerName.map { String(localized: "Conectado: \($0)") } ?? String(localized: "Nenhum controle conectado. Mostrando \(preset.title).")) + .font(Typography.body) + .foregroundStyle(Theme.textPrimary) + } + LazyVGrid(columns: [GridItem(.flexible(), spacing: Spacing.s), GridItem(.flexible(), spacing: Spacing.s)], spacing: Spacing.s) { + ForEach(entries, id: \.0) { control, label in + HStack(spacing: Spacing.s) { + Image(systemName: preset.glyph(for: control) ?? "circle") + .font(.system(size: 20, weight: .semibold)) + .foregroundStyle(Theme.textPrimary) + .frame(width: 32) + Text(label) + .font(Typography.body) + .foregroundStyle(Theme.textSecondary) + Spacer(minLength: 0) + } + .padding(Spacing.s + Spacing.xs) + .background(Theme.surface, in: RoundedRectangle.rx(Radius.m)) + } + } + HStack(spacing: Spacing.m) { + Text("Último botão") .font(Typography.caption) .foregroundStyle(Theme.textSecondary) - HStack(spacing: Spacing.m) { - Image(systemName: input.lastAction.flatMap { input.glyphs[$0] } ?? "gamecontroller") - .font(.system(size: 28, weight: .semibold)) - .foregroundStyle(input.lastAction == nil ? Theme.textSecondary : Theme.accent) - .frame(width: 56, height: 56) - .background(Theme.raised, in: RoundedRectangle.rx(Radius.m)) - .id(input.actionCount) - .transition(.scale(scale: 0.85).combined(with: .opacity)) - Text(input.lastAction.map(Self.describe) ?? String(localized: "Aperte um botão do controle para ver a ação no RetroX.")) - .font(Typography.body) - .foregroundStyle(Theme.textPrimary) - } - .animation(Motion.focus, value: input.actionCount) + Text(input.lastAction.map(Self.describe) ?? "—") + .font(Typography.bodyEmphasis) + .foregroundStyle(Theme.accent) + .id(input.actionCount) + .transition(.scale(scale: 0.85).combined(with: .opacity)) } - - Text("O mapeamento dos botões dentro do jogo é do emulador. Você pode conferir o do PCSX2 em Emuladores; para mudar, use Configurações > Controles no próprio PCSX2.") + .animation(Motion.focus, value: input.actionCount) + Text("O mapeamento dentro do jogo é do emulador: confira o do PCSX2 em Emuladores e mude no próprio PCSX2.") .font(Typography.caption) .foregroundStyle(Theme.textSecondary) - .fixedSize(horizontal: false, vertical: true) } - .padding(Spacing.l) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.surface) } static func describe(_ action: InputAction) -> String { switch action { - case .up: String(localized: "Para cima") - case .down: String(localized: "Para baixo") - case .left: String(localized: "Para a esquerda") - case .right: String(localized: "Para a direita") - case .confirm: String(localized: "Confirmar (jogar)") + case .up: String(localized: "Cima") + case .down: String(localized: "Baixo") + case .left: String(localized: "Esquerda") + case .right: String(localized: "Direita") + case .confirm: String(localized: "Confirmar") case .back: String(localized: "Voltar") case .details: String(localized: "Detalhes") case .favorite: String(localized: "Favoritar") case .previousShelf: String(localized: "Prateleira anterior") case .nextShelf: String(localized: "Próxima prateleira") - case .menu: String(localized: "Emuladores") + case .previousTab: String(localized: "Aba anterior") + case .nextTab: String(localized: "Próxima aba") + case .menu: String(localized: "Ajustes") + case .options: String(localized: "Emuladores") } } } diff --git a/Sources/RetroXApp/Input/InputCoordinator.swift b/Sources/RetroXApp/Input/InputCoordinator.swift index 10aa25f..9c42e0a 100644 --- a/Sources/RetroXApp/Input/InputCoordinator.swift +++ b/Sources/RetroXApp/Input/InputCoordinator.swift @@ -1,12 +1,64 @@ import GameController import Observation +import RetroXCore /// Ações semânticas da interface. Teclado e controle produzem as mesmas ações (ADR-0007). enum InputAction: Hashable, Sendable { case up, down, left, right case confirm, back, details, favorite case previousShelf, nextShelf + /// Gatilhos (LT/RT, L2/R2, ZL/ZR) e `[` `]`: trocam a aba de cima. + case previousTab, nextTab + /// Start / Options / +: Ajustes. case menu + /// View / Create / −: Emuladores. + case options +} + +/// Velocidade da repetição ao segurar uma direção. +enum RepeatSpeed: String, CaseIterable, Identifiable { + case slow, normal, fast + + var id: Self { self } + + var title: String { + switch self { + case .slow: String(localized: "Lenta") + case .normal: String(localized: "Normal") + case .fast: String(localized: "Rápida") + } + } + + var initialDelay: Duration { + switch self { + case .slow: .milliseconds(480) + case .normal: .milliseconds(380) + case .fast: .milliseconds(280) + } + } + + var interval: Duration { + switch self { + case .slow: .milliseconds(140) + case .normal: .milliseconds(90) + case .fast: .milliseconds(55) + } + } +} + +/// Quando mostrar glifos de controle na barra de comandos. +enum HintsMode: String, CaseIterable, Identifiable { + case automatic, keyboard, controller + + var id: Self { self } + + var title: String { + switch self { + case .automatic: String(localized: "Automático") + case .keyboard: String(localized: "Teclado") + case .controller: String(localized: "Controle") + } + } } /// Traduz o controle de jogo em `InputAction`, com repetição ao segurar uma direção. @@ -15,10 +67,13 @@ enum InputAction: Hashable, Sendable { @Observable final class InputCoordinator { private(set) var controllerName: String? - /// Símbolos SF do controle conectado para cada ação (ex.: "xmark.circle" num controle PlayStation). - private(set) var glyphs: [InputAction: String] = [:] - /// Layout estilo Nintendo: o botão da direita confirma e o de baixo volta. + /// Família detectada do controle conectado (para o preset automático). + private(set) var detectedPreset: ControllerPreset? + private(set) var preset: ControllerPreset + /// Inverte confirmar e voltar em relação ao preset. private(set) var swapsConfirmAndBack: Bool + private(set) var repeatSpeed: RepeatSpeed + private(set) var hintsMode: HintsMode /// Última ação recebida do controle e um contador, para o teste nos Ajustes. private(set) var lastAction: InputAction? private(set) var actionCount = 0 @@ -27,12 +82,14 @@ final class InputCoordinator { @ObservationIgnored private var heldDirection: InputAction? @ObservationIgnored private var repeatTask: Task? @ObservationIgnored private var observers: [NSObjectProtocol] = [] - - static let initialRepeatDelay: Duration = .milliseconds(400) - static let repeatInterval: Duration = .milliseconds(90) + @ObservationIgnored private var controllerGlyphs: [ControllerControl: String] = [:] + @ObservationIgnored private let defaults = UserDefaults.standard init() { + preset = UserDefaults.standard.string(forKey: "input.preset").flatMap(ControllerPreset.init(rawValue:)) ?? .automatic swapsConfirmAndBack = UserDefaults.standard.bool(forKey: "input.swapConfirmBack") + repeatSpeed = UserDefaults.standard.string(forKey: "input.repeatSpeed").flatMap(RepeatSpeed.init(rawValue:)) ?? .normal + hintsMode = UserDefaults.standard.string(forKey: "input.hints").flatMap(HintsMode.init(rawValue:)) ?? .automatic // Com o emulador na frente, o RetroX não deve receber nada do controle (é o default; fica explícito). GCController.shouldMonitorBackgroundEvents = false let center = NotificationCenter.default @@ -46,6 +103,82 @@ final class InputCoordinator { refreshCurrentController() } + // MARK: Ajustes + + func setPreset(_ preset: ControllerPreset) { + self.preset = preset + defaults.set(preset.rawValue, forKey: "input.preset") + refreshCurrentController() + } + + func setSwapsConfirmAndBack(_ swaps: Bool) { + swapsConfirmAndBack = swaps + defaults.set(swaps, forKey: "input.swapConfirmBack") + refreshCurrentController() + } + + func setRepeatSpeed(_ speed: RepeatSpeed) { + repeatSpeed = speed + defaults.set(speed.rawValue, forKey: "input.repeatSpeed") + } + + func setHintsMode(_ mode: HintsMode) { + hintsMode = mode + defaults.set(mode.rawValue, forKey: "input.hints") + } + + // MARK: Glifos + + /// O preset que vale agora: o escolhido, ou o detectado no automático. + var effectivePreset: ControllerPreset { + preset == .automatic ? (detectedPreset ?? .xbox) : preset + } + + /// Confirmar fica no botão da direita no layout Nintendo, ou quando o usuário inverte. + var confirmsWithEastButton: Bool { + effectivePreset.confirmsWithEastButton != swapsConfirmAndBack + } + + /// Mostrar glifos de controle (e não teclas) na barra de comandos. + var showsControllerGlyphs: Bool { + switch hintsMode { + case .automatic: controllerName != nil + case .keyboard: false + case .controller: true + } + } + + /// Símbolos SF para cada ação, conforme o preset (ou o próprio controle, no automático). + var glyphs: [InputAction: String] { + guard showsControllerGlyphs else { return [:] } + var result: [InputAction: String] = [:] + for (action, control) in controls { + let symbol = preset == .automatic + ? (controllerGlyphs[control] ?? effectivePreset.glyph(for: control)) + : preset.glyph(for: control) + result[action] = symbol + } + return result + } + + /// Qual controle físico dispara cada ação. + private var controls: [InputAction: ControllerControl] { + [ + .confirm: confirmsWithEastButton ? .east : .south, + .back: confirmsWithEastButton ? .south : .east, + .details: .west, + .favorite: .north, + .previousShelf: .leftShoulder, + .nextShelf: .rightShoulder, + .previousTab: .leftTrigger, + .nextTab: .rightTrigger, + .menu: .menu, + .options: .options, + ] + } + + // MARK: Controle + private func attach(_ controller: GCController) { guard let pad = controller.extendedGamepad else { return } // O GameController entrega os eventos na fila principal (handlerQueue padrão). @@ -55,20 +188,29 @@ final class InputCoordinator { pad.leftThumbstick.valueChangedHandler = { [weak self] _, x, y in MainActor.assumeIsolated { self?.hold(Self.direction(x: x, y: y, threshold: 0.6)) } } - let (south, east): (InputAction, InputAction) = swapsConfirmAndBack ? (.back, .confirm) : (.confirm, .back) - let buttons: [(GCControllerButtonInput?, InputAction)] = [ - (pad.buttonA, south), (pad.buttonB, east), (pad.buttonX, .details), (pad.buttonY, .favorite), - (pad.leftShoulder, .previousShelf), (pad.rightShoulder, .nextShelf), (pad.buttonMenu, .menu), + let east = confirmsWithEastButton + let buttons: [(GCControllerButtonInput?, ControllerControl, InputAction)] = [ + (pad.buttonA, .south, east ? .back : .confirm), + (pad.buttonB, .east, east ? .confirm : .back), + (pad.buttonX, .west, .details), + (pad.buttonY, .north, .favorite), + (pad.leftShoulder, .leftShoulder, .previousShelf), + (pad.rightShoulder, .rightShoulder, .nextShelf), + (pad.leftTrigger, .leftTrigger, .previousTab), + (pad.rightTrigger, .rightTrigger, .nextTab), + (pad.buttonMenu, .menu, .menu), + (pad.buttonOptions, .options, .options), ] - for (button, action) in buttons { + for (button, _, action) in buttons { button?.pressedChangedHandler = { [weak self] _, _, pressed in guard pressed else { return } MainActor.assumeIsolated { self?.send(action) } } } controllerName = controller.vendorName ?? String(localized: "Controle") - glyphs = Dictionary(uniqueKeysWithValues: buttons.compactMap { button, action in - button?.sfSymbolsName.map { (action, $0) } + detectedPreset = ControllerPreset.detect(productCategory: controller.productCategory) + controllerGlyphs = Dictionary(uniqueKeysWithValues: buttons.compactMap { button, control, _ in + button?.sfSymbolsName.map { (control, $0) } }) } @@ -78,16 +220,11 @@ final class InputCoordinator { attach(next) } else { controllerName = nil - glyphs = [:] + detectedPreset = nil + controllerGlyphs = [:] } } - func setSwapsConfirmAndBack(_ swaps: Bool) { - swapsConfirmAndBack = swaps - UserDefaults.standard.set(swaps, forKey: "input.swapConfirmBack") - refreshCurrentController() - } - private func send(_ action: InputAction) { lastAction = action actionCount += 1 @@ -101,11 +238,12 @@ final class InputCoordinator { repeatTask?.cancel() guard let direction else { return } send(direction) + let speed = repeatSpeed repeatTask = Task { [weak self] in - try? await Task.sleep(for: Self.initialRepeatDelay) + try? await Task.sleep(for: speed.initialDelay) while !Task.isCancelled { self?.send(direction) - try? await Task.sleep(for: Self.repeatInterval) + try? await Task.sleep(for: speed.interval) } } } diff --git a/Sources/RetroXApp/RetroXApp.swift b/Sources/RetroXApp/RetroXApp.swift index 21b7f63..21b1cdf 100644 --- a/Sources/RetroXApp/RetroXApp.swift +++ b/Sources/RetroXApp/RetroXApp.swift @@ -20,11 +20,21 @@ struct RetroXApp: App { } .windowStyle(.hiddenTitleBar) .defaultSize(width: 1240, height: 800) - - Settings { - SettingsRoot() - .environment(model) - .environment(model.covers) + .commands { + // Os Ajustes ficam dentro da janela, navegáveis pelo controle. + CommandGroup(replacing: .appSettings) { + Button("Ajustes…") { model.navigate(to: .settings) } + .keyboardShortcut(",") + } + CommandMenu("Ir") { + ForEach(Array(AppModel.Screen.tabs.enumerated()), id: \.element) { index, screen in + Button(screen.title) { model.navigate(to: screen) } + .keyboardShortcut(KeyEquivalent(Character("\(index + 1)"))) + } + Divider() + Button("Trocar de perfil") { model.showProfiles() } + .keyboardShortcut("p", modifiers: [.command, .shift]) + } } } } @@ -33,51 +43,89 @@ struct RootView: View { @Environment(AppModel.self) private var model var body: some View { - @Bindable var model = model ZStack { Theme.background .ignoresSafeArea() - Group { - switch model.screen { - case .profiles: ProfilePickerView() - case .home: HomeView() - case .library: LibraryView() - case .emulators: EmulatorsView() + if model.screen == .home || model.screen == .library { + AmbientBackdrop() + .transition(.opacity) + } + if model.screen == .profiles { + ProfilePickerView() + .transition(.zoom) + } else { + VStack(spacing: 0) { + TopBar() + ZStack { + screenContent + .id(model.screen) + .transition(.screen(direction: model.navigationDirection)) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .clipped() } + .transition(.zoom) + } + if let game = model.detailsGame { + ModalDim { model.showDetails(nil) } + .transition(.opacity) + .zIndex(10) + GameDetailsView(game: game) + .modalCard() + .transition(.modalCard) + .zIndex(11) + } + if let draft = model.editingProfile { + ModalDim { model.closeEditor() } + .transition(.opacity) + .zIndex(12) + ProfileEditorView(draft: draft) + .modalCard() + .transition(.modalCard) + .zIndex(13) } - .transition(.opacity) if model.session.isPresenting { SessionOverlay() .transition(.opacity) + .zIndex(20) + } + if model.splash != .done { + SplashView() + .transition(.opacity) + .zIndex(30) } } - // O tema é a identidade da árvore: trocar de tema redesenha tudo com as cores novas. - .id(model.themeSelection) + // Tema, fonte e animações formam a identidade da árvore: trocar redesenha tudo com os tokens novos. + .id(model.styleIdentity) .tint(Theme.accent) .preferredColorScheme(model.appearance.colorScheme) - .animation(Motion.fade, value: model.screen) + .animation(Motion.screen, value: model.screen) + .animation(Motion.screen, value: model.detailsGame?.id) + .animation(Motion.screen, value: model.editingProfile?.id) .animation(Motion.fade, value: model.session.isPresenting) - .sheet(item: $model.detailsGame) { game in - GameDetailsView(game: game) - .environment(model) - .environment(model.covers) - } - .sheet(item: $model.editingProfile) { draft in - ProfileEditorView(draft: draft) - .environment(model) - .environment(model.covers) - } .alert(model.notice ?? "", isPresented: Binding(get: { model.notice != nil }, set: { if !$0 { model.notice = nil } })) { Button("OK", role: .cancel) { model.notice = nil } } .frame(minWidth: 1024, minHeight: 680) .task { await model.start() } + .task { await model.runSplash() } .task { await DebugSnapshot.captureIfRequested() } .onChange(of: model.session.phase) { _, phase in announce(phase) } } + @ViewBuilder + private var screenContent: some View { + switch model.screen { + case .profiles: EmptyView() + case .home: HomeView() + case .library: LibraryView() + case .emulators: EmulatorsView() + case .settings: SettingsScreen() + } + } + private func announce(_ phase: SessionModel.Phase) { let message: String? = switch phase { case .running(let game, let emulator): String(localized: "\(game.title) aberto no \(emulator).") @@ -90,15 +138,3 @@ struct RootView: View { } } } - -/// Janela de Ajustes, com o mesmo tema e aparência do perfil atual. -private struct SettingsRoot: View { - @Environment(AppModel.self) private var model - - var body: some View { - SettingsView() - .id(model.themeSelection) - .tint(Theme.accent) - .preferredColorScheme(model.appearance.colorScheme) - } -} diff --git a/Sources/RetroXCore/Plugins/EmulatorPlugin.swift b/Sources/RetroXCore/Plugins/EmulatorPlugin.swift index 6ee458b..f17ac06 100644 --- a/Sources/RetroXCore/Plugins/EmulatorPlugin.swift +++ b/Sources/RetroXCore/Plugins/EmulatorPlugin.swift @@ -117,17 +117,28 @@ public struct PluginConfig: Codable, Sendable, Equatable { } } -/// Plugins que o RetroX oferece. Os "em breve" aparecem na tela de emuladores, mas não podem ser ativados. +/// Plugins que o RetroX oferece, e outros emuladores que ele reconhece (ainda sem plugin). public enum PluginCatalog { - public struct Upcoming: Sendable, Identifiable { + /// Emulador conhecido sem plugin: aparece em Emuladores se estiver instalado (ou se o plugin estiver planejado). + public struct KnownEmulator: Sendable, Identifiable { public let id: String public let name: String public let systems: String + /// Bundle IDs para procurar o app instalado pelo LaunchServices. + public let bundleIdentifiers: [String] + /// Plugin no plano (PRD); aparece mesmo sem estar instalado. + public let isPlanned: Bool } public static let available: [any EmulatorPlugin] = [PCSX2Plugin()] - public static let upcoming: [Upcoming] = [ - Upcoming(id: "dolphin", name: "Dolphin", systems: "GameCube · Wii"), + public static let known: [KnownEmulator] = [ + KnownEmulator(id: "dolphin", name: "Dolphin", systems: "GameCube · Wii", bundleIdentifiers: ["org.dolphin-emu.dolphin"], isPlanned: true), + KnownEmulator(id: "ryujinx", name: "Ryujinx", systems: "Switch", bundleIdentifiers: ["org.ryujinx.Ryujinx"], isPlanned: false), + KnownEmulator(id: "rpcs3", name: "RPCS3", systems: "PS3", bundleIdentifiers: ["net.rpcs3.rpcs3"], isPlanned: false), + KnownEmulator(id: "ppsspp", name: "PPSSPP", systems: "PSP", bundleIdentifiers: ["org.ppsspp.ppsspp"], isPlanned: false), + KnownEmulator(id: "duckstation", name: "DuckStation", systems: "PS1", bundleIdentifiers: ["com.github.stenzek.duckstation"], isPlanned: false), + KnownEmulator(id: "melonds", name: "melonDS", systems: "NDS", bundleIdentifiers: ["net.kuribo64.melonDS"], isPlanned: false), + KnownEmulator(id: "cemu", name: "Cemu", systems: "Wii U", bundleIdentifiers: ["info.cemu.Cemu"], isPlanned: false), ] } From aa7d5bc17264b68a65a7a59cf12c2a546aa65ec9 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 01:27:06 -0300 Subject: [PATCH 26/56] =?UTF-8?q?docs:=20controle=20no=20app=20inteiro,=20?= =?UTF-8?q?ajustes,=20anima=C3=A7=C3=B5es=20e=20visualiza=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADR-0007 emendado (controle em todas as telas, presets, níveis de animação), decisões D13-D14, brand spec com movimento, telas e texto, README com os atalhos de teclado e controle. Co-Authored-By: Claude Opus 5.5 --- README.md | 7 +++++- docs/DECISOES.md | 2 ++ .../0007-gamecontroller-e-acessibilidade.md | 8 +++++++ docs/design/brand-spec.md | 24 ++++++++++++++----- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c188f95..6877050 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,13 @@ Launcher nativo para macOS que reúne numa biblioteca visual os jogos de vários 2. Vá em **Emuladores**, ative o **PCSX2** e escolha a pasta dele: a que tem o `PCSX2.app` e as pastas de jogos (por exemplo `~/Emulators/ps2`, com `roms/` e `covers/`). O RetroX também usa as pastas de jogos, as capas (inclusive as que o PCSX2 baixa) e a BIOS que o próprio PCSX2 já conhece. 3. Em **Início**, navegue pela prateleira; em **Biblioteca**, veja todos os jogos em grade ou lista, com busca e filtro por console. Pressione **Return** (ou o botão de confirmar) para jogar. Quando o PCSX2 fecha, o RetroX volta para a frente. 4. Em **Detalhes**, troque a capa de um jogo ou busque informações na Wikipedia. +5. Em **Ajustes**, escolha tema, fonte, visualização da tela inicial (Prateleira, Carrossel ou Grade), animações e o tipo de controle. Cada perfil guarda os seus. -Teclado: setas navegam, Q/E troca de prateleira ou de console, Espaço abre os detalhes, F favorita, / busca na Biblioteca, M abre Emuladores, Esc volta. Nada nas pastas dos jogos é copiado, movido ou alterado. +Teclado: setas navegam, `[` `]` (ou ⌘1–⌘4) trocam de aba, Q/E troca de prateleira ou de console, Espaço abre os detalhes, F favorita, / busca na Biblioteca, M (ou ⌘,) abre os Ajustes, Esc volta. + +Controle: o app inteiro funciona pelo controle. O botão de baixo confirma (o da direita no layout Nintendo), o da direita volta, os gatilhos trocam de aba, Start abre os Ajustes. Em Ajustes > Controle dá para escolher os glifos de Xbox, PlayStation (DualSense) ou Switch. + +Nada nas pastas dos jogos é copiado, movido ou alterado. ## Requisitos diff --git a/docs/DECISOES.md b/docs/DECISOES.md index 2e520cb..343e2f8 100644 --- a/docs/DECISOES.md +++ b/docs/DECISOES.md @@ -23,6 +23,8 @@ Decisões do usuário e suposições de trabalho que não cabem num ADR. Decisõ | D10 | Informações de jogos: banco do PCSX2 offline e Wikipedia/Wikidata sob demanda, com escolha do resultado (ADR-0014). Capas não são baixadas da internet. | | D11 | ~~RetroAchievements e controle do PCSX2 em leitura.~~ Revisto em D12. | | D12 | RetroAchievements fica fora do RetroX (pedido do usuário em 2026-10-28): nada é lido nem mostrado. O controle do PCSX2 continua só em leitura; gravar perfil de entrada depende de consentimento e teste com controle (spike 0002). | +| D13 | Ajustes dentro da janela, navegáveis por controle, com presets Xbox, PlayStation (DualSense) e Switch. Fonte, tamanho do texto, visualização da tela inicial (Prateleira, Carrossel, Grade), fundo ambiente e animações são preferências do perfil. | +| D14 | Abertura animada ao iniciar e transições suaves entre telas, inspiradas na fluidez do iiSU, com identidade própria. | ## Suposições de trabalho diff --git a/docs/adr/0007-gamecontroller-e-acessibilidade.md b/docs/adr/0007-gamecontroller-e-acessibilidade.md index c32b3a7..76ec131 100644 --- a/docs/adr/0007-gamecontroller-e-acessibilidade.md +++ b/docs/adr/0007-gamecontroller-e-acessibilidade.md @@ -17,3 +17,11 @@ Depender só de focus engine automática (pode não bastar); handlers soltos em ## Emenda (2026-10-27) - `GCController.shouldMonitorBackgroundEvents` fica `false` (default desde o macOS 11.3), de forma explícita: com o emulador em primeiro plano, o RetroX não recebe input do controle. - O `InputCoordinator` só atua no Console Mode. No Library Mode vale o foco nativo do macOS. + +## Emenda (2026-10-28, tarde) +- O controle navega o app inteiro: perfis, Início (as três visualizações), Biblioteca, Emuladores, Ajustes, detalhes e a partida. Só a edição de texto (nome de perfil, busca) continua exigindo teclado. +- Mapa fixo por posição: baixo confirma (direita no layout Nintendo ou com "inverter"), direita volta, esquerda abre detalhes, cima favorita, LB/RB trocam prateleira ou console, gatilhos trocam de aba, Start abre Ajustes, View/Create/− abre Emuladores. +- Presets de glifos: Automático (o próprio controle), Xbox, PlayStation (DualSense) e Nintendo Switch (`ControllerPreset`, testado). +- Os Ajustes saíram da janela separada do macOS e viraram uma tela do app, para serem alcançáveis pelo controle. ⌘, continua abrindo os Ajustes. +- Níveis de animação por perfil (completas, reduzidas, desligadas) somam-se ao Reduzir Movimento do macOS: com qualquer um dos dois, nada cresce, desliza ou inclina. + diff --git a/docs/design/brand-spec.md b/docs/design/brand-spec.md index dc7382c..fc76e1a 100644 --- a/docs/design/brand-spec.md +++ b/docs/design/brand-spec.md @@ -56,14 +56,26 @@ SF Pro Rounded para títulos (tom de console), SF Pro para o resto. No máximo q Na prateleira, a capa em foco sobe 10%, ganha um halo na cor de tema e se reflete no "chão" da prateleira. Com Reduzir Movimento, fica só o anel de foco: nada cresce nem se desloca. ## Movimento -- Foco: `snappy` (0,28 s, pouco quique). -- Hover: `smooth` (0,22 s), com elevação leve (escala 1,03–1,04). -- Trocas de tela: esmaecimento de 0,18 s. -- Abas e seletor de layout deslizam a pílula selecionada (`matchedGeometryEffect`). -- Com Reduzir Movimento, só esmaece: nada cresce nem se desloca. +- Foco: `snappy` (0,32 s, quique quase imperceptível). +- Hover: `smooth` (0,24 s), com elevação leve (escala 1,03–1,04). +- Troca de aba: o conteúdo novo entra deslizando 48 pt pelo lado da aba escolhida (`smooth`, 0,45 s); a barra de cima fica parada. +- Entrar num perfil: a tela inicial aproxima (escala 1,04 → 1). +- Cartões (detalhes, perfil): crescem de 0,94 e sobem 16 pt enquanto o fundo escurece. +- Carrossel: as capas vizinhas encolhem 16% por posição e inclinam 38° em 3D. +- Fundo ambiente: a capa em foco, desfocada, troca em 0,7 s. +- Abertura: anel desenhado em 0,9 s em volta do símbolo, que entra com mola; o nome entra letra a letra (60 ms entre letras). +- O perfil escolhe o nível (completas, reduzidas, desligadas) e a velocidade (calma ×1,35, normal, rápida ×0,7). Com animações reduzidas ou o Reduzir Movimento do macOS, só esmaece: nada cresce, desliza nem inclina. ## Telas -Perfis ("Quem vai jogar?", avatares de 128 pt com anel de foco), Início (palco + prateleira), Biblioteca (grade com quatro layouts: Capas 128 pt, Capas grandes 184 pt, Capas e nomes 148 pt, Lista), Emuladores, Detalhes (folha de 880 × 620) e Ajustes (Aparência e Controle). +- **Perfis** ("Quem vai jogar?", avatares de 128 pt com anel de foco). +- **Início**, em três visualizações à escolha do perfil: Prateleira (palco + prateleira), Carrossel e Grade. +- **Biblioteca**: Capas pequenas 96 pt, Capas 128 pt, Capas grandes 184 pt, Capas e nomes 148 pt, Lista. +- **Emuladores**: ícone do app instalado, selo de estado e blocos de resumo. +- **Ajustes**: seções à esquerda, linhas `‹ valor ›` à direita. +- **Detalhes**: cartão de 880 × 620. + +## Texto +O perfil escolhe a fonte (Arredondada, Padrão, Serifada, Monoespaçada) e o tamanho (90%, 100%, 112%, 125%). Na Arredondada, só os títulos são arredondados; o corpo fica na fonte padrão. ## Voz Português do Brasil, direto e calmo. Mensagens de erro dizem o que aconteceu e oferecem a ação que resolve. From 1149083a5eaffcfc3777855b8735a3654c0c18bf Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 08:38:43 -0300 Subject: [PATCH 27/56] chore: deixa a swiftui-design-skill mais barata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modelo sonnet, sem pesquisa/download de marca (usa a brand spec do projeto), 3 direções e revisão por captura só quando pedidas, referências lidas sob demanda e seções repetidas removidas. O arquivo agora diverge do hash em skills-lock.json; um `npx skills update` sobrescreveria estas mudanças. Co-Authored-By: Claude Opus 5.5 --- .claude/skills/swiftui-design-skill/SKILL.md | 74 +++----------------- 1 file changed, 10 insertions(+), 64 deletions(-) diff --git a/.claude/skills/swiftui-design-skill/SKILL.md b/.claude/skills/swiftui-design-skill/SKILL.md index 9ae08a2..b9a7235 100644 --- a/.claude/skills/swiftui-design-skill/SKILL.md +++ b/.claude/skills/swiftui-design-skill/SKILL.md @@ -2,6 +2,7 @@ name: swiftui-design-skill description: SwiftUI frontend visual design skill. Creates beautiful, distinctive iOS/macOS interfaces that avoid generic AI slop patterns. Covers design direction, layout systems, typography, color, spacing, brand integration, and design review. Use when designing new SwiftUI views, reviewing UI quality, creating iOS prototypes, choosing visual styles, improving app aesthetics, or when the UI looks generic or AI-generated. license: MIT +model: sonnet metadata: author: wholiver version: "1.0.0" @@ -104,23 +105,10 @@ These patterns are **banned** in production UI. See `references/anti-ai-slop.md` --- -## Brand Asset Protocol +## Brand -When building UI for a specific brand, follow this 5-step hard flow: - -1. **Ask** — Request brand guidelines, logo files, color palette, typography -2. **Search** — If not provided, search the web for "[brand name] brand guidelines" -3. **Download** — Get actual asset files (PNG/SVG logos, font files) -4. **Verify** — Confirm colors match official sources (check hex values) -5. **Write brand-spec.md** — Document: primary/secondary colors, fonts, logo usage rules, spacing tokens - -**Quality threshold**: 5 real brand colors, 10 verified design tokens, 2 font families, 8pt spacing grid. - -If no brand exists, create a brand-spec.md with: -- 1 primary accent color (warm, not purple-blue gradient) -- 1 neutral palette (grays with warm undertone) -- 1 display font + 1 body font (SF Pro default is fine) -- 8pt spacing grid +If `docs/design/brand-spec.md` exists, follow it and skip direction work. +Only if no spec exists, write a short one (1 accent, neutrals, fonts, 8pt grid). No web search, no asset downloads. --- @@ -134,6 +122,7 @@ When requirements are vague or the user asks "what style should we use?", follow 3. Check: Existing design system or brand assets? ### Phase 2: Recommend 3 Directions +Only when the user asks for a new visual direction. Otherwise reuse the brand spec. Present 3 distinct design philosophies from different schools: | School | Example Directions | @@ -160,36 +149,7 @@ Present options clearly. After choice, lock in the design system. ### Step 1: Define the Design System (Before Coding) -Create or confirm these design tokens: - -```swift -// Requires: references/swift-extensions.md (Color(hex:) extension) -// DesignTokens.swift -enum DesignTokens { - // Colors - static let accent = Color(hex: "E85D3A") // Warm coral - static let background = Color(hex: "FAFAF8") // Warm white - static let textPrimary = Color(hex: "1A1A1A") // Near-black - static let textSecondary = Color(hex: "6B6B6B") // Muted gray - - // Typography - static let displayFont = "New York" // Serif for headings - static let bodyFont = "SF Pro" // System default - - // Spacing (8pt grid) - static let spaceXS: CGFloat = 4 - static let spaceS: CGFloat = 8 - static let spaceM: CGFloat = 16 - static let spaceL: CGFloat = 24 - static let spaceXL: CGFloat = 32 - static let spaceXXL: CGFloat = 48 - - // Corner radius - static let radiusS: CGFloat = 8 - static let radiusM: CGFloat = 12 - static let radiusL: CGFloat = 16 -} -``` +Create or confirm design tokens (colors, fonts, 8pt spacing, radii) before coding. ### Step 2: Build the Layout Hierarchy @@ -220,29 +180,15 @@ Examples: ### Step 5: Review Against Checklist -Before shipping, run the 5-Dimension Review (see `references/design-review.md`). - ---- - -## Common Mistakes to Avoid - -| Mistake | Fix | -| ------------------------------------------ | -------------------------------------------------------- | -| Using `UIColor` or `NSColor` | Use `Color` (SwiftUI native) | -| `UIScreen.main.bounds` for sizing | Use `containerRelativeFrame` or geometry-based modifiers | -| Default blue tint everywhere | Define a custom accent color in design tokens | -| No spacing system (random padding values) | Use 8pt grid: 4, 8, 16, 24, 32, 48 | -| Emoji as icons | Use SF Symbols or custom icon assets | -| Purple-blue gradient background | Use solid warm neutrals | -| All content in one giant VStack | Break into semantic sections with clear hierarchy | -| No visual hierarchy (everything same size) | Use 3+ type scales (display, heading, body, caption) | -| Ignoring dark mode | Define semantic colors that adapt to appearance | -| Generic "Welcome!" hero section | Show actual content immediately | +Self-check against the Validation Checklist below. Take screenshots or open +`references/design-review.md` only if the user asks for a review. --- ## Quick Reference: Topic Router +Read files in `references/` only when the task needs that topic; don't load them by default. + | Topic | Reference File | | ---------------------------- | ----------------------------------- | | Anti-AI-Slop Rules (detail) | `references/anti-ai-slop.md` | From cc16124e9e021e5444c9d40a671d449c3d395798 Mon Sep 17 00:00:00 2001 From: oLuqueJs Date: Wed, 28 Oct 2026 09:04:34 -0300 Subject: [PATCH 28/56] =?UTF-8?q?chore:=20adiciona=20a=20skill=20logo-desi?= =?UTF-8?q?gn=20com=20a=20mesma=20redu=C3=A7=C3=A3o=20de=20custo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instalada com `npx skills add kaankiziltug/logo-design-skill`. Scripts revisados: sem rede, só renderizadores locais e pastas temporárias. A biblioteca de ~1.400 SVGs é de marcas de terceiros: só estudo. Redução: modelo sonnet, brand spec do projeto como brief, 4–6 conceitos, um ciclo de teste, biblioteca e folhas de prévia só quando exigidas ou pedidas, referências sob demanda. Co-Authored-By: Claude Opus 5.5 --- .claude/skills/logo-design/SKILL.md | 224 + .../logo-design/assets/library/catalog.json | 1 + .../assets/library/classifications.json | 31038 ++++++++++++++++ .../logo-design/assets/library/gallery.html | 48 + .../logo-design/assets/library/stats.json | 392 + .../logo-design/assets/library/svg/100tb.svg | 11 + .../logo-design/assets/library/svg/500px.svg | 10 + .../library/svg/active-campaign-icon.svg | 10 + .../assets/library/svg/active-campaign.svg | 10 + .../assets/library/svg/adonisjs-icon.svg | 10 + .../assets/library/svg/adonisjs.svg | 10 + .../logo-design/assets/library/svg/adroll.svg | 11 + .../logo-design/assets/library/svg/adyen.svg | 10 + .../assets/library/svg/aerospike-icon.svg | 11 + .../assets/library/svg/aerospike.svg | 11 + .../logo-design/assets/library/svg/airbnb.svg | 10 + .../assets/library/svg/airbrake.svg | 11 + .../assets/library/svg/airflow.svg | 70 + .../assets/library/svg/airtable.svg | 13 + .../logo-design/assets/library/svg/akamai.svg | 11 + .../logo-design/assets/library/svg/akka.svg | 11 + .../assets/library/svg/alfresco.svg | 25 + .../assets/library/svg/algolia.svg | 12 + .../assets/library/svg/alpinejs-icon.svg | 11 + .../assets/library/svg/alpinejs.svg | 12 + .../logo-design/assets/library/svg/altair.svg | 14 + .../assets/library/svg/amazon-chime.svg | 35 + .../assets/library/svg/amazon-connect.svg | 10 + .../logo-design/assets/library/svg/amex.svg | 26 + .../assets/library/svg/amp-icon.svg | 10 + .../logo-design/assets/library/svg/amp.svg | 11 + .../assets/library/svg/ampersand.svg | 11 + .../assets/library/svg/amplication-icon.svg | 10 + .../assets/library/svg/amplication.svg | 11 + .../assets/library/svg/amplitude-icon.svg | 10 + .../assets/library/svg/amplitude.svg | 10 + .../assets/library/svg/android-icon.svg | 14 + .../assets/library/svg/android.svg | 17 + .../assets/library/svg/angellist.svg | 10 + .../assets/library/svg/angular-icon.svg | 12 + .../assets/library/svg/angular.svg | 18 + .../assets/library/svg/ansible.svg | 18 + .../assets/library/svg/ant-design.svg | 32 + .../assets/library/svg/apache-camel.svg | 34 + .../logo-design/assets/library/svg/apache.svg | 57 + .../assets/library/svg/apache_cloudstack.svg | 25 + .../logo-design/assets/library/svg/apiary.svg | 30 + .../assets/library/svg/apollostack.svg | 10 + .../assets/library/svg/apostrophe.svg | 30 + .../assets/library/svg/appbaseio-icon.svg | 10 + .../assets/library/svg/appbaseio.svg | 11 + .../assets/library/svg/appcircle-icon.svg | 10 + .../assets/library/svg/appcircle.svg | 11 + .../assets/library/svg/appcode.svg | 28 + .../assets/library/svg/appdynamics.svg | 11 + .../logo-design/assets/library/svg/appium.svg | 10 + .../assets/library/svg/apple-app-store.svg | 15 + .../assets/library/svg/apple-pay.svg | 10 + .../logo-design/assets/library/svg/apple.svg | 10 + .../assets/library/svg/appsignal-icon.svg | 10 + .../assets/library/svg/appsignal.svg | 11 + .../assets/library/svg/apptentive.svg | 11 + .../assets/library/svg/appveyor.svg | 10 + .../assets/library/svg/arangodb.svg | 26 + .../assets/library/svg/archlinux.svg | 10 + .../assets/library/svg/arduino.svg | 21 + .../assets/library/svg/argo-icon.svg | 34 + .../logo-design/assets/library/svg/argo.svg | 38 + .../logo-design/assets/library/svg/armory.svg | 13 + .../logo-design/assets/library/svg/asana.svg | 16 + .../assets/library/svg/asciidoctor.svg | 11 + .../assets/library/svg/assembla-icon.svg | 10 + .../assets/library/svg/assembla.svg | 11 + .../logo-design/assets/library/svg/astro.svg | 17 + .../assets/library/svg/astronomer.svg | 23 + .../assets/library/svg/atlassian.svg | 15 + .../assets/library/svg/atom-icon.svg | 11 + .../logo-design/assets/library/svg/atom.svg | 10 + .../assets/library/svg/atomic-icon.svg | 12 + .../logo-design/assets/library/svg/atomic.svg | 13 + .../assets/library/svg/aurelia.svg | 66 + .../logo-design/assets/library/svg/aurora.svg | 33 + .../assets/library/svg/auth0-icon.svg | 10 + .../logo-design/assets/library/svg/auth0.svg | 10 + .../logo-design/assets/library/svg/authy.svg | 11 + .../logo-design/assets/library/svg/autoit.svg | 12 + .../assets/library/svg/autoprefixer.svg | 10 + .../logo-design/assets/library/svg/ava.svg | 11 + .../assets/library/svg/awesome.svg | 11 + .../assets/library/svg/aws-amplify.svg | 14 + .../assets/library/svg/aws-api-gateway.svg | 15 + .../assets/library/svg/aws-app-mesh.svg | 15 + .../assets/library/svg/aws-appflow.svg | 15 + .../assets/library/svg/aws-appsync.svg | 15 + .../assets/library/svg/aws-athena.svg | 15 + .../assets/library/svg/aws-aurora.svg | 15 + .../assets/library/svg/aws-backup.svg | 15 + .../assets/library/svg/aws-batch.svg | 15 + .../library/svg/aws-certificate-manager.svg | 15 + .../assets/library/svg/aws-cloudformation.svg | 15 + .../assets/library/svg/aws-cloudfront.svg | 15 + .../assets/library/svg/aws-cloudsearch.svg | 15 + .../assets/library/svg/aws-cloudtrail.svg | 15 + .../assets/library/svg/aws-cloudwatch.svg | 15 + .../assets/library/svg/aws-codebuild.svg | 15 + .../assets/library/svg/aws-codecommit.svg | 15 + .../assets/library/svg/aws-codedeploy.svg | 15 + .../assets/library/svg/aws-codepipeline.svg | 15 + .../assets/library/svg/aws-codestar.svg | 15 + .../assets/library/svg/aws-cognito.svg | 15 + .../assets/library/svg/aws-config.svg | 15 + .../assets/library/svg/aws-documentdb.svg | 15 + .../assets/library/svg/aws-dynamodb.svg | 15 + .../assets/library/svg/aws-ec2.svg | 15 + .../assets/library/svg/aws-ecs.svg | 15 + .../assets/library/svg/aws-eks.svg | 15 + .../library/svg/aws-elastic-beanstalk.svg | 15 + .../assets/library/svg/aws-elasticache.svg | 15 + .../assets/library/svg/aws-elb.svg | 15 + .../assets/library/svg/aws-eventbridge.svg | 15 + .../assets/library/svg/aws-fargate.svg | 15 + .../assets/library/svg/aws-glacier.svg | 15 + .../assets/library/svg/aws-glue.svg | 15 + .../assets/library/svg/aws-iam.svg | 15 + .../assets/library/svg/aws-keyspaces.svg | 15 + .../assets/library/svg/aws-kinesis.svg | 15 + .../assets/library/svg/aws-kms.svg | 15 + .../assets/library/svg/aws-lake-formation.svg | 15 + .../assets/library/svg/aws-lambda.svg | 15 + .../assets/library/svg/aws-lightsail.svg | 10 + .../logo-design/assets/library/svg/aws-mq.svg | 15 + .../assets/library/svg/aws-msk.svg | 15 + .../assets/library/svg/aws-neptune.svg | 15 + .../assets/library/svg/aws-open-search.svg | 15 + .../assets/library/svg/aws-opsworks.svg | 15 + .../assets/library/svg/aws-quicksight.svg | 15 + .../assets/library/svg/aws-rds.svg | 15 + .../assets/library/svg/aws-redshift.svg | 15 + .../assets/library/svg/aws-route53.svg | 15 + .../logo-design/assets/library/svg/aws-s3.svg | 15 + .../library/svg/aws-secrets-manager.svg | 15 + .../assets/library/svg/aws-ses.svg | 15 + .../assets/library/svg/aws-shield.svg | 15 + .../assets/library/svg/aws-sns.svg | 15 + .../assets/library/svg/aws-sqs.svg | 15 + .../assets/library/svg/aws-step-functions.svg | 15 + .../library/svg/aws-systems-manager.svg | 15 + .../assets/library/svg/aws-timestream.svg | 15 + .../assets/library/svg/aws-vpc.svg | 15 + .../assets/library/svg/aws-waf.svg | 15 + .../assets/library/svg/aws-xray.svg | 15 + .../logo-design/assets/library/svg/aws.svg | 11 + .../logo-design/assets/library/svg/axios.svg | 10 + .../logo-design/assets/library/svg/babel.svg | 11 + .../assets/library/svg/backbone-icon.svg | 13 + .../assets/library/svg/backbone.svg | 24 + .../assets/library/svg/backerkit.svg | 10 + .../assets/library/svg/baker-street.svg | 15 + .../logo-design/assets/library/svg/balena.svg | 15 + .../logo-design/assets/library/svg/bamboo.svg | 21 + .../assets/library/svg/basecamp.svg | 12 + .../assets/library/svg/basekit.svg | 10 + .../assets/library/svg/bash-icon.svg | 13 + .../logo-design/assets/library/svg/bash.svg | 8 + .../logo-design/assets/library/svg/batch.svg | 12 + .../logo-design/assets/library/svg/beats.svg | 12 + .../assets/library/svg/behance.svg | 17 + .../logo-design/assets/library/svg/bem-2.svg | 12 + .../logo-design/assets/library/svg/bem.svg | 10 + .../assets/library/svg/bigpanda.svg | 11 + .../logo-design/assets/library/svg/bing.svg | 10 + .../assets/library/svg/bitbucket.svg | 15 + .../assets/library/svg/bitcoin.svg | 15 + .../assets/library/svg/bitnami.svg | 36 + .../assets/library/svg/bitrise-icon.svg | 10 + .../assets/library/svg/bitrise.svg | 11 + .../assets/library/svg/blender.svg | 12 + .../assets/library/svg/blitzjs-icon.svg | 10 + .../assets/library/svg/blitzjs.svg | 11 + .../logo-design/assets/library/svg/blocs.svg | 14 + .../assets/library/svg/blogger.svg | 12 + .../assets/library/svg/blossom.svg | 13 + .../assets/library/svg/blueprint.svg | 34 + .../assets/library/svg/bluetooth.svg | 10 + .../assets/library/svg/booqable-icon.svg | 10 + .../assets/library/svg/booqable.svg | 11 + .../assets/library/svg/bootstrap.svg | 11 + .../logo-design/assets/library/svg/bosun.svg | 32 + .../assets/library/svg/botanalytics.svg | 10 + .../assets/library/svg/bourbon.svg | 20 + .../logo-design/assets/library/svg/bower.svg | 18 + .../logo-design/assets/library/svg/box.svg | 12 + .../assets/library/svg/brackets.svg | 44 + .../assets/library/svg/brainjs.svg | 11 + .../logo-design/assets/library/svg/branch.svg | 11 + .../assets/library/svg/brandfolder-icon.svg | 10 + .../assets/library/svg/brandfolder.svg | 11 + .../logo-design/assets/library/svg/brave.svg | 26 + .../logo-design/assets/library/svg/braze.svg | 10 + .../assets/library/svg/broccoli.svg | 10 + .../logo-design/assets/library/svg/brotli.svg | 13 + .../assets/library/svg/browserify-icon.svg | 15 + .../assets/library/svg/browserify.svg | 32 + .../assets/library/svg/browserling.svg | 10 + .../assets/library/svg/browserslist.svg | 12 + .../assets/library/svg/browserstack.svg | 24 + .../assets/library/svg/browsersync.svg | 10 + .../logo-design/assets/library/svg/brunch.svg | 15 + .../logo-design/assets/library/svg/buck.svg | 11 + .../logo-design/assets/library/svg/buddy.svg | 24 + .../logo-design/assets/library/svg/buffer.svg | 10 + .../assets/library/svg/bugherd.svg | 11 + .../logo-design/assets/library/svg/bugsee.svg | 12 + .../assets/library/svg/bugsnag-icon.svg | 10 + .../assets/library/svg/bugsnag.svg | 10 + .../assets/library/svg/buildkite-icon.svg | 13 + .../assets/library/svg/buildkite.svg | 14 + .../logo-design/assets/library/svg/bulma.svg | 10 + .../assets/library/svg/c-plusplus.svg | 16 + .../assets/library/svg/c-sharp.svg | 14 + .../logo-design/assets/library/svg/c.svg | 12 + .../logo-design/assets/library/svg/cachet.svg | 12 + .../logo-design/assets/library/svg/caffe2.svg | 14 + .../assets/library/svg/cakephp-icon.svg | 10 + .../assets/library/svg/cakephp.svg | 11 + .../library/svg/campaignmonitor-icon.svg | 10 + .../assets/library/svg/campaignmonitor.svg | 11 + .../logo-design/assets/library/svg/canjs.svg | 14 + .../assets/library/svg/capacitorjs-icon.svg | 15 + .../assets/library/svg/capacitorjs.svg | 16 + .../assets/library/svg/capistrano.svg | 24 + .../assets/library/svg/carbide.svg | 10 + .../assets/library/svg/cardano-icon.svg | 10 + .../assets/library/svg/cardano.svg | 11 + .../assets/library/svg/cassandra.svg | 36 + .../assets/library/svg/centos-icon.svg | 15 + .../logo-design/assets/library/svg/centos.svg | 26 + .../assets/library/svg/certbot.svg | 24 + .../logo-design/assets/library/svg/ceylon.svg | 21 + .../logo-design/assets/library/svg/chai.svg | 16 + .../logo-design/assets/library/svg/chalk.svg | 15 + .../assets/library/svg/chargebee-icon.svg | 10 + .../assets/library/svg/chargebee.svg | 10 + .../logo-design/assets/library/svg/chef.svg | 26 + .../assets/library/svg/chevereto.svg | 10 + .../assets/library/svg/chromatic-icon.svg | 11 + .../assets/library/svg/chromatic.svg | 12 + .../logo-design/assets/library/svg/chrome.svg | 21 + .../logo-design/assets/library/svg/cinder.svg | 47 + .../assets/library/svg/circleci.svg | 11 + .../assets/library/svg/cirrus-ci.svg | 11 + .../logo-design/assets/library/svg/cirrus.svg | 13 + .../logo-design/assets/library/svg/clion.svg | 38 + .../logo-design/assets/library/svg/cljs.svg | 15 + .../assets/library/svg/clojure.svg | 15 + .../logo-design/assets/library/svg/close.svg | 36 + .../logo-design/assets/library/svg/cloud9.svg | 10 + .../assets/library/svg/cloudacademy-icon.svg | 10 + .../assets/library/svg/cloudacademy.svg | 11 + .../assets/library/svg/cloudcraft.svg | 18 + .../assets/library/svg/cloudflare.svg | 12 + .../assets/library/svg/cloudinary.svg | 13 + .../assets/library/svg/cloudlinux.svg | 10 + .../logo-design/assets/library/svg/cobalt.svg | 11 + .../assets/library/svg/cockpit.svg | 11 + .../assets/library/svg/cocoapods.svg | 12 + .../logo-design/assets/library/svg/codacy.svg | 10 + .../assets/library/svg/codebase.svg | 11 + .../assets/library/svg/codebeat.svg | 10 + .../assets/library/svg/codecademy.svg | 21 + .../assets/library/svg/codeception.svg | 15 + .../assets/library/svg/codeclimate.svg | 22 + .../assets/library/svg/codecov.svg | 10 + .../assets/library/svg/codefactor-icon.svg | 20 + .../assets/library/svg/codefactor.svg | 16 + .../assets/library/svg/codeigniter.svg | 10 + .../assets/library/svg/codepen-icon.svg | 10 + .../assets/library/svg/codepen.svg | 16 + .../assets/library/svg/codepush.svg | 19 + .../assets/library/svg/codersrank.svg | 11 + .../assets/library/svg/coderwall.svg | 15 + .../assets/library/svg/codesandbox.svg | 10 + .../assets/library/svg/codeship.svg | 15 + .../logo-design/assets/library/svg/codio.svg | 12 + .../assets/library/svg/codrops.svg | 12 + .../assets/library/svg/coffeescript.svg | 10 + .../assets/library/svg/commitizen.svg | 12 + .../assets/library/svg/compass.svg | 18 + .../assets/library/svg/componentkit.svg | 24 + .../assets/library/svg/compose.svg | 11 + .../assets/library/svg/composer.svg | 18 + .../assets/library/svg/conan-io.svg | 14 + .../assets/library/svg/concourse.svg | 10 + .../assets/library/svg/concrete5.svg | 59 + .../assets/library/svg/confluence.svg | 19 + .../logo-design/assets/library/svg/consul.svg | 10 + .../assets/library/svg/contentful.svg | 14 + .../logo-design/assets/library/svg/convox.svg | 23 + .../assets/library/svg/copyleft-pirate.svg | 13 + .../assets/library/svg/copyleft.svg | 10 + .../logo-design/assets/library/svg/corda.svg | 10 + .../assets/library/svg/cordova.svg | 10 + .../assets/library/svg/coreos-icon.svg | 12 + .../logo-design/assets/library/svg/coreos.svg | 18 + .../assets/library/svg/couchbase.svg | 10 + .../assets/library/svg/couchdb-icon.svg | 10 + .../assets/library/svg/couchdb.svg | 12 + .../assets/library/svg/coursera.svg | 10 + .../assets/library/svg/coveralls.svg | 27 + .../logo-design/assets/library/svg/cpanel.svg | 10 + .../assets/library/svg/craftcms.svg | 10 + .../assets/library/svg/crashlytics.svg | 11 + .../assets/library/svg/crateio.svg | 10 + .../assets/library/svg/create-react-app.svg | 10 + .../assets/library/svg/createjs.svg | 10 + .../library/svg/cross-browser-testing.svg | 12 + .../assets/library/svg/crucible.svg | 15 + .../assets/library/svg/crystal.svg | 10 + .../logo-design/assets/library/svg/css-3.svg | 18 + .../assets/library/svg/css-3_official.svg | 10 + .../assets/library/svg/cssnext.svg | 39 + .../assets/library/svg/cucumber.svg | 11 + .../logo-design/assets/library/svg/curl.svg | 13 + .../assets/library/svg/customerio-icon.svg | 13 + .../assets/library/svg/customerio.svg | 14 + .../assets/library/svg/cyclejs.svg | 19 + .../assets/library/svg/cypress.svg | 29 + .../logo-design/assets/library/svg/d3.svg | 39 + .../logo-design/assets/library/svg/dart.svg | 15 + .../assets/library/svg/dashlane-icon.svg | 10 + .../assets/library/svg/dashlane.svg | 10 + .../assets/library/svg/database-labs.svg | 16 + .../assets/library/svg/datadog.svg | 11 + .../assets/library/svg/datocms-icon.svg | 14 + .../assets/library/svg/datocms.svg | 15 + .../assets/library/svg/dbt-icon.svg | 10 + .../logo-design/assets/library/svg/dbt.svg | 11 + .../assets/library/svg/dcos-icon.svg | 14 + .../logo-design/assets/library/svg/dcos.svg | 20 + .../logo-design/assets/library/svg/debian.svg | 21 + .../assets/library/svg/delighted-icon.svg | 10 + .../assets/library/svg/delighted.svg | 10 + .../logo-design/assets/library/svg/deno.svg | 12 + .../assets/library/svg/deployhq.svg | 10 + .../logo-design/assets/library/svg/derby.svg | 10 + .../assets/library/svg/designernews.svg | 17 + .../assets/library/svg/deviantart.svg | 11 + .../assets/library/svg/dgraph-icon.svg | 14 + .../logo-design/assets/library/svg/dgraph.svg | 15 + .../assets/library/svg/dialogflow.svg | 18 + .../assets/library/svg/digital-ocean.svg | 11 + .../logo-design/assets/library/svg/dimer.svg | 13 + .../assets/library/svg/dinersclub.svg | 12 + .../assets/library/svg/discord-icon.svg | 10 + .../assets/library/svg/discord.svg | 10 + .../assets/library/svg/discover.svg | 28 + .../logo-design/assets/library/svg/disqus.svg | 10 + .../assets/library/svg/django-icon.svg | 11 + .../logo-design/assets/library/svg/django.svg | 10 + .../assets/library/svg/dockbit.svg | 14 + .../assets/library/svg/docker-icon.svg | 10 + .../logo-design/assets/library/svg/docker.svg | 10 + .../assets/library/svg/doctrine.svg | 11 + .../assets/library/svg/docusaurus.svg | 31 + .../assets/library/svg/dojo-icon.svg | 87 + .../assets/library/svg/dojo-toolkit.svg | 16 + .../logo-design/assets/library/svg/dojo.svg | 88 + .../logo-design/assets/library/svg/dotnet.svg | 148 + .../assets/library/svg/dreamhost.svg | 11 + .../assets/library/svg/dribbble-icon.svg | 11 + .../assets/library/svg/dribbble.svg | 10 + .../logo-design/assets/library/svg/drift.svg | 10 + .../logo-design/assets/library/svg/drip.svg | 10 + .../assets/library/svg/drizzle-icon.svg | 16 + .../assets/library/svg/drizzle.svg | 17 + .../assets/library/svg/drone-icon.svg | 10 + .../logo-design/assets/library/svg/drone.svg | 11 + .../assets/library/svg/dropbox.svg | 14 + .../assets/library/svg/dropmark.svg | 15 + .../assets/library/svg/dropzone.svg | 12 + .../assets/library/svg/drupal-icon.svg | 10 + .../logo-design/assets/library/svg/drupal.svg | 10 + .../assets/library/svg/duckduckgo.svg | 34 + .../assets/library/svg/dynatrace-icon.svg | 15 + .../assets/library/svg/dynatrace.svg | 9 + .../logo-design/assets/library/svg/dyndns.svg | 24 + .../logo-design/assets/library/svg/ebanx.svg | 13 + .../assets/library/svg/eclipse-icon.svg | 28 + .../assets/library/svg/eclipse.svg | 30 + .../assets/library/svg/editorconfig.svg | 20 + .../assets/library/svg/egghead.svg | 26 + .../assets/library/svg/elasticsearch.svg | 15 + .../assets/library/svg/electron.svg | 10 + .../assets/library/svg/element.svg | 10 + .../assets/library/svg/elemental-ui.svg | 12 + .../assets/library/svg/elementary.svg | 10 + .../logo-design/assets/library/svg/ello.svg | 10 + .../logo-design/assets/library/svg/elm.svg | 16 + .../logo-design/assets/library/svg/elo.svg | 14 + .../logo-design/assets/library/svg/emacs.svg | 16 + .../assets/library/svg/embedly.svg | 11 + .../assets/library/svg/ember-tomster.svg | 220 + .../logo-design/assets/library/svg/ember.svg | 11 + .../logo-design/assets/library/svg/emmet.svg | 12 + .../assets/library/svg/engine-yard-icon.svg | 23 + .../assets/library/svg/engine-yard.svg | 24 + .../logo-design/assets/library/svg/envato.svg | 16 + .../assets/library/svg/envoy-icon.svg | 12 + .../logo-design/assets/library/svg/envoy.svg | 13 + .../assets/library/svg/envoyer.svg | 12 + .../logo-design/assets/library/svg/enyo.svg | 25 + .../logo-design/assets/library/svg/erlang.svg | 19 + .../logo-design/assets/library/svg/es6.svg | 11 + .../assets/library/svg/esbuild.svg | 11 + .../logo-design/assets/library/svg/esdoc.svg | 11 + .../assets/library/svg/eslint-old.svg | 11 + .../logo-design/assets/library/svg/eslint.svg | 11 + .../assets/library/svg/eta-lang.svg | 11 + .../logo-design/assets/library/svg/etcd.svg | 10 + .../assets/library/svg/ethereum-color.svg | 15 + .../assets/library/svg/ethereum.svg | 15 + .../logo-design/assets/library/svg/ethers.svg | 10 + .../logo-design/assets/library/svg/ethnio.svg | 17 + .../assets/library/svg/eventbrite-icon.svg | 11 + .../assets/library/svg/eventbrite.svg | 10 + .../assets/library/svg/eventsentry.svg | 19 + .../assets/library/svg/evergreen-icon.svg | 11 + .../assets/library/svg/evergreen.svg | 12 + .../assets/library/svg/expo-icon.svg | 10 + .../logo-design/assets/library/svg/expo.svg | 11 + .../assets/library/svg/express.svg | 10 + .../logo-design/assets/library/svg/fabric.svg | 17 + .../assets/library/svg/facebook.svg | 11 + .../logo-design/assets/library/svg/falcor.svg | 27 + .../assets/library/svg/fastify-icon.svg | 10 + .../assets/library/svg/fastify.svg | 11 + .../assets/library/svg/fastlane.svg | 14 + .../logo-design/assets/library/svg/fastly.svg | 10 + .../assets/library/svg/feathersjs.svg | 10 + .../logo-design/assets/library/svg/fedora.svg | 12 + .../logo-design/assets/library/svg/fetch.svg | 12 + .../logo-design/assets/library/svg/figma.svg | 14 + .../assets/library/svg/firebase.svg | 43 + .../assets/library/svg/firefox.svg | 139 + .../assets/library/svg/flannel.svg | 10 + .../logo-design/assets/library/svg/flarum.svg | 24 + .../logo-design/assets/library/svg/flask.svg | 15 + .../assets/library/svg/flat-ui.svg | 24 + .../assets/library/svg/flattr-icon.svg | 10 + .../logo-design/assets/library/svg/flattr.svg | 19 + .../logo-design/assets/library/svg/fleep.svg | 10 + .../logo-design/assets/library/svg/flickr.svg | 10 + .../logo-design/assets/library/svg/flight.svg | 10 + .../assets/library/svg/floodio.svg | 10 + .../logo-design/assets/library/svg/flow.svg | 37 + .../logo-design/assets/library/svg/flowxo.svg | 12 + .../assets/library/svg/floydhub.svg | 10 + .../assets/library/svg/flutter.svg | 18 + .../logo-design/assets/library/svg/flux.svg | 10 + .../assets/library/svg/fluxxor.svg | 14 + .../logo-design/assets/library/svg/fly.svg | 14 + .../logo-design/assets/library/svg/fomo.svg | 10 + .../assets/library/svg/font-awesome.svg | 10 + .../assets/library/svg/forestadmin-icon.svg | 19 + .../assets/library/svg/forestadmin.svg | 20 + .../assets/library/svg/forever.svg | 10 + .../assets/library/svg/formkeep.svg | 10 + .../assets/library/svg/fortran.svg | 11 + .../assets/library/svg/foundation.svg | 41 + .../logo-design/assets/library/svg/framer.svg | 10 + .../assets/library/svg/framework7-icon.svg | 10 + .../assets/library/svg/framework7.svg | 12 + .../assets/library/svg/freebsd.svg | 12 + .../assets/library/svg/freedcamp-icon.svg | 10 + .../assets/library/svg/freedcamp.svg | 11 + .../assets/library/svg/freedomdefined.svg | 39 + .../assets/library/svg/frontapp.svg | 20 + .../logo-design/assets/library/svg/fsharp.svg | 12 + .../assets/library/svg/fuchsia.svg | 10 + .../assets/library/svg/galliumos.svg | 17 + .../library/svg/game-analytics-icon.svg | 10 + .../assets/library/svg/game-analytics.svg | 13 + .../assets/library/svg/ganache-icon.svg | 13 + .../assets/library/svg/ganache.svg | 14 + .../logo-design/assets/library/svg/gatsby.svg | 10 + .../assets/library/svg/geekbot.svg | 25 + .../assets/library/svg/getyourguide.svg | 10 + .../logo-design/assets/library/svg/ghost.svg | 19 + .../assets/library/svg/giantswarm.svg | 18 + .../assets/library/svg/git-icon.svg | 10 + .../logo-design/assets/library/svg/git.svg | 13 + .../assets/library/svg/gitboard.svg | 11 + .../assets/library/svg/github-actions.svg | 13 + .../assets/library/svg/github-copilot.svg | 10 + .../assets/library/svg/github-icon.svg | 10 + .../assets/library/svg/github-octocat.svg | 22 + .../logo-design/assets/library/svg/github.svg | 10 + .../assets/library/svg/gitkraken.svg | 10 + .../logo-design/assets/library/svg/gitlab.svg | 16 + .../logo-design/assets/library/svg/gitter.svg | 15 + .../logo-design/assets/library/svg/gitup.svg | 58 + .../assets/library/svg/glamorous.svg | 16 + .../logo-design/assets/library/svg/gleam.svg | 16 + .../assets/library/svg/glimmerjs.svg | 11 + .../logo-design/assets/library/svg/glint.svg | 14 + .../assets/library/svg/glitch-icon.svg | 45 + .../logo-design/assets/library/svg/glitch.svg | 41 + .../assets/library/svg/gnome-icon.svg | 10 + .../logo-design/assets/library/svg/gnome.svg | 10 + .../assets/library/svg/gnu-net.svg | 13 + .../logo-design/assets/library/svg/gnu.svg | 10 + .../logo-design/assets/library/svg/go.svg | 10 + .../logo-design/assets/library/svg/gocd.svg | 10 + .../assets/library/svg/gohorse.svg | 10 + .../assets/library/svg/google-360suite.svg | 48 + .../assets/library/svg/google-admob.svg | 12 + .../assets/library/svg/google-ads.svg | 12 + .../assets/library/svg/google-adsense.svg | 12 + .../assets/library/svg/google-analytics.svg | 11 + .../assets/library/svg/google-calendar.svg | 17 + .../library/svg/google-cloud-functions.svg | 21 + .../assets/library/svg/google-cloud-run.svg | 12 + .../assets/library/svg/google-cloud.svg | 13 + .../assets/library/svg/google-currents.svg | 11 + .../assets/library/svg/google-data-studio.svg | 15 + .../assets/library/svg/google-developers.svg | 13 + .../assets/library/svg/google-drive.svg | 15 + .../assets/library/svg/google-fit.svg | 13 + .../assets/library/svg/google-gmail.svg | 14 + .../assets/library/svg/google-gsuite.svg | 10 + .../assets/library/svg/google-home.svg | 13 + .../assets/library/svg/google-icon.svg | 13 + .../assets/library/svg/google-keep.svg | 12 + .../assets/library/svg/google-maps.svg | 14 + .../library/svg/google-marketing-platform.svg | 21 + .../assets/library/svg/google-meet.svg | 16 + .../assets/library/svg/google-one.svg | 17 + .../assets/library/svg/google-optimize.svg | 12 + .../assets/library/svg/google-pay-icon.svg | 13 + .../assets/library/svg/google-pay.svg | 15 + .../assets/library/svg/google-photos.svg | 13 + .../assets/library/svg/google-play-icon.svg | 13 + .../assets/library/svg/google-play.svg | 14 + .../assets/library/svg/google-tag-manager.svg | 13 + .../logo-design/assets/library/svg/google.svg | 15 + .../logo-design/assets/library/svg/gopher.svg | 29 + .../logo-design/assets/library/svg/gradle.svg | 10 + .../assets/library/svg/grafana.svg | 14 + .../logo-design/assets/library/svg/grails.svg | 10 + .../assets/library/svg/graphene.svg | 18 + .../assets/library/svg/graphql.svg | 10 + .../logo-design/assets/library/svg/grav.svg | 10 + .../assets/library/svg/gravatar.svg | 10 + .../assets/library/svg/graylog-icon.svg | 11 + .../assets/library/svg/graylog.svg | 12 + .../assets/library/svg/gridsome-icon.svg | 34 + .../assets/library/svg/gridsome.svg | 35 + .../assets/library/svg/grommet.svg | 11 + .../assets/library/svg/groovehq.svg | 11 + .../logo-design/assets/library/svg/grove.svg | 24 + .../logo-design/assets/library/svg/grpc.svg | 21 + .../logo-design/assets/library/svg/grunt.svg | 81 + .../logo-design/assets/library/svg/gulp.svg | 14 + .../assets/library/svg/gunicorn.svg | 15 + .../logo-design/assets/library/svg/gusto.svg | 13 + .../logo-design/assets/library/svg/gwt.svg | 14 + .../logo-design/assets/library/svg/hack.svg | 14 + .../assets/library/svg/hacker-one.svg | 10 + .../assets/library/svg/haiku-icon.svg | 19 + .../logo-design/assets/library/svg/haml.svg | 12 + .../logo-design/assets/library/svg/hanami.svg | 13 + .../assets/library/svg/handlebars.svg | 10 + .../logo-design/assets/library/svg/hapi.svg | 13 + .../assets/library/svg/hardhat-icon.svg | 20 + .../assets/library/svg/hardhat.svg | 21 + .../assets/library/svg/hashnode-icon.svg | 10 + .../assets/library/svg/hashnode.svg | 11 + .../assets/library/svg/haskell-icon.svg | 12 + .../assets/library/svg/haskell.svg | 13 + .../logo-design/assets/library/svg/hasura.svg | 12 + .../logo-design/assets/library/svg/haxe.svg | 22 + .../logo-design/assets/library/svg/haxl.svg | 10 + .../logo-design/assets/library/svg/hbase.svg | 10 + .../assets/library/svg/headlessui-icon.svg | 19 + .../assets/library/svg/headlessui.svg | 21 + .../logo-design/assets/library/svg/heap.svg | 14 + .../logo-design/assets/library/svg/helm.svg | 11 + .../assets/library/svg/helpscout-icon.svg | 10 + .../assets/library/svg/helpscout.svg | 11 + .../logo-design/assets/library/svg/hermes.svg | 13 + .../assets/library/svg/heroku-icon.svg | 10 + .../assets/library/svg/heroku-redis.svg | 10 + .../logo-design/assets/library/svg/heroku.svg | 11 + .../logo-design/assets/library/svg/hexo.svg | 11 + .../logo-design/assets/library/svg/hhvm.svg | 15 + .../assets/library/svg/hibernate.svg | 13 + .../assets/library/svg/highcharts.svg | 15 + .../assets/library/svg/hipercard.svg | 11 + .../logo-design/assets/library/svg/hoa.svg | 15 + .../assets/library/svg/homebrew.svg | 9 + .../logo-design/assets/library/svg/hoodie.svg | 20 + .../assets/library/svg/hosted-graphite.svg | 10 + .../assets/library/svg/hostgator-icon.svg | 50 + .../assets/library/svg/hostgator.svg | 51 + .../logo-design/assets/library/svg/hotjar.svg | 11 + .../assets/library/svg/houndci.svg | 10 + .../logo-design/assets/library/svg/html-5.svg | 19 + .../assets/library/svg/html5-boilerplate.svg | 15 + .../assets/library/svg/httpie-icon.svg | 10 + .../logo-design/assets/library/svg/httpie.svg | 11 + .../assets/library/svg/hubspot.svg | 16 + .../logo-design/assets/library/svg/huggy.svg | 15 + .../logo-design/assets/library/svg/hugo.svg | 21 + .../assets/library/svg/humongous.svg | 10 + .../logo-design/assets/library/svg/hyper.svg | 17 + .../assets/library/svg/hyperapp.svg | 11 + .../logo-design/assets/library/svg/ibm.svg | 10 + .../logo-design/assets/library/svg/ieee.svg | 10 + .../logo-design/assets/library/svg/ifttt.svg | 10 + .../assets/library/svg/imagemin.svg | 29 + .../assets/library/svg/imba-icon.svg | 10 + .../logo-design/assets/library/svg/imba.svg | 11 + .../assets/library/svg/immer-icon.svg | 10 + .../logo-design/assets/library/svg/immer.svg | 4 + .../assets/library/svg/immutable.svg | 11 + .../logo-design/assets/library/svg/impala.svg | 10 + .../assets/library/svg/importio.svg | 10 + .../logo-design/assets/library/svg/infer.svg | 11 + .../assets/library/svg/inferno.svg | 11 + .../assets/library/svg/influxdb.svg | 10 + .../logo-design/assets/library/svg/ink.svg | 33 + .../assets/library/svg/insomnia.svg | 16 + .../assets/library/svg/instagram-icon.svg | 10 + .../assets/library/svg/instagram.svg | 11 + .../assets/library/svg/intellij-idea.svg | 56 + .../assets/library/svg/intercom-icon.svg | 10 + .../assets/library/svg/intercom.svg | 10 + .../assets/library/svg/internetexplorer.svg | 10 + .../assets/library/svg/invision-icon.svg | 12 + .../assets/library/svg/invision.svg | 12 + .../assets/library/svg/ionic-icon.svg | 10 + .../logo-design/assets/library/svg/ionic.svg | 11 + .../logo-design/assets/library/svg/ios.svg | 10 + .../assets/library/svg/iron-icon.svg | 10 + .../logo-design/assets/library/svg/iron.svg | 12 + .../assets/library/svg/itsalive-icon.svg | 10 + .../assets/library/svg/itsalive.svg | 10 + .../logo-design/assets/library/svg/jade.svg | 11 + .../assets/library/svg/jamstack-icon.svg | 11 + .../assets/library/svg/jamstack.svg | 12 + .../assets/library/svg/jasmine.svg | 20 + .../logo-design/assets/library/svg/java.svg | 17 + .../assets/library/svg/javascript.svg | 12 + .../logo-design/assets/library/svg/jcb.svg | 46 + .../logo-design/assets/library/svg/jekyll.svg | 36 + .../assets/library/svg/jelastic-icon.svg | 20 + .../assets/library/svg/jelastic.svg | 17 + .../assets/library/svg/jenkins.svg | 74 + .../logo-design/assets/library/svg/jest.svg | 11 + .../assets/library/svg/jetbrains.svg | 26 + .../logo-design/assets/library/svg/jfrog.svg | 10 + .../assets/library/svg/jhipster-icon.svg | 11 + .../assets/library/svg/jhipster.svg | 12 + .../logo-design/assets/library/svg/jira.svg | 20 + .../logo-design/assets/library/svg/joomla.svg | 13 + .../assets/library/svg/jquery-mobile.svg | 16 + .../logo-design/assets/library/svg/jquery.svg | 19 + .../logo-design/assets/library/svg/jruby.svg | 14 + .../logo-design/assets/library/svg/jsbin.svg | 37 + .../assets/library/svg/jsdelivr.svg | 12 + .../logo-design/assets/library/svg/jsdom.svg | 11 + .../assets/library/svg/jsfiddle.svg | 10 + .../logo-design/assets/library/svg/json.svg | 19 + .../logo-design/assets/library/svg/jspm.svg | 15 + .../logo-design/assets/library/svg/jss.svg | 12 + .../logo-design/assets/library/svg/juju.svg | 11 + .../logo-design/assets/library/svg/julia.svg | 14 + .../assets/library/svg/jupyter.svg | 15 + .../assets/library/svg/jwt-icon.svg | 19 + .../logo-design/assets/library/svg/jwt.svg | 20 + .../assets/library/svg/kafka-icon.svg | 10 + .../logo-design/assets/library/svg/kafka.svg | 11 + .../logo-design/assets/library/svg/kaios.svg | 10 + .../assets/library/svg/kallithea.svg | 10 + .../logo-design/assets/library/svg/karma.svg | 13 + .../logo-design/assets/library/svg/kde.svg | 11 + .../logo-design/assets/library/svg/keen.svg | 13 + .../logo-design/assets/library/svg/kemal.svg | 12 + .../assets/library/svg/keycdn-icon.svg | 11 + .../logo-design/assets/library/svg/keycdn.svg | 13 + .../assets/library/svg/keystonejs.svg | 14 + .../assets/library/svg/khan_academy-icon.svg | 12 + .../assets/library/svg/khan_academy.svg | 13 + .../logo-design/assets/library/svg/kibana.svg | 13 + .../assets/library/svg/kickstarter-icon.svg | 10 + .../assets/library/svg/kickstarter.svg | 10 + .../assets/library/svg/kinto-icon.svg | 99 + .../logo-design/assets/library/svg/kinto.svg | 100 + .../assets/library/svg/kirby-icon.svg | 10 + .../logo-design/assets/library/svg/kirby.svg | 10 + .../assets/library/svg/kissmetrics.svg | 10 + .../assets/library/svg/kitematic.svg | 12 + .../assets/library/svg/kloudless.svg | 20 + .../logo-design/assets/library/svg/knex.svg | 10 + .../assets/library/svg/knockout.svg | 10 + .../logo-design/assets/library/svg/koa.svg | 10 + .../assets/library/svg/kong-icon.svg | 13 + .../logo-design/assets/library/svg/kong.svg | 14 + .../logo-design/assets/library/svg/kops.svg | 31 + .../logo-design/assets/library/svg/koreio.svg | 23 + .../assets/library/svg/kotlin-icon.svg | 15 + .../logo-design/assets/library/svg/kotlin.svg | 16 + .../logo-design/assets/library/svg/kraken.svg | 63 + .../assets/library/svg/krakenjs.svg | 11 + .../assets/library/svg/kubernetes.svg | 12 + .../assets/library/svg/kustomer.svg | 11 + .../assets/library/svg/laravel.svg | 10 + .../logo-design/assets/library/svg/lastfm.svg | 15 + .../assets/library/svg/lateral.svg | 43 + .../assets/library/svg/launchrock.svg | 10 + .../assets/library/svg/leaflet.svg | 31 + .../assets/library/svg/leankit-icon.svg | 4 + .../assets/library/svg/leankit.svg | 12 + .../logo-design/assets/library/svg/lerna.svg | 10 + .../logo-design/assets/library/svg/less.svg | 29 + .../assets/library/svg/lets-cloud.svg | 13 + .../assets/library/svg/letsencrypt.svg | 17 + .../assets/library/svg/leveldb.svg | 13 + .../assets/library/svg/liftweb.svg | 12 + .../assets/library/svg/lighthouse.svg | 124 + .../assets/library/svg/lightstep-icon.svg | 11 + .../assets/library/svg/lightstep.svg | 5 + .../assets/library/svg/lighttpd.svg | 13 + .../assets/library/svg/linkedin-icon.svg | 10 + .../assets/library/svg/linkedin.svg | 10 + .../assets/library/svg/linkerd.svg | 57 + .../logo-design/assets/library/svg/linode.svg | 12 + .../assets/library/svg/linux-mint.svg | 24 + .../assets/library/svg/linux-tux.svg | 124 + .../assets/library/svg/lit-icon.svg | 13 + .../logo-design/assets/library/svg/lit.svg | 14 + .../logo-design/assets/library/svg/litmus.svg | 19 + .../logo-design/assets/library/svg/loader.svg | 13 + .../logo-design/assets/library/svg/lodash.svg | 12 + .../assets/library/svg/logentries.svg | 13 + .../assets/library/svg/logstash.svg | 12 + .../assets/library/svg/lookback.svg | 10 + .../assets/library/svg/looker-icon.svg | 13 + .../logo-design/assets/library/svg/looker.svg | 14 + .../logo-design/assets/library/svg/loom.svg | 11 + .../assets/library/svg/loopback-icon.svg | 10 + .../assets/library/svg/loopback.svg | 11 + .../logo-design/assets/library/svg/losant.svg | 11 + .../logo-design/assets/library/svg/lua.svg | 16 + .../assets/library/svg/lucene.net.svg | 25 + .../logo-design/assets/library/svg/lucene.svg | 12 + .../logo-design/assets/library/svg/lumen.svg | 10 + .../logo-design/assets/library/svg/macOS.svg | 10 + .../logo-design/assets/library/svg/madge.svg | 24 + .../assets/library/svg/maestro.svg | 13 + .../logo-design/assets/library/svg/mageia.svg | 22 + .../assets/library/svg/magento.svg | 12 + .../assets/library/svg/mailchimp-freddie.svg | 49 + .../assets/library/svg/mailchimp.svg | 15 + .../assets/library/svg/maildeveloper.svg | 16 + .../assets/library/svg/mailgun-icon.svg | 10 + .../assets/library/svg/mailgun.svg | 11 + .../assets/library/svg/mailjet.svg | 4 + .../assets/library/svg/malinajs.svg | 11 + .../assets/library/svg/manjaro.svg | 10 + .../assets/library/svg/manuscript.svg | 15 + .../assets/library/svg/mapbox-icon.svg | 10 + .../logo-design/assets/library/svg/mapbox.svg | 10 + .../assets/library/svg/maps-me.svg | 21 + .../assets/library/svg/mapzen-icon.svg | 10 + .../logo-design/assets/library/svg/mapzen.svg | 11 + .../assets/library/svg/mariadb-icon.svg | 12 + .../assets/library/svg/mariadb.svg | 13 + .../assets/library/svg/marionette.svg | 24 + .../assets/library/svg/markdown.svg | 10 + .../logo-design/assets/library/svg/marko.svg | 65 + .../logo-design/assets/library/svg/marvel.svg | 10 + .../assets/library/svg/mastercard.svg | 13 + .../assets/library/svg/mastodon-icon.svg | 11 + .../assets/library/svg/mastodon.svg | 11 + .../assets/library/svg/material-ui.svg | 13 + .../assets/library/svg/materializecss.svg | 15 + .../assets/library/svg/matplotlib-icon.svg | 27 + .../assets/library/svg/matplotlib.svg | 29 + .../assets/library/svg/mattermost-icon.svg | 10 + .../assets/library/svg/mattermost.svg | 10 + .../logo-design/assets/library/svg/maven.svg | 101 + .../logo-design/assets/library/svg/maxcdn.svg | 12 + .../logo-design/assets/library/svg/mdn.svg | 37 + .../logo-design/assets/library/svg/mdx.svg | 14 + .../assets/library/svg/medium-icon.svg | 10 + .../logo-design/assets/library/svg/medium.svg | 10 + .../assets/library/svg/memcached.svg | 31 + .../assets/library/svg/memsql-icon.svg | 77 + .../logo-design/assets/library/svg/memsql.svg | 60 + .../assets/library/svg/mention.svg | 11 + .../assets/library/svg/mercurial.svg | 30 + .../logo-design/assets/library/svg/mesos.svg | 33 + .../assets/library/svg/metabase.svg | 31 + .../assets/library/svg/metamask-icon.svg | 38 + .../assets/library/svg/metamask.svg | 39 + .../assets/library/svg/meteor-icon.svg | 16 + .../logo-design/assets/library/svg/meteor.svg | 21 + .../assets/library/svg/microcosm.svg | 12 + .../assets/library/svg/microsoft-azure.svg | 28 + .../assets/library/svg/microsoft-edge.svg | 46 + .../assets/library/svg/microsoft-onedrive.svg | 13 + .../assets/library/svg/microsoft-power-bi.svg | 31 + .../assets/library/svg/microsoft-teams.svg | 28 + .../assets/library/svg/microsoft-windows.svg | 10 + .../assets/library/svg/microsoft.svg | 14 + .../assets/library/svg/middleman.svg | 16 + .../assets/library/svg/milligram.svg | 10 + .../assets/library/svg/mint-lang.svg | 20 + .../logo-design/assets/library/svg/mio.svg | 14 + .../logo-design/assets/library/svg/mist.svg | 30 + .../assets/library/svg/mithril.svg | 10 + .../logo-design/assets/library/svg/mixmax.svg | 14 + .../assets/library/svg/mixpanel.svg | 20 + .../logo-design/assets/library/svg/mlab.svg | 20 + .../logo-design/assets/library/svg/mobx.svg | 14 + .../logo-design/assets/library/svg/mocha.svg | 11 + .../assets/library/svg/mockflow-icon.svg | 13 + .../assets/library/svg/mockflow.svg | 14 + .../assets/library/svg/modernizr.svg | 11 + .../assets/library/svg/modx-icon.svg | 13 + .../logo-design/assets/library/svg/modx.svg | 7 + .../assets/library/svg/moltin-icon.svg | 27 + .../logo-design/assets/library/svg/moltin.svg | 28 + .../assets/library/svg/momentjs.svg | 11 + .../assets/library/svg/monday-icon.svg | 12 + .../logo-design/assets/library/svg/monday.svg | 7 + .../logo-design/assets/library/svg/monero.svg | 11 + .../assets/library/svg/mongodb.svg | 17 + .../logo-design/assets/library/svg/mono.svg | 14 + .../logo-design/assets/library/svg/moon.svg | 16 + .../assets/library/svg/mootools.svg | 13 + .../assets/library/svg/morpheus-icon.svg | 11 + .../assets/library/svg/morpheus.svg | 12 + .../assets/library/svg/mozilla.svg | 10 + .../assets/library/svg/mparticle-icon.svg | 10 + .../assets/library/svg/mparticle.svg | 10 + .../assets/library/svg/multipass.svg | 11 + .../assets/library/svg/mysql-icon.svg | 11 + .../logo-design/assets/library/svg/mysql.svg | 12 + .../assets/library/svg/naiveui.svg | 12 + .../assets/library/svg/namecheap.svg | 34 + .../assets/library/svg/nanonets.svg | 10 + .../assets/library/svg/nativescript.svg | 10 + .../assets/library/svg/nats-icon.svg | 14 + .../logo-design/assets/library/svg/nats.svg | 14 + .../logo-design/assets/library/svg/neat.svg | 12 + .../logo-design/assets/library/svg/neo4j.svg | 12 + .../logo-design/assets/library/svg/neovim.svg | 32 + .../logo-design/assets/library/svg/nestjs.svg | 10 + .../assets/library/svg/netbeans.svg | 29 + .../assets/library/svg/netflix-icon.svg | 26 + .../assets/library/svg/netflix.svg | 10 + .../assets/library/svg/netlify.svg | 14 + .../assets/library/svg/new-relic.svg | 20 + .../assets/library/svg/nextjs-icon.svg | 10 + .../logo-design/assets/library/svg/nextjs.svg | 10 + .../logo-design/assets/library/svg/nginx.svg | 11 + .../assets/library/svg/nightwatch.svg | 17 + .../assets/library/svg/nim-lang.svg | 12 + .../logo-design/assets/library/svg/nocodb.svg | 13 + .../logo-design/assets/library/svg/nodal.svg | 13 + .../assets/library/svg/node-sass.svg | 10 + .../assets/library/svg/nodebots.svg | 14 + .../assets/library/svg/nodejs-icon.svg | 10 + .../logo-design/assets/library/svg/nodejs.svg | 56 + .../assets/library/svg/nodemon.svg | 11 + .../logo-design/assets/library/svg/nodeos.svg | 13 + .../assets/library/svg/nodewebkit.svg | 15 + .../logo-design/assets/library/svg/nomad.svg | 13 + .../logo-design/assets/library/svg/noysi.svg | 13 + .../assets/library/svg/npm-icon.svg | 11 + .../logo-design/assets/library/svg/npm.svg | 10 + .../assets/library/svg/nuclide.svg | 13 + .../logo-design/assets/library/svg/numpy.svg | 11 + .../assets/library/svg/nuxt-icon.svg | 11 + .../logo-design/assets/library/svg/nuxt.svg | 12 + .../logo-design/assets/library/svg/nx.svg | 12 + .../logo-design/assets/library/svg/oauth.svg | 53 + .../logo-design/assets/library/svg/ocaml.svg | 30 + .../assets/library/svg/octodns.svg | 18 + .../assets/library/svg/octopus-deploy.svg | 10 + .../logo-design/assets/library/svg/olark.svg | 10 + .../assets/library/svg/onesignal.svg | 10 + .../assets/library/svg/open-graph.svg | 14 + .../assets/library/svg/open-zeppelin-icon.svg | 12 + .../assets/library/svg/open-zeppelin.svg | 13 + .../assets/library/svg/openai-icon.svg | 10 + .../logo-design/assets/library/svg/openai.svg | 11 + .../assets/library/svg/opencart.svg | 14 + .../assets/library/svg/opencollective.svg | 11 + .../logo-design/assets/library/svg/opencv.svg | 13 + .../assets/library/svg/openframeworks.svg | 10 + .../logo-design/assets/library/svg/opengl.svg | 10 + .../library/svg/openjs-foundation-icon.svg | 15 + .../assets/library/svg/openjs-foundation.svg | 17 + .../assets/library/svg/openlayers.svg | 13 + .../assets/library/svg/openshift.svg | 21 + .../assets/library/svg/opensource.svg | 12 + .../assets/library/svg/openstack-icon.svg | 10 + .../assets/library/svg/openstack.svg | 11 + .../assets/library/svg/opentelemetry-icon.svg | 11 + .../assets/library/svg/opentelemetry.svg | 11 + .../logo-design/assets/library/svg/opera.svg | 23 + .../assets/library/svg/opsgenie.svg | 20 + .../assets/library/svg/optimizely.svg | 12 + .../logo-design/assets/library/svg/oracle.svg | 10 + .../assets/library/svg/oreilly.svg | 11 + .../assets/library/svg/origami.svg | 37 + .../logo-design/assets/library/svg/origin.svg | 14 + .../logo-design/assets/library/svg/oshw.svg | 27 + .../assets/library/svg/osquery.svg | 17 + .../logo-design/assets/library/svg/packer.svg | 11 + .../assets/library/svg/pagekit.svg | 10 + .../assets/library/svg/pagekite.svg | 12 + .../assets/library/svg/pagerduty-icon.svg | 10 + .../assets/library/svg/pagerduty.svg | 10 + .../logo-design/assets/library/svg/panda.svg | 22 + .../assets/library/svg/parcel-icon.svg | 114 + .../logo-design/assets/library/svg/parcel.svg | 10 + .../logo-design/assets/library/svg/parse.svg | 10 + .../assets/library/svg/parsehub.svg | 11 + .../assets/library/svg/partytown-icon.svg | 20 + .../assets/library/svg/partytown.svg | 21 + .../assets/library/svg/passbolt-icon.svg | 10 + .../assets/library/svg/passbolt.svg | 11 + .../assets/library/svg/passport.svg | 13 + .../assets/library/svg/patreon.svg | 10 + .../logo-design/assets/library/svg/paypal.svg | 13 + .../logo-design/assets/library/svg/peer5.svg | 13 + .../assets/library/svg/pepperoni.svg | 78 + .../assets/library/svg/percona.svg | 16 + .../assets/library/svg/percy-icon.svg | 10 + .../logo-design/assets/library/svg/percy.svg | 10 + .../assets/library/svg/perf-rocks.svg | 10 + .../logo-design/assets/library/svg/perl.svg | 16 + .../assets/library/svg/phalcon.svg | 37 + .../assets/library/svg/phoenix.svg | 10 + .../assets/library/svg/phonegap-bot.svg | 261 + .../assets/library/svg/phonegap.svg | 14 + .../assets/library/svg/php-alt.svg | 10 + .../logo-design/assets/library/svg/php.svg | 21 + .../assets/library/svg/phpstorm.svg | 31 + .../assets/library/svg/pinterest.svg | 10 + .../assets/library/svg/pipedrive.svg | 33 + .../logo-design/assets/library/svg/pipefy.svg | 10 + .../assets/library/svg/pivotal_tracker.svg | 11 + .../logo-design/assets/library/svg/pixijs.svg | 10 + .../logo-design/assets/library/svg/pkg.svg | 10 + .../assets/library/svg/planless-icon.svg | 13 + .../assets/library/svg/planless.svg | 7 + .../assets/library/svg/plastic-scm.svg | 12 + .../assets/library/svg/platformio.svg | 13 + .../logo-design/assets/library/svg/play.svg | 12 + .../assets/library/svg/playwright.svg | 16 + .../logo-design/assets/library/svg/pm2.svg | 15 + .../logo-design/assets/library/svg/pnpm.svg | 11 + .../assets/library/svg/poeditor.svg | 18 + .../assets/library/svg/polymer.svg | 31 + .../assets/library/svg/postcss.svg | 12 + .../assets/library/svg/postgraphile.svg | 34 + .../assets/library/svg/postgresql.svg | 14 + .../assets/library/svg/postman-icon.svg | 30 + .../assets/library/svg/postman.svg | 31 + .../assets/library/svg/pouchdb.svg | 20 + .../logo-design/assets/library/svg/preact.svg | 13 + .../assets/library/svg/precursor.svg | 10 + .../assets/library/svg/prerender-icon.svg | 13 + .../assets/library/svg/prerender.svg | 14 + .../assets/library/svg/prestashop.svg | 52 + .../logo-design/assets/library/svg/presto.svg | 31 + .../assets/library/svg/prettier.svg | 50 + .../logo-design/assets/library/svg/prisma.svg | 10 + .../assets/library/svg/prismic-icon.svg | 13 + .../assets/library/svg/prismic.svg | 10 + .../assets/library/svg/processwire.svg | 10 + .../assets/library/svg/productboard-icon.svg | 12 + .../assets/library/svg/productboard.svg | 6 + .../assets/library/svg/producthunt.svg | 15 + .../assets/library/svg/progress.svg | 10 + .../assets/library/svg/prometheus.svg | 10 + .../assets/library/svg/promises.svg | 11 + .../logo-design/assets/library/svg/proofy.svg | 12 + .../assets/library/svg/prospect.svg | 11 + .../assets/library/svg/protactor.svg | 12 + .../assets/library/svg/protoio.svg | 10 + .../assets/library/svg/protonet.svg | 10 + .../logo-design/assets/library/svg/prott.svg | 10 + .../logo-design/assets/library/svg/pug.svg | 35 + .../assets/library/svg/pumpkindb.svg | 22 + .../assets/library/svg/puppet-icon.svg | 10 + .../logo-design/assets/library/svg/puppet.svg | 11 + .../assets/library/svg/puppeteer.svg | 15 + .../assets/library/svg/puppy-linux.svg | 47 + .../assets/library/svg/purescript-icon.svg | 10 + .../assets/library/svg/purescript.svg | 10 + .../assets/library/svg/pushbullet.svg | 23 + .../assets/library/svg/pusher-icon.svg | 10 + .../logo-design/assets/library/svg/pusher.svg | 10 + .../logo-design/assets/library/svg/pwa.svg | 12 + .../assets/library/svg/pycharm.svg | 63 + .../logo-design/assets/library/svg/python.svg | 19 + .../assets/library/svg/pytorch.svg | 10 + .../logo-design/assets/library/svg/pyup.svg | 12 + .../logo-design/assets/library/svg/q.svg | 18 + .../logo-design/assets/library/svg/qlik.svg | 12 + .../logo-design/assets/library/svg/qt.svg | 11 + .../assets/library/svg/quarkus-icon.svg | 12 + .../assets/library/svg/quarkus.svg | 13 + .../logo-design/assets/library/svg/quay.svg | 11 + .../assets/library/svg/quobyte.svg | 10 + .../logo-design/assets/library/svg/quora.svg | 10 + .../logo-design/assets/library/svg/r-lang.svg | 15 + .../assets/library/svg/rabbitmq-icon.svg | 10 + .../assets/library/svg/rabbitmq.svg | 12 + .../assets/library/svg/rackspace.svg | 10 + .../logo-design/assets/library/svg/rails.svg | 11 + .../logo-design/assets/library/svg/ramda.svg | 10 + .../logo-design/assets/library/svg/raml.svg | 10 + .../assets/library/svg/rancher-icon.svg | 10 + .../assets/library/svg/rancher.svg | 11 + .../assets/library/svg/raphael.svg | 12 + .../assets/library/svg/raspberry-pi.svg | 23 + .../logo-design/assets/library/svg/rax.svg | 10 + .../assets/library/svg/react-query-icon.svg | 13 + .../assets/library/svg/react-query.svg | 14 + .../assets/library/svg/react-router.svg | 11 + .../assets/library/svg/react-spring.svg | 17 + .../assets/library/svg/react-styleguidist.svg | 76 + .../logo-design/assets/library/svg/react.svg | 10 + .../assets/library/svg/reactivex.svg | 35 + .../logo-design/assets/library/svg/realm.svg | 23 + .../logo-design/assets/library/svg/reapp.svg | 11 + .../assets/library/svg/reasonml-icon.svg | 11 + .../assets/library/svg/reasonml.svg | 12 + .../assets/library/svg/reddit-icon.svg | 11 + .../logo-design/assets/library/svg/reddit.svg | 13 + .../assets/library/svg/redhat-icon.svg | 11 + .../logo-design/assets/library/svg/redhat.svg | 12 + .../logo-design/assets/library/svg/redis.svg | 20 + .../assets/library/svg/redsmin.svg | 20 + .../assets/library/svg/redux-observable.svg | 177 + .../assets/library/svg/redux-saga.svg | 11 + .../logo-design/assets/library/svg/redux.svg | 10 + .../assets/library/svg/redwoodjs.svg | 11 + .../assets/library/svg/reindex.svg | 13 + .../logo-design/assets/library/svg/relay.svg | 10 + .../assets/library/svg/release.svg | 10 + .../assets/library/svg/remix-icon.svg | 10 + .../logo-design/assets/library/svg/remix.svg | 10 + .../assets/library/svg/require.svg | 32 + .../assets/library/svg/rescript-icon.svg | 10 + .../assets/library/svg/rescript.svg | 10 + .../assets/library/svg/rest-li.svg | 10 + .../assets/library/svg/rethinkdb.svg | 10 + .../assets/library/svg/retool-icon.svg | 10 + .../logo-design/assets/library/svg/retool.svg | 11 + .../logo-design/assets/library/svg/riak.svg | 15 + .../logo-design/assets/library/svg/riot.svg | 10 + .../assets/library/svg/rocket-chat-icon.svg | 10 + .../assets/library/svg/rocket-chat.svg | 10 + .../assets/library/svg/rocksdb.svg | 37 + .../assets/library/svg/rocky-linux-icon.svg | 10 + .../assets/library/svg/rocky-linux.svg | 11 + .../assets/library/svg/rollbar-icon.svg | 10 + .../assets/library/svg/rollbar.svg | 11 + .../assets/library/svg/rollupjs.svg | 48 + .../assets/library/svg/rome-icon.svg | 11 + .../logo-design/assets/library/svg/rome.svg | 12 + .../logo-design/assets/library/svg/rsa.svg | 13 + .../logo-design/assets/library/svg/rsmq.svg | 15 + .../assets/library/svg/rubocop.svg | 11 + .../logo-design/assets/library/svg/ruby.svg | 120 + .../assets/library/svg/rubygems.svg | 11 + .../assets/library/svg/rubymine.svg | 36 + .../logo-design/assets/library/svg/rum.svg | 14 + .../assets/library/svg/runscope.svg | 12 + .../logo-design/assets/library/svg/rust.svg | 10 + .../logo-design/assets/library/svg/rxdb.svg | 12 + .../logo-design/assets/library/svg/safari.svg | 180 + .../logo-design/assets/library/svg/sagui.svg | 10 + .../logo-design/assets/library/svg/sails.svg | 11 + .../assets/library/svg/salesforce.svg | 20 + .../assets/library/svg/sameroom.svg | 15 + .../assets/library/svg/samsung.svg | 10 + .../logo-design/assets/library/svg/sanity.svg | 19 + .../assets/library/svg/sass-doc.svg | 11 + .../logo-design/assets/library/svg/sass.svg | 10 + .../assets/library/svg/saucelabs.svg | 10 + .../logo-design/assets/library/svg/scala.svg | 34 + .../assets/library/svg/scaledrone.svg | 16 + .../assets/library/svg/scribd-icon.svg | 10 + .../logo-design/assets/library/svg/scribd.svg | 11 + .../assets/library/svg/section-icon.svg | 12 + .../assets/library/svg/section.svg | 13 + .../assets/library/svg/segment-icon.svg | 10 + .../assets/library/svg/segment.svg | 10 + .../assets/library/svg/selenium.svg | 10 + .../assets/library/svg/semantic-release.svg | 10 + .../assets/library/svg/semantic-ui.svg | 11 + .../assets/library/svg/semantic-web.svg | 13 + .../assets/library/svg/semaphoreci.svg | 11 + .../logo-design/assets/library/svg/sencha.svg | 31 + .../assets/library/svg/sendgrid-icon.svg | 15 + .../assets/library/svg/sendgrid.svg | 16 + .../logo-design/assets/library/svg/seneca.svg | 10 + .../assets/library/svg/sensu-icon.svg | 10 + .../logo-design/assets/library/svg/sensu.svg | 11 + .../assets/library/svg/sentry-icon.svg | 10 + .../logo-design/assets/library/svg/sentry.svg | 10 + .../assets/library/svg/sequelize.svg | 36 + .../assets/library/svg/serverless.svg | 10 + .../assets/library/svg/sherlock-icon.svg | 12 + .../assets/library/svg/sherlock.svg | 13 + .../assets/library/svg/shields.svg | 19 + .../logo-design/assets/library/svg/shipit.svg | 14 + .../assets/library/svg/shippable.svg | 11 + .../logo-design/assets/library/svg/shogun.svg | 10 + .../assets/library/svg/shopify.svg | 12 + .../assets/library/svg/sidekick.svg | 10 + .../assets/library/svg/sidekiq-icon.svg | 11 + .../assets/library/svg/sidekiq.svg | 12 + .../logo-design/assets/library/svg/signal.svg | 10 + .../assets/library/svg/sinatra.svg | 61 + .../assets/library/svg/sitepoint.svg | 11 + .../assets/library/svg/skaffolder.svg | 11 + .../logo-design/assets/library/svg/sketch.svg | 18 + .../assets/library/svg/skylight.svg | 18 + .../logo-design/assets/library/svg/skype.svg | 10 + .../assets/library/svg/slack-icon.svg | 13 + .../logo-design/assets/library/svg/slack.svg | 14 + .../logo-design/assets/library/svg/slides.svg | 13 + .../logo-design/assets/library/svg/slim.svg | 4 + .../assets/library/svg/smartling.svg | 10 + .../assets/library/svg/smashingmagazine.svg | 15 + .../assets/library/svg/snap-svg.svg | 34 + .../assets/library/svg/snowflake-icon.svg | 10 + .../assets/library/svg/snowflake.svg | 11 + .../assets/library/svg/snowpack.svg | 10 + .../logo-design/assets/library/svg/snupps.svg | 10 + .../logo-design/assets/library/svg/snyk.svg | 35 + .../assets/library/svg/socket.io.svg | 6 + .../assets/library/svg/solarwinds.svg | 11 + .../logo-design/assets/library/svg/solid.svg | 14 + .../assets/library/svg/solidity.svg | 15 + .../assets/library/svg/solidjs-icon.svg | 35 + .../assets/library/svg/solidjs.svg | 36 + .../logo-design/assets/library/svg/solr.svg | 14 + .../assets/library/svg/sonarqube.svg | 11 + .../assets/library/svg/soundcloud.svg | 108 + .../assets/library/svg/sourcegraph.svg | 12 + .../assets/library/svg/sourcetrail.svg | 10 + .../assets/library/svg/sourcetree.svg | 15 + .../logo-design/assets/library/svg/spark.svg | 16 + .../assets/library/svg/sparkcentral.svg | 11 + .../assets/library/svg/sparkpost.svg | 11 + .../assets/library/svg/speakerdeck.svg | 10 + .../assets/library/svg/speedcurve.svg | 10 + .../assets/library/svg/spidermonkey-icon.svg | 10 + .../assets/library/svg/spidermonkey.svg | 10 + .../assets/library/svg/spinnaker.svg | 38 + .../logo-design/assets/library/svg/splunk.svg | 10 + .../assets/library/svg/spotify-icon.svg | 10 + .../assets/library/svg/spotify.svg | 10 + .../logo-design/assets/library/svg/spree.svg | 15 + .../assets/library/svg/spring-icon.svg | 11 + .../logo-design/assets/library/svg/spring.svg | 12 + .../logo-design/assets/library/svg/sqlite.svg | 18 + .../logo-design/assets/library/svg/square.svg | 11 + .../assets/library/svg/squarespace.svg | 10 + .../assets/library/svg/stackbit-icon.svg | 10 + .../assets/library/svg/stackbit.svg | 12 + .../assets/library/svg/stackoverflow-icon.svg | 11 + .../assets/library/svg/stackoverflow.svg | 28 + .../assets/library/svg/stackshare.svg | 11 + .../assets/library/svg/statuspage.svg | 15 + .../assets/library/svg/stdlib-icon.svg | 51 + .../logo-design/assets/library/svg/stdlib.svg | 53 + .../logo-design/assets/library/svg/steam.svg | 10 + .../assets/library/svg/stenciljs-icon.svg | 10 + .../assets/library/svg/stenciljs.svg | 10 + .../logo-design/assets/library/svg/stetho.svg | 12 + .../assets/library/svg/stickermule.svg | 12 + .../assets/library/svg/stimulus.svg | 10 + .../logo-design/assets/library/svg/stitch.svg | 10 + .../assets/library/svg/stoplight.svg | 12 + .../assets/library/svg/storybook-icon.svg | 16 + .../assets/library/svg/storybook.svg | 17 + .../assets/library/svg/strapi-icon.svg | 12 + .../logo-design/assets/library/svg/strapi.svg | 6 + .../assets/library/svg/strider.svg | 14 + .../logo-design/assets/library/svg/stripe.svg | 10 + .../logo-design/assets/library/svg/struts.svg | 19 + .../assets/library/svg/styleci.svg | 11 + .../assets/library/svg/stylefmt.svg | 13 + .../assets/library/svg/stylelint.svg | 10 + .../logo-design/assets/library/svg/stylis.svg | 14 + .../logo-design/assets/library/svg/stylus.svg | 10 + .../assets/library/svg/sublimetext-icon.svg | 17 + .../assets/library/svg/sublimetext.svg | 13 + .../assets/library/svg/subversion.svg | 10 + .../assets/library/svg/sugarss.svg | 571 + .../assets/library/svg/supabase-icon.svg | 20 + .../assets/library/svg/supabase.svg | 21 + .../logo-design/assets/library/svg/surge.svg | 39 + .../assets/library/svg/survicate.svg | 12 + .../logo-design/assets/library/svg/suse.svg | 12 + .../logo-design/assets/library/svg/susy.svg | 10 + .../assets/library/svg/svelte-icon.svg | 11 + .../logo-design/assets/library/svg/svelte.svg | 12 + .../logo-design/assets/library/svg/svg.svg | 11 + .../assets/library/svg/swagger.svg | 12 + .../logo-design/assets/library/svg/swift.svg | 20 + .../assets/library/svg/swiftype.svg | 11 + .../assets/library/svg/symfony.svg | 11 + .../assets/library/svg/sysdig-icon.svg | 10 + .../logo-design/assets/library/svg/t3.svg | 21 + .../assets/library/svg/tableau-icon.svg | 18 + .../assets/library/svg/tableau.svg | 19 + .../logo-design/assets/library/svg/taiga.svg | 18 + .../assets/library/svg/tailwindcss-icon.svg | 14 + .../assets/library/svg/tailwindcss.svg | 15 + .../assets/library/svg/tapcart-icon.svg | 10 + .../assets/library/svg/tapcart.svg | 11 + .../assets/library/svg/targetprocess.svg | 22 + .../assets/library/svg/taskade-icon.svg | 12 + .../assets/library/svg/taskade.svg | 6 + .../assets/library/svg/tastejs.svg | 615 + .../logo-design/assets/library/svg/tauri.svg | 13 + .../assets/library/svg/tealium.svg | 11 + .../assets/library/svg/teamgrid.svg | 10 + .../assets/library/svg/teamwork-icon.svg | 12 + .../assets/library/svg/teamwork.svg | 11 + .../assets/library/svg/telegram.svg | 13 + .../assets/library/svg/tensorflow.svg | 12 + .../assets/library/svg/terminal.svg | 11 + .../assets/library/svg/terraform-icon.svg | 11 + .../assets/library/svg/terraform.svg | 12 + .../assets/library/svg/terser-icon.svg | 16 + .../logo-design/assets/library/svg/terser.svg | 31 + .../assets/library/svg/testing-library.svg | 295 + .../assets/library/svg/testlodge.svg | 21 + .../assets/library/svg/threejs.svg | 10 + .../assets/library/svg/tidal-icon.svg | 10 + .../logo-design/assets/library/svg/tidal.svg | 11 + .../assets/library/svg/tiktok-icon.svg | 12 + .../logo-design/assets/library/svg/tiktok.svg | 15 + .../logo-design/assets/library/svg/tnw.svg | 10 + .../assets/library/svg/todoist-icon.svg | 13 + .../assets/library/svg/todoist.svg | 14 + .../assets/library/svg/todomvc.svg | 11 + .../logo-design/assets/library/svg/tomcat.svg | 15 + .../logo-design/assets/library/svg/toml.svg | 12 + .../logo-design/assets/library/svg/tor.svg | 15 + .../logo-design/assets/library/svg/torus.svg | 23 + .../assets/library/svg/traackr.svg | 10 + .../logo-design/assets/library/svg/trac.svg | 11 + .../library/svg/travis-ci-monochrome.svg | 13 + .../assets/library/svg/travis-ci.svg | 52 + .../assets/library/svg/treasuredata-icon.svg | 29 + .../assets/library/svg/treasuredata.svg | 30 + .../assets/library/svg/treehouse.svg | 10 + .../logo-design/assets/library/svg/trello.svg | 16 + .../assets/library/svg/truffle-icon.svg | 13 + .../assets/library/svg/truffle.svg | 14 + .../logo-design/assets/library/svg/tsnode.svg | 22 + .../logo-design/assets/library/svg/tsu.svg | 10 + .../logo-design/assets/library/svg/tsuru.svg | 10 + .../assets/library/svg/tumblr-icon.svg | 10 + .../logo-design/assets/library/svg/tumblr.svg | 10 + .../logo-design/assets/library/svg/tunein.svg | 10 + .../logo-design/assets/library/svg/tuple.svg | 12 + .../assets/library/svg/turborepo-icon.svg | 40 + .../assets/library/svg/turborepo.svg | 40 + .../logo-design/assets/library/svg/turret.svg | 10 + .../assets/library/svg/twilio-icon.svg | 10 + .../logo-design/assets/library/svg/twilio.svg | 10 + .../logo-design/assets/library/svg/twitch.svg | 10 + .../assets/library/svg/twitter.svg | 10 + .../assets/library/svg/typeform-icon.svg | 10 + .../assets/library/svg/typeform.svg | 10 + .../assets/library/svg/typescript-icon.svg | 12 + .../assets/library/svg/typescript.svg | 10 + .../assets/library/svg/typo3-icon.svg | 10 + .../logo-design/assets/library/svg/typo3.svg | 11 + .../logo-design/assets/library/svg/ubuntu.svg | 11 + .../assets/library/svg/udacity-icon.svg | 10 + .../assets/library/svg/udacity.svg | 11 + .../assets/library/svg/udemy-icon.svg | 11 + .../logo-design/assets/library/svg/udemy.svg | 11 + .../logo-design/assets/library/svg/uikit.svg | 10 + .../logo-design/assets/library/svg/umu.svg | 10 + .../assets/library/svg/unbounce-icon.svg | 10 + .../assets/library/svg/unbounce.svg | 10 + .../assets/library/svg/undertow.svg | 13 + .../assets/library/svg/unionpay.svg | 13 + .../logo-design/assets/library/svg/unitjs.svg | 19 + .../assets/library/svg/unito-icon.svg | 10 + .../logo-design/assets/library/svg/unito.svg | 11 + .../logo-design/assets/library/svg/unity.svg | 10 + .../logo-design/assets/library/svg/unocss.svg | 12 + .../assets/library/svg/unrealengine-icon.svg | 10 + .../assets/library/svg/unrealengine.svg | 12 + .../logo-design/assets/library/svg/upcase.svg | 15 + .../logo-design/assets/library/svg/upwork.svg | 11 + .../assets/library/svg/user-testing-icon.svg | 10 + .../assets/library/svg/user-testing.svg | 10 + .../assets/library/svg/uservoice-icon.svg | 10 + .../assets/library/svg/uservoice.svg | 11 + .../logo-design/assets/library/svg/uwsgi.svg | 26 + .../assets/library/svg/v8-ignition.svg | 32 + .../assets/library/svg/v8-turbofan.svg | 40 + .../logo-design/assets/library/svg/v8.svg | 22 + .../logo-design/assets/library/svg/vaadin.svg | 11 + .../logo-design/assets/library/svg/vaddy.svg | 14 + .../assets/library/svg/vagrant-icon.svg | 11 + .../assets/library/svg/vagrant.svg | 12 + .../assets/library/svg/vault-icon.svg | 10 + .../logo-design/assets/library/svg/vault.svg | 10 + .../assets/library/svg/vector-timber.svg | 10 + .../assets/library/svg/vercel-icon.svg | 10 + .../logo-design/assets/library/svg/vercel.svg | 10 + .../assets/library/svg/verdaccio-icon.svg | 12 + .../assets/library/svg/verdaccio.svg | 14 + .../assets/library/svg/vernemq.svg | 27 + .../logo-design/assets/library/svg/vim.svg | 29 + .../assets/library/svg/vimeo-icon.svg | 10 + .../logo-design/assets/library/svg/vimeo.svg | 14 + .../logo-design/assets/library/svg/visa.svg | 14 + .../assets/library/svg/visaelectron.svg | 10 + .../assets/library/svg/visual-studio-code.svg | 22 + .../assets/library/svg/visual-studio.svg | 13 + .../logo-design/assets/library/svg/vitejs.svg | 20 + .../logo-design/assets/library/svg/vitest.svg | 12 + .../assets/library/svg/vivaldi-icon.svg | 16 + .../assets/library/svg/vivaldi.svg | 17 + .../logo-design/assets/library/svg/vlang.svg | 28 + .../logo-design/assets/library/svg/void.svg | 16 + .../logo-design/assets/library/svg/vue.svg | 12 + .../assets/library/svg/vuetifyjs.svg | 13 + .../logo-design/assets/library/svg/vueuse.svg | 11 + .../logo-design/assets/library/svg/vulkan.svg | 10 + .../logo-design/assets/library/svg/vultr.svg | 11 + .../logo-design/assets/library/svg/vwo.svg | 12 + .../logo-design/assets/library/svg/w3c.svg | 13 + .../assets/library/svg/waffle-icon.svg | 183 + .../logo-design/assets/library/svg/waffle.svg | 10 + .../assets/library/svg/wagtail.svg | 10 + .../assets/library/svg/wakatime.svg | 10 + .../assets/library/svg/watchman.svg | 17 + .../logo-design/assets/library/svg/wearos.svg | 13 + .../logo-design/assets/library/svg/weave.svg | 13 + .../assets/library/svg/web-fundamentals.svg | 11 + .../assets/library/svg/web.dev-icon.svg | 12 + .../assets/library/svg/web.dev.svg | 6 + .../logo-design/assets/library/svg/web3js.svg | 12 + .../assets/library/svg/webassembly.svg | 10 + .../assets/library/svg/webcomponents.svg | 33 + .../assets/library/svg/webdriverio.svg | 13 + .../assets/library/svg/webflow.svg | 10 + .../assets/library/svg/webhint-icon.svg | 10 + .../assets/library/svg/webhint.svg | 14 + .../assets/library/svg/webhooks.svg | 12 + .../assets/library/svg/webix-icon.svg | 80 + .../logo-design/assets/library/svg/webix.svg | 76 + .../logo-design/assets/library/svg/webmin.svg | 10 + .../assets/library/svg/webpack.svg | 12 + .../assets/library/svg/webplatform.svg | 21 + .../logo-design/assets/library/svg/webrtc.svg | 20 + .../assets/library/svg/websocket.svg | 10 + .../assets/library/svg/webstorm.svg | 26 + .../assets/library/svg/webtask.svg | 14 + .../assets/library/svg/webtorrent.svg | 12 + .../logo-design/assets/library/svg/weebly.svg | 10 + .../logo-design/assets/library/svg/whalar.svg | 10 + .../assets/library/svg/whatsapp.svg | 11 + .../logo-design/assets/library/svg/whatwg.svg | 12 + .../assets/library/svg/wicket-icon.svg | 11 + .../logo-design/assets/library/svg/wicket.svg | 12 + .../logo-design/assets/library/svg/wifi.svg | 10 + .../assets/library/svg/wildfly.svg | 22 + .../logo-design/assets/library/svg/wire.svg | 10 + .../logo-design/assets/library/svg/wix.svg | 10 + .../logo-design/assets/library/svg/wmr.svg | 91 + .../assets/library/svg/woocommerce-icon.svg | 10 + .../assets/library/svg/woocommerce.svg | 11 + .../logo-design/assets/library/svg/woopra.svg | 10 + .../assets/library/svg/wordpress-icon.svg | 10 + .../assets/library/svg/wordpress.svg | 12 + .../assets/library/svg/workboard.svg | 11 + .../assets/library/svg/workplace.svg | 10 + .../assets/library/svg/wpengine.svg | 10 + .../logo-design/assets/library/svg/wufoo.svg | 12 + .../assets/library/svg/xamarin.svg | 10 + .../logo-design/assets/library/svg/xampp.svg | 11 + .../logo-design/assets/library/svg/xcart.svg | 24 + .../logo-design/assets/library/svg/xero.svg | 11 + .../assets/library/svg/xplenty.svg | 12 + .../logo-design/assets/library/svg/xstate.svg | 11 + .../logo-design/assets/library/svg/xtend.svg | 10 + .../assets/library/svg/xwiki-icon.svg | 14 + .../logo-design/assets/library/svg/xwiki.svg | 15 + .../logo-design/assets/library/svg/yahoo.svg | 10 + .../logo-design/assets/library/svg/yaml.svg | 15 + .../logo-design/assets/library/svg/yammer.svg | 10 + .../assets/library/svg/yandex-ru.svg | 11 + .../logo-design/assets/library/svg/yarn.svg | 11 + .../assets/library/svg/ycombinator.svg | 11 + .../logo-design/assets/library/svg/yeoman.svg | 49 + .../logo-design/assets/library/svg/yii.svg | 30 + .../assets/library/svg/youtrack.svg | 20 + .../assets/library/svg/youtube-icon.svg | 11 + .../assets/library/svg/youtube.svg | 5 + .../assets/library/svg/zapier-icon.svg | 10 + .../logo-design/assets/library/svg/zapier.svg | 10 + .../assets/library/svg/zend-framework.svg | 13 + .../assets/library/svg/zendesk-icon.svg | 10 + .../assets/library/svg/zendesk.svg | 10 + .../assets/library/svg/zenhub-icon.svg | 11 + .../logo-design/assets/library/svg/zenhub.svg | 10 + .../logo-design/assets/library/svg/zeplin.svg | 17 + .../logo-design/assets/library/svg/zoho.svg | 41 + .../assets/library/svg/zorin-os.svg | 10 + .../logo-design/assets/library/svg/zube.svg | 10 + .../assets/library/svg/zulip-icon.svg | 14 + .../logo-design/assets/library/svg/zulip.svg | 10 + .../logo-design/assets/library/svg/zwave.svg | 10 + .../skills/logo-design/references/color.md | 142 + .../skills/logo-design/references/critique.md | 66 + .../logo-design/references/discovery-brief.md | 187 + .../logo-design/references/identity-system.md | 146 + .../logo-design/references/library-guide.md | 164 + .../logo-design/references/mark-types.md | 186 + .../references/presentation-delivery.md | 121 + .../logo-design/references/principles.md | 234 + .../skills/logo-design/references/process.md | 131 + .../skills/logo-design/references/redesign.md | 72 + .../references/svg-construction.md | 193 + .../references/testing-checklist.md | 75 + .../logo-design/references/typography.md | 135 + .../references/visual-techniques.md | 226 + .../logo-design/scripts/build_catalog.py | 216 + .../logo-design/scripts/concept_sheet.py | 146 + .../logo-design/scripts/export_variants.py | 233 + .../logo-design/scripts/presentation_board.py | 409 + .../logo-design/scripts/preview_sheet.py | 249 + .../skills/logo-design/scripts/render_png.py | 381 + .../logo-design/scripts/search_library.py | 201 + .../skills/logo-design/scripts/svg_audit.py | 261 + .claude/skills/logo-design/scripts/svglib.py | 599 + .../templates/brand-guidelines-template.md | 39 + .../templates/presentation-spec.example.json | 59 + skills-lock.json | 6 + 1463 files changed, 62355 insertions(+) create mode 100644 .claude/skills/logo-design/SKILL.md create mode 100644 .claude/skills/logo-design/assets/library/catalog.json create mode 100644 .claude/skills/logo-design/assets/library/classifications.json create mode 100644 .claude/skills/logo-design/assets/library/gallery.html create mode 100644 .claude/skills/logo-design/assets/library/stats.json create mode 100644 .claude/skills/logo-design/assets/library/svg/100tb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/500px.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/active-campaign-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/active-campaign.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/adonisjs-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/adonisjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/adroll.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/adyen.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aerospike-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aerospike.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/airbnb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/airbrake.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/airflow.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/airtable.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/akamai.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/akka.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/alfresco.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/algolia.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/alpinejs-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/alpinejs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/altair.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/amazon-chime.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/amazon-connect.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/amex.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/amp-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/amp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ampersand.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/amplication-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/amplication.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/amplitude-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/amplitude.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/android-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/android.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/angellist.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/angular-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/angular.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ansible.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ant-design.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/apache-camel.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/apache.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/apache_cloudstack.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/apiary.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/apollostack.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/apostrophe.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/appbaseio-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/appbaseio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/appcircle-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/appcircle.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/appcode.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/appdynamics.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/appium.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/apple-app-store.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/apple-pay.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/apple.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/appsignal-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/appsignal.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/apptentive.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/appveyor.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/arangodb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/archlinux.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/arduino.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/argo-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/argo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/armory.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/asana.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/asciidoctor.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/assembla-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/assembla.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/astro.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/astronomer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/atlassian.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/atom-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/atom.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/atomic-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/atomic.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aurelia.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aurora.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/auth0-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/auth0.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/authy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/autoit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/autoprefixer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ava.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/awesome.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-amplify.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-api-gateway.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-app-mesh.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-appflow.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-appsync.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-athena.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-aurora.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-backup.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-batch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-certificate-manager.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-cloudformation.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-cloudfront.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-cloudsearch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-cloudtrail.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-cloudwatch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-codebuild.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-codecommit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-codedeploy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-codepipeline.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-codestar.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-cognito.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-config.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-documentdb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-dynamodb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-ec2.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-ecs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-eks.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-elastic-beanstalk.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-elasticache.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-elb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-eventbridge.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-fargate.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-glacier.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-glue.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-iam.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-keyspaces.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-kinesis.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-kms.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-lake-formation.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-lambda.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-lightsail.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-mq.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-msk.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-neptune.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-open-search.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-opsworks.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-quicksight.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-rds.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-redshift.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-route53.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-s3.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-secrets-manager.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-ses.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-shield.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-sns.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-sqs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-step-functions.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-systems-manager.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-timestream.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-vpc.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-waf.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws-xray.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/aws.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/axios.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/babel.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/backbone-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/backbone.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/backerkit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/baker-street.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/balena.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bamboo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/basecamp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/basekit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bash-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bash.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/batch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/beats.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/behance.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bem-2.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bem.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bigpanda.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bing.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bitbucket.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bitcoin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bitnami.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bitrise-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bitrise.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/blender.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/blitzjs-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/blitzjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/blocs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/blogger.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/blossom.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/blueprint.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bluetooth.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/booqable-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/booqable.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bootstrap.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bosun.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/botanalytics.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bourbon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bower.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/box.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/brackets.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/brainjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/branch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/brandfolder-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/brandfolder.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/brave.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/braze.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/broccoli.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/brotli.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/browserify-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/browserify.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/browserling.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/browserslist.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/browserstack.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/browsersync.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/brunch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/buck.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/buddy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/buffer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bugherd.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bugsee.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bugsnag-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bugsnag.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/buildkite-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/buildkite.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/bulma.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/c-plusplus.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/c-sharp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/c.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cachet.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/caffe2.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cakephp-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cakephp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/campaignmonitor-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/campaignmonitor.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/canjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/capacitorjs-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/capacitorjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/capistrano.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/carbide.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cardano-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cardano.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cassandra.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/centos-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/centos.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/certbot.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ceylon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/chai.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/chalk.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/chargebee-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/chargebee.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/chef.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/chevereto.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/chromatic-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/chromatic.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/chrome.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cinder.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/circleci.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cirrus-ci.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cirrus.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/clion.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cljs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/clojure.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/close.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cloud9.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cloudacademy-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cloudacademy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cloudcraft.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cloudflare.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cloudinary.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cloudlinux.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cobalt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cockpit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cocoapods.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codacy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codebase.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codebeat.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codecademy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codeception.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codeclimate.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codecov.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codefactor-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codefactor.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codeigniter.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codepen-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codepen.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codepush.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codersrank.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/coderwall.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codesandbox.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codeship.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/codrops.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/coffeescript.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/commitizen.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/compass.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/componentkit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/compose.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/composer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/conan-io.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/concourse.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/concrete5.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/confluence.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/consul.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/contentful.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/convox.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/copyleft-pirate.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/copyleft.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/corda.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cordova.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/coreos-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/coreos.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/couchbase.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/couchdb-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/couchdb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/coursera.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/coveralls.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cpanel.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/craftcms.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/crashlytics.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/crateio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/create-react-app.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/createjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cross-browser-testing.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/crucible.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/crystal.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/css-3.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/css-3_official.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cssnext.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cucumber.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/curl.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/customerio-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/customerio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cyclejs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/cypress.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/d3.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dart.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dashlane-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dashlane.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/database-labs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/datadog.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/datocms-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/datocms.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dbt-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dbt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dcos-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dcos.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/debian.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/delighted-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/delighted.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/deno.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/deployhq.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/derby.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/designernews.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/deviantart.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dgraph-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dgraph.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dialogflow.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/digital-ocean.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dimer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dinersclub.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/discord-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/discord.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/discover.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/disqus.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/django-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/django.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dockbit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/docker-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/docker.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/doctrine.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/docusaurus.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dojo-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dojo-toolkit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dojo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dotnet.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dreamhost.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dribbble-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dribbble.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/drift.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/drip.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/drizzle-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/drizzle.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/drone-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/drone.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dropbox.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dropmark.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dropzone.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/drupal-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/drupal.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/duckduckgo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dynatrace-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dynatrace.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/dyndns.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ebanx.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/eclipse-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/eclipse.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/editorconfig.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/egghead.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/elasticsearch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/electron.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/element.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/elemental-ui.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/elementary.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ello.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/elm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/elo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/emacs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/embedly.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ember-tomster.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ember.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/emmet.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/engine-yard-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/engine-yard.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/envato.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/envoy-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/envoy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/envoyer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/enyo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/erlang.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/es6.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/esbuild.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/esdoc.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/eslint-old.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/eslint.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/eta-lang.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/etcd.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ethereum-color.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ethereum.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ethers.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ethnio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/eventbrite-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/eventbrite.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/eventsentry.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/evergreen-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/evergreen.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/expo-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/expo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/express.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fabric.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/facebook.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/falcor.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fastify-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fastify.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fastlane.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fastly.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/feathersjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fedora.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fetch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/figma.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/firebase.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/firefox.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flannel.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flarum.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flask.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flat-ui.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flattr-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flattr.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fleep.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flickr.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flight.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/floodio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flow.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flowxo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/floydhub.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flutter.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/flux.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fluxxor.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fly.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fomo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/font-awesome.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/forestadmin-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/forestadmin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/forever.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/formkeep.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fortran.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/foundation.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/framer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/framework7-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/framework7.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/freebsd.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/freedcamp-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/freedcamp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/freedomdefined.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/frontapp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fsharp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/fuchsia.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/galliumos.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/game-analytics-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/game-analytics.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ganache-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ganache.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gatsby.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/geekbot.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/getyourguide.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ghost.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/giantswarm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/git-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/git.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gitboard.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/github-actions.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/github-copilot.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/github-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/github-octocat.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/github.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gitkraken.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gitlab.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gitter.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gitup.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/glamorous.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gleam.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/glimmerjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/glint.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/glitch-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/glitch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gnome-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gnome.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gnu-net.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gnu.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/go.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gocd.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gohorse.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-360suite.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-admob.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-ads.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-adsense.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-analytics.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-calendar.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-cloud-functions.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-cloud-run.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-cloud.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-currents.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-data-studio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-developers.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-drive.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-fit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-gmail.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-gsuite.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-home.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-keep.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-maps.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-marketing-platform.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-meet.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-one.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-optimize.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-pay-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-pay.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-photos.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-play-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-play.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google-tag-manager.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/google.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gopher.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gradle.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/grafana.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/grails.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/graphene.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/graphql.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/grav.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gravatar.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/graylog-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/graylog.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gridsome-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gridsome.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/grommet.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/groovehq.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/grove.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/grpc.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/grunt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gulp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gunicorn.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gusto.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/gwt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hack.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hacker-one.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/haiku-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/haml.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hanami.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/handlebars.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hapi.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hardhat-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hardhat.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hashnode-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hashnode.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/haskell-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/haskell.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hasura.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/haxe.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/haxl.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hbase.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/headlessui-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/headlessui.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/heap.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/helm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/helpscout-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/helpscout.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hermes.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/heroku-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/heroku-redis.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/heroku.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hexo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hhvm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hibernate.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/highcharts.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hipercard.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hoa.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/homebrew.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hoodie.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hosted-graphite.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hostgator-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hostgator.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hotjar.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/houndci.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/html-5.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/html5-boilerplate.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/httpie-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/httpie.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hubspot.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/huggy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hugo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/humongous.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hyper.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/hyperapp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ibm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ieee.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ifttt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/imagemin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/imba-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/imba.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/immer-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/immer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/immutable.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/impala.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/importio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/infer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/inferno.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/influxdb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ink.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/insomnia.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/instagram-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/instagram.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/intellij-idea.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/intercom-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/intercom.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/internetexplorer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/invision-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/invision.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ionic-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ionic.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ios.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/iron-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/iron.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/itsalive-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/itsalive.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jade.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jamstack-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jamstack.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jasmine.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/java.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/javascript.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jcb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jekyll.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jelastic-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jelastic.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jenkins.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jest.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jetbrains.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jfrog.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jhipster-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jhipster.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jira.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/joomla.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jquery-mobile.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jquery.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jruby.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jsbin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jsdelivr.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jsdom.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jsfiddle.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/json.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jspm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jss.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/juju.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/julia.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jupyter.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jwt-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/jwt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kafka-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kafka.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kaios.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kallithea.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/karma.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kde.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/keen.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kemal.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/keycdn-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/keycdn.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/keystonejs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/khan_academy-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/khan_academy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kibana.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kickstarter-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kickstarter.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kinto-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kinto.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kirby-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kirby.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kissmetrics.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kitematic.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kloudless.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/knex.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/knockout.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/koa.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kong-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kong.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kops.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/koreio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kotlin-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kotlin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kraken.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/krakenjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kubernetes.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/kustomer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/laravel.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lastfm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lateral.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/launchrock.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/leaflet.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/leankit-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/leankit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lerna.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/less.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lets-cloud.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/letsencrypt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/leveldb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/liftweb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lighthouse.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lightstep-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lightstep.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lighttpd.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/linkedin-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/linkedin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/linkerd.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/linode.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/linux-mint.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/linux-tux.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lit-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/litmus.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/loader.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lodash.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/logentries.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/logstash.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lookback.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/looker-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/looker.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/loom.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/loopback-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/loopback.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/losant.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lua.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lucene.net.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lucene.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/lumen.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/macOS.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/madge.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/maestro.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mageia.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/magento.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mailchimp-freddie.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mailchimp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/maildeveloper.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mailgun-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mailgun.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mailjet.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/malinajs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/manjaro.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/manuscript.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mapbox-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mapbox.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/maps-me.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mapzen-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mapzen.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mariadb-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mariadb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/marionette.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/markdown.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/marko.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/marvel.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mastercard.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mastodon-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mastodon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/material-ui.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/materializecss.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/matplotlib-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/matplotlib.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mattermost-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mattermost.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/maven.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/maxcdn.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mdn.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mdx.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/medium-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/medium.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/memcached.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/memsql-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/memsql.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mention.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mercurial.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mesos.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/metabase.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/metamask-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/metamask.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/meteor-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/meteor.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/microcosm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/microsoft-azure.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/microsoft-edge.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/microsoft-onedrive.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/microsoft-power-bi.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/microsoft-teams.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/microsoft-windows.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/microsoft.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/middleman.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/milligram.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mint-lang.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mist.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mithril.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mixmax.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mixpanel.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mlab.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mobx.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mocha.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mockflow-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mockflow.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/modernizr.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/modx-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/modx.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/moltin-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/moltin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/momentjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/monday-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/monday.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/monero.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mongodb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mono.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/moon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mootools.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/morpheus-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/morpheus.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mozilla.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mparticle-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mparticle.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/multipass.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mysql-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/mysql.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/naiveui.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/namecheap.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nanonets.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nativescript.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nats-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nats.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/neat.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/neo4j.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/neovim.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nestjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/netbeans.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/netflix-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/netflix.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/netlify.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/new-relic.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nextjs-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nextjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nginx.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nightwatch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nim-lang.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nocodb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nodal.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/node-sass.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nodebots.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nodejs-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nodejs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nodemon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nodeos.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nodewebkit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nomad.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/noysi.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/npm-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/npm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nuclide.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/numpy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nuxt-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nuxt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/nx.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/oauth.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ocaml.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/octodns.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/octopus-deploy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/olark.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/onesignal.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/open-graph.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/open-zeppelin-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/open-zeppelin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/openai-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/openai.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/opencart.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/opencollective.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/opencv.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/openframeworks.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/opengl.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/openjs-foundation-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/openjs-foundation.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/openlayers.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/openshift.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/opensource.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/openstack-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/openstack.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/opentelemetry-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/opentelemetry.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/opera.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/opsgenie.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/optimizely.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/oracle.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/oreilly.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/origami.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/origin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/oshw.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/osquery.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/packer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pagekit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pagekite.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pagerduty-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pagerduty.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/panda.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/parcel-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/parcel.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/parse.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/parsehub.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/partytown-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/partytown.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/passbolt-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/passbolt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/passport.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/patreon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/paypal.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/peer5.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pepperoni.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/percona.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/percy-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/percy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/perf-rocks.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/perl.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/phalcon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/phoenix.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/phonegap-bot.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/phonegap.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/php-alt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/php.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/phpstorm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pinterest.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pipedrive.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pipefy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pivotal_tracker.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pixijs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pkg.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/planless-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/planless.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/plastic-scm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/platformio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/play.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/playwright.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pm2.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pnpm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/poeditor.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/polymer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/postcss.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/postgraphile.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/postgresql.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/postman-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/postman.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pouchdb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/preact.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/precursor.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/prerender-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/prerender.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/prestashop.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/presto.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/prettier.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/prisma.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/prismic-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/prismic.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/processwire.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/productboard-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/productboard.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/producthunt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/progress.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/prometheus.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/promises.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/proofy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/prospect.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/protactor.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/protoio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/protonet.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/prott.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pug.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pumpkindb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/puppet-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/puppet.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/puppeteer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/puppy-linux.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/purescript-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/purescript.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pushbullet.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pusher-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pusher.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pwa.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pycharm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/python.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pytorch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/pyup.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/q.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/qlik.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/qt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/quarkus-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/quarkus.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/quay.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/quobyte.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/quora.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/r-lang.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rabbitmq-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rabbitmq.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rackspace.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rails.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ramda.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/raml.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rancher-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rancher.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/raphael.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/raspberry-pi.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rax.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/react-query-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/react-query.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/react-router.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/react-spring.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/react-styleguidist.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/react.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/reactivex.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/realm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/reapp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/reasonml-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/reasonml.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/reddit-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/reddit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/redhat-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/redhat.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/redis.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/redsmin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/redux-observable.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/redux-saga.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/redux.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/redwoodjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/reindex.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/relay.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/release.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/remix-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/remix.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/require.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rescript-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rescript.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rest-li.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rethinkdb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/retool-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/retool.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/riak.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/riot.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rocket-chat-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rocket-chat.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rocksdb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rocky-linux-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rocky-linux.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rollbar-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rollbar.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rollupjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rome-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rome.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rsa.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rsmq.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rubocop.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ruby.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rubygems.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rubymine.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rum.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/runscope.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rust.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/rxdb.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/safari.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sagui.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sails.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/salesforce.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sameroom.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/samsung.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sanity.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sass-doc.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sass.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/saucelabs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/scala.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/scaledrone.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/scribd-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/scribd.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/section-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/section.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/segment-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/segment.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/selenium.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/semantic-release.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/semantic-ui.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/semantic-web.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/semaphoreci.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sencha.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sendgrid-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sendgrid.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/seneca.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sensu-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sensu.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sentry-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sentry.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sequelize.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/serverless.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sherlock-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sherlock.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/shields.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/shipit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/shippable.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/shogun.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/shopify.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sidekick.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sidekiq-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sidekiq.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/signal.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sinatra.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sitepoint.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/skaffolder.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sketch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/skylight.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/skype.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/slack-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/slack.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/slides.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/slim.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/smartling.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/smashingmagazine.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/snap-svg.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/snowflake-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/snowflake.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/snowpack.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/snupps.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/snyk.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/socket.io.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/solarwinds.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/solid.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/solidity.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/solidjs-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/solidjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/solr.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sonarqube.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/soundcloud.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sourcegraph.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sourcetrail.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sourcetree.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/spark.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sparkcentral.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sparkpost.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/speakerdeck.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/speedcurve.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/spidermonkey-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/spidermonkey.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/spinnaker.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/splunk.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/spotify-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/spotify.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/spree.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/spring-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/spring.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sqlite.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/square.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/squarespace.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stackbit-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stackbit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stackoverflow-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stackoverflow.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stackshare.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/statuspage.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stdlib-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stdlib.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/steam.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stenciljs-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stenciljs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stetho.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stickermule.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stimulus.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stitch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stoplight.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/storybook-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/storybook.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/strapi-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/strapi.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/strider.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stripe.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/struts.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/styleci.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stylefmt.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stylelint.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stylis.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/stylus.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sublimetext-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sublimetext.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/subversion.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sugarss.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/supabase-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/supabase.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/surge.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/survicate.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/suse.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/susy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/svelte-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/svelte.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/svg.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/swagger.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/swift.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/swiftype.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/symfony.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/sysdig-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/t3.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tableau-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tableau.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/taiga.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tailwindcss-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tailwindcss.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tapcart-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tapcart.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/targetprocess.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/taskade-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/taskade.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tastejs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tauri.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tealium.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/teamgrid.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/teamwork-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/teamwork.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/telegram.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tensorflow.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/terminal.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/terraform-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/terraform.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/terser-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/terser.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/testing-library.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/testlodge.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/threejs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tidal-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tidal.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tiktok-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tiktok.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tnw.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/todoist-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/todoist.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/todomvc.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tomcat.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/toml.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tor.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/torus.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/traackr.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/trac.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/travis-ci-monochrome.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/travis-ci.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/treasuredata-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/treasuredata.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/treehouse.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/trello.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/truffle-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/truffle.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tsnode.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tsu.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tsuru.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tumblr-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tumblr.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tunein.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/tuple.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/turborepo-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/turborepo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/turret.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/twilio-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/twilio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/twitch.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/twitter.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/typeform-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/typeform.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/typescript-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/typescript.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/typo3-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/typo3.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ubuntu.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/udacity-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/udacity.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/udemy-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/udemy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/uikit.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/umu.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/unbounce-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/unbounce.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/undertow.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/unionpay.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/unitjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/unito-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/unito.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/unity.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/unocss.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/unrealengine-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/unrealengine.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/upcase.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/upwork.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/user-testing-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/user-testing.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/uservoice-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/uservoice.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/uwsgi.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/v8-ignition.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/v8-turbofan.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/v8.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vaadin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vaddy.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vagrant-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vagrant.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vault-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vault.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vector-timber.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vercel-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vercel.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/verdaccio-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/verdaccio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vernemq.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vim.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vimeo-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vimeo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/visa.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/visaelectron.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/visual-studio-code.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/visual-studio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vitejs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vitest.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vivaldi-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vivaldi.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vlang.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/void.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vue.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vuetifyjs.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vueuse.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vulkan.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vultr.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/vwo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/w3c.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/waffle-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/waffle.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wagtail.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wakatime.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/watchman.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wearos.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/weave.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/web-fundamentals.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/web.dev-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/web.dev.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/web3js.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webassembly.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webcomponents.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webdriverio.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webflow.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webhint-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webhint.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webhooks.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webix-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webix.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webmin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webpack.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webplatform.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webrtc.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/websocket.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webstorm.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webtask.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/webtorrent.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/weebly.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/whalar.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/whatsapp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/whatwg.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wicket-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wicket.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wifi.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wildfly.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wire.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wix.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wmr.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/woocommerce-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/woocommerce.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/woopra.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wordpress-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wordpress.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/workboard.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/workplace.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wpengine.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/wufoo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/xamarin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/xampp.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/xcart.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/xero.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/xplenty.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/xstate.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/xtend.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/xwiki-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/xwiki.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/yahoo.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/yaml.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/yammer.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/yandex-ru.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/yarn.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/ycombinator.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/yeoman.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/yii.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/youtrack.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/youtube-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/youtube.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zapier-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zapier.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zend-framework.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zendesk-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zendesk.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zenhub-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zenhub.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zeplin.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zoho.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zorin-os.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zube.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zulip-icon.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zulip.svg create mode 100644 .claude/skills/logo-design/assets/library/svg/zwave.svg create mode 100644 .claude/skills/logo-design/references/color.md create mode 100644 .claude/skills/logo-design/references/critique.md create mode 100644 .claude/skills/logo-design/references/discovery-brief.md create mode 100644 .claude/skills/logo-design/references/identity-system.md create mode 100644 .claude/skills/logo-design/references/library-guide.md create mode 100644 .claude/skills/logo-design/references/mark-types.md create mode 100644 .claude/skills/logo-design/references/presentation-delivery.md create mode 100644 .claude/skills/logo-design/references/principles.md create mode 100644 .claude/skills/logo-design/references/process.md create mode 100644 .claude/skills/logo-design/references/redesign.md create mode 100644 .claude/skills/logo-design/references/svg-construction.md create mode 100644 .claude/skills/logo-design/references/testing-checklist.md create mode 100644 .claude/skills/logo-design/references/typography.md create mode 100644 .claude/skills/logo-design/references/visual-techniques.md create mode 100644 .claude/skills/logo-design/scripts/build_catalog.py create mode 100644 .claude/skills/logo-design/scripts/concept_sheet.py create mode 100644 .claude/skills/logo-design/scripts/export_variants.py create mode 100644 .claude/skills/logo-design/scripts/presentation_board.py create mode 100644 .claude/skills/logo-design/scripts/preview_sheet.py create mode 100644 .claude/skills/logo-design/scripts/render_png.py create mode 100644 .claude/skills/logo-design/scripts/search_library.py create mode 100644 .claude/skills/logo-design/scripts/svg_audit.py create mode 100644 .claude/skills/logo-design/scripts/svglib.py create mode 100644 .claude/skills/logo-design/templates/brand-guidelines-template.md create mode 100644 .claude/skills/logo-design/templates/presentation-spec.example.json diff --git a/.claude/skills/logo-design/SKILL.md b/.claude/skills/logo-design/SKILL.md new file mode 100644 index 0000000..e242ced --- /dev/null +++ b/.claude/skills/logo-design/SKILL.md @@ -0,0 +1,224 @@ +--- +name: logo-design +model: sonnet +description: Professional logo and brand-mark design, from brief to production files. Guides discovery and the design brief, concept generation, choosing a mark type (wordmark, monogram, letterform, pictorial, abstract, emblem, mascot, combination), building clean geometric SVG logos, optical refinement, colour and typography, testing (16 px, one-colour, reversed, shelf test), client presentation, delivery variants and brand guidelines. Includes a searchable library of 1,400+ real-world SVG logos classified by type, technique, geometry and industry, plus scripts that audit SVGs and generate test sheets, presentation boards and export variants. Use this skill whenever the user wants a logo, logotype, wordmark, monogram, brand mark, symbol, app icon or favicon designed, redesigned, refreshed, critiqued or compared; asks for logo ideas or concepts; needs a design brief, logo guidelines, lockups or an identity system; or mentions branding a new company, product, app or project — even if they don't say the word "logo". +--- + +# Logo Design + +You are acting as a senior identity designer. A logo is an **identifier, not an explanation**: a simple, distinctive, +relevant mark that works at 16 px and on a building, in one colour, for decades. Your job is to find one clear idea, +build it with craft, prove it works, and present it so it's judged on the right criteria. + +Reply in the user's language. Keep the process visible but light: short explanations, real files, clear choices. + +**Keep it cheap.** If the project has `docs/design/brand-spec.md`, use it as the brief and skip discovery questions. +Read files in `references/` only when a step needs that topic. Use the library and the HTML/PNG sheets only where +this file marks them as required, or when the user asks. + +## Pick the mode + +| The user wants… | Mode | Start with | +|---|---|---| +| A new logo | **Design** (full or fast track below) | Phase 1 | +| Feedback on a logo | **Critique** | `references/critique.md` | +| To modernise/replace a logo | **Redesign** | `references/redesign.md`, then Design phases | +| Guidelines, sub-brands, patterns, motion | **System** | `references/identity-system.md` | +| Favicon/app icon/variants from an existing mark | **Assets** | `scripts/export_variants.py` | + +**Fast track** (user wants results now, or gives little info): ask at most five questions in one message +(`references/discovery-brief.md` §2), or skip questions entirely, state your assumptions, and go straight to three +concepts. You can always iterate after they react. + +**Concept checkpoint — show the logos before building anything else.** Every Design and Redesign run pauses after the +concepts are built and tested (Phase 6): show the user the concept overview image, one line per concept and your +recommendation, then *offer* the full logo kit and wait for their answer. Build the kit (Phase 7) only after they pick a +direction and say yes. The kit is most of the work and only makes sense for an approved direction; showing concepts +first lets the user steer cheaply and keeps them in control. Skip the pause only when the user explicitly says not to +check in (e.g. "don't ask, just deliver everything"). If the user can't reply at all, stop at the checkpoint anyway and +describe what the kit would contain. + +## Tools in this skill + +All scripts are dependency-free Python 3 and live in the `scripts/` folder next to this SKILL.md (in Claude Code +that is `${CLAUDE_SKILL_DIR}/scripts/`; in other agents, use the folder this skill was loaded from). Run them with +`python3` and the full path, e.g. +`python3 /scripts/svg_audit.py logo.svg` (examples below write `scripts/…` for brevity). +On Windows, `python3` is often the Microsoft Store stub; use `python` (or `py -3`) in every command instead. + +| Script | Use it to | +|---|---| +| `concept_sheet.py` | One-image concept overview (large mark, lockup, true 64/32/16 px sizes, name, one-line idea, recommendation) — what you show at the checkpoint | +| `search_library.py` | Find reference logos by `--type`, `--technique`, `--geometry`, `--subject`, `--industry`, `--color`, `--mood`…; `--summary` shows a category's conventions; `--format paths` gives files to read | +| `svg_audit.py` | Check an SVG: live text, rasters, filters, colour count, gradients, strokes, near-miss angles, tiny details, centring, complexity vs. the library | +| `preview_sheet.py` | HTML test sheet: size ladder, 16/32 px pixel test, backgrounds, one-colour, squint blur, mirror/rotate, favicon/app-icon/header/card contexts, side-by-side, shelf test vs. competitors | +| `presentation_board.py` | Client presentation (brief, each concept with rationale + 6 **industry-specific** mockups — cup, packaging, payment card, README, terminal, signage…; comparison, recommendation) from a JSON spec (`templates/presentation-spec.example.json`); `--png-dir` exports every slide as PNG; `--list-mockups` | +| `render_png.py` | Render SVG → transparent PNG at exact sizes (for looking at your work and for deliverables); screenshots HTML sheets/boards (Chrome); builds `favicon.ico`; `--which` lists renderers | +| `export_variants.py` | Black, white, brand-mono, square, favicon and app-icon SVGs; `--png` sizes; `--web-icons` = favicon.ico + PNG icon set + webmanifest + `` snippet; `--favicon-source` for a simplified small-size drawing | +| `build_catalog.py` | Maintainers only: rebuild the library catalog | + +**Look at your work.** Drawing in SVG code is drawing blind. After writing or changing a logo, render it and look: +`python3 scripts/render_png.py concept-a.svg concept-b.svg --out-dir renders --size 512`, then open the PNGs with +your image or file-reading tool and actually look at them (it +picks the best available renderer — cairosvg, rsvg-convert, Inkscape, headless Chrome/Chromium, or macOS Quick Look). +Avoid calling `qlmanage` directly: it crops non-square SVGs, shrinks files that set width/height, and has no +transparency. The HTML sheets can also be opened in a browser tool. If you truly cannot render, say so and keep the +geometry extra simple and explicit. + +## Design workflow + +### Phase 1 — Discovery → brief +Learn: name (exact spelling), what they do, audience, 3–5 brand adjectives, competitors, constraints (colours, equity, +where it must work), decision-maker. Write a short brief (template in `references/discovery-brief.md` §5) and list your +assumptions. Adjectives are the most valuable input — they become visual cues. + +### Phase 2 — Research & strategy +1. Use your own knowledge of the category to avoid blending in. Run + `search_library.py --industry --summary` only if the user asks for a category study. +2. List the category's **clichés** explicitly (e.g. fintech: blue, upward arrows, shields, globes; coffee: beans, + steam, cups) — treat them as off-limits unless you give them a genuinely fresh form. +3. **Word map** (`references/discovery-brief.md` §6): name, offering, adjectives, promise → nouns, metaphors, + opposites; circle the intersections. +4. Choose candidate **mark types** with `references/mark-types.md` §12. Explore at least two different types. + +### Phase 3 — Concepts +- Write **4–6 one-sentence concepts** spread across mark types. Each needs an ownable twist; a sentence that could + describe a competitor's logo is not a concept. (If you can't say it in one sentence, it won't read in a glance.) +- Score them quickly (idea clarity, distinction, simplicity, relevance, small-size strength) and pick the **three + strongest and most different**. Briefly show the user the longlist only if it helps them steer. +- Required: before building, check you're not recreating an existing mark (`search_library.py --subject `, + summary only). Study exemplary files only if a construction problem calls for it. +- Keep it lean: one-liners are cheap, builds are expensive. Build only the three; don't polish ideas you'll drop. + +### Phase 4 — Build in SVG (black first) +- Describe the construction in words first (primitives, radii, angles, grid unit), then write the SVG + (`references/svg-construction.md`). Canvas `viewBox="0 0 256 256"` for symbols; lockups keep height 256. +- Solid black on white; no colour yet. Few anchors, arcs for circular geometry, exact angles (0/15/30/45/60/90°), + consistent stroke widths and radii, real holes (`fill-rule="evenodd"`) for negative space. +- No `` in finished marks — construct letterforms as paths. For exploration you may use `` but flag it. +- Save every meaningful iteration (`concept-a-v1.svg`, `-v2.svg`…) instead of overwriting — you'll want to compare. + +### Phase 5 — Test & refine (once; loop again only if a test fails) +```bash +python3 scripts/svg_audit.py concept-a.svg concept-b.svg concept-c.svg +python3 scripts/render_png.py concept-a.svg concept-b.svg concept-c.svg --out-dir renders --size 256 +``` +Look at the renders. Fix what fails. Use `preview_sheet.py` (size ladder, shelf test) only when the user asks or a small-size issue needs it. Key refinements (details in `references/visual-techniques.md`): +- **Scale**: the idea survives 16–24 px; gaps and strokes big enough; otherwise simplify or add a small-size version. +- **Optical corrections**: overshoot round/pointed forms (~1–3 %), fix the bone effect on rounded shapes, thin + horizontals slightly, centre optically (slightly above geometric centre), thin the reversed version. +- **Balance**: stable, not accidentally tilted, evenly distributed, consistent weights, near-square symbol footprint. +- **Readings**: mirror, rotate 180°, view tiny — check for unintended shapes or meanings. +- **Distinction**: shelf test against competitors; the familiarity test (if it feels familiar and isn't yours, it's + someone else's). +- **Craft pass** (where AI-drawn marks usually fall short): (1) *Letter test* — does every modified letter still read + as the intended letter at first glance? If a K reads as an h, revise. (2) *Junctions* — inspect every place strokes + meet: no accidental notches, slivers, lumps or ink traps. (3) *Peer test* — optional, only on request. (4) *Literalness* — if a concept is simply the product drawn (a cup for coffee), + push it further or drop it. +Full list: `references/testing-checklist.md`. + +### Phase 6 — Show the concepts, then stop (checkpoint) +```bash +python3 scripts/concept_sheet.py a-symbol.svg b-symbol.svg c-symbol.svg --lockups a-lockup.svg b-lockup.svg c-lockup.svg \ + --names "Name A" "Name B" "Name C" --notes "One-line idea A" "…" "…" --recommend 1 --greyscale -o concepts.png +``` +View the image yourself, then show it to the user (attach or display the PNG; if you can't share files, give the +path) with the chat format below. Greyscale first — colour triggers taste debates; you may add a small colour hint +for your recommendation. End with the kit offer and **wait for the answer**: + +> Want me to prepare the full logo kit for the direction you choose? It includes: the colour palette with one-colour +> and reversed versions, horizontal and stacked lockups, a small-size cut, favicon + app-icon + web-icon set, a +> presentation board with mockups for your industry, and a one-page usage guide. + +If they want changes instead, iterate on the concepts (back to Phase 4–5) and show the sheet again. + +### Phase 7 — Build the kit (only after the user says yes) +1. **Refine the chosen direction**: final geometry, optical corrections, small-size cut, thinned reversed version. +2. **Colour**: 1–2 colours ideally, ownable in the category, reproducible (HEX/RGB/CMYK/Pantone), accessible; the + one-colour and greyscale versions must still work (`references/color.md`). +3. **Typography & lockups**: type study, custom letters for ownership, optical spacing, max two families + (`references/typography.md`); horizontal, stacked, symbol-only, wordmark-only — lock relative sizes and spacing. +4. **Presentation board** with industry-relevant mockups: `presentation_board.py` (copy + `templates/presentation-spec.example.json`; set `"industry"` or an explicit `"mockups"` list — a café gets cups and + bags, a dev tool gets a README and terminal). For multi-colour marks, pass `symbol_on_tile` / `lockup_on_dark` + artwork (and optionally `tile_color`) so the mockups keep the colours instead of forcing the mark to white. + `--png-dir slides` exports every slide as an image for sharing. Guidance: `references/presentation-delivery.md`. +5. **Export the files**: + ```bash + python3 scripts/export_variants.py final-symbol.svg --title "Brand logo" --mono "#HEX" --icon-bg "#HEX" --web-icons --favicon-source final-symbol-small.svg + python3 scripts/export_variants.py final-horizontal.svg --title "Brand logo" --only black white mono --mono "#HEX" --png 1200 + ``` +6. **Guidelines & handover**: compact guidelines (`templates/brand-guidelines-template.md`: clear space from a logo + element, minimum sizes, colour codes, approved backgrounds, misuse), masters (SVG; PDF/AI/EPS if the user has the + tools), and handover notes (rationale, test results, open items). Run the final checklist in `references/process.md` + §7. For bigger brands, extend into a system (`references/identity-system.md`). + +## Principles to hold onto + +1. **Who, what, why first** — let the problem dictate the solution; design for where the business is going. +2. **Identify, don't explain** — one signpost, not a catalogue of services. +3. **Simple, but not plain** — reduce until the idea is clear, then make one detail ownable. +4. **Relevant, not literal** — evoke the attitude; don't draw the product. Fresh forms of familiar signs work. +5. **Distinct** — know the category; depart from what blends together. +6. **Memorable** — shape and colour are the first memory hooks; one defining feature. +7. **One idea** — explainable in one sentence; a light puzzle is good, a riddle is not. +8. **Small and large** — 16 px and 16 m; one colour; reversed; embroidered. +9. **Timeless over trendy** — build on a concept, not an effect. +10. **Foundation of a system** — never judge a logo in a void; it must seed patterns, icons, motion. +11. **Craft matters** — geometry, optical corrections, spacing; the invisible details separate good from great. +12. **Be strong, not stubborn** — defend the strategy, stay open on details, and value feedback. +Deeper reasoning: `references/principles.md`. + +## Red flags — fix before showing anything + +- Clip-art literalism (a tooth for a dentist, a house for real estate) or category clichés with no twist. +- Generic initials in an unmodified stock font; default-weight geometric sans with nothing ownable. +- More than three colours without a conceptual reason; gradients or shadows used to rescue a weak form. +- Details smaller than ~1/48 of the mark, hairlines, tight gaps that close at small sizes. +- Near-miss angles, lumpy curves from too many anchors, inconsistent stroke weights. +- Live ``, embedded rasters, filters or masks in a "final" file. +- A concept that needs a paragraph to understand. +- Anything that looks like an existing logo — including the library's. The library is for learning, never tracing. + +## Presenting concepts in chat (the checkpoint message) + +```markdown + + +### A — · ← recommended +**Idea:** +**Why it fits:** <2–3 bullets linked to the brief's adjectives/audience/competition> + +### B — … / ### C — … (same shape) + +**My recommendation:** +**Next:** pick a direction (or tell me what you like in each). Want me to prepare the full logo kit for it? + +``` +Keep it short: the image does the work. Don't attach variants, boards or icon sets yet. + +## Honesty and limits + +- You can't guarantee trademark clearance; recommend a professional search (trademark databases, reverse image search). +- Font licences must allow logo use; say which fonts you assumed and that outlines were constructed or must be made. +- If you couldn't render and inspect a file, say so. Don't claim tests you didn't run. +- Library logos are trademarks of their owners — study only. + +## Reference map + +| Read | When | +|---|---| +| `references/principles.md` | Justifying decisions, resolving debates, deep critique | +| `references/discovery-brief.md` | Questions, brief template, word mapping | +| `references/mark-types.md` | Choosing the type of mark; pros/cons; decision guide | +| `references/visual-techniques.md` | Geometry, grids, balance, optical corrections, negative space, gradients, paradoxes | +| `references/color.md` | Palette strategy, harmony, reproduction, accessibility, library colour data | +| `references/typography.md` | Type study, custom letterforms, spacing, lockups, licensing | +| `references/process.md` | Stage-by-stage process, exploration, vector development, final checklist | +| `references/svg-construction.md` | Writing clean SVG logos, recipes, what to avoid | +| `references/testing-checklist.md` | Everything to test before presenting or delivering | +| `references/presentation-delivery.md` | Presenting, feedback, committees, deliverables, working relationship | +| `references/identity-system.md` | Kit of parts, sub-brands, dynamic identities, patterns, motion, guidelines, rollout | +| `references/redesign.md` | Refresh vs. rebrand, equity audit, refresh techniques | +| `references/critique.md` | Structured logo critique with scorecard and fixes | +| `references/library-guide.md` | What's in the 1,400+ logo library, insights, curated examples by technique | diff --git a/.claude/skills/logo-design/assets/library/catalog.json b/.claude/skills/logo-design/assets/library/catalog.json new file mode 100644 index 0000000..31825ec --- /dev/null +++ b/.claude/skills/logo-design/assets/library/catalog.json @@ -0,0 +1 @@ +[{"file":"100tb.svg","brand":"100tb","variant":"main","pair":null,"width":512.0,"height":190.0,"aspect":2.695,"aspect_class":"horizontal","bytes":3862,"shapes":3,"anchors":104,"colors":["#919fa1","#3390da"],"n_colors":2,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"numerals 100 with 00 as infinity loop","geometry":[],"techniques":["infinity-loop","ligature","letter-substitution"],"type_style":"display-custom","case":"uppercase","mood":["bold","technical"],"industry":"hosting-cdn","exemplary":true,"note":"Double zero turned into infinity loop within the numerals"},{"file":"500px.svg","brand":"500px","variant":"main","pair":null,"width":512.0,"height":128.0,"aspect":4.0,"aspect_class":"horizontal","bytes":3096,"shapes":2,"anchors":82,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"thin geometric name with superscript px","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["minimal","modern"],"industry":"design-creative","exemplary":false,"note":""},{"file":"active-campaign-icon.svg","brand":"active-campaign","variant":"icon","pair":"active-campaign.svg","width":256.0,"height":391.0,"aspect":0.655,"aspect_class":"tall","bytes":1438,"shapes":2,"anchors":38,"colors":["#004cff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"bold chevron arrow pointing right","geometry":["freeform"],"techniques":["arrow"],"type_style":null,"case":null,"mood":["dynamic","confident"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"active-campaign.svg","brand":"active-campaign","variant":"main","pair":"active-campaign-icon.svg","width":512.0,"height":52.0,"aspect":9.846,"aspect_class":"extra-wide","bytes":9709,"shapes":2,"anchors":310,"colors":["#004cff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"camel-case name with trailing chevron","geometry":[],"techniques":["arrow"],"type_style":"grotesque-sans","case":"mixed","mood":["clean","corporate"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"adonisjs-icon.svg","brand":"adonisjs","variant":"icon","pair":"adonisjs.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1090,"shapes":2,"anchors":25,"colors":["#5a46ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"rounded letter A in rounded square","geometry":["rounded-square","triangle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["friendly","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"adonisjs.svg","brand":"adonisjs","variant":"main","pair":"adonisjs-icon.svg","width":512.0,"height":161.0,"aspect":3.18,"aspect_class":"horizontal","bytes":8542,"shapes":2,"anchors":211,"colors":["#5a46ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"rounded A tile beside lowercase name","geometry":["rounded-square"],"techniques":["containment","negative-space"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"adroll.svg","brand":"adroll","variant":"main","pair":null,"width":512.0,"height":95.0,"aspect":5.389,"aspect_class":"extra-wide","bytes":2659,"shapes":3,"anchors":89,"colors":["#0dbdff","#333333"],"n_colors":2,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"curled hook shape beside bold name","geometry":["organic"],"techniques":[],"type_style":"geometric-sans","case":"mixed","mood":["playful","bold"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"adyen.svg","brand":"adyen","variant":"main","pair":null,"width":512.0,"height":166.0,"aspect":3.084,"aspect_class":"horizontal","bytes":1542,"shapes":2,"anchors":71,"colors":["#32aa52"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"custom squared lowercase green name","geometry":[],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["bold","distinctive"],"industry":"payments-fintech","exemplary":true,"note":"Fully custom squared letterforms make a plain name unmistakable"},{"file":"aerospike-icon.svg","brand":"aerospike","variant":"icon","pair":"aerospike.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":512,"shapes":3,"anchors":19,"colors":["#c4373a","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"sideways letter A in red square","geometry":["square","triangle"],"techniques":["containment","letter-substitution"],"type_style":null,"case":null,"mood":["sharp","technical"],"industry":"database-data","exemplary":false,"note":""},{"file":"aerospike.svg","brand":"aerospike","variant":"main","pair":"aerospike-icon.svg","width":512.0,"height":89.0,"aspect":5.753,"aspect_class":"extra-wide","bytes":5840,"shapes":3,"anchors":197,"colors":["#c4373a","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"spaced name in red bar with rotated A","geometry":["square"],"techniques":["containment","letter-substitution"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","sharp"],"industry":"database-data","exemplary":false,"note":""},{"file":"airbnb.svg","brand":"airbnb","variant":"main","pair":null,"width":256.0,"height":276.0,"aspect":0.928,"aspect_class":"square","bytes":3377,"shapes":2,"anchors":73,"colors":["#e0565b"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"Belo loop merging pin, heart and A","geometry":["organic"],"techniques":["line-monoline","hidden-meaning","mirror-symmetry"],"type_style":null,"case":null,"mood":["friendly","warm"],"industry":"travel-transport","exemplary":true,"note":"Single monoline loop encodes location, love and the letter A"},{"file":"airbrake.svg","brand":"airbrake","variant":"main","pair":null,"width":512.0,"height":90.0,"aspect":5.689,"aspect_class":"extra-wide","bytes":3255,"shapes":3,"anchors":122,"colors":["#ffa500"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold name with orange-yellow gradient","geometry":[],"techniques":["gradient"],"type_style":"grotesque-sans","case":"titlecase","mood":["energetic","bold"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"airflow.svg","brand":"airflow","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":5581,"shapes":14,"anchors":60,"colors":["#000000","#00c812","#006e00","#56affd","#04a3ff","#df1f00","#560d00","#00fffd","#00daff","#008200","#007500","#3166d4","#1a509e","#8e1400","#4b0b00","#0090c4","#005d8c","#00cd1c","#00e950","#b1c8fd","#7ec3fd","#e12a00","#b62f00","#00b6dd","#00ffff"],"n_colors":25,"color_families":["black","blue","cyan","green","orange","red"],"primary_family":"multi","gradients":12,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"multicolor pinwheel of four blades","geometry":["radial"],"techniques":["radial-symmetry","color-segments"],"type_style":null,"case":null,"mood":["dynamic","colorful"],"industry":"database-data","exemplary":false,"note":""},{"file":"airtable.svg","brand":"airtable","variant":"main","pair":null,"width":256.0,"height":215.0,"aspect":1.191,"aspect_class":"square","bytes":1456,"shapes":5,"anchors":36,"colors":["#ffbf00","#26b5f8","#ed3049","#000000"],"n_colors":4,"color_families":["black","blue","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric box shapes in three colors","geometry":["diamond","freeform"],"techniques":["isometric-3d","color-segments"],"type_style":null,"case":null,"mood":["playful","colorful"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"akamai.svg","brand":"akamai","variant":"main","pair":null,"width":512.0,"height":209.0,"aspect":2.45,"aspect_class":"wide","bytes":3779,"shapes":3,"anchors":125,"colors":["#f79838","#0098cc"],"n_colors":2,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"wave swoosh arc beside italic name","geometry":["organic"],"techniques":["motion-lines","gradient"],"type_style":"humanist-sans","case":"titlecase","mood":["dynamic","corporate"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"akka.svg","brand":"akka","variant":"main","pair":null,"width":256.0,"height":182.0,"aspect":1.407,"aspect_class":"wide","bytes":774,"shapes":3,"anchors":13,"colors":["#0b5567","#15a9ce"],"n_colors":2,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two-tone swooping mountain-like fin shape","geometry":["organic"],"techniques":["dimensional-shading"],"type_style":null,"case":null,"mood":["dynamic","smooth"],"industry":"framework-library","exemplary":false,"note":""},{"file":"alfresco.svg","brand":"alfresco","variant":"main","pair":null,"width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":5411,"shapes":17,"anchors":149,"colors":["#87c040","#ed9a2d","#5698c6","#446ba6","#fff101","#45ab47"],"n_colors":6,"color_families":["blue","green","orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"flower-like radial petal pinwheel","geometry":["radial","organic"],"techniques":["radial-symmetry","color-segments","overlap-transparency"],"type_style":null,"case":null,"mood":["colorful","organic"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"algolia.svg","brand":"algolia","variant":"main","pair":null,"width":512.0,"height":127.0,"aspect":4.031,"aspect_class":"horizontal","bytes":8297,"shapes":4,"anchors":212,"colors":["#5468ff","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"stopwatch tile beside lowercase name","geometry":["rounded-square","circle"],"techniques":["containment","negative-space"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"alpinejs-icon.svg","brand":"alpinejs","variant":"icon","pair":"alpinejs.svg","width":256.0,"height":118.0,"aspect":2.169,"aspect_class":"wide","bytes":427,"shapes":3,"anchors":10,"colors":["#77c1d2","#2d3441"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"dark parallelogram beside light diamond","geometry":["diamond"],"techniques":[],"type_style":null,"case":null,"mood":["minimal","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"alpinejs.svg","brand":"alpinejs","variant":"main","pair":"alpinejs-icon.svg","width":512.0,"height":83.0,"aspect":6.169,"aspect_class":"extra-wide","bytes":6766,"shapes":4,"anchors":197,"colors":["#2d3441","#77c1d2"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"two diamond shapes beside bold name","geometry":["diamond"],"techniques":[],"type_style":"geometric-sans","case":"titlecase","mood":["minimal","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"altair.svg","brand":"altair","variant":"main","pair":null,"width":256.0,"height":288.0,"aspect":0.889,"aspect_class":"square","bytes":2136,"shapes":6,"anchors":55,"colors":["#33363b","#7ebc59","#368cbf"],"n_colors":3,"color_families":["blue","gray","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"triangle inside hexagon with node dots","geometry":["hexagon","triangle"],"techniques":["geometric-construction","line-monoline"],"type_style":null,"case":null,"mood":["technical","structured"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"amazon-chime.svg","brand":"amazon-chime","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3041,"shapes":27,"anchors":146,"colors":["#c9ebec","#00868c","#00b3bb"],"n_colors":3,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"radial ring of angular teal blades","geometry":["radial"],"techniques":["radial-symmetry","modular-repetition","dimensional-shading"],"type_style":null,"case":null,"mood":["dynamic","technical"],"industry":"social-communication","exemplary":false,"note":""},{"file":"amazon-connect.svg","brand":"amazon-connect","variant":"main","pair":null,"width":256.0,"height":235.0,"aspect":1.089,"aspect_class":"square","bytes":5616,"shapes":2,"anchors":139,"colors":["#26bf95"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cloud speech bubble with nodes in circle","geometry":["circle"],"techniques":["line-monoline","speech-bubble","motion-lines","containment"],"type_style":null,"case":null,"mood":["friendly","technical"],"industry":"social-communication","exemplary":false,"note":""},{"file":"amex.svg","brand":"amex","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":8218,"shapes":10,"anchors":365,"colors":["#ffffff","#2f9bca","#2ea3d0","#55b2d8","#88cde7","#2274ad"],"n_colors":6,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":true,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"outlined name inside blue square","geometry":["square"],"techniques":["containment","gradient"],"type_style":"display-custom","case":"uppercase","mood":["trustworthy","classic"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"amp-icon.svg","brand":"amp","variant":"icon","pair":"amp.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1362,"shapes":2,"anchors":25,"colors":["#1d5fe6"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"lightning bolt in blue circle","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["fast","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"amp.svg","brand":"amp","variant":"main","pair":"amp-icon.svg","width":512.0,"height":164.0,"aspect":3.122,"aspect_class":"horizontal","bytes":5120,"shapes":3,"anchors":108,"colors":["#1d5fe6","#1d60e6"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"bolt circle beside bold uppercase AMP","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":"geometric-sans","case":"uppercase","mood":["fast","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"ampersand.svg","brand":"ampersand","variant":"main","pair":null,"width":256.0,"height":298.0,"aspect":0.859,"aspect_class":"square","bytes":4014,"shapes":3,"anchors":94,"colors":["#e7168e","#000000"],"n_colors":2,"color_families":["black","pink"],"primary_family":"pink","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"shaded magenta ampersand glyph","geometry":["organic"],"techniques":["dimensional-shading"],"type_style":null,"case":null,"mood":["bold","playful"],"industry":"other","exemplary":false,"note":""},{"file":"amplication-icon.svg","brand":"amplication","variant":"icon","pair":"amplication.svg","width":256.0,"height":262.0,"aspect":0.977,"aspect_class":"square","bytes":484,"shapes":2,"anchors":10,"colors":["#7950ed"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"split arch of half-circle and bar","geometry":["circle","square"],"techniques":["negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["modern","minimal"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"amplication.svg","brand":"amplication","variant":"main","pair":"amplication-icon.svg","width":512.0,"height":105.0,"aspect":4.876,"aspect_class":"extra-wide","bytes":4246,"shapes":3,"anchors":151,"colors":["#7950ed"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"split arch beside lowercase name","geometry":["circle"],"techniques":["negative-space","geometric-construction"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"amplitude-icon.svg","brand":"amplitude","variant":"icon","pair":"amplitude.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2253,"shapes":2,"anchors":62,"colors":["#10069f"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"monoline A with wave in circle","geometry":["circle"],"techniques":["containment","line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["modern","confident"],"industry":"marketing-analytics","exemplary":true,"note":"A doubles as a sound wave: letter and meaning in one stroke"},{"file":"amplitude.svg","brand":"amplitude","variant":"main","pair":"amplitude-icon.svg","width":512.0,"height":107.0,"aspect":4.785,"aspect_class":"extra-wide","bytes":5730,"shapes":2,"anchors":211,"colors":["#10069f"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"A-wave circle beside bold name","geometry":["circle"],"techniques":["containment","line-monoline","hidden-meaning"],"type_style":"geometric-sans","case":"titlecase","mood":["modern","confident"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"android-icon.svg","brand":"android","variant":"icon","pair":"android.svg","width":256.0,"height":301.0,"aspect":0.85,"aspect_class":"square","bytes":3945,"shapes":6,"anchors":110,"colors":["#ffffff","#a4c639"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"green robot with antennae and eyes","geometry":["circle","rounded-square"],"techniques":["modular-repetition","mirror-symmetry"],"type_style":null,"case":null,"mood":["friendly","playful"],"industry":"os-platform","exemplary":true,"note":"Character built from simple rounded primitives, instantly readable"},{"file":"android.svg","brand":"android","variant":"main","pair":"android-icon.svg","width":512.0,"height":111.0,"aspect":4.613,"aspect_class":"extra-wide","bytes":7473,"shapes":9,"anchors":182,"colors":["#77c159"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"rounded lowercase green name","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","modern"],"industry":"os-platform","exemplary":false,"note":""},{"file":"angellist.svg","brand":"angellist","variant":"main","pair":null,"width":256.0,"height":369.0,"aspect":0.694,"aspect_class":"tall","bytes":5398,"shapes":2,"anchors":121,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"peace-sign victory hand outline","geometry":["organic"],"techniques":["line-monoline","hand-drawn"],"type_style":null,"case":null,"mood":["playful","bold"],"industry":"finance-banking","exemplary":false,"note":""},{"file":"angular-icon.svg","brand":"angular","variant":"icon","pair":"angular.svg","width":256.0,"height":272.0,"aspect":0.941,"aspect_class":"square","bytes":734,"shapes":4,"anchors":28,"colors":["#e23237","#b52e31","#ffffff"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white A inside red shield","geometry":["shield","triangle"],"techniques":["containment","dimensional-shading","mirror-symmetry"],"type_style":null,"case":null,"mood":["strong","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"angular.svg","brand":"angular","variant":"main","pair":"angular-icon.svg","width":512.0,"height":139.0,"aspect":3.683,"aspect_class":"horizontal","bytes":2183,"shapes":10,"anchors":94,"colors":["#b52e31","#e23237","#ffffff"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"shield A replacing first letter of name","geometry":["shield"],"techniques":["containment","letter-substitution"],"type_style":"geometric-sans","case":"uppercase","mood":["strong","corporate"],"industry":"framework-library","exemplary":false,"note":""},{"file":"ansible.svg","brand":"ansible","variant":"main","pair":null,"width":256.0,"height":315.0,"aspect":0.813,"aspect_class":"square","bytes":3880,"shapes":10,"anchors":117,"colors":["#1a1918","#ffffff"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"A in black circle above spaced name","geometry":["circle"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","simple"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"ant-design.svg","brand":"ant-design","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3230,"shapes":5,"anchors":52,"colors":["#4285eb","#2ec7ff","#29cdff","#148eff","#0a60ff","#fa816e","#f74a5c","#f51d2c","#fa8e7d"],"n_colors":9,"color_families":["blue","cyan","red"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"diamond outline with dot and chevron","geometry":["diamond","circle"],"techniques":["gradient","arrow","bracket-code"],"type_style":null,"case":null,"mood":["modern","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"apache-camel.svg","brand":"apache-camel","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3183,"shapes":7,"anchors":42,"colors":["#28170b","#ffffff","#f69923","#f79a23","#e97826","#f6e423"],"n_colors":6,"color_families":["orange","white","yellow"],"primary_family":"multi","gradients":3,"has_mask":true,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"camel silhouette in orange circle","geometry":["circle"],"techniques":["negative-space","containment","gradient"],"type_style":null,"case":null,"mood":["warm","friendly"],"industry":"framework-library","exemplary":true,"note":"Camel carved from circle with confident negative space"},{"file":"apache.svg","brand":"apache","variant":"main","pair":null,"width":256.0,"height":512.0,"aspect":0.5,"aspect_class":"tall","bytes":8935,"shapes":8,"anchors":153,"colors":["#f69923","#f79a23","#e97826","#9e2064","#c92037","#cd2335","#282662","#662e8d","#9f2064","#cd2032"],"n_colors":10,"color_families":["blue","orange","pink","purple","red"],"primary_family":"multi","gradients":7,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"gradient red-orange feather","geometry":["organic"],"techniques":["gradient"],"type_style":null,"case":null,"mood":["classic","vibrant"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"apache_cloudstack.svg","brand":"apache_cloudstack","variant":"main","pair":null,"width":257.0,"height":208.0,"aspect":1.236,"aspect_class":"square","bytes":9511,"shapes":17,"anchors":207,"colors":["#369ac9","#b9deeb"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"cartoon monkey sitting on cloud","geometry":["organic"],"techniques":["hand-drawn"],"type_style":null,"case":null,"mood":["playful","cheerful"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"apiary.svg","brand":"apiary","variant":"main","pair":null,"width":256.0,"height":259.0,"aspect":0.988,"aspect_class":"square","bytes":1995,"shapes":10,"anchors":53,"colors":["#13a049","#a2cc39","#231f20","#37bda6","#8ad3b8","#4bb6ad","#78bbc1","#4379a7","#7cc9b8"],"n_colors":9,"color_families":["black","blue","cyan","green"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric cubes forming a Y","geometry":["hexagon"],"techniques":["isometric-3d","color-segments","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","fresh"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"apollostack.svg","brand":"apollostack","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1136,"shapes":2,"anchors":30,"colors":["#112b49"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"A inside orbit ring with dot","geometry":["circle"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["technical","confident"],"industry":"framework-library","exemplary":false,"note":""},{"file":"apostrophe.svg","brand":"apostrophe","variant":"main","pair":null,"width":256.0,"height":259.0,"aspect":0.988,"aspect_class":"square","bytes":3030,"shapes":5,"anchors":56,"colors":["#000000","#cc9300","#ea433a","#b327bf","#6666ff","#00bf9a","#00c09a"],"n_colors":7,"color_families":["black","blue","cyan","pink","red","yellow"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"outlined square circle triangle in tile","geometry":["rounded-square","circle","triangle"],"techniques":["gradient","containment","line-monoline"],"type_style":null,"case":null,"mood":["playful","creative"],"industry":"framework-library","exemplary":false,"note":""},{"file":"appbaseio-icon.svg","brand":"appbaseio","variant":"icon","pair":"appbaseio.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1591,"shapes":2,"anchors":36,"colors":["#232e44"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"connected node graph inside circle","geometry":["circle"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["technical","minimal"],"industry":"database-data","exemplary":false,"note":""},{"file":"appbaseio.svg","brand":"appbaseio","variant":"main","pair":"appbaseio-icon.svg","width":512.0,"height":105.0,"aspect":4.876,"aspect_class":"extra-wide","bytes":6416,"shapes":3,"anchors":178,"colors":["#232e44"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"node circle beside thin lowercase name","geometry":["circle"],"techniques":["containment","line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["minimal","technical"],"industry":"database-data","exemplary":false,"note":""},{"file":"appcircle-icon.svg","brand":"appcircle","variant":"icon","pair":"appcircle.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1275,"shapes":2,"anchors":27,"colors":["#ff8f34"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"orange rounded A with circle hole","geometry":["triangle","circle"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["friendly","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"appcircle.svg","brand":"appcircle","variant":"main","pair":"appcircle-icon.svg","width":512.0,"height":106.0,"aspect":4.83,"aspect_class":"extra-wide","bytes":7190,"shapes":3,"anchors":195,"colors":["#ffffff","#ff8f34"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"small A icon with white lowercase name","geometry":["circle"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","modern"],"industry":"developer-tools","exemplary":false,"note":"Wordmark is white, only visible on dark backgrounds"},{"file":"appcode.svg","brand":"appcode","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2061,"shapes":7,"anchors":59,"colors":["#247ce6","#000000","#ffffff","#00daf0","#1ddf93"],"n_colors":5,"color_families":["black","blue","cyan","green","white"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"AC in black square over gradient shapes","geometry":["square"],"techniques":["containment","gradient","overlap-transparency"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","vibrant"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"appdynamics.svg","brand":"appdynamics","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":581,"shapes":3,"anchors":16,"colors":["#43af49","#ffffff"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"chevron A in green square","geometry":["square","triangle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["simple","confident"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"appium.svg","brand":"appium","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":870,"shapes":2,"anchors":16,"colors":["#662d91"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"purple circle with swirling segments","geometry":["circle"],"techniques":["negative-space","radial-symmetry"],"type_style":null,"case":null,"mood":["dynamic","modern"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"apple-app-store.svg","brand":"apple-app-store","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2226,"shapes":3,"anchors":61,"colors":["#ffffff","#17c9fb","#1a74e8"],"n_colors":3,"color_families":["blue","cyan","white"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"A built from pencil, brush and ruler","geometry":["rounded-square"],"techniques":["containment","gradient","hidden-meaning","line-monoline"],"type_style":null,"case":null,"mood":["clean","creative"],"industry":"os-platform","exemplary":true,"note":"Letter A assembled from creative tools: layered hidden meaning"},{"file":"apple-pay.svg","brand":"apple-pay","variant":"main","pair":null,"width":512.0,"height":211.0,"aspect":2.427,"aspect_class":"wide","bytes":2269,"shapes":2,"anchors":67,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"apple silhouette beside Pay","geometry":["organic"],"techniques":[],"type_style":"grotesque-sans","case":"titlecase","mood":["premium","minimal"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"apple.svg","brand":"apple","variant":"main","pair":null,"width":256.0,"height":315.0,"aspect":0.813,"aspect_class":"square","bytes":1068,"shapes":2,"anchors":19,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"apple silhouette with bite","geometry":["organic","circle"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["premium","minimal"],"industry":"hardware-devices","exemplary":true,"note":"Iconic single silhouette; bite adds scale cue and memorability"},{"file":"appsignal-icon.svg","brand":"appsignal","variant":"icon","pair":"appsignal.svg","width":256.0,"height":188.0,"aspect":1.362,"aspect_class":"wide","bytes":1715,"shapes":2,"anchors":40,"colors":["#21375a"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"monoline crown-like wave outline","geometry":["organic"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["friendly","simple"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"appsignal.svg","brand":"appsignal","variant":"main","pair":"appsignal-icon.svg","width":512.0,"height":91.0,"aspect":5.626,"aspect_class":"extra-wide","bytes":9303,"shapes":3,"anchors":266,"colors":["#21375a"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"camel-case name with crown outline","geometry":["organic"],"techniques":["line-monoline"],"type_style":"humanist-sans","case":"mixed","mood":["friendly","clean"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"apptentive.svg","brand":"apptentive","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1360,"shapes":3,"anchors":30,"colors":["#df2637","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"heart outline inside speech bubble","geometry":["circle"],"techniques":["speech-bubble","negative-space","line-monoline"],"type_style":null,"case":null,"mood":["warm","friendly"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"appveyor.svg","brand":"appveyor","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1024,"shapes":2,"anchors":21,"colors":["#00b3e0"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"white loop shape in blue circle","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["modern","simple"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"arangodb.svg","brand":"arangodb","variant":"main","pair":null,"width":512.0,"height":77.0,"aspect":6.649,"aspect_class":"extra-wide","bytes":413765,"shapes":18,"anchors":11776,"colors":["#423334","#3d2f30","#6c4317","#a3b34f","#dde072","#eaeca2","#633c11","#949952","#b0ad51","#7c9350","#577138"],"n_colors":11,"color_families":["gray","green","orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"avocado beside embossed slab name","geometry":["organic"],"techniques":["dimensional-shading"],"type_style":"slab","case":"mixed","mood":["quirky","dated"],"industry":"database-data","exemplary":false,"note":"Bevel effects and olive palette feel dated"},{"file":"archlinux.svg","brand":"archlinux","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":942,"shapes":2,"anchors":16,"colors":["#1793d1"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"blue arrowhead peak with inner arch","geometry":["triangle"],"techniques":["negative-space","mirror-symmetry"],"type_style":null,"case":null,"mood":["sharp","technical"],"industry":"os-platform","exemplary":false,"note":""},{"file":"arduino.svg","brand":"arduino","variant":"main","pair":null,"width":256.0,"height":174.0,"aspect":1.471,"aspect_class":"wide","bytes":6269,"shapes":13,"anchors":210,"colors":["#00979c"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"infinity loop with minus and plus","geometry":["circle"],"techniques":["infinity-loop","hidden-meaning","negative-space"],"type_style":"display-custom","case":"uppercase","mood":["technical","friendly"],"industry":"hardware-devices","exemplary":true,"note":"Infinity loop holding minus and plus tells the story simply"},{"file":"argo-icon.svg","brand":"argo","variant":"icon","pair":"argo.svg","width":256.0,"height":327.0,"aspect":0.783,"aspect_class":"tall","bytes":16131,"shapes":26,"anchors":360,"colors":["#fefefe","#fe733e","#b5d2f3","#fe684b","#fe6446","#fed6c8","#feebe3","#fe9166","#fe8f64","#e2f5fc","#cdecf6","#fe6b3c","#fe6142","#fe6143","#070909","#fdfcfb","#fea777","#fdfefe","#fbfdfe","#090b0b","#090c0c"],"n_colors":21,"color_families":["black","blue","cyan","orange","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"orange octopus in astronaut helmet","geometry":["circle","organic"],"techniques":["containment"],"type_style":null,"case":null,"mood":["playful","quirky"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"argo.svg","brand":"argo","variant":"main","pair":"argo-icon.svg","width":512.0,"height":234.0,"aspect":2.188,"aspect_class":"wide","bytes":20253,"shapes":30,"anchors":426,"colors":["#000000","#010101","#fefefe","#fe733e","#b5d2f3","#fe684b","#fe6446","#fed6c8","#feebe3","#fe9166","#fe8f64","#e2f5fc","#cdecf6","#fe6b3c","#fe6142","#fe6143","#070909","#fdfcfb","#fea777","#fdfefe","#fbfdfe","#090b0b","#090c0c"],"n_colors":23,"color_families":["black","blue","cyan","orange","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"octopus astronaut beside lowercase name","geometry":["circle"],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["playful","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"armory.svg","brand":"armory","variant":"main","pair":null,"width":256.0,"height":308.0,"aspect":0.831,"aspect_class":"square","bytes":1684,"shapes":5,"anchors":51,"colors":["#5bc5df","#3189aa","#136a8f","#000000"],"n_colors":4,"color_families":["black","blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"shield containing clouds and waves","geometry":["shield"],"techniques":["containment","stacked-layers"],"type_style":null,"case":null,"mood":["strong","calm"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"asana.svg","brand":"asana","variant":"main","pair":null,"width":256.0,"height":169.0,"aspect":1.515,"aspect_class":"wide","bytes":5601,"shapes":3,"anchors":148,"colors":["#283343","#ffb900","#f95d8f","#f95353"],"n_colors":4,"color_families":["blue","red","yellow"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"three coral dots above lowercase name","geometry":["circle"],"techniques":["radial-symmetry"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","calm"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"asciidoctor.svg","brand":"asciidoctor","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1740,"shapes":3,"anchors":46,"colors":["#e40046","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"monoline A with long crossbar in tile","geometry":["rounded-square"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"assembla-icon.svg","brand":"assembla","variant":"icon","pair":"assembla.svg","width":256.0,"height":284.0,"aspect":0.901,"aspect_class":"square","bytes":1386,"shapes":2,"anchors":35,"colors":["#263238"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"double-stroke A in dark hexagon","geometry":["hexagon"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["technical","serious"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"assembla.svg","brand":"assembla","variant":"main","pair":"assembla-icon.svg","width":512.0,"height":142.0,"aspect":3.606,"aspect_class":"horizontal","bytes":10092,"shapes":3,"anchors":283,"colors":["#263238"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"hexagon A beside spaced uppercase name","geometry":["hexagon"],"techniques":["containment","line-monoline"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","clean"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"astro.svg","brand":"astro","variant":"main","pair":null,"width":256.0,"height":264.0,"aspect":0.97,"aspect_class":"square","bytes":5005,"shapes":5,"anchors":124,"colors":["#000000","#ff5d01","#ff1639"],"n_colors":3,"color_families":["black","orange","red"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"A-shaped rocket with flame above name","geometry":["triangle"],"techniques":["hidden-meaning","letter-substitution"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","modern"],"industry":"framework-library","exemplary":true,"note":"Letter A becomes a rocket with one added flame"},{"file":"astronomer.svg","brand":"astronomer","variant":"main","pair":null,"width":256.0,"height":271.0,"aspect":0.945,"aspect_class":"square","bytes":5686,"shapes":11,"anchors":135,"colors":["#f48e06","#302c43","#00ac6b","#09a6d1","#f4362c","#a39a8b","#ff9a09"],"n_colors":7,"color_families":["blue","cyan","gray","green","orange","red"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter A with orbit swoosh and stars","geometry":["triangle","freeform"],"techniques":["motion-lines"],"type_style":null,"case":null,"mood":["playful","energetic"],"industry":"database-data","exemplary":false,"note":""},{"file":"atlassian.svg","brand":"atlassian","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1145,"shapes":3,"anchors":17,"colors":["#2681ff","#0052cc","#2684ff"],"n_colors":3,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two gradient blue mountain peaks","geometry":["triangle"],"techniques":["gradient"],"type_style":null,"case":null,"mood":["confident","modern"],"industry":"productivity-collaboration","exemplary":true,"note":"Two gradient peaks, strong simplicity scalable to favicon"},{"file":"atom-icon.svg","brand":"atom","variant":"icon","pair":"atom.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":8545,"shapes":3,"anchors":262,"colors":["#60b57d","#ffffff"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"monoline atom orbits in green circle","geometry":["circle","radial"],"techniques":["line-monoline","containment","radial-symmetry"],"type_style":null,"case":null,"mood":["technical","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"atom.svg","brand":"atom","variant":"main","pair":"atom-icon.svg","width":512.0,"height":106.0,"aspect":4.83,"aspect_class":"extra-wide","bytes":10174,"shapes":2,"anchors":323,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"atom orbit beside thin spaced name","geometry":["radial"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"uppercase","mood":["light","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"atomic-icon.svg","brand":"atomic","variant":"icon","pair":"atomic.svg","width":256.0,"height":232.0,"aspect":1.103,"aspect_class":"square","bytes":934,"shapes":4,"anchors":21,"colors":["#1e6efa","#ff3c5a","#ffc5ce"],"n_colors":3,"color_families":["blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter A split into three rounded pieces","geometry":["triangle"],"techniques":["color-segments","negative-space"],"type_style":null,"case":null,"mood":["playful","modern"],"industry":"design-creative","exemplary":false,"note":""},{"file":"atomic.svg","brand":"atomic","variant":"main","pair":"atomic-icon.svg","width":512.0,"height":99.0,"aspect":5.172,"aspect_class":"extra-wide","bytes":3570,"shapes":5,"anchors":111,"colors":["#000000","#1e6efa","#ff3c5a","#ffc5ce"],"n_colors":4,"color_families":["black","blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"split A beside bold lowercase name","geometry":["triangle"],"techniques":["color-segments"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","playful"],"industry":"design-creative","exemplary":false,"note":""},{"file":"aurelia.svg","brand":"aurelia","variant":"main","pair":null,"width":256.0,"height":249.0,"aspect":1.028,"aspect_class":"square","bytes":4535,"shapes":17,"anchors":99,"colors":["#714896","#6f4795","#88519f","#85509e","#8d166a","#a70d6f","#9e61ad","#8053a3","#c06fbb","#6e4d9b","#77327a","#b31777","#cd0f7e","#ed2c89"],"n_colors":14,"color_families":["pink","purple"],"primary_family":"multi","gradients":8,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"diagonal gradient bars and fragments","geometry":["freeform"],"techniques":["gradient","modular-repetition"],"type_style":null,"case":null,"mood":["dynamic","vibrant"],"industry":"framework-library","exemplary":false,"note":""},{"file":"aurora.svg","brand":"aurora","variant":"main","pair":null,"width":256.0,"height":226.0,"aspect":1.133,"aspect_class":"square","bytes":2245,"shapes":25,"anchors":96,"colors":["#63c4b1","#ffffff"],"n_colors":2,"color_families":["cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter A assembled from small triangles","geometry":["triangle","grid-modular"],"techniques":["modular-repetition","geometric-construction"],"type_style":null,"case":null,"mood":["structured","fresh"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"auth0-icon.svg","brand":"auth0","variant":"icon","pair":"auth0.svg","width":256.0,"height":285.0,"aspect":0.898,"aspect_class":"square","bytes":623,"shapes":2,"anchors":21,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"black shield with star cut out","geometry":["shield","star"],"techniques":["negative-space","mirror-symmetry"],"type_style":null,"case":null,"mood":["secure","bold"],"industry":"security-identity","exemplary":true,"note":"Star carved from shield via negative space, strong at any size"},{"file":"auth0.svg","brand":"auth0","variant":"main","pair":"auth0-icon.svg","width":512.0,"height":152.0,"aspect":3.368,"aspect_class":"horizontal","bytes":2713,"shapes":2,"anchors":103,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"star shield beside lowercase name","geometry":["shield","star"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"lowercase","mood":["secure","modern"],"industry":"security-identity","exemplary":false,"note":""},{"file":"authy.svg","brand":"authy","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1744,"shapes":3,"anchors":39,"colors":["#ec1c24","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"white chain-link swirl in red circle","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["bold","secure"],"industry":"security-identity","exemplary":false,"note":""},{"file":"autoit.svg","brand":"autoit","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1248,"shapes":4,"anchors":32,"colors":["#5d83ac","#f0f0f0"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"stylized A in blue circle with ring","geometry":["circle","triangle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["simple","technical"],"industry":"programming-language","exemplary":false,"note":""},{"file":"autoprefixer.svg","brand":"autoprefixer","variant":"main","pair":null,"width":256.0,"height":193.0,"aspect":1.326,"aspect_class":"wide","bytes":590,"shapes":2,"anchors":22,"colors":["#dd3835"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"red serif A with dash lines","geometry":["triangle"],"techniques":["motion-lines"],"type_style":null,"case":null,"mood":["bold","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"ava.svg","brand":"ava","variant":"main","pair":null,"width":512.0,"height":280.0,"aspect":1.829,"aspect_class":"wide","bytes":6671,"shapes":3,"anchors":139,"colors":["#4b4b77","#e0c7c1"],"n_colors":2,"color_families":["blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold AVA with rocket flames under As","geometry":["triangle"],"techniques":["hidden-meaning"],"type_style":"display-custom","case":"uppercase","mood":["bold","playful"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"awesome.svg","brand":"awesome","variant":"main","pair":null,"width":256.0,"height":190.0,"aspect":1.347,"aspect_class":"wide","bytes":5362,"shapes":3,"anchors":200,"colors":["#494368","#fc60a8"],"n_colors":2,"color_families":["blue","pink"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"pink sunglasses above lowercase name","geometry":["freeform"],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["playful","cool"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"aws-amplify.svg","brand":"aws-amplify","variant":"main","pair":null,"width":256.0,"height":191.0,"aspect":1.34,"aspect_class":"wide","bytes":743,"shapes":2,"anchors":19,"colors":["#ff9900","#ffc300"],"n_colors":2,"color_families":["orange","yellow"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"yellow-orange striped A-like triangle","geometry":["triangle"],"techniques":["gradient"],"type_style":null,"case":null,"mood":["bold","energetic"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-api-gateway.svg","brand":"aws-api-gateway","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2181,"shapes":3,"anchors":106,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"gateway doors framing code brackets","geometry":["square"],"techniques":["containment","gradient","line-monoline","bracket-code"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-app-mesh.svg","brand":"aws-app-mesh","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":6490,"shapes":3,"anchors":194,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"dotted isometric cube with nodes","geometry":["square","hexagon"],"techniques":["containment","gradient","line-monoline","isometric-3d"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-appflow.svg","brand":"aws-appflow","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1022,"shapes":3,"anchors":41,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two arrows inside hexagon outline","geometry":["square","hexagon"],"techniques":["containment","gradient","line-monoline","arrow"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-appsync.svg","brand":"aws-appsync","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2820,"shapes":3,"anchors":72,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"circular arrows around node triangle","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline","arrow"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-athena.svg","brand":"aws-athena","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3710,"shapes":3,"anchors":96,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"magnifier over bucket with speed lines","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline","motion-lines"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-aurora.svg","brand":"aws-aurora","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2648,"shapes":3,"anchors":85,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"database cylinder with sparkle stars","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-backup.svg","brand":"aws-backup","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3926,"shapes":3,"anchors":112,"colors":["#ffffff","#1b660f","#6cae3e"],"n_colors":3,"color_families":["green","white"],"primary_family":"green","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"node pentagon around circular arrow","geometry":["square","hexagon"],"techniques":["containment","gradient","line-monoline","arrow"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-batch.svg","brand":"aws-batch","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3726,"shapes":3,"anchors":91,"colors":["#ffffff","#c8511b","#ff9900"],"n_colors":3,"color_families":["orange","white"],"primary_family":"orange","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"branching tree of node circles","geometry":["square","grid-modular"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-certificate-manager.svg","brand":"aws-certificate-manager","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2109,"shapes":3,"anchors":85,"colors":["#ffffff","#bd0816","#ff5252"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"browser window with certificate star","geometry":["square","star"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"security-identity","exemplary":false,"note":""},{"file":"aws-cloudformation.svg","brand":"aws-cloudformation","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1940,"shapes":3,"anchors":75,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"document template beside cloud","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-cloudfront.svg","brand":"aws-cloudfront","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3974,"shapes":3,"anchors":95,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"globe with connected node path","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"aws-cloudsearch.svg","brand":"aws-cloudsearch","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2723,"shapes":3,"anchors":61,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"magnifier over cloud","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-cloudtrail.svg","brand":"aws-cloudtrail","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1832,"shapes":3,"anchors":72,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cloud with dashed speed trail","geometry":["square"],"techniques":["containment","gradient","line-monoline","motion-lines"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"aws-cloudwatch.svg","brand":"aws-cloudwatch","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3131,"shapes":3,"anchors":70,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cloud with magnifying glass","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"aws-codebuild.svg","brand":"aws-codebuild","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2515,"shapes":3,"anchors":122,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"crane lifting code box","geometry":["square"],"techniques":["containment","gradient","line-monoline","bracket-code"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"aws-codecommit.svg","brand":"aws-codecommit","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3386,"shapes":3,"anchors":104,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"git branch nodes with code page","geometry":["square"],"techniques":["containment","gradient","line-monoline","bracket-code","arrow"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"aws-codedeploy.svg","brand":"aws-codedeploy","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3131,"shapes":3,"anchors":94,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"parachute carrying a box","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"aws-codepipeline.svg","brand":"aws-codepipeline","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1663,"shapes":3,"anchors":70,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"slot with block feeding out","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"aws-codestar.svg","brand":"aws-codestar","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":5253,"shapes":3,"anchors":150,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"code brackets ringed by node glyphs","geometry":["square","radial"],"techniques":["containment","gradient","line-monoline","bracket-code"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"aws-cognito.svg","brand":"aws-cognito","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3255,"shapes":3,"anchors":106,"colors":["#ffffff","#bd0816","#ff5252"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"ID card with user and checkmark","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"security-identity","exemplary":false,"note":""},{"file":"aws-config.svg","brand":"aws-config","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":7072,"shapes":3,"anchors":274,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"slider controls with gear","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-documentdb.svg","brand":"aws-documentdb","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3460,"shapes":3,"anchors":113,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"database cylinder with brace document","geometry":["square"],"techniques":["containment","gradient","line-monoline","bracket-code"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-dynamodb.svg","brand":"aws-dynamodb","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4175,"shapes":3,"anchors":124,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"database cylinder with lightning bolt","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-ec2.svg","brand":"aws-ec2","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1914,"shapes":3,"anchors":133,"colors":["#ffffff","#c8511b","#ff9900"],"n_colors":3,"color_families":["orange","white"],"primary_family":"orange","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"processor chip over stacked squares","geometry":["square"],"techniques":["containment","gradient","line-monoline","stacked-layers"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-ecs.svg","brand":"aws-ecs","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1969,"shapes":3,"anchors":63,"colors":["#ffffff","#c8511b","#ff9900"],"n_colors":3,"color_families":["orange","white"],"primary_family":"orange","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"hexagonal container outline","geometry":["square","hexagon"],"techniques":["containment","gradient","line-monoline","isometric-3d"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-eks.svg","brand":"aws-eks","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2092,"shapes":3,"anchors":75,"colors":["#ffffff","#c8511b","#ff9900"],"n_colors":3,"color_families":["orange","white"],"primary_family":"orange","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter K inside hexagon outline","geometry":["square","hexagon"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-elastic-beanstalk.svg","brand":"aws-elastic-beanstalk","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3204,"shapes":3,"anchors":79,"colors":["#ffffff","#c8511b","#ff9900"],"n_colors":3,"color_families":["orange","white"],"primary_family":"orange","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cloud with sprouting plant","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-elasticache.svg","brand":"aws-elasticache","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3743,"shapes":3,"anchors":155,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"memory chip with database cylinder","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-elb.svg","brand":"aws-elb","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2029,"shapes":3,"anchors":52,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"circle branching to three nodes","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-eventbridge.svg","brand":"aws-eventbridge","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3359,"shapes":3,"anchors":98,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"hexagon linked to branching nodes","geometry":["square","hexagon"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-fargate.svg","brand":"aws-fargate","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3145,"shapes":3,"anchors":126,"colors":["#ffffff","#c8511b","#ff9900"],"n_colors":3,"color_families":["orange","white"],"primary_family":"orange","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cube on ring with small cubes","geometry":["square"],"techniques":["containment","gradient","line-monoline","isometric-3d"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-glacier.svg","brand":"aws-glacier","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2951,"shapes":3,"anchors":102,"colors":["#ffffff","#1b660f","#6cae3e"],"n_colors":3,"color_families":["green","white"],"primary_family":"green","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"bucket with snowflake","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-glue.svg","brand":"aws-glue","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2665,"shapes":3,"anchors":99,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"funnel with blocks and down arrow","geometry":["square","triangle"],"techniques":["containment","gradient","line-monoline","arrow"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-iam.svg","brand":"aws-iam","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2157,"shapes":3,"anchors":94,"colors":["#ffffff","#bd0816","#ff5252"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"ID card with padlock","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"security-identity","exemplary":false,"note":""},{"file":"aws-keyspaces.svg","brand":"aws-keyspaces","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2875,"shapes":3,"anchors":76,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"database cylinder with C asterisk","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-kinesis.svg","brand":"aws-kinesis","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1185,"shapes":3,"anchors":35,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"converging streams of flowing lines","geometry":["square"],"techniques":["containment","gradient","line-monoline","motion-lines"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-kms.svg","brand":"aws-kms","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3392,"shapes":3,"anchors":106,"colors":["#ffffff","#bd0816","#ff5252"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"key beside keycard","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"security-identity","exemplary":false,"note":""},{"file":"aws-lake-formation.svg","brand":"aws-lake-formation","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":5426,"shapes":3,"anchors":173,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"funnel over circle of waves","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-lambda.svg","brand":"aws-lambda","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1567,"shapes":3,"anchors":49,"colors":["#ffffff","#c8511b","#ff9900"],"n_colors":3,"color_families":["orange","white"],"primary_family":"orange","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"outlined Greek lambda","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-lightsail.svg","brand":"aws-lightsail","variant":"main","pair":null,"width":256.0,"height":221.0,"aspect":1.158,"aspect_class":"square","bytes":3219,"shapes":2,"anchors":86,"colors":["#e17107"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"sail and sparkles in orange circle outline","geometry":["circle"],"techniques":["line-monoline","containment","motion-lines"],"type_style":null,"case":null,"mood":["light","technical"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"aws-mq.svg","brand":"aws-mq","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":5071,"shapes":3,"anchors":149,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"nodes and arrows around square","geometry":["square","radial"],"techniques":["containment","gradient","line-monoline","arrow"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-msk.svg","brand":"aws-msk","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4405,"shapes":3,"anchors":134,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"node triangle with K over waves","geometry":["square","triangle"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-neptune.svg","brand":"aws-neptune","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3995,"shapes":3,"anchors":112,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"database cylinder with node graph","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-open-search.svg","brand":"aws-open-search","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2709,"shapes":3,"anchors":106,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"bar chart with magnifier","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-opsworks.svg","brand":"aws-opsworks","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":5556,"shapes":3,"anchors":187,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"gear above org-chart blocks","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-quicksight.svg","brand":"aws-quicksight","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2270,"shapes":3,"anchors":74,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"rising line chart in frame","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"aws-rds.svg","brand":"aws-rds","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2546,"shapes":3,"anchors":96,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"database cylinder with expand arrows","geometry":["square"],"techniques":["containment","gradient","line-monoline","arrow"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-redshift.svg","brand":"aws-redshift","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3115,"shapes":3,"anchors":75,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cylinder with line chart","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-route53.svg","brand":"aws-route53","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":5679,"shapes":3,"anchors":132,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"highway route shield with number 53","geometry":["square","shield"],"techniques":["containment","gradient","line-monoline"],"type_style":"grotesque-sans","case":null,"mood":["technical","corporate"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"aws-s3.svg","brand":"aws-s3","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2023,"shapes":3,"anchors":47,"colors":["#ffffff","#1b660f","#6cae3e"],"n_colors":3,"color_families":["green","white"],"primary_family":"green","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"storage bucket outline","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-secrets-manager.svg","brand":"aws-secrets-manager","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2986,"shapes":3,"anchors":127,"colors":["#ffffff","#bd0816","#ff5252"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"padlock within crosshair","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"security-identity","exemplary":false,"note":""},{"file":"aws-ses.svg","brand":"aws-ses","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2593,"shapes":3,"anchors":87,"colors":["#ffffff","#bd0816","#ff5252"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"envelope in circle with nodes","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"social-communication","exemplary":false,"note":""},{"file":"aws-shield.svg","brand":"aws-shield","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2330,"shapes":3,"anchors":70,"colors":["#ffffff","#bd0816","#ff5252"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"shield with plus badge","geometry":["square","shield"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"security-identity","exemplary":false,"note":""},{"file":"aws-sns.svg","brand":"aws-sns","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3530,"shapes":3,"anchors":101,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"funnel in circle fanning to nodes","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"social-communication","exemplary":false,"note":""},{"file":"aws-sqs.svg","brand":"aws-sqs","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4237,"shapes":3,"anchors":106,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"square between arrows in circle","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline","arrow"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-step-functions.svg","brand":"aws-step-functions","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2195,"shapes":3,"anchors":94,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"flowchart of blocks and nodes","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-systems-manager.svg","brand":"aws-systems-manager","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":5779,"shapes":3,"anchors":190,"colors":["#ffffff","#b0084d","#ff4f8b"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cloud with settings gear","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-timestream.svg","brand":"aws-timestream","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2331,"shapes":3,"anchors":103,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"database cylinder with trend chart","geometry":["square"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"database-data","exemplary":false,"note":""},{"file":"aws-vpc.svg","brand":"aws-vpc","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2921,"shapes":3,"anchors":77,"colors":["#ffffff","#4d27a8","#a166ff"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cloud with shield","geometry":["square","shield"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"aws-waf.svg","brand":"aws-waf","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3800,"shapes":3,"anchors":119,"colors":["#ffffff","#bd0816","#ff5252"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"flame inside crossed-out crosshair","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"security-identity","exemplary":false,"note":""},{"file":"aws-xray.svg","brand":"aws-xray","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2271,"shapes":3,"anchors":61,"colors":["#ffffff","#2e27ad","#527fff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cloud over circle with bar chart","geometry":["square","circle"],"techniques":["containment","gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","corporate"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"aws.svg","brand":"aws","variant":"main","pair":null,"width":256.0,"height":153.0,"aspect":1.673,"aspect_class":"wide","bytes":5846,"shapes":3,"anchors":138,"colors":["#252f3e","#ff9900"],"n_colors":2,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"lowercase aws over smile arrow","geometry":[],"techniques":["arrow","hidden-meaning"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","corporate"],"industry":"cloud-infrastructure","exemplary":true,"note":"Smile arrow adds warmth and motion under a plain wordmark"},{"file":"axios.svg","brand":"axios","variant":"main","pair":null,"width":512.0,"height":75.0,"aspect":6.827,"aspect_class":"extra-wide","bytes":3950,"shapes":2,"anchors":131,"colors":["#5a29e4"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"widely spaced uppercase name, custom I","geometry":[],"techniques":["letter-substitution"],"type_style":"geometric-sans","case":"uppercase","mood":["light","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"babel.svg","brand":"babel","variant":"main","pair":null,"width":512.0,"height":200.0,"aspect":2.56,"aspect_class":"horizontal","bytes":65784,"shapes":3,"anchors":2330,"colors":["#000000","#f9dc3e"],"n_colors":2,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"yellow brush-stroke uppercase name","geometry":[],"techniques":["hand-drawn"],"type_style":"display-custom","case":"uppercase","mood":["energetic","raw"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"backbone-icon.svg","brand":"backbone","variant":"icon","pair":"backbone.svg","width":256.0,"height":318.0,"aspect":0.805,"aspect_class":"square","bytes":767,"shapes":5,"anchors":36,"colors":["#002a41","#0071b5"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"interlocking chevrons forming bow-tie","geometry":["triangle","square"],"techniques":["mirror-symmetry","overlap-transparency","geometric-construction"],"type_style":null,"case":null,"mood":["structured","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"backbone.svg","brand":"backbone","variant":"main","pair":"backbone-icon.svg","width":512.0,"height":92.0,"aspect":5.565,"aspect_class":"extra-wide","bytes":6476,"shapes":16,"anchors":221,"colors":["#002a41","#0071b5"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"chevron bow-tie beside thin uppercase name","geometry":["triangle"],"techniques":["mirror-symmetry","geometric-construction"],"type_style":"geometric-sans","case":"uppercase","mood":["light","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"backerkit.svg","brand":"backerkit","variant":"main","pair":null,"width":256.0,"height":249.0,"aspect":1.028,"aspect_class":"square","bytes":941,"shapes":2,"anchors":36,"colors":["#2d2e2b"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"mountain peaks with summit flag","geometry":["triangle"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["bold","adventurous"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"baker-street.svg","brand":"baker-street","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2401,"shapes":7,"anchors":50,"colors":["#f99d59","#178dbc","#e5d332","#3e7947","#e57428","#4a6f5d"],"n_colors":6,"color_families":["blue","green","orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"ring of overlapping colored arcs","geometry":["circle"],"techniques":["overlap-transparency","color-segments"],"type_style":null,"case":null,"mood":["colorful","dynamic"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"balena.svg","brand":"balena","variant":"main","pair":null,"width":256.0,"height":282.0,"aspect":0.908,"aspect_class":"square","bytes":2383,"shapes":7,"anchors":67,"colors":["#ffc600","#f6eb61","#439879","#28cdfb","#fdd757","#ec8b00"],"n_colors":6,"color_families":["cyan","green","orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric cube with colored faces","geometry":["hexagon"],"techniques":["isometric-3d","color-segments"],"type_style":null,"case":null,"mood":["bright","playful"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"bamboo.svg","brand":"bamboo","variant":"main","pair":null,"width":256.0,"height":296.0,"aspect":0.865,"aspect_class":"square","bytes":1720,"shapes":5,"anchors":29,"colors":["#2684ff","#0052cc"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"segmented circle ending in arrow","geometry":["circle","radial"],"techniques":["arrow","gradient"],"type_style":null,"case":null,"mood":["dynamic","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"basecamp.svg","brand":"basecamp","variant":"main","pair":null,"width":256.0,"height":213.0,"aspect":1.202,"aspect_class":"square","bytes":1294,"shapes":4,"anchors":24,"colors":["#b6deff","#66cc66","#17ad49"],"n_colors":3,"color_families":["blue","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"green hill inside soft smile shape","geometry":["organic"],"techniques":["containment","hidden-meaning"],"type_style":null,"case":null,"mood":["friendly","calm"],"industry":"productivity-collaboration","exemplary":true,"note":"Hill silhouette doubles as a smile inside soft container"},{"file":"basekit.svg","brand":"basekit","variant":"main","pair":null,"width":256.0,"height":217.0,"aspect":1.18,"aspect_class":"square","bytes":924,"shapes":2,"anchors":33,"colors":["#02161f"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"BK initials in black rectangle","geometry":["square"],"techniques":["containment","ligature"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","simple"],"industry":"design-creative","exemplary":false,"note":""},{"file":"bash-icon.svg","brand":"bash","variant":"icon","pair":"bash.svg","width":224.0,"height":256.0,"aspect":0.875,"aspect_class":"square","bytes":3186,"shapes":5,"anchors":84,"colors":["#ffffff","#2f3a3e","#3ab14a"],"n_colors":3,"color_families":["gray","green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"hexagonal block with terminal prompt","geometry":["hexagon"],"techniques":["bracket-code","dimensional-shading","isometric-3d"],"type_style":null,"case":null,"mood":["technical","solid"],"industry":"programming-language","exemplary":false,"note":""},{"file":"bash.svg","brand":"bash","variant":"main","pair":"bash-icon.svg","width":512.0,"height":217.0,"aspect":2.359,"aspect_class":"wide","bytes":18598,"shapes":6,"anchors":605,"colors":["#ffffff","#2f3a3e","#3ab14a"],"n_colors":3,"color_families":["gray","green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"prompt block beside bold name and tagline","geometry":["hexagon"],"techniques":["bracket-code","dimensional-shading"],"type_style":"grotesque-sans","case":"uppercase","mood":["technical","solid"],"industry":"programming-language","exemplary":false,"note":""},{"file":"batch.svg","brand":"batch","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1231,"shapes":4,"anchors":36,"colors":["#1a293b","#ffffff","#53b6e4"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"lowercase b with underline in dark tile","geometry":["rounded-square"],"techniques":["containment"],"type_style":null,"case":null,"mood":["minimal","modern"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"beats.svg","brand":"beats","variant":"main","pair":null,"width":256.0,"height":328.0,"aspect":0.78,"aspect_class":"tall","bytes":823,"shapes":4,"anchors":21,"colors":["#0077cc","#343741","#00bfb3"],"n_colors":3,"color_families":["blue","cyan","gray"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"stacked color bands forming rounded B","geometry":["freeform"],"techniques":["color-segments","stacked-layers"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"database-data","exemplary":false,"note":""},{"file":"behance.svg","brand":"behance","variant":"main","pair":null,"width":512.0,"height":95.0,"aspect":5.389,"aspect_class":"extra-wide","bytes":8845,"shapes":9,"anchors":221,"colors":["#0a0b09"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold name with macron over e","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"titlecase","mood":["bold","confident"],"industry":"design-creative","exemplary":false,"note":""},{"file":"bem-2.svg","brand":"bem-2","variant":"main","pair":null,"width":256.0,"height":220.0,"aspect":1.164,"aspect_class":"square","bytes":621,"shapes":4,"anchors":26,"colors":["#010101","#f7b334"],"n_colors":2,"color_families":["black","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"blocky bird-like head with underscore","geometry":["square","grid-modular"],"techniques":["geometric-construction","bracket-code"],"type_style":null,"case":null,"mood":["quirky","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"bem.svg","brand":"bem","variant":"main","pair":null,"width":256.0,"height":212.0,"aspect":1.208,"aspect_class":"square","bytes":1180,"shapes":2,"anchors":52,"colors":["#010101"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"striped bars forming block shapes with underscore","geometry":["grid-modular"],"techniques":["modular-repetition","line-monoline"],"type_style":null,"case":null,"mood":["technical","structured"],"industry":"framework-library","exemplary":false,"note":""},{"file":"bigpanda.svg","brand":"bigpanda","variant":"main","pair":null,"width":256.0,"height":222.0,"aspect":1.153,"aspect_class":"square","bytes":8652,"shapes":3,"anchors":243,"colors":["#ffffff","#454545"],"n_colors":2,"color_families":["gray","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"panda face wearing glasses","geometry":["organic"],"techniques":["line-monoline","mirror-symmetry"],"type_style":null,"case":null,"mood":["friendly","smart"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"bing.svg","brand":"bing","variant":"main","pair":null,"width":256.0,"height":320.0,"aspect":0.8,"aspect_class":"square","bytes":420,"shapes":2,"anchors":12,"colors":["#f4bd27"],"n_colors":1,"color_families":["yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"angular ribbon lowercase b","geometry":["freeform"],"techniques":["geometric-construction","dimensional-shading"],"type_style":null,"case":null,"mood":["bold","dynamic"],"industry":"other","exemplary":false,"note":""},{"file":"bitbucket.svg","brand":"bitbucket","variant":"main","pair":null,"width":256.0,"height":231.0,"aspect":1.108,"aspect_class":"square","bytes":1177,"shapes":3,"anchors":25,"colors":["#2684ff","#0052cc"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"blue gradient bucket with cutout","geometry":["freeform"],"techniques":["gradient","negative-space"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"bitcoin.svg","brand":"bitcoin","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1996,"shapes":3,"anchors":47,"colors":["#ffffff","#f9aa4b","#f7931a"],"n_colors":3,"color_families":["orange","white"],"primary_family":"orange","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"tilted B currency sign in orange circle","geometry":["circle"],"techniques":["containment","gradient"],"type_style":null,"case":null,"mood":["bold","trustworthy"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"bitnami.svg","brand":"bitnami","variant":"main","pair":null,"width":256.0,"height":287.0,"aspect":0.892,"aspect_class":"square","bytes":2835,"shapes":8,"anchors":67,"colors":["#2a5d84","#1a3b54","#ffffff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"lowercase b in isometric hexagon","geometry":["hexagon"],"techniques":["negative-space","dimensional-shading","isometric-3d"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"bitrise-icon.svg","brand":"bitrise","variant":"icon","pair":"bitrise.svg","width":256.0,"height":211.0,"aspect":1.213,"aspect_class":"square","bytes":2477,"shapes":2,"anchors":67,"colors":["#683d87"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"smiling robot face with antenna","geometry":["rounded-square"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"bitrise.svg","brand":"bitrise","variant":"main","pair":"bitrise-icon.svg","width":512.0,"height":148.0,"aspect":3.459,"aspect_class":"horizontal","bytes":5356,"shapes":3,"anchors":178,"colors":["#683d87"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"robot face beside bold lowercase name","geometry":["rounded-square"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["playful","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"blender.svg","brand":"blender","variant":"main","pair":null,"width":256.0,"height":208.0,"aspect":1.231,"aspect_class":"square","bytes":2834,"shapes":4,"anchors":62,"colors":["#ffffff","#265787","#ea7600"],"n_colors":3,"color_families":["blue","orange","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orbiting ring with blue eye core","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["dynamic","creative"],"industry":"design-creative","exemplary":false,"note":""},{"file":"blitzjs-icon.svg","brand":"blitzjs","variant":"icon","pair":"blitzjs.svg","width":256.0,"height":394.0,"aspect":0.65,"aspect_class":"tall","bytes":698,"shapes":2,"anchors":16,"colors":["#6700eb"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two slanted purple bars forming bolt","geometry":["freeform"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["fast","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"blitzjs.svg","brand":"blitzjs","variant":"main","pair":"blitzjs-icon.svg","width":512.0,"height":203.0,"aspect":2.522,"aspect_class":"horizontal","bytes":4405,"shapes":3,"anchors":143,"colors":["#6700eb"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"slanted bolt beside titlecase name","geometry":["freeform"],"techniques":["geometric-construction"],"type_style":"geometric-sans","case":"titlecase","mood":["fast","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"blocs.svg","brand":"blocs","variant":"main","pair":null,"width":256.0,"height":283.0,"aspect":0.905,"aspect_class":"square","bytes":1792,"shapes":6,"anchors":56,"colors":["#ffffff","#298aec","#44546c"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"hexagon outline with three lines","geometry":["hexagon"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["simple","calm"],"industry":"design-creative","exemplary":false,"note":""},{"file":"blogger.svg","brand":"blogger","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2646,"shapes":4,"anchors":57,"colors":["#f06a35","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"rounded B in orange tile","geometry":["rounded-square"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["friendly","simple"],"industry":"social-communication","exemplary":false,"note":""},{"file":"blossom.svg","brand":"blossom","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1542,"shapes":5,"anchors":30,"colors":["#122941"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"lotus flower in dark ring","geometry":["circle"],"techniques":["negative-space","containment","mirror-symmetry"],"type_style":null,"case":null,"mood":["calm","balanced"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"blueprint.svg","brand":"blueprint","variant":"main","pair":null,"width":256.0,"height":298.0,"aspect":0.859,"aspect_class":"square","bytes":2561,"shapes":26,"anchors":137,"colors":["#00b46f","#2294d9","#f85551","#30b2e9","#00ab64","#00ce8e","#00c783","#2caee7","#fb716c","#1f8ed6","#f64743","#f96560","#b71d1d","#b21a1a","#10161a","#007233","#00682c","#0759ba","#0860bf","#febcb7","#4edcf8","#00f3c9"],"n_colors":22,"color_families":["blue","cyan","green","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric cluster of colored cubes","geometry":["hexagon","grid-modular"],"techniques":["isometric-3d","color-segments","modular-repetition"],"type_style":null,"case":null,"mood":["colorful","structured"],"industry":"framework-library","exemplary":false,"note":""},{"file":"bluetooth.svg","brand":"bluetooth","variant":"main","pair":null,"width":256.0,"height":348.0,"aspect":0.736,"aspect_class":"tall","bytes":757,"shapes":2,"anchors":26,"colors":["#0060a9"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"bind-rune of H and B in blue","geometry":["organic"],"techniques":["hidden-meaning","containment","line-monoline"],"type_style":null,"case":null,"mood":["technical","trustworthy"],"industry":"hardware-devices","exemplary":true,"note":"Runic initials merged into one glyph: history encoded simply"},{"file":"booqable-icon.svg","brand":"booqable","variant":"icon","pair":"booqable.svg","width":256.0,"height":135.0,"aspect":1.896,"aspect_class":"wide","bytes":3465,"shapes":2,"anchors":78,"colors":["#1d1d1b"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"monoline boomerang arc","geometry":["organic"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["minimal","friendly"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"booqable.svg","brand":"booqable","variant":"main","pair":"booqable-icon.svg","width":512.0,"height":82.0,"aspect":6.244,"aspect_class":"extra-wide","bytes":8709,"shapes":3,"anchors":222,"colors":["#1d1d1b","#000000"],"n_colors":2,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"boomerang arc beside lowercase name","geometry":["organic"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","modern"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"bootstrap.svg","brand":"bootstrap","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1722,"shapes":3,"anchors":45,"colors":["#563d7c","#ffffff"],"n_colors":2,"color_families":["purple","white"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"bold B in purple rounded square","geometry":["rounded-square"],"techniques":["containment"],"type_style":null,"case":null,"mood":["solid","simple"],"industry":"framework-library","exemplary":false,"note":""},{"file":"bosun.svg","brand":"bosun","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4605,"shapes":20,"anchors":132,"colors":["#1f5296","#4ba2d9","#356eb6","#ffffff"],"n_colors":4,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"grid of linked nodes on blue tiles","geometry":["square","grid-modular"],"techniques":["containment","modular-repetition"],"type_style":null,"case":null,"mood":["technical","structured"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"botanalytics.svg","brand":"botanalytics","variant":"main","pair":null,"width":256.0,"height":300.0,"aspect":0.853,"aspect_class":"square","bytes":1979,"shapes":2,"anchors":58,"colors":["#0385cd"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"speech bubble with chart-line top edge","geometry":["freeform"],"techniques":["speech-bubble","line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["clever","technical"],"industry":"marketing-analytics","exemplary":true,"note":"Speech bubble edge doubles as a chart line: two ideas fused"},{"file":"bourbon.svg","brand":"bourbon","variant":"main","pair":null,"width":256.0,"height":252.0,"aspect":1.016,"aspect_class":"square","bytes":2792,"shapes":7,"anchors":63,"colors":["#e5d1bf","#fef9ec","#ff992e","#ff4c2e","#e3302e"],"n_colors":5,"color_families":["orange","red","white"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"glass of bourbon with ice","geometry":["square"],"techniques":["gradient"],"type_style":null,"case":null,"mood":["warm","classic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"bower.svg","brand":"bower","variant":"main","pair":null,"width":256.0,"height":225.0,"aspect":1.138,"aspect_class":"square","bytes":4873,"shapes":10,"anchors":100,"colors":["#543729","#00acee","#2baf2b","#ffcc2f","#cecece","#ef5734","#ffffff"],"n_colors":7,"color_families":["blue","gray","green","orange","red","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"colorful cartoon bird head","geometry":["organic"],"techniques":["color-segments"],"type_style":null,"case":null,"mood":["playful","colorful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"box.svg","brand":"box","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1939,"shapes":4,"anchors":54,"colors":["#00aeef","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"white lowercase box in blue tile","geometry":["rounded-square"],"techniques":["containment"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","simple"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"brackets.svg","brand":"brackets","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3019,"shapes":6,"anchors":54,"colors":["#115a91","#ffffff","#4d4d4d","#29abe2","#28a9e1","#23a2dc","#1a96d4","#0e85c9","#0071bc"],"n_colors":9,"color_families":["blue","gray","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":true,"mark_type":"abstract","symbol_type":null,"subject":"square brackets on raised blue button","geometry":["rounded-square"],"techniques":["bracket-code","containment","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","solid"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"brainjs.svg","brand":"brainjs","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":725,"shapes":3,"anchors":32,"colors":["#f3df49","#2e2e2c"],"n_colors":2,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"faceted black brain on yellow square","geometry":["square"],"techniques":["containment","geometric-construction"],"type_style":null,"case":null,"mood":["bold","technical"],"industry":"ai-ml","exemplary":false,"note":""},{"file":"branch.svg","brand":"branch","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2936,"shapes":3,"anchors":72,"colors":["#333e48","#009bde"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"tree branch with node dots in ring","geometry":["circle"],"techniques":["containment","line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["organic","technical"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"brandfolder-icon.svg","brand":"brandfolder","variant":"icon","pair":"brandfolder.svg","width":256.0,"height":241.0,"aspect":1.062,"aspect_class":"square","bytes":2373,"shapes":2,"anchors":61,"colors":["#40d1f5"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"B inside open frame with arrow","geometry":["square"],"techniques":["containment","arrow"],"type_style":null,"case":null,"mood":["bright","modern"],"industry":"design-creative","exemplary":false,"note":""},{"file":"brandfolder.svg","brand":"brandfolder","variant":"main","pair":"brandfolder-icon.svg","width":512.0,"height":121.0,"aspect":4.231,"aspect_class":"horizontal","bytes":11766,"shapes":3,"anchors":347,"colors":["#343333","#39c5eb"],"n_colors":2,"color_families":["cyan","gray"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"bracket frame hugging titlecase name","geometry":["square"],"techniques":["containment"],"type_style":"grotesque-sans","case":"titlecase","mood":["clean","modern"],"industry":"design-creative","exemplary":false,"note":""},{"file":"brave.svg","brand":"brave","variant":"main","pair":null,"width":256.0,"height":301.0,"aspect":0.85,"aspect_class":"square","bytes":6084,"shapes":6,"anchors":177,"colors":["#f15a22","#ffffff","#f1f1f2","#e4e5e6","#d9dadb","#d2d4d5","#d0d2d3"],"n_colors":7,"color_families":["gray","orange","white"],"primary_family":"orange","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"faceted lion head in shield form","geometry":["shield"],"techniques":["geometric-construction","gradient","mirror-symmetry","dimensional-shading"],"type_style":null,"case":null,"mood":["bold","brave"],"industry":"other","exemplary":false,"note":""},{"file":"braze.svg","brand":"braze","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1579,"shapes":2,"anchors":34,"colors":["#212124"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"script lowercase b inside ring","geometry":["circle"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["elegant","modern"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"broccoli.svg","brand":"broccoli","variant":"main","pair":null,"width":256.0,"height":266.0,"aspect":0.962,"aspect_class":"square","bytes":2989,"shapes":2,"anchors":59,"colors":["#598527"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"green broccoli floret","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["playful","organic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"brotli.svg","brand":"brotli","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1187,"shapes":5,"anchors":20,"colors":["#eeaa33","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three slanted cuts in golden circle","geometry":["circle"],"techniques":["containment","negative-space","modular-repetition"],"type_style":null,"case":null,"mood":["warm","simple"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"browserify-icon.svg","brand":"browserify","variant":"icon","pair":"browserify.svg","width":256.0,"height":216.0,"aspect":1.185,"aspect_class":"square","bytes":11544,"shapes":7,"anchors":244,"colors":["#3c6991","#e6b35a"],"n_colors":2,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"blue wizard hat with moon and stars","geometry":["triangle","organic"],"techniques":[],"type_style":null,"case":null,"mood":["whimsical","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"browserify.svg","brand":"browserify","variant":"main","pair":"browserify-icon.svg","width":512.0,"height":152.0,"aspect":3.368,"aspect_class":"horizontal","bytes":81742,"shapes":24,"anchors":1764,"colors":["#e6b35a","#5a8ce6","#c8dceb"],"n_colors":3,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"hand-lettered gold lowercase name","geometry":[],"techniques":["hand-drawn"],"type_style":"display-custom","case":"lowercase","mood":["whimsical","quirky"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"browserling.svg","brand":"browserling","variant":"main","pair":null,"width":256.0,"height":229.0,"aspect":1.118,"aspect_class":"square","bytes":2484,"shapes":2,"anchors":69,"colors":["#5581b5"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"UFO outline with tractor beams","geometry":["organic"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["playful","light"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"browserslist.svg","brand":"browserslist","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2646,"shapes":4,"anchors":56,"colors":["#ffd539","#ffffff","#000000"],"n_colors":3,"color_families":["black","white","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"hedgehog silhouette in yellow circle","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"browserstack.svg","brand":"browserstack","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3094,"shapes":12,"anchors":55,"colors":["#f5bb60","#e86f32","#e53d42","#bfd141","#6db64c","#afdbe7","#57badf","#02b2d6","#231f20","#ffffff","#797979","#4c4c4c"],"n_colors":12,"color_families":["black","blue","cyan","gray","green","orange","red","white"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"eye inside colorful concentric rings","geometry":["circle","radial"],"techniques":["color-segments","stacked-layers"],"type_style":null,"case":null,"mood":["colorful","vibrant"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"browsersync.svg","brand":"browsersync","variant":"main","pair":null,"width":256.0,"height":387.0,"aspect":0.661,"aspect_class":"tall","bytes":754,"shapes":2,"anchors":18,"colors":["#f14646"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two slanted red tower blocks","geometry":["freeform"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"brunch.svg","brand":"brunch","variant":"main","pair":null,"width":256.0,"height":501.0,"aspect":0.511,"aspect_class":"tall","bytes":12252,"shapes":7,"anchors":468,"colors":["#86ad8a","#ffffff","#ceccae","#3f894a"],"n_colors":4,"color_families":["green","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"fork knife spoon in faceted diamond","geometry":["diamond"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["fresh","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"buck.svg","brand":"buck","variant":"main","pair":null,"width":256.0,"height":223.0,"aspect":1.148,"aspect_class":"square","bytes":817,"shapes":3,"anchors":45,"colors":["#4a69a5"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"geometric monoline deer head and antlers","geometry":["freeform"],"techniques":["line-monoline","geometric-construction","mirror-symmetry"],"type_style":null,"case":null,"mood":["sharp","technical"],"industry":"developer-tools","exemplary":true,"note":"Deer head built from strict geometric monoline strokes"},{"file":"buddy.svg","brand":"buddy","variant":"main","pair":null,"width":256.0,"height":289.0,"aspect":0.886,"aspect_class":"square","bytes":2448,"shapes":12,"anchors":58,"colors":["#00c9ff","#1a67fd","#0da7fe","#05bbff","#1a86fd","#d6ffff"],"n_colors":6,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"chevron inside faceted blue hexagon","geometry":["hexagon"],"techniques":["gradient","arrow","dimensional-shading"],"type_style":null,"case":null,"mood":["modern","dynamic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"buffer.svg","brand":"buffer","variant":"main","pair":null,"width":256.0,"height":262.0,"aspect":0.977,"aspect_class":"square","bytes":2352,"shapes":2,"anchors":45,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three stacked rhombus layers","geometry":["diamond"],"techniques":["stacked-layers","modular-repetition"],"type_style":null,"case":null,"mood":["simple","calm"],"industry":"marketing-analytics","exemplary":true,"note":"Three stacked layers: minimal, memorable, name-literal"},{"file":"bugherd.svg","brand":"bugherd","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":8389,"shapes":3,"anchors":188,"colors":["#222222","#6db6d1"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"condensed name inside black circle","geometry":["circle"],"techniques":["containment"],"type_style":"grotesque-sans","case":"mixed","mood":["bold","friendly"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"bugsee.svg","brand":"bugsee","variant":"main","pair":null,"width":256.0,"height":131.0,"aspect":1.954,"aspect_class":"wide","bytes":1233,"shapes":4,"anchors":37,"colors":["#fc5252","#f9ffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red anteater silhouette","geometry":["organic"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["playful","quirky"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"bugsnag-icon.svg","brand":"bugsnag","variant":"icon","pair":"bugsnag.svg","width":256.0,"height":369.0,"aspect":0.694,"aspect_class":"tall","bytes":1670,"shapes":2,"anchors":45,"colors":["#000d47"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"monoline b wrapping target dot","geometry":["circle"],"techniques":["line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["modern","precise"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"bugsnag.svg","brand":"bugsnag","variant":"main","pair":"bugsnag-icon.svg","width":512.0,"height":141.0,"aspect":3.631,"aspect_class":"horizontal","bytes":5121,"shapes":2,"anchors":134,"colors":["#000d47"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"rounded navy lowercase name","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","modern"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"buildkite-icon.svg","brand":"buildkite","variant":"icon","pair":"buildkite.svg","width":256.0,"height":171.0,"aspect":1.497,"aspect_class":"wide","bytes":550,"shapes":5,"anchors":19,"colors":["#30f2a2","#14cc80"],"n_colors":2,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"folded green isometric ribbon kite","geometry":["freeform"],"techniques":["isometric-3d","dimensional-shading"],"type_style":null,"case":null,"mood":["fresh","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"buildkite.svg","brand":"buildkite","variant":"main","pair":"buildkite-icon.svg","width":512.0,"height":91.0,"aspect":5.626,"aspect_class":"extra-wide","bytes":3684,"shapes":6,"anchors":140,"colors":["#000000","#30f2a2","#14cc80"],"n_colors":3,"color_families":["black","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"folded ribbon beside bold titlecase name","geometry":["freeform"],"techniques":["isometric-3d","dimensional-shading"],"type_style":"grotesque-sans","case":"titlecase","mood":["fresh","confident"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"bulma.svg","brand":"bulma","variant":"main","pair":null,"width":256.0,"height":373.0,"aspect":0.686,"aspect_class":"tall","bytes":378,"shapes":2,"anchors":8,"colors":["#00d1b2"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"angular teal B-like faceted shape","geometry":["freeform"],"techniques":["geometric-construction","negative-space"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"c-plusplus.svg","brand":"c-plusplus","variant":"main","pair":null,"width":256.0,"height":288.0,"aspect":0.889,"aspect_class":"square","bytes":2454,"shapes":8,"anchors":74,"colors":["#5c8dbc","#1a4674","#1b598e","#ffffff"],"n_colors":4,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"C with ++ inside shaded hexagon","geometry":["hexagon"],"techniques":["containment","dimensional-shading","negative-space"],"type_style":null,"case":null,"mood":["technical","solid"],"industry":"programming-language","exemplary":false,"note":""},{"file":"c-sharp.svg","brand":"c-sharp","variant":"main","pair":null,"width":256.0,"height":288.0,"aspect":0.889,"aspect_class":"square","bytes":2429,"shapes":6,"anchors":81,"colors":["#a179dc","#280068","#390091","#ffffff"],"n_colors":4,"color_families":["purple","white"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"C with sharp sign in purple hexagon","geometry":["hexagon"],"techniques":["containment","dimensional-shading","negative-space"],"type_style":null,"case":null,"mood":["technical","solid"],"industry":"programming-language","exemplary":false,"note":""},{"file":"c.svg","brand":"c","variant":"main","pair":null,"width":256.0,"height":288.0,"aspect":0.889,"aspect_class":"square","bytes":1766,"shapes":4,"anchors":37,"colors":["#a9b9cb","#7f8b99","#ffffff"],"n_colors":3,"color_families":["blue","gray","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter C in gray shaded hexagon","geometry":["hexagon"],"techniques":["containment","dimensional-shading","negative-space"],"type_style":null,"case":null,"mood":["technical","plain"],"industry":"programming-language","exemplary":false,"note":""},{"file":"cachet.svg","brand":"cachet","variant":"main","pair":null,"width":512.0,"height":130.0,"aspect":3.938,"aspect_class":"horizontal","bytes":9574,"shapes":4,"anchors":255,"colors":["#7ed321","#5e5e5e"],"n_colors":2,"color_families":["gray","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"check mark circle beside thin name","geometry":["circle"],"techniques":["line-monoline"],"type_style":"humanist-sans","case":"titlecase","mood":["light","calm"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"caffe2.svg","brand":"caffe2","variant":"main","pair":null,"width":255.0,"height":292.0,"aspect":0.873,"aspect_class":"square","bytes":2383,"shapes":6,"anchors":74,"colors":["#ffffff","#303846"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"coffee cup with plus signs as steam","geometry":["circle"],"techniques":["line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["friendly","technical"],"industry":"ai-ml","exemplary":false,"note":""},{"file":"cakephp-icon.svg","brand":"cakephp","variant":"icon","pair":"cakephp.svg","width":256.0,"height":200.0,"aspect":1.28,"aspect_class":"wide","bytes":761,"shapes":2,"anchors":21,"colors":["#d33c44"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"layered cake with slice removed","geometry":["circle"],"techniques":["stacked-layers","dimensional-shading"],"type_style":null,"case":null,"mood":["bold","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"cakephp.svg","brand":"cakephp","variant":"main","pair":"cakephp-icon.svg","width":512.0,"height":103.0,"aspect":4.971,"aspect_class":"extra-wide","bytes":3345,"shapes":3,"anchors":130,"colors":["#d33c44"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"cake icon beside bold mixed-case name","geometry":["circle"],"techniques":["stacked-layers"],"type_style":"geometric-sans","case":"mixed","mood":["bold","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"campaignmonitor-icon.svg","brand":"campaignmonitor","variant":"icon","pair":"campaignmonitor.svg","width":256.0,"height":174.0,"aspect":1.471,"aspect_class":"wide","bytes":733,"shapes":2,"anchors":17,"colors":["#7856ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"purple envelope from angular shapes","geometry":["triangle","square"],"techniques":["geometric-construction","negative-space"],"type_style":null,"case":null,"mood":["modern","bold"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"campaignmonitor.svg","brand":"campaignmonitor","variant":"main","pair":"campaignmonitor-icon.svg","width":512.0,"height":51.0,"aspect":10.039,"aspect_class":"extra-wide","bytes":11044,"shapes":3,"anchors":347,"colors":["#002b45","#7856ff"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"small envelope beside titlecase name","geometry":["triangle"],"techniques":["geometric-construction"],"type_style":"geometric-sans","case":"titlecase","mood":["clean","corporate"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"canjs.svg","brand":"canjs","variant":"main","pair":null,"width":256.0,"height":102.0,"aspect":2.51,"aspect_class":"horizontal","bytes":8794,"shapes":6,"anchors":233,"colors":["#1a1918"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy tightly kerned lowercase name","geometry":[],"techniques":["ligature"],"type_style":"grotesque-sans","case":"lowercase","mood":["bold","compact"],"industry":"framework-library","exemplary":false,"note":""},{"file":"capacitorjs-icon.svg","brand":"capacitorjs","variant":"icon","pair":"capacitorjs.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1013,"shapes":7,"anchors":36,"colors":["#53b9ff","#119eff","#000000"],"n_colors":3,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"X formed by overlapping blue bars","geometry":["freeform"],"techniques":["overlap-transparency","mirror-symmetry"],"type_style":null,"case":null,"mood":["dynamic","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"capacitorjs.svg","brand":"capacitorjs","variant":"main","pair":"capacitorjs-icon.svg","width":512.0,"height":98.0,"aspect":5.224,"aspect_class":"extra-wide","bytes":4217,"shapes":8,"anchors":143,"colors":["#000000","#53b9ff","#119eff"],"n_colors":3,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"blue X beside bold titlecase name","geometry":["freeform"],"techniques":["overlap-transparency"],"type_style":"geometric-sans","case":"titlecase","mood":["modern","confident"],"industry":"framework-library","exemplary":false,"note":""},{"file":"capistrano.svg","brand":"capistrano","variant":"main","pair":null,"width":256.0,"height":269.0,"aspect":0.952,"aspect_class":"square","bytes":18198,"shapes":16,"anchors":466,"colors":["#52c1db","#3b528a","#00aee8","#3f8abd"],"n_colors":4,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"C made of segmented blue ring","geometry":["circle","radial"],"techniques":["modular-repetition","color-segments"],"type_style":null,"case":null,"mood":["technical","dynamic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"carbide.svg","brand":"carbide","variant":"main","pair":null,"width":256.0,"height":313.0,"aspect":0.818,"aspect_class":"square","bytes":848,"shapes":2,"anchors":17,"colors":["#4b608e"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"turbine-like gear forming letter C","geometry":["circle","radial"],"techniques":["negative-space","radial-symmetry"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"cardano-icon.svg","brand":"cardano","variant":"icon","pair":"cardano.svg","width":256.0,"height":237.0,"aspect":1.08,"aspect_class":"square","bytes":7852,"shapes":2,"anchors":186,"colors":["#0033ad"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"radial pattern of graduated dots","geometry":["radial","circle"],"techniques":["radial-symmetry","modular-repetition"],"type_style":null,"case":null,"mood":["technical","precise"],"industry":"payments-fintech","exemplary":true,"note":"Graduated dot sizes build a radial form through pure repetition"},{"file":"cardano.svg","brand":"cardano","variant":"main","pair":"cardano-icon.svg","width":512.0,"height":103.0,"aspect":4.971,"aspect_class":"extra-wide","bytes":11174,"shapes":3,"anchors":362,"colors":["#0033ad"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"dot constellation beside uppercase name","geometry":["radial"],"techniques":["radial-symmetry","modular-repetition"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","trustworthy"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"cassandra.svg","brand":"cassandra","variant":"main","pair":null,"width":256.0,"height":169.0,"aspect":1.515,"aspect_class":"wide","bytes":17940,"shapes":28,"anchors":486,"colors":["#373535","#bbe6fb","#ffffff","#1287b1"],"n_colors":4,"color_families":["blue","gray","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"detailed eye above italic lowercase name","geometry":["organic"],"techniques":["gradient"],"type_style":"humanist-sans","case":"lowercase","mood":["mystical","dated"],"industry":"database-data","exemplary":false,"note":"Detailed illustration struggles at small sizes"},{"file":"centos-icon.svg","brand":"centos","variant":"icon","pair":"centos.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2080,"shapes":7,"anchors":136,"colors":["#932279","#efa724","#262577","#9ccd2a","#ffffff"],"n_colors":5,"color_families":["blue","green","orange","pink","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"pinwheel of colored squares with arrows","geometry":["diamond","radial"],"techniques":["radial-symmetry","color-segments","arrow","modular-repetition"],"type_style":null,"case":null,"mood":["colorful","structured"],"industry":"os-platform","exemplary":true,"note":"Rotated modules and arrows create strict radial symmetry"},{"file":"centos.svg","brand":"centos","variant":"main","pair":"centos-icon.svg","width":512.0,"height":144.0,"aspect":3.556,"aspect_class":"horizontal","bytes":5873,"shapes":18,"anchors":251,"colors":["#000000","#932279","#efa724","#262577","#9ccd2a","#ffffff"],"n_colors":6,"color_families":["black","blue","green","orange","pink","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"colored pinwheel beside bold mixed-case name","geometry":["diamond","radial"],"techniques":["radial-symmetry","color-segments"],"type_style":"geometric-sans","case":"mixed","mood":["structured","solid"],"industry":"os-platform","exemplary":false,"note":""},{"file":"certbot.svg","brand":"certbot","variant":"main","pair":null,"width":512.0,"height":176.0,"aspect":2.909,"aspect_class":"horizontal","bytes":11367,"shapes":16,"anchors":345,"colors":["#000000","#ed1c24"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"lock robot holding key beside name","geometry":["freeform"],"techniques":[],"type_style":"grotesque-sans","case":"lowercase","mood":["playful","secure"],"industry":"security-identity","exemplary":false,"note":""},{"file":"ceylon.svg","brand":"ceylon","variant":"main","pair":null,"width":512.0,"height":174.0,"aspect":2.943,"aspect_class":"horizontal","bytes":10875,"shapes":5,"anchors":248,"colors":["#ab710a","#e3a835","#ffffff","#d5d5d5","#141006"],"n_colors":5,"color_families":["black","gray","orange","white"],"primary_family":"orange","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"gold elephant beside heavy lowercase name","geometry":["organic"],"techniques":["gradient"],"type_style":"display-custom","case":"lowercase","mood":["bold","warm"],"industry":"programming-language","exemplary":false,"note":""},{"file":"chai.svg","brand":"chai","variant":"main","pair":null,"width":256.0,"height":296.0,"aspect":0.865,"aspect_class":"square","bytes":3143,"shapes":4,"anchors":72,"colors":["#a1070c","#f7f6f3","#fef6d5"],"n_colors":3,"color_families":["red","white","yellow"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"script serif c in red hexagon","geometry":["hexagon"],"techniques":["containment","gradient"],"type_style":null,"case":null,"mood":["classic","warm"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"chalk.svg","brand":"chalk","variant":"main","pair":null,"width":256.0,"height":118.0,"aspect":2.169,"aspect_class":"wide","bytes":123289,"shapes":7,"anchors":8923,"colors":["#ed8a8a","#a7d5a8","#f9d472","#76a9d8","#d8abd7","#72d4d7"],"n_colors":6,"color_families":["blue","cyan","green","pink","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"rainbow chalk-textured uppercase letters","geometry":[],"techniques":["hand-drawn","color-segments"],"type_style":"display-custom","case":"uppercase","mood":["playful","colorful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"chargebee-icon.svg","brand":"chargebee","variant":"icon","pair":"chargebee.svg","width":256.0,"height":288.0,"aspect":0.889,"aspect_class":"square","bytes":6650,"shapes":2,"anchors":139,"colors":["#ff6c36"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"orange C with dot and speed lines","geometry":["circle"],"techniques":["motion-lines","negative-space"],"type_style":null,"case":null,"mood":["energetic","friendly"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"chargebee.svg","brand":"chargebee","variant":"main","pair":"chargebee-icon.svg","width":512.0,"height":158.0,"aspect":3.241,"aspect_class":"horizontal","bytes":6810,"shapes":2,"anchors":143,"colors":["#222222"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"dark script titlecase name","geometry":[],"techniques":[],"type_style":"script","case":"titlecase","mood":["friendly","personal"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"chef.svg","brand":"chef","variant":"main","pair":null,"width":256.0,"height":274.0,"aspect":0.934,"aspect_class":"square","bytes":4726,"shapes":18,"anchors":149,"colors":["#435363","#f38b00"],"n_colors":2,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"concentric segmented C above spaced name","geometry":["circle","radial"],"techniques":["color-segments","modular-repetition"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","solid"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"chevereto.svg","brand":"chevereto","variant":"main","pair":null,"width":512.0,"height":79.0,"aspect":6.481,"aspect_class":"extra-wide","bytes":15728,"shapes":2,"anchors":373,"colors":["#34a8dd"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"blue bold italic script lowercase name","geometry":[],"techniques":[],"type_style":"script","case":"lowercase","mood":["playful","casual"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"chromatic-icon.svg","brand":"chromatic","variant":"icon","pair":"chromatic.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1968,"shapes":3,"anchors":55,"colors":["#fc521f","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"white interlocking knot loops on orange disc","geometry":["circle","radial"],"techniques":["radial-symmetry","overlap-transparency","containment"],"type_style":null,"case":null,"mood":["vibrant","dynamic"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"chromatic.svg","brand":"chromatic","variant":"main","pair":"chromatic-icon.svg","width":512.0,"height":101.0,"aspect":5.069,"aspect_class":"extra-wide","bytes":5693,"shapes":4,"anchors":182,"colors":["#333333","#fc521f","#ffffff"],"n_colors":3,"color_families":["gray","red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"interlocking knot disc beside name","geometry":["circle","radial"],"techniques":["radial-symmetry","containment"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","modern"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"chrome.svg","brand":"chrome","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":2373,"shapes":9,"anchors":44,"colors":["#ef3f36","#fcd900","#61bc5b","#5ab055","#ffffff","#eaca05","#df3a32","#86bbe5","#1072ba"],"n_colors":9,"color_families":["blue","green","red","white","yellow"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"tricolor ring segments around blue core","geometry":["circle","radial"],"techniques":["color-segments","radial-symmetry","gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["vibrant","iconic"],"industry":"os-platform","exemplary":true,"note":"Three color segments plus core; strong radial construction."},{"file":"cinder.svg","brand":"cinder","variant":"main","pair":null,"width":512.0,"height":156.0,"aspect":3.282,"aspect_class":"horizontal","bytes":4222,"shapes":39,"anchors":295,"colors":["#58585a","#f05129","#f15a22","#be1e2d","#ffd529","#f36c21","#fbb040","#f7941e","#d51920","#ef4123","#c9252c","#ed1c24","#f58220","#da2128","#962f34","#b8292f","#faa61a","#f37021","#fff200","#ffdd00","#fdb913"],"n_colors":21,"color_families":["gray","orange","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"mountain peak with rising sparks","geometry":["triangle"],"techniques":["letter-substitution"],"type_style":"serif","case":"uppercase","mood":["crafted","warm"],"industry":"framework-library","exemplary":false,"note":""},{"file":"circleci.svg","brand":"circleci","variant":"main","pair":null,"width":256.0,"height":259.0,"aspect":0.988,"aspect_class":"square","bytes":1206,"shapes":3,"anchors":22,"colors":["#343434"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"notched ring around a solid dot","geometry":["circle"],"techniques":["negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["minimal","technical"],"industry":"developer-tools","exemplary":true,"note":"Pure circle geometry; one notch creates motion and identity."},{"file":"cirrus-ci.svg","brand":"cirrus-ci","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1537,"shapes":3,"anchors":39,"colors":["#000000","#fafafa"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"curling horizontal lines like wind","geometry":["circle"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["minimal","calm"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"cirrus.svg","brand":"cirrus","variant":"main","pair":null,"width":256.0,"height":199.0,"aspect":1.286,"aspect_class":"wide","bytes":4254,"shapes":5,"anchors":114,"colors":["#2271ce","#005eb6","#0099df","#231f20"],"n_colors":4,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"two overlapping blue circles","geometry":["circle"],"techniques":["overlap-transparency"],"type_style":"geometric-sans","case":"lowercase","mood":["trustworthy","calm"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"clion.svg","brand":"clion","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2537,"shapes":7,"anchors":54,"colors":["#000000","#ffffff","#ed358c","#e9388c","#de418c","#cc508c","#b2658d","#90808d","#67a18e","#37c78f","#22d88f","#029de0"],"n_colors":12,"color_families":["black","blue","gray","green","pink","white"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"CL initials in black square on polygons","geometry":["square","freeform"],"techniques":["containment","gradient","overlap-transparency"],"type_style":"grotesque-sans","case":"uppercase","mood":["bold","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"cljs.svg","brand":"cljs","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3557,"shapes":7,"anchors":92,"colors":["#96ca4b","#5f7fbf"],"n_colors":2,"color_families":["blue","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"cljs set inside two-tone ring","geometry":["circle"],"techniques":["containment","color-segments"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","technical"],"industry":"programming-language","exemplary":false,"note":""},{"file":"clojure.svg","brand":"clojure","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2791,"shapes":7,"anchors":58,"colors":["#ffffff","#91dc47","#63b132","#90b4fe","#5881d8"],"n_colors":5,"color_families":["blue","green","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"lambda in two-tone circle","geometry":["circle"],"techniques":["negative-space","color-segments","hidden-meaning"],"type_style":null,"case":null,"mood":["clever","balanced"],"industry":"programming-language","exemplary":true,"note":"Lambda emerges from negative space between two colored halves."},{"file":"close.svg","brand":"close","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":23432,"shapes":28,"anchors":508,"colors":["#49bc82","#57b6df","#276392","#fabb66"],"n_colors":4,"color_families":["blue","green","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"interlocking colored ellipses like orbits","geometry":["radial","circle"],"techniques":["overlap-transparency","radial-symmetry","color-segments"],"type_style":null,"case":null,"mood":["energetic","playful"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"cloud9.svg","brand":"cloud9","variant":"main","pair":null,"width":256.0,"height":234.0,"aspect":1.094,"aspect_class":"square","bytes":9560,"shapes":2,"anchors":211,"colors":["#00a8e9"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"cloud with numeral 9","geometry":["organic"],"techniques":["letter-substitution"],"type_style":"slab","case":"titlecase","mood":["playful","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"cloudacademy-icon.svg","brand":"cloudacademy","variant":"icon","pair":"cloudacademy.svg","width":256.0,"height":279.0,"aspect":0.918,"aspect_class":"square","bytes":6318,"shapes":2,"anchors":157,"colors":["#005eec"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"flower outline with network nodes","geometry":["organic","radial"],"techniques":["line-monoline","radial-symmetry"],"type_style":null,"case":null,"mood":["technical","friendly"],"industry":"education","exemplary":false,"note":""},{"file":"cloudacademy.svg","brand":"cloudacademy","variant":"main","pair":"cloudacademy-icon.svg","width":512.0,"height":75.0,"aspect":6.827,"aspect_class":"extra-wide","bytes":18980,"shapes":3,"anchors":502,"colors":["#005eec"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"network flower icon beside name","geometry":["organic","radial"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","approachable"],"industry":"education","exemplary":false,"note":""},{"file":"cloudcraft.svg","brand":"cloudcraft","variant":"main","pair":null,"width":256.0,"height":399.0,"aspect":0.642,"aspect_class":"tall","bytes":3202,"shapes":10,"anchors":135,"colors":["#c08a07","#f6b71f","#4286c5","#22496e","#30689c","#e4a409","#241200"],"n_colors":7,"color_families":["black","blue","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric square frame in blue and yellow","geometry":["square"],"techniques":["isometric-3d","dimensional-shading","color-segments"],"type_style":null,"case":null,"mood":["technical","structured"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"cloudflare.svg","brand":"cloudflare","variant":"main","pair":null,"width":256.0,"height":116.0,"aspect":2.207,"aspect_class":"wide","bytes":1967,"shapes":4,"anchors":48,"colors":["#ffffff","#f4811f","#faad3f"],"n_colors":3,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"orange cloud with lighter trailing lobe","geometry":["organic"],"techniques":["color-segments"],"type_style":null,"case":null,"mood":["warm","reliable"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"cloudinary.svg","brand":"cloudinary","variant":"main","pair":null,"width":256.0,"height":168.0,"aspect":1.524,"aspect_class":"wide","bytes":8336,"shapes":5,"anchors":319,"colors":["#0071ce","#dc8327","#f4b21b","#f2d864"],"n_colors":4,"color_families":["blue","orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cloud outline over three upload arrows","geometry":["organic"],"techniques":["line-monoline","arrow","color-segments"],"type_style":null,"case":null,"mood":["friendly","clear"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"cloudlinux.svg","brand":"cloudlinux","variant":"main","pair":null,"width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":6758,"shapes":2,"anchors":147,"colors":["#265597"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"swirling vortex of blue blades","geometry":["circle","radial"],"techniques":["radial-symmetry","motion-lines"],"type_style":null,"case":null,"mood":["dynamic","technical"],"industry":"os-platform","exemplary":false,"note":""},{"file":"cobalt.svg","brand":"cobalt","variant":"main","pair":null,"width":256.0,"height":294.0,"aspect":0.871,"aspect_class":"square","bytes":3872,"shapes":3,"anchors":99,"colors":["#248bd2","#423b3d"],"n_colors":2,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter C with radiating ticks and eye","geometry":["circle","radial"],"techniques":["radial-symmetry","containment"],"type_style":null,"case":null,"mood":["technical","vigilant"],"industry":"security-identity","exemplary":false,"note":""},{"file":"cockpit.svg","brand":"cockpit","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":789,"shapes":3,"anchors":20,"colors":["#000000","#ffffff"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"white interlocking strokes in black disc","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"cocoapods.svg","brand":"cocoapods","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":916,"shapes":4,"anchors":25,"colors":["#fa2a00","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"C with chevron in red square","geometry":["square"],"techniques":["containment","bracket-code","negative-space"],"type_style":null,"case":null,"mood":["bold","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"codacy.svg","brand":"codacy","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1414,"shapes":2,"anchors":40,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"ring of heavy dashed segments","geometry":["circle","radial"],"techniques":["modular-repetition","radial-symmetry"],"type_style":null,"case":null,"mood":["minimal","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"codebase.svg","brand":"codebase","variant":"main","pair":null,"width":512.0,"height":93.0,"aspect":5.505,"aspect_class":"extra-wide","bytes":6435,"shapes":3,"anchors":175,"colors":["#1b6db2"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with code-diamond replacing o","geometry":[],"techniques":["letter-substitution","bracket-code"],"type_style":"geometric-sans","case":"lowercase","mood":["technical","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"codebeat.svg","brand":"codebeat","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":635,"shapes":2,"anchors":22,"colors":["#27a8e0"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"heartbeat pulse line in blue circle","geometry":["circle"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["clean","energetic"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"codecademy.svg","brand":"codecademy","variant":"main","pair":null,"width":512.0,"height":108.0,"aspect":4.741,"aspect_class":"extra-wide","bytes":11811,"shapes":13,"anchors":340,"colors":["#204156"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"code boxed beside cademy","geometry":["square"],"techniques":["containment"],"type_style":"monospace","case":"lowercase","mood":["technical","educational"],"industry":"education","exemplary":false,"note":""},{"file":"codeception.svg","brand":"codeception","variant":"main","pair":null,"width":256.0,"height":190.0,"aspect":1.347,"aspect_class":"wide","bytes":1458,"shapes":2,"anchors":27,"colors":["#20a4c1","#008490","#1fa4bf"],"n_colors":3,"color_families":["cyan"],"primary_family":"cyan","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"concentric C arcs with checkmark","geometry":["circle"],"techniques":["gradient","motion-lines"],"type_style":null,"case":null,"mood":["confident","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"codeclimate.svg","brand":"codeclimate","variant":"main","pair":null,"width":512.0,"height":58.0,"aspect":8.828,"aspect_class":"extra-wide","bytes":5964,"shapes":14,"anchors":201,"colors":["#0b2734"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"double chevron mountain peaks","geometry":["triangle"],"techniques":[],"type_style":"geometric-sans","case":"uppercase","mood":["solid","professional"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"codecov.svg","brand":"codecov","variant":"main","pair":null,"width":256.0,"height":281.0,"aspect":0.911,"aspect_class":"square","bytes":2837,"shapes":2,"anchors":63,"colors":["#e0225c"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"umbrella outline in magenta","geometry":["organic"],"techniques":["line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["clever","friendly"],"industry":"testing-monitoring","exemplary":true,"note":"Umbrella as coverage metaphor: one simple, memorable idea."},{"file":"codefactor-icon.svg","brand":"codefactor","variant":"icon","pair":"codefactor.svg","width":256.0,"height":259.0,"aspect":0.988,"aspect_class":"square","bytes":1793,"shapes":4,"anchors":31,"colors":["#f44a6a","#0aa1a5","#50d690"],"n_colors":3,"color_families":["cyan","green","red"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"F built from dots and bars","geometry":["grid-modular"],"techniques":["modular-repetition","gradient"],"type_style":null,"case":null,"mood":["modern","playful"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"codefactor.svg","brand":"codefactor","variant":"main","pair":"codefactor-icon.svg","width":512.0,"height":77.0,"aspect":6.649,"aspect_class":"extra-wide","bytes":7459,"shapes":4,"anchors":195,"colors":["#232344","#f44a6a","#0aa1a5","#50d690"],"n_colors":4,"color_families":["blue","cyan","green","red"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"dot-and-bar F icon beside name","geometry":["grid-modular"],"techniques":["modular-repetition"],"type_style":"monospace","case":"mixed","mood":["technical","modern"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"codeigniter.svg","brand":"codeigniter","variant":"main","pair":null,"width":256.0,"height":304.0,"aspect":0.842,"aspect_class":"square","bytes":7713,"shapes":2,"anchors":227,"colors":["#ee4323"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"stylized flame","geometry":["organic"],"techniques":["negative-space"],"type_style":"humanist-sans","case":"mixed","mood":["energetic","warm"],"industry":"framework-library","exemplary":false,"note":""},{"file":"codepen-icon.svg","brand":"codepen","variant":"icon","pair":"codepen.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3861,"shapes":2,"anchors":106,"colors":["#cccccc"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"wireframe isometric cube","geometry":["hexagon"],"techniques":["isometric-3d","line-monoline","geometric-construction"],"type_style":null,"case":null,"mood":["technical","minimal"],"industry":"developer-tools","exemplary":true,"note":"Cube drawn with pure monoline geometry; works at any size."},{"file":"codepen.svg","brand":"codepen","variant":"main","pair":"codepen-icon.svg","width":512.0,"height":93.0,"aspect":5.505,"aspect_class":"extra-wide","bytes":5952,"shapes":8,"anchors":198,"colors":["#cccccc"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"tracked name with cube as O","geometry":[],"techniques":["letter-substitution","isometric-3d"],"type_style":"geometric-sans","case":"uppercase","mood":["minimal","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"codepush.svg","brand":"codepush","variant":"main","pair":null,"width":256.0,"height":118.0,"aspect":2.169,"aspect_class":"wide","bytes":5387,"shapes":11,"anchors":138,"colors":["#57abdf","#7bcd33"],"n_colors":2,"color_families":["blue","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"toy ray gun firing lines","geometry":["freeform"],"techniques":["motion-lines","color-segments"],"type_style":null,"case":null,"mood":["playful","energetic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"codersrank.svg","brand":"codersrank","variant":"main","pair":null,"width":256.0,"height":164.0,"aspect":1.561,"aspect_class":"wide","bytes":2381,"shapes":3,"anchors":59,"colors":["#19223c","#67a4ac"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"code chevron with stylized R","geometry":["freeform"],"techniques":["bracket-code","color-segments"],"type_style":null,"case":null,"mood":["dynamic","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"coderwall.svg","brand":"coderwall","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1651,"shapes":7,"anchors":30,"colors":["#3e8dcc"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"six dots stepped into triangle","geometry":["grid-modular","triangle"],"techniques":["modular-repetition"],"type_style":null,"case":null,"mood":["minimal","orderly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"codesandbox.svg","brand":"codesandbox","variant":"main","pair":null,"width":256.0,"height":296.0,"aspect":0.865,"aspect_class":"square","bytes":639,"shapes":2,"anchors":28,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric cube with cut-out faces","geometry":["hexagon"],"techniques":["isometric-3d","negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["bold","technical"],"industry":"developer-tools","exemplary":true,"note":"Cube built purely from negative-space cuts; bold single-color geometry."},{"file":"codeship.svg","brand":"codeship","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4725,"shapes":7,"anchors":98,"colors":["#ffffff","#3c4655","#6e717e","#777885"],"n_colors":4,"color_families":["blue","gray","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"ship bow inside ring","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["sturdy","dependable"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"codio.svg","brand":"codio","variant":"main","pair":null,"width":256.0,"height":296.0,"aspect":0.865,"aspect_class":"square","bytes":800,"shapes":4,"anchors":25,"colors":["#a3baf0","#4474e1","#c7d6f7"],"n_colors":3,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"isometric letter C in blues","geometry":["hexagon"],"techniques":["isometric-3d","dimensional-shading"],"type_style":null,"case":null,"mood":["modern","structured"],"industry":"education","exemplary":false,"note":""},{"file":"codrops.svg","brand":"codrops","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":858,"shapes":4,"anchors":15,"colors":["#237dac","#ffffff","#61aad4"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"water drop in blue circle","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["calm","simple"],"industry":"design-creative","exemplary":false,"note":""},{"file":"coffeescript.svg","brand":"coffeescript","variant":"main","pair":null,"width":256.0,"height":206.0,"aspect":1.243,"aspect_class":"square","bytes":2931,"shapes":2,"anchors":60,"colors":["#28334c"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"coffee cup with steam swirl","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["warm","friendly"],"industry":"programming-language","exemplary":false,"note":""},{"file":"commitizen.svg","brand":"commitizen","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":21257,"shapes":4,"anchors":508,"colors":["#3385ff","#99c9ff","#ffffff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter C ringed by scattered dots","geometry":["circle","radial"],"techniques":["radial-symmetry","modular-repetition"],"type_style":null,"case":null,"mood":["energetic","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"compass.svg","brand":"compass","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3126,"shapes":6,"anchors":52,"colors":["#ffffff","#e21708","#fa524a","#ae0e10"],"n_colors":4,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"compass star in red teardrop","geometry":["organic","star"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["bold","adventurous"],"industry":"framework-library","exemplary":false,"note":""},{"file":"componentkit.svg","brand":"componentkit","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":13106,"shapes":16,"anchors":741,"colors":["#26c6da","#21afd0","#1d9cc8","#d3faff","#ffffff"],"n_colors":5,"color_families":["blue","cyan","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"stacked translucent L shapes on tile","geometry":["rounded-square"],"techniques":["stacked-layers","overlap-transparency","isometric-3d"],"type_style":null,"case":null,"mood":["modern","layered"],"industry":"framework-library","exemplary":false,"note":""},{"file":"compose.svg","brand":"compose","variant":"main","pair":null,"width":256.0,"height":148.0,"aspect":1.73,"aspect_class":"wide","bytes":1208,"shapes":3,"anchors":64,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"row of three isometric cubes","geometry":["square"],"techniques":["isometric-3d","modular-repetition","dimensional-shading"],"type_style":null,"case":null,"mood":["structured","technical"],"industry":"database-data","exemplary":false,"note":""},{"file":"composer.svg","brand":"composer","variant":"main","pair":null,"width":256.0,"height":339.0,"aspect":0.755,"aspect_class":"tall","bytes":196943,"shapes":10,"anchors":4826,"colors":["#7d6a4c","#644d31","#885630","#ffffff","#1a1a1a","#2e2e2e","#f6e5cc"],"n_colors":7,"color_families":["black","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"conductor raising baton above name","geometry":["freeform"],"techniques":["hand-drawn"],"type_style":"display-custom","case":"uppercase","mood":["whimsical","quirky"],"industry":"developer-tools","exemplary":false,"note":"Overly detailed illustration; fails at small sizes."},{"file":"conan-io.svg","brand":"conan-io","variant":"main","pair":null,"width":241.0,"height":256.0,"aspect":0.941,"aspect_class":"square","bytes":1048,"shapes":6,"anchors":30,"colors":["#afd4e5","#6699cc","#7da7d3","#336699"],"n_colors":4,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"isometric package box with C","geometry":["square"],"techniques":["isometric-3d","dimensional-shading"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"concourse.svg","brand":"concourse","variant":"main","pair":null,"width":256.0,"height":254.0,"aspect":1.008,"aspect_class":"square","bytes":9908,"shapes":2,"anchors":311,"colors":["#4da9e1"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"swirling propeller blades around hub","geometry":["radial","circle"],"techniques":["radial-symmetry","motion-lines"],"type_style":null,"case":null,"mood":["dynamic","light"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"concrete5.svg","brand":"concrete5","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":6490,"shapes":9,"anchors":130,"colors":["#010101","#ffffff","#7a7a7a","#6b6b6b","#fcfcfc","#f4f4f4","#e5e5e5","#d1d1d1","#b6b6b6","#959595","#6e6e6e","#414141","#0f0f0f","#f7f7f7","#d3d3d3","#b2b2b2","#979797","#818181","#707070","#646464","#5e5e5e","#5c5c5c","#666666","#404040","#383838"],"n_colors":25,"color_families":["black","gray","white"],"primary_family":"mono","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"white hand in black rounded tile","geometry":["rounded-square"],"techniques":["containment","dimensional-shading"],"type_style":null,"case":null,"mood":["friendly","approachable"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"confluence.svg","brand":"confluence","variant":"main","pair":null,"width":256.0,"height":246.0,"aspect":1.041,"aspect_class":"square","bytes":1983,"shapes":3,"anchors":30,"colors":["#0052cc","#2684ff"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two opposing blue gradient swooshes","geometry":["freeform"],"techniques":["gradient","mirror-symmetry"],"type_style":null,"case":null,"mood":["fluid","collaborative"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"consul.svg","brand":"consul","variant":"main","pair":null,"width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":2560,"shapes":2,"anchors":57,"colors":["#694a9c"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"open C ring with dot grid","geometry":["circle"],"techniques":["modular-repetition"],"type_style":null,"case":null,"mood":["technical","connected"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"contentful.svg","brand":"contentful","variant":"main","pair":null,"width":256.0,"height":289.0,"aspect":0.886,"aspect_class":"square","bytes":1955,"shapes":6,"anchors":37,"colors":["#fae501","#4fb5e1","#f05751","#0681b6","#cd4739"],"n_colors":5,"color_families":["blue","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"segmented C with colored dot ends","geometry":["circle"],"techniques":["color-segments","overlap-transparency"],"type_style":null,"case":null,"mood":["playful","vibrant"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"convox.svg","brand":"convox","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1543,"shapes":4,"anchors":15,"colors":["#8cafc4","#1777bb","#eb9b23"],"n_colors":3,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":true,"mark_type":"abstract","symbol_type":null,"subject":"orange dot in blue ringed disc","geometry":["circle"],"techniques":["containment","dimensional-shading"],"type_style":null,"case":null,"mood":["calm","simple"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"copyleft-pirate.svg","brand":"copyleft-pirate","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":6774,"shapes":5,"anchors":174,"colors":["#000000","#ffffff"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"copyleft sign over crossed cutlasses","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["rebellious","playful"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"copyleft.svg","brand":"copyleft","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":997,"shapes":2,"anchors":21,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"reversed C in heavy ring","geometry":["circle"],"techniques":["containment","mirror-symmetry"],"type_style":null,"case":null,"mood":["minimal","principled"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"corda.svg","brand":"corda","variant":"main","pair":null,"width":512.0,"height":157.0,"aspect":3.261,"aspect_class":"horizontal","bytes":1986,"shapes":2,"anchors":56,"colors":["#e0081c"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with dot replacing o","geometry":[],"techniques":["letter-substitution"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","confident"],"industry":"finance-banking","exemplary":false,"note":""},{"file":"cordova.svg","brand":"cordova","variant":"main","pair":null,"width":256.0,"height":245.0,"aspect":1.045,"aspect_class":"square","bytes":988,"shapes":2,"anchors":36,"colors":["#444444"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"robot-like head with two eyes","geometry":["freeform"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["sturdy","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"coreos-icon.svg","brand":"coreos","variant":"icon","pair":"coreos.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1639,"shapes":4,"anchors":31,"colors":["#53a3da","#f1606d","#ffffff"],"n_colors":3,"color_families":["blue","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"coral rounded shape inside blue circle","geometry":["circle"],"techniques":["negative-space","overlap-transparency"],"type_style":null,"case":null,"mood":["modern","warm"],"industry":"os-platform","exemplary":false,"note":""},{"file":"coreos.svg","brand":"coreos","variant":"main","pair":"coreos-icon.svg","width":512.0,"height":150.0,"aspect":3.413,"aspect_class":"horizontal","bytes":4565,"shapes":10,"anchors":105,"colors":["#53a3da","#f1606d","#ffffff","#231f20","#53a4d9"],"n_colors":5,"color_families":["black","blue","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"coral shape in blue disc","geometry":["circle"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"mixed","mood":["modern","clean"],"industry":"os-platform","exemplary":false,"note":""},{"file":"couchbase.svg","brand":"couchbase","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":992,"shapes":2,"anchors":23,"colors":["#ed2226"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"couch silhouette in red circle","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["bold","simple"],"industry":"database-data","exemplary":true,"note":"Couch reduced to one rounded negative shape; direct name reference."},{"file":"couchdb-icon.svg","brand":"couchdb","variant":"icon","pair":"couchdb.svg","width":256.0,"height":168.0,"aspect":1.524,"aspect_class":"wide","bytes":1566,"shapes":2,"anchors":55,"colors":["#e42528"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red couch built from stacked bars","geometry":["rounded-square"],"techniques":["modular-repetition"],"type_style":null,"case":null,"mood":["relaxed","friendly"],"industry":"database-data","exemplary":false,"note":""},{"file":"couchdb.svg","brand":"couchdb","variant":"main","pair":"couchdb-icon.svg","width":512.0,"height":132.0,"aspect":3.879,"aspect_class":"horizontal","bytes":7683,"shapes":4,"anchors":263,"colors":["#444444","#777777","#e42528"],"n_colors":3,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"red couch beside name and tagline","geometry":["rounded-square"],"techniques":["modular-repetition"],"type_style":"humanist-sans","case":"mixed","mood":["relaxed","friendly"],"industry":"database-data","exemplary":false,"note":""},{"file":"coursera.svg","brand":"coursera","variant":"main","pair":null,"width":512.0,"height":73.0,"aspect":7.014,"aspect_class":"extra-wide","bytes":3638,"shapes":2,"anchors":102,"colors":["#0056d2"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"custom lowercase blue name","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","trustworthy"],"industry":"education","exemplary":false,"note":""},{"file":"coveralls.svg","brand":"coveralls","variant":"main","pair":null,"width":512.0,"height":89.0,"aspect":5.753,"aspect_class":"extra-wide","bytes":15898,"shapes":19,"anchors":428,"colors":["#dce1e2","#394a56"],"n_colors":2,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy italic condensed name","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"uppercase","mood":["bold","energetic"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"cpanel.svg","brand":"cpanel","variant":"main","pair":null,"width":512.0,"height":114.0,"aspect":4.491,"aspect_class":"horizontal","bytes":6371,"shapes":2,"anchors":172,"colors":["#ff6c2c"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"custom connected italic name","geometry":[],"techniques":["ligature"],"type_style":"display-custom","case":"mixed","mood":["dynamic","bold"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"craftcms.svg","brand":"craftcms","variant":"main","pair":null,"width":512.0,"height":125.0,"aspect":4.096,"aspect_class":"horizontal","bytes":4356,"shapes":2,"anchors":137,"colors":["#e5422b"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"lowercase c in red square","geometry":["rounded-square"],"techniques":["containment"],"type_style":"humanist-sans","case":"lowercase","mood":["crafted","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"crashlytics.svg","brand":"crashlytics","variant":"main","pair":null,"width":256.0,"height":276.0,"aspect":0.928,"aspect_class":"square","bytes":2132,"shapes":3,"anchors":41,"colors":["#9b1b1d"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"cog-like shape with C and dot","geometry":["radial","freeform"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["bold","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"crateio.svg","brand":"crateio","variant":"main","pair":null,"width":256.0,"height":193.0,"aspect":1.326,"aspect_class":"wide","bytes":361,"shapes":2,"anchors":13,"colors":["#54d2f4"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"asymmetric light blue plus shape","geometry":["grid-modular"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["minimal","clean"],"industry":"database-data","exemplary":false,"note":""},{"file":"create-react-app.svg","brand":"create-react-app","variant":"main","pair":null,"width":256.0,"height":235.0,"aspect":1.089,"aspect_class":"square","bytes":15664,"shapes":2,"anchors":394,"colors":["#09d3ac"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"atom inside stacked outline squares","geometry":["square","radial"],"techniques":["containment","stacked-layers","line-monoline"],"type_style":null,"case":null,"mood":["technical","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"createjs.svg","brand":"createjs","variant":"main","pair":null,"width":256.0,"height":293.0,"aspect":0.874,"aspect_class":"square","bytes":1386,"shapes":2,"anchors":39,"colors":["#405261"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"dark cube with code chevrons","geometry":["hexagon"],"techniques":["isometric-3d","negative-space","bracket-code"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"cross-browser-testing.svg","brand":"cross-browser-testing","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1397,"shapes":4,"anchors":44,"colors":["#50e4ea","#05263a"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"rotating dark segments inside cyan square","geometry":["square","radial"],"techniques":["radial-symmetry","containment","negative-space"],"type_style":null,"case":null,"mood":["dynamic","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"crucible.svg","brand":"crucible","variant":"main","pair":null,"width":256.0,"height":264.0,"aspect":0.97,"aspect_class":"square","bytes":1368,"shapes":3,"anchors":23,"colors":["#2684ff","#0052cc"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"blue gradient vessel with V notch","geometry":["organic"],"techniques":["gradient"],"type_style":null,"case":null,"mood":["modern","smooth"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"crystal.svg","brand":"crystal","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":416,"shapes":2,"anchors":11,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"faceted black polygon with white triangle","geometry":["hexagon","freeform"],"techniques":["negative-space","dimensional-shading"],"type_style":null,"case":null,"mood":["sharp","precise"],"industry":"programming-language","exemplary":false,"note":""},{"file":"css-3.svg","brand":"css-3","variant":"main","pair":null,"width":256.0,"height":361.0,"aspect":0.709,"aspect_class":"tall","bytes":1327,"shapes":10,"anchors":81,"colors":["#264de4","#2965f1","#ebebeb","#000000","#ffffff"],"n_colors":5,"color_families":["black","blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"emblem","subject":"numeral 3 inside blue shield","geometry":["shield"],"techniques":["containment","dimensional-shading"],"type_style":"display-custom","case":"uppercase","mood":["solid","technical"],"industry":"programming-language","exemplary":false,"note":""},{"file":"css-3_official.svg","brand":"css-3_official","variant":"main","pair":null,"width":256.0,"height":232.0,"aspect":1.103,"aspect_class":"square","bytes":495,"shapes":2,"anchors":17,"colors":["#444444"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"numeral 3 formed as shield","geometry":["shield"],"techniques":["negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["solid","minimal"],"industry":"programming-language","exemplary":false,"note":""},{"file":"cssnext.svg","brand":"cssnext","variant":"main","pair":null,"width":256.0,"height":311.0,"aspect":0.823,"aspect_class":"square","bytes":3781,"shapes":6,"anchors":67,"colors":["#5c70b5","#507dbf","#428bca"],"n_colors":3,"color_families":["blue"],"primary_family":"blue","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"curly brace with speed lines","geometry":["freeform"],"techniques":["bracket-code","motion-lines"],"type_style":null,"case":null,"mood":["fast","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"cucumber.svg","brand":"cucumber","variant":"main","pair":null,"width":256.0,"height":295.0,"aspect":0.868,"aspect_class":"square","bytes":2727,"shapes":3,"anchors":58,"colors":["#00a818","#ffffff"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cucumber slice as speech bubble","geometry":["circle","radial"],"techniques":["speech-bubble","radial-symmetry","hidden-meaning"],"type_style":null,"case":null,"mood":["fresh","friendly"],"industry":"testing-monitoring","exemplary":true,"note":"Cucumber cross-section doubles as speech bubble for plain-language specs."},{"file":"curl.svg","brand":"curl","variant":"main","pair":null,"width":512.0,"height":154.0,"aspect":3.325,"aspect_class":"horizontal","bytes":5606,"shapes":5,"anchors":150,"colors":["#0c544c","#073551"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name followed by URL slashes","geometry":[],"techniques":["bracket-code"],"type_style":"display-custom","case":"lowercase","mood":["technical","quirky"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"customerio-icon.svg","brand":"customerio","variant":"icon","pair":"customerio.svg","width":256.0,"height":180.0,"aspect":1.422,"aspect_class":"wide","bytes":1229,"shapes":5,"anchors":29,"colors":["#ffcd00","#00ecbb","#af64ff","#7131ff"],"n_colors":4,"color_families":["cyan","purple","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"yellow dot above gradient arc","geometry":["circle","organic"],"techniques":["gradient","color-segments"],"type_style":null,"case":null,"mood":["friendly","vibrant"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"customerio.svg","brand":"customerio","variant":"main","pair":"customerio-icon.svg","width":512.0,"height":94.0,"aspect":5.447,"aspect_class":"extra-wide","bytes":8558,"shapes":6,"anchors":229,"colors":["#ffcd00","#00ecbb","#af64ff","#7131ff","#2f326a"],"n_colors":5,"color_families":["blue","cyan","purple","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"yellow dot over gradient arc","geometry":["circle","organic"],"techniques":["gradient","color-segments"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","modern"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"cyclejs.svg","brand":"cyclejs","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1422,"shapes":3,"anchors":28,"colors":["#51d3d9","#c8ff8c","#5a919b"],"n_colors":3,"color_families":["cyan","green"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"open gradient hexagon ring","geometry":["hexagon"],"techniques":["gradient","overlap-transparency"],"type_style":null,"case":null,"mood":["fresh","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"cypress.svg","brand":"cypress","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2879,"shapes":6,"anchors":46,"colors":["#000000","#ffffff","#5c5c5e"],"n_colors":3,"color_families":["black","gray","white"],"primary_family":"mono","gradients":0,"has_mask":true,"has_filter":true,"mark_type":"lettermark","symbol_type":null,"subject":"cy letters in grey circle","geometry":["circle"],"techniques":["containment"],"type_style":"geometric-sans","case":"lowercase","mood":["solid","friendly"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"d3.svg","brand":"d3","variant":"main","pair":null,"width":256.0,"height":243.0,"aspect":1.053,"aspect_class":"square","bytes":3680,"shapes":7,"anchors":63,"colors":["#f9a03c","#f7974e","#f26d58","#b84e51","#f68e48"],"n_colors":5,"color_families":["orange","red"],"primary_family":"multi","gradients":6,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"joined D and 3 gradient shapes","geometry":["freeform"],"techniques":["gradient","ligature"],"type_style":"display-custom","case":"uppercase","mood":["bold","warm"],"industry":"framework-library","exemplary":false,"note":""},{"file":"dart.svg","brand":"dart","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1669,"shapes":7,"anchors":57,"colors":["#00d2b8","#55ddca","#0081c6","#0079b3","#00a4e4"],"n_colors":5,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"faceted teal dart-like shape","geometry":["diamond","freeform"],"techniques":["overlap-transparency","dimensional-shading","color-segments"],"type_style":null,"case":null,"mood":["sharp","modern"],"industry":"programming-language","exemplary":false,"note":""},{"file":"dashlane-icon.svg","brand":"dashlane","variant":"icon","pair":"dashlane.svg","width":256.0,"height":346.0,"aspect":0.74,"aspect_class":"tall","bytes":1782,"shapes":2,"anchors":56,"colors":["#10363d"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter D built from skewed bars","geometry":["grid-modular"],"techniques":["modular-repetition","negative-space"],"type_style":null,"case":null,"mood":["secure","structured"],"industry":"security-identity","exemplary":true,"note":"Letter D emerges from repeated bars; strong modular construction."},{"file":"dashlane.svg","brand":"dashlane","variant":"main","pair":"dashlane-icon.svg","width":512.0,"height":137.0,"aspect":3.737,"aspect_class":"horizontal","bytes":9660,"shapes":2,"anchors":324,"colors":["#10363d"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"bar-built D beside name","geometry":["grid-modular"],"techniques":["modular-repetition"],"type_style":"grotesque-sans","case":"uppercase","mood":["secure","solid"],"industry":"security-identity","exemplary":false,"note":""},{"file":"database-labs.svg","brand":"database-labs","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4306,"shapes":8,"anchors":132,"colors":["#83292a","#b3b2b2","#040707"],"n_colors":3,"color_families":["black","gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"connected hexagons with circuit lines","geometry":["hexagon","grid-modular"],"techniques":["modular-repetition","line-monoline"],"type_style":null,"case":null,"mood":["technical","connected"],"industry":"database-data","exemplary":false,"note":""},{"file":"datadog.svg","brand":"datadog","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":7061,"shapes":3,"anchors":215,"colors":["#632ca6"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"dog holding chart above name","geometry":["square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["friendly","playful"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"datocms-icon.svg","brand":"datocms","variant":"icon","pair":"datocms.svg","width":256.0,"height":259.0,"aspect":0.988,"aspect_class":"square","bytes":876,"shapes":2,"anchors":12,"colors":["#ff593d","#ff7751"],"n_colors":2,"color_families":["red"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"orange D with circular counter","geometry":["circle","square"],"techniques":["negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["bold","simple"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"datocms.svg","brand":"datocms","variant":"main","pair":"datocms-icon.svg","width":512.0,"height":158.0,"aspect":3.241,"aspect_class":"horizontal","bytes":3219,"shapes":3,"anchors":112,"colors":["#ff7751","#ff593d"],"n_colors":2,"color_families":["red"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"orange D beside stacked name","geometry":["circle"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"dbt-icon.svg","brand":"dbt","variant":"icon","pair":"dbt.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2232,"shapes":2,"anchors":49,"colors":["#ff694a"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange X with diamond center cut","geometry":["freeform"],"techniques":["negative-space","mirror-symmetry"],"type_style":null,"case":null,"mood":["bold","energetic"],"industry":"database-data","exemplary":false,"note":""},{"file":"dbt.svg","brand":"dbt","variant":"main","pair":"dbt-icon.svg","width":512.0,"height":196.0,"aspect":2.612,"aspect_class":"horizontal","bytes":4526,"shapes":3,"anchors":114,"colors":["#262a38","#ff694a"],"n_colors":2,"color_families":["blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"orange X beside name","geometry":["freeform"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","modern"],"industry":"database-data","exemplary":false,"note":""},{"file":"dcos-icon.svg","brand":"dcos","variant":"icon","pair":"dcos.svg","width":256.0,"height":201.0,"aspect":1.274,"aspect_class":"wide","bytes":1465,"shapes":2,"anchors":48,"colors":["#7d58ff","#ff007d"],"n_colors":2,"color_families":["blue","pink"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"gradient outline of crossing lines in square","geometry":["square"],"techniques":["line-monoline","gradient","geometric-construction"],"type_style":null,"case":null,"mood":["vibrant","technical"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"dcos.svg","brand":"dcos","variant":"main","pair":"dcos-icon.svg","width":512.0,"height":118.0,"aspect":4.339,"aspect_class":"horizontal","bytes":8218,"shapes":4,"anchors":229,"colors":["#251c4b","#7d58ff","#ff007d"],"n_colors":3,"color_families":["blue","pink"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"gradient crossed-line square","geometry":["square"],"techniques":["line-monoline","gradient"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","modern"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"debian.svg","brand":"debian","variant":"main","pair":null,"width":256.0,"height":317.0,"aspect":0.808,"aspect_class":"square","bytes":5976,"shapes":13,"anchors":137,"colors":["#a80030"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"red brushed spiral swirl","geometry":["organic"],"techniques":["hand-drawn"],"type_style":null,"case":null,"mood":["organic","iconic"],"industry":"os-platform","exemplary":false,"note":""},{"file":"delighted-icon.svg","brand":"delighted","variant":"icon","pair":"delighted.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1185,"shapes":2,"anchors":25,"colors":["#4c4c4b"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"script D in grey circle","geometry":["circle"],"techniques":["containment","hand-drawn"],"type_style":null,"case":null,"mood":["elegant","friendly"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"delighted.svg","brand":"delighted","variant":"main","pair":"delighted-icon.svg","width":512.0,"height":174.0,"aspect":2.943,"aspect_class":"horizontal","bytes":7096,"shapes":2,"anchors":180,"colors":["#323232"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"flowing script name","geometry":[],"techniques":["hand-drawn"],"type_style":"script","case":"titlecase","mood":["elegant","cheerful"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"deno.svg","brand":"deno","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":5222,"shapes":4,"anchors":228,"colors":["#000000","#ffffff"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"dinosaur silhouette in rainy circle","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["playful","bold"],"industry":"programming-language","exemplary":false,"note":""},{"file":"deployhq.svg","brand":"deployhq","variant":"main","pair":null,"width":512.0,"height":144.0,"aspect":3.556,"aspect_class":"horizontal","bytes":7519,"shapes":2,"anchors":203,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold deploy with light hq","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"lowercase","mood":["confident","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"derby.svg","brand":"derby","variant":"main","pair":null,"width":256.0,"height":166.0,"aspect":1.542,"aspect_class":"wide","bytes":2623,"shapes":2,"anchors":58,"colors":["#e84b52"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red horse head profile","geometry":["freeform"],"techniques":[],"type_style":null,"case":null,"mood":["spirited","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"designernews.svg","brand":"designernews","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1314,"shapes":5,"anchors":39,"colors":["#b3bbc6","#666c76","#ffffff"],"n_colors":3,"color_families":["gray","white"],"primary_family":"mono","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"DN in circle with long shadow","geometry":["circle"],"techniques":["containment","dimensional-shading"],"type_style":"geometric-sans","case":"uppercase","mood":["flat","modern"],"industry":"design-creative","exemplary":false,"note":""},{"file":"deviantart.svg","brand":"deviantart","variant":"main","pair":null,"width":512.0,"height":130.0,"aspect":3.938,"aspect_class":"horizontal","bytes":2122,"shapes":3,"anchors":134,"colors":["#45ad47","#1f211f"],"n_colors":2,"color_families":["black","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"angular green glyph beside stacked name","geometry":["freeform"],"techniques":[],"type_style":"display-custom","case":"uppercase","mood":["edgy","creative"],"industry":"design-creative","exemplary":false,"note":""},{"file":"dgraph-icon.svg","brand":"dgraph","variant":"icon","pair":"dgraph.svg","width":256.0,"height":305.0,"aspect":0.839,"aspect_class":"square","bytes":1693,"shapes":2,"anchors":35,"colors":["#ff1800","#ff009b"],"n_colors":2,"color_families":["pink","red"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"lightning bolt linking two nodes in circle","geometry":["circle"],"techniques":["gradient","containment"],"type_style":null,"case":null,"mood":["energetic","fast"],"industry":"database-data","exemplary":false,"note":""},{"file":"dgraph.svg","brand":"dgraph","variant":"main","pair":"dgraph-icon.svg","width":512.0,"height":155.0,"aspect":3.303,"aspect_class":"horizontal","bytes":6984,"shapes":3,"anchors":192,"colors":["#000000","#ff1800","#ff009b"],"n_colors":3,"color_families":["black","pink","red"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"bolt-and-node circle beside name","geometry":["circle"],"techniques":["gradient"],"type_style":"monospace","case":"titlecase","mood":["technical","energetic"],"industry":"database-data","exemplary":false,"note":""},{"file":"dialogflow.svg","brand":"dialogflow","variant":"main","pair":null,"width":256.0,"height":326.0,"aspect":0.785,"aspect_class":"tall","bytes":1319,"shapes":6,"anchors":25,"colors":["#ef6c00","#ff9800"],"n_colors":2,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric cube with speech tail","geometry":["hexagon"],"techniques":["isometric-3d","speech-bubble","dimensional-shading"],"type_style":null,"case":null,"mood":["warm","conversational"],"industry":"ai-ml","exemplary":false,"note":""},{"file":"digital-ocean.svg","brand":"digital-ocean","variant":"main","pair":null,"width":256.0,"height":192.0,"aspect":1.333,"aspect_class":"wide","bytes":8533,"shapes":3,"anchors":258,"colors":["#0080ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"open ring with pixel squares","geometry":["circle"],"techniques":["pixel","negative-space"],"type_style":"geometric-sans","case":"mixed","mood":["friendly","reliable"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"dimer.svg","brand":"dimer","variant":"main","pair":null,"width":512.0,"height":139.0,"aspect":3.683,"aspect_class":"horizontal","bytes":7892,"shapes":5,"anchors":229,"colors":["#6142d2","#461c7c","#02e2ff","#110122"],"n_colors":4,"color_families":["black","blue","cyan","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"two-tone overlapping D","geometry":["freeform"],"techniques":["overlap-transparency","color-segments"],"type_style":"serif","case":"titlecase","mood":["editorial","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"dinersclub.svg","brand":"dinersclub","variant":"main","pair":null,"width":512.0,"height":134.0,"aspect":3.821,"aspect_class":"horizontal","bytes":16689,"shapes":4,"anchors":562,"colors":["#006095","#ffffff","#1a1918"],"n_colors":3,"color_families":["black","blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"circle split by twin half-discs","geometry":["circle"],"techniques":["negative-space","mirror-symmetry"],"type_style":"serif","case":"titlecase","mood":["classic","trustworthy"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"discord-icon.svg","brand":"discord","variant":"icon","pair":"discord.svg","width":256.0,"height":199.0,"aspect":1.286,"aspect_class":"wide","bytes":1447,"shapes":2,"anchors":27,"colors":["#5865f2"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"controller-shaped face with two eyes","geometry":["organic"],"techniques":["mirror-symmetry","negative-space"],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"social-communication","exemplary":true,"note":"Controller shape doubles as friendly face; minimal features, maximum personality."},{"file":"discord.svg","brand":"discord","variant":"main","pair":"discord-icon.svg","width":512.0,"height":100.0,"aspect":5.12,"aspect_class":"extra-wide","bytes":6523,"shapes":2,"anchors":163,"colors":["#5865f2"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"controller face beside name","geometry":["organic"],"techniques":["mirror-symmetry"],"type_style":"display-custom","case":"titlecase","mood":["playful","bold"],"industry":"social-communication","exemplary":false,"note":""},{"file":"discover.svg","brand":"discover","variant":"main","pair":null,"width":512.0,"height":86.0,"aspect":5.953,"aspect_class":"extra-wide","bytes":3824,"shapes":4,"anchors":95,"colors":["#000000","#0b1015","#f34f26","#f69e35"],"n_colors":4,"color_families":["black","orange","red"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":true,"mark_type":"wordmark","symbol_type":null,"subject":"name with solid ball as O","geometry":["circle"],"techniques":["letter-substitution"],"type_style":"grotesque-sans","case":"uppercase","mood":["clean","confident"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"disqus.svg","brand":"disqus","variant":"main","pair":null,"width":256.0,"height":249.0,"aspect":1.028,"aspect_class":"square","bytes":814,"shapes":2,"anchors":22,"colors":["#2e9fff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter D inside speech bubble","geometry":["circle"],"techniques":["speech-bubble","negative-space"],"type_style":null,"case":null,"mood":["friendly","conversational"],"industry":"social-communication","exemplary":false,"note":""},{"file":"django-icon.svg","brand":"django","variant":"icon","pair":"django.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1174,"shapes":3,"anchors":37,"colors":["#092e20","#fffffd"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"dj in dark green tile","geometry":["rounded-square"],"techniques":["containment"],"type_style":"geometric-sans","case":"lowercase","mood":["solid","dependable"],"industry":"framework-library","exemplary":false,"note":""},{"file":"django.svg","brand":"django","variant":"main","pair":"django-icon.svg","width":512.0,"height":179.0,"aspect":2.86,"aspect_class":"horizontal","bytes":3216,"shapes":2,"anchors":99,"colors":["#092e20"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy custom lowercase name","geometry":[],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["solid","confident"],"industry":"framework-library","exemplary":false,"note":""},{"file":"dockbit.svg","brand":"dockbit","variant":"main","pair":null,"width":256.0,"height":286.0,"aspect":0.895,"aspect_class":"square","bytes":1252,"shapes":2,"anchors":26,"colors":["#7236dc","#3f37ae"],"n_colors":2,"color_families":["blue","purple"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"small hexagon inside gradient hexagon","geometry":["hexagon"],"techniques":["gradient","containment"],"type_style":null,"case":null,"mood":["modern","calm"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"docker-icon.svg","brand":"docker","variant":"icon","pair":"docker.svg","width":256.0,"height":185.0,"aspect":1.384,"aspect_class":"wide","bytes":1277,"shapes":2,"anchors":62,"colors":["#2396ed"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"whale carrying stacked containers","geometry":["organic","grid-modular"],"techniques":["modular-repetition"],"type_style":null,"case":null,"mood":["friendly","memorable"],"industry":"cloud-infrastructure","exemplary":true,"note":"Whale carrying containers: literal product metaphor, instantly memorable."},{"file":"docker.svg","brand":"docker","variant":"main","pair":"docker-icon.svg","width":512.0,"height":131.0,"aspect":3.908,"aspect_class":"horizontal","bytes":8674,"shapes":2,"anchors":236,"colors":["#2396ed"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"container-carrying whale beside name","geometry":["organic","grid-modular"],"techniques":["modular-repetition"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","approachable"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"doctrine.svg","brand":"doctrine","variant":"main","pair":null,"width":256.0,"height":339.0,"aspect":0.755,"aspect_class":"tall","bytes":1196,"shapes":3,"anchors":27,"colors":["#fe8439","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange teardrop with arrow cutout","geometry":["organic"],"techniques":["arrow","negative-space"],"type_style":null,"case":null,"mood":["dynamic","warm"],"industry":"framework-library","exemplary":true,"note":"Arrow carved from teardrop via negative space; single bold idea."},{"file":"docusaurus.svg","brand":"docusaurus","variant":"main","pair":null,"width":256.0,"height":218.0,"aspect":1.174,"aspect_class":"square","bytes":13480,"shapes":23,"anchors":344,"colors":["#ffffff","#3ecc5f","#44d860","#000000","#ffff50"],"n_colors":5,"color_families":["black","green","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"green dinosaur holding a document","geometry":["freeform"],"techniques":[],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"dojo-icon.svg","brand":"dojo","variant":"icon","pair":"dojo.svg","width":256.0,"height":183.0,"aspect":1.399,"aspect_class":"wide","bytes":15191,"shapes":42,"anchors":296,"colors":["#f15a24","#ed1c24","#c1272d","#2db5f9","#5fd2ff","#219058","#f7b852","#ff8431","#fffb69","#44c688","#29b36e","#6fd191","#c83ad7","#fba9ff","#ff737d","#fff4c0","#fffa8f","#fb784b","#5bcb99","#85a8e8","#34e28b","#c297ff","#ae31bb","#d23de2","#48080a","#891014","#bc151b","#e01a21","#f71c24","#ff1d25"],"n_colors":30,"color_families":["blue","green","orange","pink","purple","red","yellow"],"primary_family":"multi","gradients":8,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"colorful ribbon dragon","geometry":["freeform"],"techniques":["infinity-loop","gradient"],"type_style":null,"case":null,"mood":["ornate","energetic"],"industry":"framework-library","exemplary":false,"note":"Detailed multicolor dragon; loses clarity at small sizes."},{"file":"dojo-toolkit.svg","brand":"dojo-toolkit","variant":"main","pair":null,"width":512.0,"height":239.0,"aspect":2.142,"aspect_class":"wide","bytes":2630,"shapes":8,"anchors":67,"colors":["#353535","#8c8c8c"],"n_colors":2,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"lowercase name with macrons over o","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["calm","minimal"],"industry":"framework-library","exemplary":false,"note":""},{"file":"dojo.svg","brand":"dojo","variant":"main","pair":"dojo-icon.svg","width":512.0,"height":147.0,"aspect":3.483,"aspect_class":"horizontal","bytes":16604,"shapes":43,"anchors":344,"colors":["#000000","#f15a24","#ed1c24","#c1272d","#2db5f9","#5fd2ff","#219058","#f7b852","#ff8431","#fffb69","#44c688","#29b36e","#6fd191","#c83ad7","#fba9ff","#ff737d","#fff4c0","#fffa8f","#fb784b","#5bcb99","#85a8e8","#34e28b","#c297ff","#ae31bb","#d23de2","#48080a","#891014","#bc151b","#e01a21","#f71c24","#ff1d25"],"n_colors":31,"color_families":["black","blue","green","orange","pink","purple","red","yellow"],"primary_family":"multi","gradients":8,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"ribbon dragon beside thin name","geometry":["freeform"],"techniques":["gradient","infinity-loop"],"type_style":"geometric-sans","case":"uppercase","mood":["ornate","light"],"industry":"framework-library","exemplary":false,"note":""},{"file":"dotnet.svg","brand":"dotnet","variant":"main","pair":null,"width":256.0,"height":244.0,"aspect":1.049,"aspect_class":"square","bytes":29378,"shapes":52,"anchors":676,"colors":["#000000","#14559a","#3092c4","#1969bc","#2b74b1","#125a9e","#0d82ca","#127bca","#05a1e6","#079ae1","#1e5cb3","#1d60b5","#175fab","#7dcbec","#5ec5ed","#0994dc","#66cef5","#0e76bc","#36aee8","#00adef","#1c63b7","#33bdf2","#166ab8","#0798dd","#124379","#1487cb","#165197","#1dacd8","#136ab4","#59caf5","#318ed5","#38a7e4","#1959a6","#7ec5ea","#165096","#0495d6","#0e88d3","#168cd4","#1c87cc","#154b8d","#97d6ee","#55c1ea","#7accec","#3fb7ed","#1da7e7","#37abe7"],"n_colors":46,"color_families":["black","blue","cyan"],"primary_family":"multi","gradients":18,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"blue gradient ribbon wave","geometry":["organic"],"techniques":["gradient","dimensional-shading"],"type_style":"humanist-sans","case":"mixed","mood":["corporate","dynamic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"dreamhost.svg","brand":"dreamhost","variant":"main","pair":null,"width":256.0,"height":253.0,"aspect":1.012,"aspect_class":"square","bytes":939,"shapes":3,"anchors":15,"colors":["#1f3244","#3e95be"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"dark crescent moon around blue disc","geometry":["circle"],"techniques":["negative-space","overlap-transparency"],"type_style":null,"case":null,"mood":["calm","dreamy"],"industry":"hosting-cdn","exemplary":true,"note":"Two circles make a crescent moon; minimal geometry, clear name link."},{"file":"dribbble-icon.svg","brand":"dribbble","variant":"icon","pair":"dribbble.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1495,"shapes":3,"anchors":42,"colors":["#e74d89","#b2215a"],"n_colors":2,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"pink basketball","geometry":["circle"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["playful","vibrant"],"industry":"design-creative","exemplary":false,"note":""},{"file":"dribbble.svg","brand":"dribbble","variant":"main","pair":"dribbble-icon.svg","width":512.0,"height":126.0,"aspect":4.063,"aspect_class":"horizontal","bytes":5199,"shapes":2,"anchors":110,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bouncy script name","geometry":[],"techniques":["hand-drawn"],"type_style":"script","case":"lowercase","mood":["playful","creative"],"industry":"design-creative","exemplary":false,"note":""},{"file":"drift.svg","brand":"drift","variant":"main","pair":null,"width":512.0,"height":117.0,"aspect":4.376,"aspect_class":"horizontal","bytes":2293,"shapes":2,"anchors":92,"colors":["#111111"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with lightning bolt as I","geometry":[],"techniques":["letter-substitution"],"type_style":"grotesque-sans","case":"uppercase","mood":["bold","energetic"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"drip.svg","brand":"drip","variant":"main","pair":null,"width":512.0,"height":183.0,"aspect":2.798,"aspect_class":"horizontal","bytes":2787,"shapes":2,"anchors":86,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"smiling droplet face","geometry":["organic"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","cheerful"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"drizzle-icon.svg","brand":"drizzle","variant":"icon","pair":"drizzle.svg","width":256.0,"height":217.0,"aspect":1.18,"aspect_class":"square","bytes":7558,"shapes":4,"anchors":162,"colors":["#ffffff","#e911bd","#5e464d"],"n_colors":3,"color_families":["gray","pink","white"],"primary_family":"pink","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"chocolate truffle with pink zigzag drizzle","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["sweet","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"drizzle.svg","brand":"drizzle","variant":"main","pair":"drizzle-icon.svg","width":512.0,"height":683.0,"aspect":0.75,"aspect_class":"tall","bytes":13362,"shapes":5,"anchors":323,"colors":["#ffffff","#e911bd","#5e464d"],"n_colors":3,"color_families":["gray","pink","white"],"primary_family":"pink","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"drizzled truffle above name with zigzag z","geometry":["organic"],"techniques":["letter-substitution"],"type_style":"geometric-sans","case":"lowercase","mood":["sweet","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"drone-icon.svg","brand":"drone","variant":"icon","pair":"drone.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1564,"shapes":2,"anchors":33,"colors":["#00abe4"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"ring split by diagonal cut in disc","geometry":["circle"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["clean","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"drone.svg","brand":"drone","variant":"main","pair":"drone-icon.svg","width":512.0,"height":136.0,"aspect":3.765,"aspect_class":"horizontal","bytes":3830,"shapes":3,"anchors":120,"colors":["#1e375a","#00abe4"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"split-ring disc beside tracked name","geometry":["circle"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"uppercase","mood":["clean","confident"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"dropbox.svg","brand":"dropbox","variant":"main","pair":null,"width":256.0,"height":218.0,"aspect":1.174,"aspect_class":"square","bytes":686,"shapes":6,"anchors":25,"colors":["#0061ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"open box built from blue rhombi","geometry":["diamond","grid-modular"],"techniques":["modular-repetition","isometric-3d"],"type_style":null,"case":null,"mood":["simple","trustworthy"],"industry":"productivity-collaboration","exemplary":true,"note":"Five rhombi form an open box; modular and instantly legible."},{"file":"dropmark.svg","brand":"dropmark","variant":"main","pair":null,"width":256.0,"height":348.0,"aspect":0.736,"aspect_class":"tall","bytes":893,"shapes":3,"anchors":13,"colors":["#38dedf"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"teal drop with down-arrow cutout","geometry":["organic"],"techniques":["negative-space","arrow"],"type_style":null,"case":null,"mood":["fresh","simple"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"dropzone.svg","brand":"dropzone","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1215,"shapes":4,"anchors":39,"colors":["#028bf4"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"concentric rounded D in blue square","geometry":["square"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["clean","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"drupal-icon.svg","brand":"drupal","variant":"icon","pair":"drupal.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2367,"shapes":2,"anchors":59,"colors":["#009dde"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"water drop with inner loop in disc","geometry":["circle","organic"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["friendly","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"drupal.svg","brand":"drupal","variant":"main","pair":"drupal-icon.svg","width":512.0,"height":138.0,"aspect":3.71,"aspect_class":"horizontal","bytes":4525,"shapes":2,"anchors":137,"colors":["#009dde"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"drop symbol beside name","geometry":["organic"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"titlecase","mood":["friendly","confident"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"duckduckgo.svg","brand":"duckduckgo","variant":"main","pair":null,"width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":8561,"shapes":18,"anchors":175,"colors":["#de5833","#d5d7d8","#ffffff","#2d4f8e","#fdd209","#65bc46","#43a244","#394a9f","#6176b9"],"n_colors":9,"color_families":["blue","gray","green","red","white","yellow"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"duck head with bowtie in ring","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["friendly","quirky"],"industry":"security-identity","exemplary":false,"note":""},{"file":"dynatrace-icon.svg","brand":"dynatrace","variant":"icon","pair":"dynatrace.svg","width":256.0,"height":260.0,"aspect":0.985,"aspect_class":"square","bytes":2561,"shapes":7,"anchors":52,"colors":["#1496ff","#1284ea","#b4dc00","#6f2da8","#591f91","#73be28"],"n_colors":6,"color_families":["blue","green","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"multicolor isometric square frame","geometry":["square"],"techniques":["isometric-3d","color-segments","gradient"],"type_style":null,"case":null,"mood":["vibrant","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"dynatrace.svg","brand":"dynatrace","variant":"main","pair":"dynatrace-icon.svg","width":512.0,"height":91.0,"aspect":5.626,"aspect_class":"extra-wide","bytes":7311,"shapes":7,"anchors":233,"colors":["#1a1a1a","#1496ff","#1284ea","#b4dc00","#6f2da8","#591f91","#73be28"],"n_colors":7,"color_families":["black","blue","green","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"multicolor square frame beside name","geometry":["square"],"techniques":["isometric-3d","color-segments"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"dyndns.svg","brand":"dyndns","variant":"main","pair":null,"width":257.0,"height":256.0,"aspect":1.004,"aspect_class":"square","bytes":1622,"shapes":4,"anchors":22,"colors":["#e6e7e8","#939598","#fefad8","#fcee21"],"n_colors":4,"color_families":["gray","white","yellow"],"primary_family":"yellow","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"crescent ring from black to yellow","geometry":["circle"],"techniques":["gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["dynamic","glossy"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"ebanx.svg","brand":"ebanx","variant":"main","pair":null,"width":512.0,"height":97.0,"aspect":5.278,"aspect_class":"extra-wide","bytes":4026,"shapes":5,"anchors":134,"colors":["#2397d4","#2f4a75"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold name with chevron-cut E","geometry":[],"techniques":["negative-space"],"type_style":"grotesque-sans","case":"uppercase","mood":["solid","corporate"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"eclipse-icon.svg","brand":"eclipse","variant":"icon","pair":"eclipse.svg","width":256.0,"height":240.0,"aspect":1.067,"aspect_class":"square","bytes":3170,"shapes":8,"anchors":66,"colors":["#2c2255","#f7941e","#ffffff","#473788"],"n_colors":4,"color_families":["blue","orange","white"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"striped dark disc eclipsing orange sun","geometry":["circle"],"techniques":["negative-space","overlap-transparency"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"eclipse.svg","brand":"eclipse","variant":"main","pair":"eclipse-icon.svg","width":512.0,"height":121.0,"aspect":4.231,"aspect_class":"horizontal","bytes":7818,"shapes":10,"anchors":195,"colors":["#2c2255","#f7941e","#ffffff","#473788"],"n_colors":4,"color_families":["blue","orange","white"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"striped eclipse disc beside name","geometry":["circle"],"techniques":["negative-space"],"type_style":"humanist-sans","case":"lowercase","mood":["solid","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"editorconfig.svg","brand":"editorconfig","variant":"main","pair":null,"width":256.0,"height":248.0,"aspect":1.032,"aspect_class":"square","bytes":8994,"shapes":12,"anchors":196,"colors":["#e3e3f8","#fdfdfd","#020202","#fdf2f2","#fef3f3","#efefef","#faf1f1"],"n_colors":7,"color_families":["black","blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"sketched mouse wearing glasses","geometry":["freeform"],"techniques":["hand-drawn","line-monoline"],"type_style":null,"case":null,"mood":["quirky","nerdy"],"industry":"developer-tools","exemplary":false,"note":"Loose sketch lines; weak reproduction at small sizes."},{"file":"egghead.svg","brand":"egghead","variant":"main","pair":null,"width":256.0,"height":263.0,"aspect":0.973,"aspect_class":"square","bytes":7600,"shapes":18,"anchors":214,"colors":["#ffffff","#fcfbfa","#252526","#e0e0e0","#56555c"],"n_colors":5,"color_families":["black","gray","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"egg wearing thick glasses","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["nerdy","playful"],"industry":"education","exemplary":false,"note":""},{"file":"elasticsearch.svg","brand":"elasticsearch","variant":"main","pair":null,"width":256.0,"height":286.0,"aspect":0.895,"aspect_class":"square","bytes":1409,"shapes":7,"anchors":32,"colors":["#f0bf1a","#07a5de","#3ebeb0","#231f20","#d7a229","#019b8f"],"n_colors":6,"color_families":["black","blue","cyan","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"E built from colored stacked bands","geometry":["circle"],"techniques":["color-segments","stacked-layers"],"type_style":null,"case":null,"mood":["vibrant","modern"],"industry":"database-data","exemplary":false,"note":""},{"file":"electron.svg","brand":"electron","variant":"main","pair":null,"width":256.0,"height":278.0,"aspect":0.921,"aspect_class":"square","bytes":3855,"shapes":2,"anchors":84,"colors":["#47848f"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"atom orbits with nodes","geometry":["radial"],"techniques":["line-monoline","radial-symmetry"],"type_style":null,"case":null,"mood":["technical","light"],"industry":"framework-library","exemplary":false,"note":""},{"file":"element.svg","brand":"element","variant":"main","pair":null,"width":256.0,"height":293.0,"aspect":0.874,"aspect_class":"square","bytes":1631,"shapes":2,"anchors":35,"colors":["#409eff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter e inside blue hexagon","geometry":["hexagon"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["clean","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"elemental-ui.svg","brand":"elemental-ui","variant":"main","pair":null,"width":256.0,"height":229.0,"aspect":1.118,"aspect_class":"square","bytes":5138,"shapes":4,"anchors":145,"colors":["#ebf8f9","#31adb8","#ffffff"],"n_colors":3,"color_families":["cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"E hexagon over faint atom orbits","geometry":["hexagon","radial"],"techniques":["containment","overlap-transparency"],"type_style":null,"case":null,"mood":["light","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"elementary.svg","brand":"elementary","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2249,"shapes":2,"anchors":49,"colors":["#333333"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"monoline script e inside circle","geometry":["circle"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["elegant","minimal"],"industry":"os-platform","exemplary":false,"note":""},{"file":"ello.svg","brand":"ello","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":817,"shapes":2,"anchors":14,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"white smile curve in black disc","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["minimal","friendly"],"industry":"social-communication","exemplary":true,"note":"A single smile arc in a circle; radical reduction of a face."},{"file":"elm.svg","brand":"elm","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":814,"shapes":8,"anchors":30,"colors":["#5fb4cb","#eea400","#596277","#8cd636"],"n_colors":4,"color_families":["cyan","gray","green","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"tangram pieces forming a square","geometry":["square","triangle","grid-modular"],"techniques":["geometric-construction","color-segments","modular-repetition"],"type_style":null,"case":null,"mood":["playful","structured"],"industry":"programming-language","exemplary":true,"note":"Tangram pieces tile a perfect square; exemplary geometric construction."},{"file":"elo.svg","brand":"elo","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2161,"shapes":6,"anchors":53,"colors":["#0e0e11","#ffffff","#2091c3","#faec32","#d0352a"],"n_colors":5,"color_families":["black","blue","red","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"elo name in black disc, tricolor o","geometry":["circle"],"techniques":["containment","color-segments","letter-substitution"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","modern"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"emacs.svg","brand":"emacs","variant":"main","pair":null,"width":256.0,"height":216.0,"aspect":1.185,"aspect_class":"square","bytes":11633,"shapes":8,"anchors":281,"colors":["#ffffff","#000000","#c73d27","#1370c2"],"n_colors":4,"color_families":["black","blue","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"calligraphic name entwined with gnu horns","geometry":["freeform"],"techniques":["hand-drawn","dimensional-shading"],"type_style":"script","case":"titlecase","mood":["ornate","quirky"],"industry":"developer-tools","exemplary":false,"note":"Ornate 3D calligraphy; poor scalability and legibility."},{"file":"embedly.svg","brand":"embedly","variant":"main","pair":null,"width":256.0,"height":292.0,"aspect":0.877,"aspect_class":"square","bytes":916,"shapes":3,"anchors":26,"colors":["#4ec6e6","#ffffff"],"n_colors":2,"color_families":["cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter e in rounded blue diamond","geometry":["diamond"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["friendly","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"ember-tomster.svg","brand":"ember-tomster","variant":"main","pair":null,"width":256.0,"height":245.0,"aspect":1.045,"aspect_class":"square","bytes":64894,"shapes":96,"anchors":1592,"colors":["#ffffff","#ba8449","#fff8ee","#895b2e","#e5d0ae","#e3ab5e","#fcd4c3","#f8a38f","#e5bfa1","#f7e8d0","#d8cab2","#333333","#fff7e3","#ffdc99","#eadcbe","#1a1a1a","#000000","#d0dddc","#e24b31"],"n_colors":19,"color_families":["black","cyan","gray","orange","red","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"hamster with glasses above script name","geometry":["freeform"],"techniques":[],"type_style":"script","case":"lowercase","mood":["playful","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"ember.svg","brand":"ember","variant":"main","pair":null,"width":512.0,"height":213.0,"aspect":2.404,"aspect_class":"wide","bytes":7621,"shapes":3,"anchors":177,"colors":["#ffffff","#e24b31"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"flowing brush script name","geometry":[],"techniques":["hand-drawn"],"type_style":"script","case":"lowercase","mood":["warm","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"emmet.svg","brand":"emmet","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":829,"shapes":4,"anchors":24,"colors":["#1c1c20","#baffa9","#7acb16"],"n_colors":3,"color_families":["black","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"green angular chevron shape in black disc","geometry":["circle","triangle"],"techniques":["arrow","containment"],"type_style":null,"case":null,"mood":["sharp","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"engine-yard-icon.svg","brand":"engine-yard","variant":"icon","pair":"engine-yard.svg","width":256.0,"height":254.0,"aspect":1.008,"aspect_class":"square","bytes":1681,"shapes":3,"anchors":21,"colors":["#477cd8","#4573d2","#3f5bc2","#3633a7","#2f1391","#2055da","#00bff6"],"n_colors":7,"color_families":["blue","cyan"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"thick gradient ring with offset notch","geometry":["circle"],"techniques":["gradient"],"type_style":null,"case":null,"mood":["modern","dynamic"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"engine-yard.svg","brand":"engine-yard","variant":"main","pair":"engine-yard-icon.svg","width":512.0,"height":82.0,"aspect":6.244,"aspect_class":"extra-wide","bytes":9521,"shapes":4,"anchors":268,"colors":["#3b62de","#477cd8","#4573d2","#3f5bc2","#3633a7","#2f1391","#2055da","#00bff6"],"n_colors":8,"color_families":["blue","cyan"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"gradient ring beside name","geometry":["circle"],"techniques":["gradient"],"type_style":"geometric-sans","case":"uppercase","mood":["modern","corporate"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"envato.svg","brand":"envato","variant":"main","pair":null,"width":512.0,"height":97.0,"aspect":5.278,"aspect_class":"extra-wide","bytes":4423,"shapes":8,"anchors":114,"colors":["#82b541","#000000"],"n_colors":2,"color_families":["black","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"green leaf beside name","geometry":["organic"],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["fresh","friendly"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"envoy-icon.svg","brand":"envoy","variant":"icon","pair":"envoy.svg","width":256.0,"height":191.0,"aspect":1.34,"aspect_class":"wide","bytes":2073,"shapes":4,"anchors":73,"colors":["#b31aab","#d163ce","#e13eaf"],"n_colors":3,"color_families":["pink"],"primary_family":"pink","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"overlapping outlined magenta hexagons","geometry":["hexagon"],"techniques":["overlap-transparency","line-monoline","modular-repetition"],"type_style":null,"case":null,"mood":["technical","vibrant"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"envoy.svg","brand":"envoy","variant":"main","pair":"envoy-icon.svg","width":512.0,"height":166.0,"aspect":3.084,"aspect_class":"horizontal","bytes":6547,"shapes":5,"anchors":196,"colors":["#4a0d66","#b31aab","#d163ce","#e13eaf"],"n_colors":4,"color_families":["pink","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"overlapping hexagon outlines beside name","geometry":["hexagon"],"techniques":["overlap-transparency","line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","technical"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"envoyer.svg","brand":"envoyer","variant":"main","pair":null,"width":256.0,"height":304.0,"aspect":0.842,"aspect_class":"square","bytes":2630,"shapes":4,"anchors":62,"colors":["#f56857","#f96853"],"n_colors":2,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"rocket framed by circular arcs","geometry":["circle","radial"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["energetic","warm"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"enyo.svg","brand":"enyo","variant":"main","pair":null,"width":256.0,"height":435.0,"aspect":0.589,"aspect_class":"tall","bytes":3802,"shapes":13,"anchors":125,"colors":["#000000","#2a3141","#262c3a","#ecedec","#a5c8e6","#353d4b"],"n_colors":6,"color_families":["black","blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"stacked chevrons shield above name","geometry":["shield","hexagon"],"techniques":["stacked-layers","dimensional-shading","gradient"],"type_style":"display-custom","case":"uppercase","mood":["solid","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"erlang.svg","brand":"erlang","variant":"main","pair":null,"width":256.0,"height":225.0,"aspect":1.138,"aspect_class":"square","bytes":2369,"shapes":11,"anchors":104,"colors":["#ffffff","#a90533","#000000"],"n_colors":3,"color_families":["black","red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"red e framed by brackets above name","geometry":["square"],"techniques":["negative-space","bracket-code"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","classic"],"industry":"programming-language","exemplary":false,"note":""},{"file":"es6.svg","brand":"es6","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1701,"shapes":3,"anchors":53,"colors":["#f26522","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"ES6 in corner of orange square","geometry":["square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","direct"],"industry":"programming-language","exemplary":false,"note":""},{"file":"esbuild.svg","brand":"esbuild","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":642,"shapes":3,"anchors":19,"colors":["#ffcf00","#191919"],"n_colors":2,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"black double chevron in yellow disc","geometry":["circle"],"techniques":["arrow","motion-lines"],"type_style":null,"case":null,"mood":["fast","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"esdoc.svg","brand":"esdoc","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2121,"shapes":3,"anchors":53,"colors":["#e55151","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"owl face cut into red disc","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["wise","friendly"],"industry":"developer-tools","exemplary":true,"note":"Owl face formed entirely by negative space in a disc."},{"file":"eslint-old.svg","brand":"eslint-old","variant":"main","pair":null,"width":256.0,"height":263.0,"aspect":0.973,"aspect_class":"square","bytes":713,"shapes":3,"anchors":28,"colors":["#3a33d1","#6464e2"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"offset faceted purple hexagons","geometry":["hexagon"],"techniques":["containment","dimensional-shading","isometric-3d"],"type_style":null,"case":null,"mood":["technical","solid"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"eslint.svg","brand":"eslint","variant":"main","pair":null,"width":256.0,"height":225.0,"aspect":1.138,"aspect_class":"square","bytes":1404,"shapes":3,"anchors":39,"colors":["#8080f2","#4b32c3"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"nested purple hexagons","geometry":["hexagon"],"techniques":["containment","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","structured"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"eta-lang.svg","brand":"eta-lang","variant":"main","pair":null,"width":256.0,"height":282.0,"aspect":0.908,"aspect_class":"square","bytes":2250,"shapes":3,"anchors":50,"colors":["#32bebe","#ffffff"],"n_colors":2,"color_families":["cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"white sea dragon in teal hexagon","geometry":["hexagon"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["mystical","playful"],"industry":"programming-language","exemplary":false,"note":""},{"file":"etcd.svg","brand":"etcd","variant":"main","pair":null,"width":256.0,"height":248.0,"aspect":1.032,"aspect_class":"square","bytes":2789,"shapes":2,"anchors":70,"colors":["#419eda"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"cog-shaped creature with two eyes","geometry":["radial"],"techniques":["mirror-symmetry","negative-space"],"type_style":null,"case":null,"mood":["friendly","technical"],"industry":"database-data","exemplary":false,"note":""},{"file":"ethereum-color.svg","brand":"ethereum-color","variant":"main","pair":null,"width":256.0,"height":427.0,"aspect":0.6,"aspect_class":"tall","bytes":963,"shapes":7,"anchors":44,"colors":["#5a9ded","#53d3e0","#d995d1","#a6e276","#ff9c92","#ffe94d"],"n_colors":6,"color_families":["blue","cyan","green","pink","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"pastel outlined octahedron","geometry":["diamond","triangle"],"techniques":["line-monoline","color-segments","isometric-3d"],"type_style":null,"case":null,"mood":["light","futuristic"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"ethereum.svg","brand":"ethereum","variant":"main","pair":null,"width":256.0,"height":417.0,"aspect":0.614,"aspect_class":"tall","bytes":796,"shapes":7,"anchors":29,"colors":["#343434","#8c8c8c","#3c3c3b","#141414","#393939"],"n_colors":5,"color_families":["black","gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"faceted grey octahedron","geometry":["diamond"],"techniques":["dimensional-shading","mirror-symmetry","isometric-3d"],"type_style":null,"case":null,"mood":["solid","iconic"],"industry":"payments-fintech","exemplary":true,"note":"Faceted octahedron from flat tones; iconic, symmetrical, scalable."},{"file":"ethers.svg","brand":"ethers","variant":"main","pair":null,"width":256.0,"height":162.0,"aspect":1.58,"aspect_class":"wide","bytes":864,"shapes":2,"anchors":13,"colors":["#24339b"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"brushy cloud outline with swoosh","geometry":["organic"],"techniques":["line-monoline","hand-drawn"],"type_style":null,"case":null,"mood":["light","airy"],"industry":"framework-library","exemplary":false,"note":""},{"file":"ethnio.svg","brand":"ethnio","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1385,"shapes":5,"anchors":20,"colors":["#24373e","#e5d4c4","#8fb1be","#ffffff"],"n_colors":4,"color_families":["blue","orange","white"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"target-like concentric rings in dark disc","geometry":["circle"],"techniques":["containment","dimensional-shading"],"type_style":null,"case":null,"mood":["calm","focused"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"eventbrite-icon.svg","brand":"eventbrite","variant":"icon","pair":"eventbrite.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":974,"shapes":3,"anchors":21,"colors":["#f05537","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white e in orange disc","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["bold","friendly"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"eventbrite.svg","brand":"eventbrite","variant":"main","pair":"eventbrite-icon.svg","width":512.0,"height":92.0,"aspect":5.565,"aspect_class":"extra-wide","bytes":3710,"shapes":2,"anchors":149,"colors":["#f05537"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold orange lowercase name","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","energetic"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"eventsentry.svg","brand":"eventsentry","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1819,"shapes":7,"anchors":31,"colors":["#ffffff","#f4922e"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange hexagon sliced by curved stripes","geometry":["hexagon"],"techniques":["negative-space","motion-lines"],"type_style":null,"case":null,"mood":["dynamic","warm"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"evergreen-icon.svg","brand":"evergreen","variant":"icon","pair":"evergreen.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":519,"shapes":3,"anchors":14,"colors":["#38a065","#ffffff"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"white conifer tree in green disc","geometry":["circle","triangle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["calm","natural"],"industry":"framework-library","exemplary":false,"note":""},{"file":"evergreen.svg","brand":"evergreen","variant":"main","pair":"evergreen-icon.svg","width":512.0,"height":107.0,"aspect":4.785,"aspect_class":"extra-wide","bytes":2449,"shapes":4,"anchors":143,"colors":["#1f4160","#38a065","#ffffff"],"n_colors":3,"color_families":["blue","green","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"tree disc beside tracked name","geometry":["circle","triangle"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"uppercase","mood":["calm","clean"],"industry":"framework-library","exemplary":false,"note":""},{"file":"expo-icon.svg","brand":"expo","variant":"icon","pair":"expo.svg","width":256.0,"height":231.0,"aspect":1.108,"aspect_class":"square","bytes":941,"shapes":2,"anchors":16,"colors":["#000020"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"rounded black caret chevron","geometry":["triangle"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["minimal","confident"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"expo.svg","brand":"expo","variant":"main","pair":"expo-icon.svg","width":512.0,"height":145.0,"aspect":3.531,"aspect_class":"horizontal","bytes":2106,"shapes":3,"anchors":67,"colors":["#000020"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"caret chevron beside bold name","geometry":["triangle"],"techniques":[],"type_style":"geometric-sans","case":"titlecase","mood":["bold","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"express.svg","brand":"express","variant":"main","pair":null,"width":512.0,"height":149.0,"aspect":3.436,"aspect_class":"horizontal","bytes":7852,"shapes":2,"anchors":202,"colors":["#222222"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"ultra-thin titlecase name","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"titlecase","mood":["minimal","light"],"industry":"framework-library","exemplary":false,"note":""},{"file":"fabric.svg","brand":"fabric","variant":"main","pair":null,"width":256.0,"height":195.0,"aspect":1.313,"aspect_class":"wide","bytes":2944,"shapes":9,"anchors":57,"colors":["#fec32d","#2c6db0"],"n_colors":2,"color_families":["blue","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"interwoven yellow and blue strands","geometry":["freeform"],"techniques":["overlap-transparency","modular-repetition","color-segments"],"type_style":null,"case":null,"mood":["woven","energetic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"facebook.svg","brand":"facebook","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":758,"shapes":3,"anchors":26,"colors":["#395185","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white f in blue rounded square","geometry":["rounded-square"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["familiar","trustworthy"],"industry":"social-communication","exemplary":false,"note":""},{"file":"falcor.svg","brand":"falcor","variant":"main","pair":null,"width":256.0,"height":299.0,"aspect":0.856,"aspect_class":"square","bytes":1963,"shapes":19,"anchors":92,"colors":["#4cad31","#64b32c","#8bbe2d","#76b828","#5db12e","#82bb24","#751f82","#934c98","#8a398d","#b987bb","#a466a7","#7b1f82","#0062ae","#007ec6","#26b2e7","#008bd0","#0071bb","#009ddc"],"n_colors":18,"color_families":["blue","green","pink"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"faceted multicolor hexagon ring","geometry":["hexagon"],"techniques":["color-segments","gradient","geometric-construction"],"type_style":null,"case":null,"mood":["vibrant","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"fastify-icon.svg","brand":"fastify","variant":"icon","pair":"fastify.svg","width":256.0,"height":165.0,"aspect":1.552,"aspect_class":"wide","bytes":1948,"shapes":2,"anchors":56,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"panther head with speed stripes","geometry":["freeform"],"techniques":["motion-lines","negative-space"],"type_style":null,"case":null,"mood":["fierce","fast"],"industry":"framework-library","exemplary":false,"note":""},{"file":"fastify.svg","brand":"fastify","variant":"main","pair":"fastify-icon.svg","width":512.0,"height":152.0,"aspect":3.368,"aspect_class":"horizontal","bytes":5106,"shapes":3,"anchors":162,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"speed-striped panther head","geometry":["freeform"],"techniques":["motion-lines"],"type_style":"display-custom","case":"lowercase","mood":["fast","aggressive"],"industry":"framework-library","exemplary":false,"note":""},{"file":"fastlane.svg","brand":"fastlane","variant":"main","pair":null,"width":256.0,"height":248.0,"aspect":1.032,"aspect_class":"square","bytes":3304,"shapes":6,"anchors":75,"colors":["#0a7bff","#eb3d00","#00bcd4","#86c351","#9032e9"],"n_colors":5,"color_families":["blue","cyan","green","orange","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"pentagon of colored connected nodes","geometry":["radial","circle"],"techniques":["color-segments","line-monoline","radial-symmetry"],"type_style":null,"case":null,"mood":["playful","connected"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"fastly.svg","brand":"fastly","variant":"main","pair":null,"width":512.0,"height":199.0,"aspect":2.573,"aspect_class":"horizontal","bytes":2980,"shapes":2,"anchors":130,"colors":["#d52f2f"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with stopwatch replacing a","geometry":[],"techniques":["letter-substitution","hidden-meaning"],"type_style":"humanist-sans","case":"lowercase","mood":["fast","bold"],"industry":"hosting-cdn","exemplary":true,"note":"Stopwatch folded into a letter conveys speed without extra symbol."},{"file":"feathersjs.svg","brand":"feathersjs","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1692,"shapes":2,"anchors":36,"colors":["#333333"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"feather inside circle outline","geometry":["circle"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["light","elegant"],"industry":"framework-library","exemplary":false,"note":""},{"file":"fedora.svg","brand":"fedora","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2128,"shapes":4,"anchors":61,"colors":["#294172","#3c6eb4","#ffffff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"infinity f in speech-bubble disc","geometry":["circle"],"techniques":["infinity-loop","speech-bubble","negative-space","hidden-meaning"],"type_style":null,"case":null,"mood":["friendly","open"],"industry":"os-platform","exemplary":true,"note":"Letter f, infinity loop and speech bubble fused in one mark."},{"file":"fetch.svg","brand":"fetch","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1309,"shapes":4,"anchors":27,"colors":["#ffffff","#3c790a"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"dog bone inside green ring","geometry":["circle"],"techniques":["containment","hidden-meaning"],"type_style":null,"case":null,"mood":["playful","simple"],"industry":"framework-library","exemplary":false,"note":""},{"file":"figma.svg","brand":"figma","variant":"main","pair":null,"width":256.0,"height":384.0,"aspect":0.667,"aspect_class":"tall","bytes":843,"shapes":6,"anchors":29,"colors":["#0acf83","#a259ff","#f24e1e","#ff7262","#1abcfe"],"n_colors":5,"color_families":["blue","green","purple","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"five colored circles and half-rounds","geometry":["grid-modular","circle"],"techniques":["color-segments","modular-repetition","geometric-construction"],"type_style":null,"case":null,"mood":["playful","creative"],"industry":"design-creative","exemplary":true,"note":"Modular circle and half-round units; each color a separate building block."},{"file":"firebase.svg","brand":"firebase","variant":"main","pair":null,"width":256.0,"height":351.0,"aspect":0.729,"aspect_class":"tall","bytes":3493,"shapes":11,"anchors":70,"colors":["#ffc24a","#ffa712","#000000","#f4bd62","#ffa50e","#f6820c","#fde068","#fcca3f","#eeab37"],"n_colors":9,"color_families":["black","orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":true,"mark_type":"pictorial","symbol_type":null,"subject":"flame from overlapping triangular shards","geometry":["triangle"],"techniques":["overlap-transparency","dimensional-shading","color-segments"],"type_style":null,"case":null,"mood":["warm","energetic"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"firefox.svg","brand":"firefox","variant":"main","pair":null,"width":256.0,"height":265.0,"aspect":0.966,"aspect_class":"square","bytes":16884,"shapes":15,"anchors":274,"colors":["#ffea00","#ffde00","#ffbf00","#ff8e00","#ff272d","#e0255a","#cc2477","#c42482","#00ccda","#0083ff","#007af9","#005fe7","#2639ad","#401e84","#4a1475","#000f43","#001962","#002079","#ffe900","#ffaf0e","#ff7a1b","#ff4e26","#ff2c2e","#ff1434","#ff0538","#ff0039","#620700","#f92433","#e91c45","#cf0e62","#b5007f","#ffdd00","#ffba00","#ff9100","#ff6711","#ff4a1d","#ff2c2c","#ff7a1a","#ffb20d","#ffd605","#ffe302","#891551","#fff14f","#ffee4c","#ffe643","#ffd834","#ffc41e","#ffab02","#ffa900","#ffa000"],"n_colors":50,"color_families":["blue","cyan","orange","pink","purple","red","yellow"],"primary_family":"multi","gradients":14,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"fiery fox wrapped around globe","geometry":["circle"],"techniques":["gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["vibrant","energetic"],"industry":"os-platform","exemplary":false,"note":""},{"file":"flannel.svg","brand":"flannel","variant":"main","pair":null,"width":256.0,"height":477.0,"aspect":0.537,"aspect_class":"tall","bytes":4355,"shapes":2,"anchors":132,"colors":["#54a3da"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter f from woven blue tiles","geometry":["grid-modular"],"techniques":["modular-repetition"],"type_style":null,"case":null,"mood":["structured","technical"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"flarum.svg","brand":"flarum","variant":"main","pair":null,"width":512.0,"height":116.0,"aspect":4.414,"aspect_class":"horizontal","bytes":2914,"shapes":4,"anchors":106,"colors":["#d22929","#b71717","#e7762e","#e7562e"],"n_colors":4,"color_families":["orange","red"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"folded orange flag","geometry":["square"],"techniques":["dimensional-shading"],"type_style":"grotesque-sans","case":"uppercase","mood":["bold","loud"],"industry":"social-communication","exemplary":false,"note":""},{"file":"flask.svg","brand":"flask","variant":"main","pair":null,"width":256.0,"height":329.0,"aspect":0.778,"aspect_class":"tall","bytes":24879,"shapes":7,"anchors":697,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"engraved horn above blackletter name","geometry":["freeform"],"techniques":["hand-drawn"],"type_style":"serif","case":"titlecase","mood":["vintage","crafted"],"industry":"framework-library","exemplary":false,"note":"Fine engraving detail breaks down at small sizes."},{"file":"flat-ui.svg","brand":"flat-ui","variant":"main","pair":null,"width":256.0,"height":194.0,"aspect":1.32,"aspect_class":"wide","bytes":2358,"shapes":16,"anchors":87,"colors":["#57bbfb","#48acec","#2b8fcf","#2d91d1","#7acbff","#55b9f9","#3b9fdf","#52b6f7","#8fd3ff","#ff2690","#41a5e5","#3ca0e0","#4eb2f2","#1a7ebe","#ffffff"],"n_colors":15,"color_families":["blue","pink","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"faceted blue gem with sparkle","geometry":["diamond"],"techniques":["dimensional-shading","color-segments"],"type_style":null,"case":null,"mood":["polished","bright"],"industry":"design-creative","exemplary":false,"note":""},{"file":"flattr-icon.svg","brand":"flattr","variant":"icon","pair":"flattr.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3369,"shapes":2,"anchors":108,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two interlocking arrowed brackets forming loop","geometry":["rounded-square"],"techniques":["arrow","negative-space","line-monoline"],"type_style":null,"case":null,"mood":["minimal","cyclical"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"flattr.svg","brand":"flattr","variant":"main","pair":"flattr-icon.svg","width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":1547,"shapes":3,"anchors":30,"colors":["#ea5f29","#fabd1f","#abd33c","#6cb02f"],"n_colors":4,"color_families":["green","orange","yellow"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"gradient interlocking arrowed halves","geometry":["rounded-square"],"techniques":["gradient","arrow","negative-space"],"type_style":null,"case":null,"mood":["fresh","cyclical"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"fleep.svg","brand":"fleep","variant":"main","pair":null,"width":512.0,"height":165.0,"aspect":3.103,"aspect_class":"horizontal","bytes":2789,"shapes":2,"anchors":124,"colors":["#3e81de"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"F inside blue speech bubble","geometry":["rounded-square"],"techniques":["speech-bubble","containment"],"type_style":"slab","case":"titlecase","mood":["friendly","bold"],"industry":"social-communication","exemplary":false,"note":""},{"file":"flickr.svg","brand":"flickr","variant":"main","pair":null,"width":512.0,"height":160.0,"aspect":3.2,"aspect_class":"horizontal","bytes":1578,"shapes":2,"anchors":72,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy black lowercase name","geometry":[],"techniques":[],"type_style":"humanist-sans","case":"lowercase","mood":["bold","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"flight.svg","brand":"flight","variant":"main","pair":null,"width":256.0,"height":353.0,"aspect":0.725,"aspect_class":"tall","bytes":1430,"shapes":2,"anchors":25,"colors":["#00acee"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"blue wing forming letter F","geometry":["organic"],"techniques":["hidden-meaning","motion-lines"],"type_style":null,"case":null,"mood":["light","fast"],"industry":"framework-library","exemplary":false,"note":""},{"file":"floodio.svg","brand":"floodio","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1868,"shapes":2,"anchors":37,"colors":["#298eea"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"wave line inside blue ring","geometry":["circle"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["calm","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"flow.svg","brand":"flow","variant":"main","pair":null,"width":256.0,"height":317.0,"aspect":0.808,"aspect_class":"square","bytes":2344,"shapes":13,"anchors":49,"colors":["#ffdf51","#ff8900","#ffdf4f","#ffb700","#ffcd25","#ffd441","#ffb047","#ffd754","#ffb532","#ffa829"],"n_colors":10,"color_families":["orange","yellow"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"translucent triangles forming F","geometry":["triangle","freeform"],"techniques":["overlap-transparency","geometric-construction","color-segments"],"type_style":null,"case":null,"mood":["warm","layered"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"flowxo.svg","brand":"flowxo","variant":"main","pair":null,"width":256.0,"height":182.0,"aspect":1.407,"aspect_class":"wide","bytes":2066,"shapes":4,"anchors":53,"colors":["#1db2ca","#2a3645","#6ac08f"],"n_colors":3,"color_families":["blue","cyan","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"overlapping X and ring O","geometry":["circle"],"techniques":["overlap-transparency","color-segments"],"type_style":"display-custom","case":"uppercase","mood":["fresh","connected"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"floydhub.svg","brand":"floydhub","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1774,"shapes":2,"anchors":45,"colors":["#3b99ed"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"monoline double-stroke F in ring","geometry":["circle"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["clean","technical"],"industry":"ai-ml","exemplary":false,"note":""},{"file":"flutter.svg","brand":"flutter","variant":"main","pair":null,"width":256.0,"height":317.0,"aspect":0.808,"aspect_class":"square","bytes":989,"shapes":6,"anchors":25,"colors":["#47c5fb","#00569e","#00b5f8"],"n_colors":3,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"layered blue bars forming chevron","geometry":["triangle","freeform"],"techniques":["overlap-transparency","dimensional-shading","geometric-construction"],"type_style":null,"case":null,"mood":["fast","modern"],"industry":"framework-library","exemplary":true,"note":"Few angled bars suggest F and motion; clean layered geometry."},{"file":"flux.svg","brand":"flux","variant":"main","pair":null,"width":256.0,"height":102.0,"aspect":2.51,"aspect_class":"horizontal","bytes":1480,"shapes":2,"anchors":35,"colors":["#44b74a"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"green open infinity loop crossing","geometry":["organic"],"techniques":["infinity-loop","line-monoline"],"type_style":null,"case":null,"mood":["fluid","light"],"industry":"framework-library","exemplary":false,"note":""},{"file":"fluxxor.svg","brand":"fluxxor","variant":"main","pair":null,"width":256.0,"height":322.0,"aspect":0.795,"aspect_class":"tall","bytes":8367,"shapes":6,"anchors":264,"colors":["#ffffff","#000000"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"flux capacitor in framed panel with name","geometry":["square"],"techniques":["containment","hidden-meaning","line-monoline"],"type_style":"display-custom","case":"uppercase","mood":["retro","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"fly.svg","brand":"fly","variant":"main","pair":null,"width":256.0,"height":400.0,"aspect":0.64,"aspect_class":"tall","bytes":6733,"shapes":2,"anchors":223,"colors":["#3285ef","#a63ee1"],"n_colors":2,"color_families":["blue","purple"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"gradient hot-air balloon with drop","geometry":["organic"],"techniques":["gradient","negative-space"],"type_style":null,"case":null,"mood":["light","uplifting"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"fomo.svg","brand":"fomo","variant":"main","pair":null,"width":512.0,"height":179.0,"aspect":2.86,"aspect_class":"horizontal","bytes":3559,"shapes":2,"anchors":88,"colors":["#eca16c"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"peach script name","geometry":[],"techniques":["hand-drawn"],"type_style":"script","case":"titlecase","mood":["friendly","casual"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"font-awesome.svg","brand":"font-awesome","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1352,"shapes":2,"anchors":34,"colors":["#339af0"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"white flag in blue rounded square","geometry":["rounded-square"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["friendly","simple"],"industry":"design-creative","exemplary":false,"note":""},{"file":"forestadmin-icon.svg","brand":"forestadmin","variant":"icon","pair":"forestadmin.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1597,"shapes":7,"anchors":44,"colors":["#9b183d","#ee0036","#702440","#ffffff"],"n_colors":4,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"italic F on four-tone red square","geometry":["square","grid-modular"],"techniques":["color-segments","containment"],"type_style":null,"case":null,"mood":["bold","structured"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"forestadmin.svg","brand":"forestadmin","variant":"main","pair":"forestadmin-icon.svg","width":512.0,"height":128.0,"aspect":4.0,"aspect_class":"horizontal","bytes":8084,"shapes":8,"anchors":256,"colors":["#3a3335","#9b183d","#ee0036","#702440","#ffffff"],"n_colors":5,"color_families":["gray","red","white"],"primary_family":"red","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"italic F on red quadrants","geometry":["square"],"techniques":["color-segments","containment"],"type_style":"humanist-sans","case":"titlecase","mood":["professional","clean"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"forever.svg","brand":"forever","variant":"main","pair":null,"width":256.0,"height":127.0,"aspect":2.016,"aspect_class":"wide","bytes":1513,"shapes":2,"anchors":35,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"heavy black infinity symbol","geometry":["organic"],"techniques":["infinity-loop"],"type_style":null,"case":null,"mood":["bold","simple"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"formkeep.svg","brand":"formkeep","variant":"main","pair":null,"width":256.0,"height":283.0,"aspect":0.905,"aspect_class":"square","bytes":1752,"shapes":2,"anchors":56,"colors":["#524b5a"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"castle tower in dark hexagon","geometry":["hexagon"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["secure","solid"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"fortran.svg","brand":"fortran","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1708,"shapes":3,"anchors":54,"colors":["#734f96","#ffffff"],"n_colors":2,"color_families":["purple","white"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"serif F in purple square","geometry":["square"],"techniques":["containment"],"type_style":null,"case":null,"mood":["classic","academic"],"industry":"programming-language","exemplary":false,"note":""},{"file":"foundation.svg","brand":"foundation","variant":"main","pair":null,"width":256.0,"height":380.0,"aspect":0.674,"aspect_class":"tall","bytes":20034,"shapes":33,"anchors":451,"colors":["#1a4658","#edf7fa","#cde9ee","#abd8d7","#83bac0","#545352","#6e7979","#ffffff","#474746","#a0d1de","#b2dce5"],"n_colors":11,"color_families":["blue","cyan","gray","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"fluffy yeti wearing glasses","geometry":["freeform"],"techniques":[],"type_style":null,"case":null,"mood":["friendly","quirky"],"industry":"framework-library","exemplary":false,"note":""},{"file":"framer.svg","brand":"framer","variant":"main","pair":null,"width":256.0,"height":384.0,"aspect":0.667,"aspect_class":"tall","bytes":335,"shapes":2,"anchors":12,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"F-like shape from triangles and squares","geometry":["square","triangle","grid-modular"],"techniques":["geometric-construction","negative-space"],"type_style":null,"case":null,"mood":["bold","minimal"],"industry":"design-creative","exemplary":true,"note":"Squares and triangles tessellate into an F; rigorous modular geometry."},{"file":"framework7-icon.svg","brand":"framework7","variant":"icon","pair":"framework7.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":624,"shapes":2,"anchors":14,"colors":["#ee350f"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"numeral 7 cut into red disc","geometry":["circle"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["bold","dynamic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"framework7.svg","brand":"framework7","variant":"main","pair":"framework7-icon.svg","width":512.0,"height":275.0,"aspect":1.862,"aspect_class":"wide","bytes":7918,"shapes":4,"anchors":224,"colors":["#ffffff","#ee350f"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"name overlapping red 7 disc","geometry":["circle"],"techniques":["negative-space","overlap-transparency"],"type_style":"geometric-sans","case":"titlecase","mood":["bold","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"freebsd.svg","brand":"freebsd","variant":"main","pair":null,"width":256.0,"height":252.0,"aspect":1.016,"aspect_class":"square","bytes":1339,"shapes":4,"anchors":23,"colors":["#b5010f"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red orb with devil horns","geometry":["circle"],"techniques":[],"type_style":null,"case":null,"mood":["mischievous","bold"],"industry":"os-platform","exemplary":false,"note":""},{"file":"freedcamp-icon.svg","brand":"freedcamp","variant":"icon","pair":"freedcamp.svg","width":256.0,"height":228.0,"aspect":1.123,"aspect_class":"square","bytes":7715,"shapes":2,"anchors":249,"colors":["#38a1e7"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"tree built from modular rounded nodes","geometry":["grid-modular","organic"],"techniques":["modular-repetition","mirror-symmetry"],"type_style":null,"case":null,"mood":["organic","connected"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"freedcamp.svg","brand":"freedcamp","variant":"main","pair":"freedcamp-icon.svg","width":512.0,"height":95.0,"aspect":5.389,"aspect_class":"extra-wide","bytes":13484,"shapes":3,"anchors":416,"colors":["#3d4d66","#38a1e7"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"modular node tree beside name","geometry":["grid-modular"],"techniques":["modular-repetition"],"type_style":"script","case":"lowercase","mood":["friendly","organic"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"freedomdefined.svg","brand":"freedomdefined","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3290,"shapes":7,"anchors":43,"colors":["#ff5959","#df0000","#ffb73d","#ffa000","#fff18d","#ffcd01","#ffffff","#00a000","#008000","#263cce","#652f99","#502679"],"n_colors":12,"color_families":["blue","green","orange","purple","red","white","yellow"],"primary_family":"multi","gradients":7,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"concentric rainbow rings target","geometry":["circle","radial"],"techniques":["color-segments","gradient","radial-symmetry"],"type_style":null,"case":null,"mood":["vibrant","open"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"frontapp.svg","brand":"frontapp","variant":"main","pair":null,"width":256.0,"height":366.0,"aspect":0.699,"aspect_class":"tall","bytes":1521,"shapes":4,"anchors":23,"colors":["#001b38","#ff0057"],"n_colors":2,"color_families":["blue","red"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"navy F with pink gradient dot","geometry":["square","circle"],"techniques":["overlap-transparency","gradient"],"type_style":null,"case":null,"mood":["modern","bold"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"fsharp.svg","brand":"fsharp","variant":"main","pair":null,"width":256.0,"height":243.0,"aspect":1.053,"aspect_class":"square","bytes":554,"shapes":4,"anchors":18,"colors":["#378bba","#30b9db"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"split diamond chevrons in blues","geometry":["diamond"],"techniques":["bracket-code","negative-space","color-segments"],"type_style":null,"case":null,"mood":["sharp","technical"],"industry":"programming-language","exemplary":false,"note":""},{"file":"fuchsia.svg","brand":"fuchsia","variant":"main","pair":null,"width":256.0,"height":229.0,"aspect":1.118,"aspect_class":"square","bytes":2105,"shapes":2,"anchors":40,"colors":["#ed1d7f"],"n_colors":1,"color_families":["pink"],"primary_family":"pink","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"pink monoline ring with loop tail","geometry":["circle"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["playful","fluid"],"industry":"os-platform","exemplary":false,"note":""},{"file":"galliumos.svg","brand":"galliumos","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2919,"shapes":9,"anchors":99,"colors":["#68a5c6","#98b7d4","#347294","#5089af","#367ba0","#5495bf","#71b6db","#a5c8e8"],"n_colors":8,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"square of blue triangles with white dot","geometry":["square","triangle"],"techniques":["color-segments","radial-symmetry","geometric-construction"],"type_style":null,"case":null,"mood":["calm","structured"],"industry":"os-platform","exemplary":false,"note":""},{"file":"game-analytics-icon.svg","brand":"game-analytics","variant":"icon","pair":"game-analytics.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1314,"shapes":2,"anchors":30,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"GA with barless A in black disc","geometry":["circle"],"techniques":["containment","letter-substitution"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","modern"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"game-analytics.svg","brand":"game-analytics","variant":"main","pair":"game-analytics-icon.svg","width":512.0,"height":67.0,"aspect":7.642,"aspect_class":"extra-wide","bytes":5169,"shapes":5,"anchors":189,"colors":["#ffffff","#1955a6","#4cc0ad"],"n_colors":3,"color_families":["blue","cyan","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"reversed white name with color squares","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"mixed","mood":["clean","modern"],"industry":"marketing-analytics","exemplary":false,"note":"White-only artwork; unusable on light backgrounds."},{"file":"ganache-icon.svg","brand":"ganache","variant":"icon","pair":"ganache.svg","width":256.0,"height":288.0,"aspect":0.889,"aspect_class":"square","bytes":3881,"shapes":5,"anchors":88,"colors":["#e4a663","#5e464d","#ffffff"],"n_colors":3,"color_families":["gray","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"caramel cube dripping over chocolate","geometry":["hexagon"],"techniques":["isometric-3d"],"type_style":null,"case":null,"mood":["sweet","warm"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"ganache.svg","brand":"ganache","variant":"main","pair":"ganache-icon.svg","width":512.0,"height":789.0,"aspect":0.649,"aspect_class":"tall","bytes":21534,"shapes":6,"anchors":501,"colors":["#5e464d","#e4a663","#ffffff"],"n_colors":3,"color_families":["gray","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"dripping caramel cube above script name","geometry":["hexagon"],"techniques":["isometric-3d"],"type_style":"script","case":"titlecase","mood":["sweet","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"gatsby.svg","brand":"gatsby","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":860,"shapes":2,"anchors":24,"colors":["#744c9e"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"G with diagonal cut in purple disc","geometry":["circle"],"techniques":["negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["modern","confident"],"industry":"framework-library","exemplary":true,"note":"Letter G built from circle and diagonal negative-space cut."},{"file":"geekbot.svg","brand":"geekbot","variant":"main","pair":null,"width":256.0,"height":284.0,"aspect":0.901,"aspect_class":"square","bytes":6101,"shapes":17,"anchors":128,"colors":["#6fc0bf","#d4d4d4","#a3a3a3","#bfbfbf","#b3b3b3","#f0f0f0","#333333","#ffffff","#666666","#4d4d4d"],"n_colors":10,"color_families":["cyan","gray","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"robot head with glasses smiling","geometry":["circle"],"techniques":["containment","dimensional-shading"],"type_style":null,"case":null,"mood":["friendly","playful"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"getyourguide.svg","brand":"getyourguide","variant":"main","pair":null,"width":256.0,"height":203.0,"aspect":1.261,"aspect_class":"wide","bytes":5063,"shapes":2,"anchors":212,"colors":["#ff5533"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"stacked name with notched custom letters","geometry":[],"techniques":[],"type_style":"display-custom","case":"uppercase","mood":["bold","energetic"],"industry":"travel-transport","exemplary":false,"note":""},{"file":"ghost.svg","brand":"ghost","variant":"main","pair":null,"width":512.0,"height":165.0,"aspect":3.103,"aspect_class":"horizontal","bytes":4659,"shapes":11,"anchors":127,"colors":["#3d515b","#404041"],"n_colors":2,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"stacked dashed horizontal lines","geometry":[],"techniques":["modular-repetition"],"type_style":"geometric-sans","case":"lowercase","mood":["minimal","calm"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"giantswarm.svg","brand":"giantswarm","variant":"main","pair":null,"width":256.0,"height":229.0,"aspect":1.118,"aspect_class":"square","bytes":2721,"shapes":6,"anchors":57,"colors":["#ffffff","#e54d42","#e14760","#fa8816"],"n_colors":4,"color_families":["orange","red","white"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"ant head with terminal-prompt eyes","geometry":["organic"],"techniques":["gradient","hidden-meaning","mirror-symmetry"],"type_style":null,"case":null,"mood":["playful","technical"],"industry":"cloud-infrastructure","exemplary":true,"note":"Terminal glyphs as eyes merge character with developer meaning."},{"file":"git-icon.svg","brand":"git","variant":"icon","pair":"git.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1270,"shapes":2,"anchors":29,"colors":["#de4c36"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"branch graph nodes in rotated square","geometry":["diamond","rounded-square"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"developer-tools","exemplary":true,"note":"Single memorable idea: version branch diagram in simple diamond."},{"file":"git.svg","brand":"git","variant":"main","pair":"git-icon.svg","width":256.0,"height":108.0,"aspect":2.37,"aspect_class":"wide","bytes":3408,"shapes":5,"anchors":96,"colors":["#2f2707","#de4c36"],"n_colors":2,"color_families":["red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"branch graph in rotated square","geometry":["diamond"],"techniques":["negative-space","containment"],"type_style":"grotesque-sans","case":"lowercase","mood":["technical","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"gitboard.svg","brand":"gitboard","variant":"main","pair":null,"width":256.0,"height":249.0,"aspect":1.028,"aspect_class":"square","bytes":1632,"shapes":3,"anchors":41,"colors":["#f39800","#3e3a39"],"n_colors":2,"color_families":["gray","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"monoline G in circle with orange quadrant","geometry":["circle"],"techniques":["line-monoline","geometric-construction","containment"],"type_style":null,"case":null,"mood":["clean","modern"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"github-actions.svg","brand":"github-actions","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4790,"shapes":5,"anchors":123,"colors":["#4a7ebf","#85b3df"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"workflow diagram of connected play and check circles","geometry":["circle"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["technical","clean"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"github-copilot.svg","brand":"github-copilot","variant":"main","pair":null,"width":256.0,"height":208.0,"aspect":1.231,"aspect_class":"square","bytes":2893,"shapes":2,"anchors":76,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"face with goggles and headphones","geometry":["organic"],"techniques":["negative-space","mirror-symmetry"],"type_style":null,"case":null,"mood":["friendly","playful"],"industry":"ai-ml","exemplary":false,"note":""},{"file":"github-icon.svg","brand":"github","variant":"icon","pair":"github.svg","width":256.0,"height":250.0,"aspect":1.024,"aspect_class":"square","bytes":2871,"shapes":2,"anchors":61,"colors":["#161614"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"octocat silhouette in circle","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["iconic","bold"],"industry":"developer-tools","exemplary":true,"note":"Strong silhouette carved by negative space inside a circle."},{"file":"github-octocat.svg","brand":"github-octocat","variant":"main","pair":null,"width":256.0,"height":260.0,"aspect":0.985,"aspect_class":"square","bytes":6005,"shapes":20,"anchors":158,"colors":["#9edcf2","#7dbce7","#010101","#f5ccb3","#ffffff","#af5c51","#c4e5d9"],"n_colors":7,"color_families":["black","blue","green","orange","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"octopus-cat character on puddle","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"github.svg","brand":"github","variant":"main","pair":"github-icon.svg","width":512.0,"height":139.0,"aspect":3.683,"aspect_class":"horizontal","bytes":4088,"shapes":2,"anchors":121,"colors":["#11110f"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold camel-case name","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"mixed","mood":["bold","confident"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"gitkraken.svg","brand":"gitkraken","variant":"main","pair":null,"width":256.0,"height":224.0,"aspect":1.143,"aspect_class":"square","bytes":3054,"shapes":2,"anchors":70,"colors":["#128379"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"kraken squid inside circular arcs","geometry":["circle"],"techniques":["line-monoline","mirror-symmetry","containment"],"type_style":null,"case":null,"mood":["technical","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"gitlab.svg","brand":"gitlab","variant":"main","pair":null,"width":256.0,"height":236.0,"aspect":1.085,"aspect_class":"square","bytes":1063,"shapes":8,"anchors":32,"colors":["#e24329","#fc6d26","#fca326"],"n_colors":3,"color_families":["orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"geometric tanuki head from triangles","geometry":["triangle"],"techniques":["color-segments","geometric-construction","mirror-symmetry"],"type_style":null,"case":null,"mood":["bold","warm"],"industry":"developer-tools","exemplary":true,"note":"Animal head built purely from faceted triangles."},{"file":"gitter.svg","brand":"gitter","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":723,"shapes":3,"anchors":25,"colors":["#ffffff","#fb0766","#c50948"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"vertical bars in magenta square","geometry":["square"],"techniques":["gradient","containment","modular-repetition"],"type_style":null,"case":null,"mood":["modern","bold"],"industry":"social-communication","exemplary":false,"note":""},{"file":"gitup.svg","brand":"gitup","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4622,"shapes":6,"anchors":44,"colors":["#f5f5f5","#fbfbfb","#fcfcfc","#ffffff","#000000"],"n_colors":5,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":true,"mark_type":"abstract","symbol_type":null,"subject":"faint concentric circles on tilted tiles","geometry":["circle","rounded-square"],"techniques":["radial-symmetry","stacked-layers"],"type_style":null,"case":null,"mood":["minimal","soft"],"industry":"developer-tools","exemplary":false,"note":"Very low contrast; weak at small sizes."},{"file":"glamorous.svg","brand":"glamorous","variant":"main","pair":null,"width":256.0,"height":342.0,"aspect":0.749,"aspect_class":"tall","bytes":2777,"shapes":8,"anchors":72,"colors":["#d53a56","#e47176","#505457","#e8e8e3","#adbbb5","#393d3e","#f93954"],"n_colors":7,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"script g beside lipstick","geometry":["freeform"],"techniques":["overlap-transparency"],"type_style":"serif","case":"lowercase","mood":["glamorous","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"gleam.svg","brand":"gleam","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":904,"shapes":8,"anchors":40,"colors":["#f36a22","#f3852f","#f2c32e","#cbdc38","#b5d66d","#69c5e5","#6d9fd5"],"n_colors":7,"color_families":["blue","green","orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"multicolor triangular pinwheel star","geometry":["radial","triangle"],"techniques":["color-segments","radial-symmetry"],"type_style":null,"case":null,"mood":["vibrant","playful"],"industry":"programming-language","exemplary":false,"note":""},{"file":"glimmerjs.svg","brand":"glimmerjs","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2799,"shapes":3,"anchors":68,"colors":["#f8835a","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"diagonal rounded dashes in orange circle","geometry":["circle"],"techniques":["containment","negative-space","motion-lines"],"type_style":null,"case":null,"mood":["energetic","warm"],"industry":"framework-library","exemplary":false,"note":""},{"file":"glint.svg","brand":"glint","variant":"main","pair":null,"width":512.0,"height":133.0,"aspect":3.85,"aspect_class":"horizontal","bytes":1563,"shapes":6,"anchors":58,"colors":["#6bbfa4","#73be88","#a3cc69","#ece23c","#72736d"],"n_colors":5,"color_families":["gray","green","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with bracket-shaped T","geometry":[],"techniques":["gradient","letter-substitution"],"type_style":"geometric-sans","case":"uppercase","mood":["modern","fresh"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"glitch-icon.svg","brand":"glitch","variant":"icon","pair":"glitch.svg","width":256.0,"height":200.0,"aspect":1.28,"aspect_class":"wide","bytes":9427,"shapes":21,"anchors":187,"colors":["#974dff","#f1a5ff","#373fff","#000000","#ffffff","#e459ff","#914dff","#f0a5ff","#ff676b","#6e3bff","#3633ff"],"n_colors":11,"color_families":["black","blue","pink","purple","red","white"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"two stacked gradient fish","geometry":["organic"],"techniques":["gradient","modular-repetition"],"type_style":null,"case":null,"mood":["playful","vibrant"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"glitch.svg","brand":"glitch","variant":"main","pair":"glitch-icon.svg","width":512.0,"height":157.0,"aspect":3.261,"aspect_class":"horizontal","bytes":10901,"shapes":21,"anchors":260,"colors":["#974dff","#f1a5ff","#373fff","#000000","#ffffff","#e459ff","#914dff","#f0a5ff","#ff676b","#6e3bff","#3633ff"],"n_colors":11,"color_families":["black","blue","pink","purple","red","white"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"two stacked gradient fish","geometry":["organic"],"techniques":["gradient","modular-repetition"],"type_style":"grotesque-sans","case":"titlecase","mood":["playful","vibrant"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"gnome-icon.svg","brand":"gnome","variant":"icon","pair":"gnome.svg","width":256.0,"height":315.0,"aspect":0.813,"aspect_class":"square","bytes":1001,"shapes":2,"anchors":19,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"footprint whose sole forms a G","geometry":["organic"],"techniques":["hidden-meaning"],"type_style":null,"case":null,"mood":["friendly","bold"],"industry":"os-platform","exemplary":true,"note":"Footprint doubles as letter G; clever dual reading."},{"file":"gnome.svg","brand":"gnome","variant":"main","pair":"gnome-icon.svg","width":512.0,"height":187.0,"aspect":2.738,"aspect_class":"horizontal","bytes":3027,"shapes":2,"anchors":100,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"footprint forming letter G","geometry":["organic"],"techniques":["hidden-meaning"],"type_style":"humanist-sans","case":"uppercase","mood":["friendly","bold"],"industry":"os-platform","exemplary":false,"note":""},{"file":"gnu-net.svg","brand":"gnu-net","variant":"main","pair":null,"width":256.0,"height":216.0,"aspect":1.185,"aspect_class":"square","bytes":17849,"shapes":5,"anchors":585,"colors":["#000000","#666666","#3498db"],"n_colors":3,"color_families":["black","blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"gnu horns drawn as network graph","geometry":["freeform"],"techniques":["line-monoline","hidden-meaning"],"type_style":"geometric-sans","case":"lowercase","mood":["technical","light"],"industry":"open-source-community","exemplary":true,"note":"Network graph drawn as gnu horns merges subject and name."},{"file":"gnu.svg","brand":"gnu","variant":"main","pair":null,"width":256.0,"height":251.0,"aspect":1.02,"aspect_class":"square","bytes":27326,"shapes":2,"anchors":661,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"illustrated gnu head","geometry":["organic"],"techniques":["hand-drawn"],"type_style":null,"case":null,"mood":["quirky","classic"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"go.svg","brand":"go","variant":"main","pair":null,"width":512.0,"height":192.0,"aspect":2.667,"aspect_class":"horizontal","bytes":2899,"shapes":2,"anchors":74,"colors":["#00acd7"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"italic GO with speed lines","geometry":[],"techniques":["motion-lines"],"type_style":"display-custom","case":"uppercase","mood":["fast","bold"],"industry":"programming-language","exemplary":true,"note":"Italic custom letters plus speed lines express speed with minimal means."},{"file":"gocd.svg","brand":"gocd","variant":"main","pair":null,"width":512.0,"height":257.0,"aspect":1.992,"aspect_class":"wide","bytes":4393,"shapes":2,"anchors":99,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"play arrow chevron","geometry":["triangle"],"techniques":["arrow"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"gohorse.svg","brand":"gohorse","variant":"main","pair":null,"width":201.0,"height":256.0,"aspect":0.785,"aspect_class":"tall","bytes":72084,"shapes":2,"anchors":1546,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"sketched horse head in circle with text","geometry":["circle"],"techniques":["hand-drawn","containment"],"type_style":"display-custom","case":"uppercase","mood":["humorous","rough"],"industry":"other","exemplary":false,"note":"Hand-drawn sketch; poor reproduction, joke branding."},{"file":"google-360suite.svg","brand":"google-360suite","variant":"main","pair":null,"width":256.0,"height":269.0,"aspect":0.952,"aspect_class":"square","bytes":12346,"shapes":17,"anchors":232,"colors":["#4fc3f7","#4285f4","#1a237e","#ffc107","#ffffff","#bf360c","#000000","#3367d6"],"n_colors":8,"color_families":["black","blue","red","white","yellow"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":true,"mark_type":"abstract","symbol_type":null,"subject":"two overlapping gradient rings","geometry":["circle"],"techniques":["overlap-transparency","gradient"],"type_style":null,"case":null,"mood":["modern","vibrant"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"google-admob.svg","brand":"google-admob","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1374,"shapes":4,"anchors":31,"colors":["#fbbc04","#4285f4","#ea4335"],"n_colors":3,"color_families":["blue","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"lowercase a from arc and dot","geometry":["circle"],"techniques":["color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["friendly","vibrant"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"google-ads.svg","brand":"google-ads","variant":"main","pair":null,"width":256.0,"height":230.0,"aspect":1.113,"aspect_class":"square","bytes":917,"shapes":4,"anchors":19,"colors":["#fbbc04","#4285f4","#34a853"],"n_colors":3,"color_families":["blue","green","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter A from rounded bars and dot","geometry":["triangle"],"techniques":["color-segments","overlap-transparency"],"type_style":null,"case":null,"mood":["friendly","vibrant"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"google-adsense.svg","brand":"google-adsense","variant":"main","pair":null,"width":256.0,"height":227.0,"aspect":1.128,"aspect_class":"square","bytes":1257,"shapes":4,"anchors":26,"colors":["#fbbc04","#34a853","#4285f4"],"n_colors":3,"color_families":["blue","green","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two slanted rounded bars with dot","geometry":["freeform"],"techniques":["color-segments"],"type_style":null,"case":null,"mood":["friendly","vibrant"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"google-analytics.svg","brand":"google-analytics","variant":"main","pair":null,"width":256.0,"height":284.0,"aspect":0.901,"aspect_class":"square","bytes":1129,"shapes":3,"anchors":23,"colors":["#f9ab00","#e37400"],"n_colors":2,"color_families":["orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"rising rounded bar chart with dot","geometry":["grid-modular"],"techniques":["color-segments","modular-repetition"],"type_style":null,"case":null,"mood":["clear","warm"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"google-calendar.svg","brand":"google-calendar","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2564,"shapes":9,"anchors":86,"colors":["#ffffff","#ea4335","#188038","#1967d2","#fbbc04","#34a853","#4285f4"],"n_colors":7,"color_families":["blue","green","red","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"calendar page showing 31","geometry":["square"],"techniques":["color-segments","containment"],"type_style":"geometric-sans","case":null,"mood":["friendly","clear"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"google-cloud-functions.svg","brand":"google-cloud-functions","variant":"main","pair":null,"width":256.0,"height":231.0,"aspect":1.108,"aspect_class":"square","bytes":2588,"shapes":9,"anchors":66,"colors":["#4285f4","#000000","#ffffff"],"n_colors":3,"color_families":["black","blue","white"],"primary_family":"blue","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"code brackets with dots in hexagon","geometry":["hexagon"],"techniques":["bracket-code","containment","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","clean"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"google-cloud-run.svg","brand":"google-cloud-run","variant":"main","pair":null,"width":256.0,"height":231.0,"aspect":1.108,"aspect_class":"square","bytes":1242,"shapes":4,"anchors":42,"colors":["#4285f4","#000000","#ffffff"],"n_colors":3,"color_families":["black","blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"forward chevrons in hexagon","geometry":["hexagon"],"techniques":["arrow","motion-lines","containment","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","fast"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"google-cloud.svg","brand":"google-cloud","variant":"main","pair":null,"width":256.0,"height":206.0,"aspect":1.243,"aspect_class":"square","bytes":1531,"shapes":5,"anchors":42,"colors":["#ea4335","#4285f4","#34a853","#fbbc05"],"n_colors":4,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"multicolor cloud outline","geometry":["organic"],"techniques":["color-segments","line-monoline"],"type_style":null,"case":null,"mood":["friendly","vibrant"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"google-currents.svg","brand":"google-currents","variant":"main","pair":null,"width":256.0,"height":262.0,"aspect":0.977,"aspect_class":"square","bytes":1131,"shapes":3,"anchors":37,"colors":["#174ea6","#4285f4"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"interlocking zigzag M shape","geometry":["freeform"],"techniques":["overlap-transparency"],"type_style":null,"case":null,"mood":["dynamic","modern"],"industry":"social-communication","exemplary":false,"note":""},{"file":"google-data-studio.svg","brand":"google-data-studio","variant":"main","pair":null,"width":256.0,"height":239.0,"aspect":1.071,"aspect_class":"square","bytes":1389,"shapes":7,"anchors":33,"colors":["#669df6","#1a73e8"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three toggle-like bars with dots","geometry":["grid-modular"],"techniques":["modular-repetition"],"type_style":null,"case":null,"mood":["clean","technical"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"google-developers.svg","brand":"google-developers","variant":"main","pair":null,"width":256.0,"height":125.0,"aspect":2.048,"aspect_class":"wide","bytes":2136,"shapes":5,"anchors":40,"colors":["#fabc05","#109d58","#e94436","#4385f3"],"n_colors":4,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"angle brackets from colored bars","geometry":["freeform"],"techniques":["bracket-code","color-segments","mirror-symmetry"],"type_style":null,"case":null,"mood":["technical","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"google-drive.svg","brand":"google-drive","variant":"main","pair":null,"width":256.0,"height":229.0,"aspect":1.118,"aspect_class":"square","bytes":1849,"shapes":7,"anchors":48,"colors":["#0066da","#ea4335","#00832d","#2684fc","#00ac47","#ffba00"],"n_colors":6,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"triangle of three colored bands","geometry":["triangle"],"techniques":["color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["clean","vibrant"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"google-fit.svg","brand":"google-fit","variant":"main","pair":null,"width":256.0,"height":216.0,"aspect":1.185,"aspect_class":"square","bytes":2317,"shapes":5,"anchors":53,"colors":["#ea4335","#34a853","#fbbc05","#4285f4"],"n_colors":4,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"heart from interlocking colored strokes","geometry":["organic"],"techniques":["color-segments","overlap-transparency"],"type_style":null,"case":null,"mood":["healthy","vibrant"],"industry":"health","exemplary":false,"note":""},{"file":"google-gmail.svg","brand":"google-gmail","variant":"main","pair":null,"width":256.0,"height":193.0,"aspect":1.326,"aspect_class":"wide","bytes":967,"shapes":6,"anchors":36,"colors":["#4285f4","#34a853","#ea4335","#fbbc04","#c5221f"],"n_colors":5,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"M shaped as envelope","geometry":["square"],"techniques":["color-segments","hidden-meaning"],"type_style":null,"case":null,"mood":["friendly","vibrant"],"industry":"social-communication","exemplary":false,"note":""},{"file":"google-gsuite.svg","brand":"google-gsuite","variant":"main","pair":null,"width":512.0,"height":127.0,"aspect":4.031,"aspect_class":"horizontal","bytes":5105,"shapes":2,"anchors":136,"colors":["#737373"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"product name in sans","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"titlecase","mood":["neutral","clean"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"google-home.svg","brand":"google-home","variant":"main","pair":null,"width":256.0,"height":265.0,"aspect":0.966,"aspect_class":"square","bytes":2511,"shapes":5,"anchors":47,"colors":["#3bab59","#4586f7","#fdc00d","#ec5043"],"n_colors":4,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"multicolor house outline","geometry":["freeform"],"techniques":["color-segments","line-monoline"],"type_style":null,"case":null,"mood":["friendly","warm"],"industry":"hardware-devices","exemplary":false,"note":""},{"file":"google-icon.svg","brand":"google","variant":"icon","pair":"google.svg","width":256.0,"height":262.0,"aspect":0.977,"aspect_class":"square","bytes":1284,"shapes":5,"anchors":35,"colors":["#4285f4","#34a853","#fbbc05","#eb4335"],"n_colors":4,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"four-color G","geometry":["circle"],"techniques":["color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["iconic","friendly"],"industry":"other","exemplary":true,"note":"Geometric G with clean color segmentation; scales well."},{"file":"google-keep.svg","brand":"google-keep","variant":"main","pair":null,"width":256.0,"height":352.0,"aspect":0.727,"aspect_class":"tall","bytes":673,"shapes":4,"anchors":26,"colors":["#ffba00","#ff9500","#ffffff"],"n_colors":3,"color_families":["orange","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"lightbulb on folded page","geometry":["rounded-square"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["simple","bright"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"google-maps.svg","brand":"google-maps","variant":"main","pair":null,"width":256.0,"height":367.0,"aspect":0.698,"aspect_class":"tall","bytes":1752,"shapes":6,"anchors":47,"colors":["#34a853","#fbbc04","#4285f4","#1a73e8","#ea4335"],"n_colors":5,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"map pin in color segments","geometry":["organic"],"techniques":["color-segments","negative-space"],"type_style":null,"case":null,"mood":["friendly","vibrant"],"industry":"travel-transport","exemplary":false,"note":""},{"file":"google-marketing-platform.svg","brand":"google-marketing-platform","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1599,"shapes":6,"anchors":29,"colors":["#ea4335","#fbbc04","#34a853","#246fdb","#2973df","#377deb","#3f83f2","#4285f4"],"n_colors":8,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"ring of colored segments","geometry":["circle"],"techniques":["color-segments","gradient"],"type_style":null,"case":null,"mood":["modern","vibrant"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"google-meet.svg","brand":"google-meet","variant":"main","pair":null,"width":256.0,"height":211.0,"aspect":1.213,"aspect_class":"square","bytes":1232,"shapes":8,"anchors":49,"colors":["#00832d","#0066da","#e94235","#2684fc","#00ac47","#ffba00"],"n_colors":6,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"video camera from colored blocks","geometry":["square"],"techniques":["color-segments","negative-space"],"type_style":null,"case":null,"mood":["friendly","clean"],"industry":"social-communication","exemplary":false,"note":""},{"file":"google-one.svg","brand":"google-one","variant":"main","pair":null,"width":256.0,"height":516.0,"aspect":0.496,"aspect_class":"tall","bytes":3335,"shapes":5,"anchors":72,"colors":["#34a853","#ea4335","#fbbc04","#1a73e8","#4285f4"],"n_colors":5,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"numeral 1 from colored strokes","geometry":["freeform"],"techniques":["color-segments","overlap-transparency"],"type_style":null,"case":null,"mood":["bold","friendly"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"google-optimize.svg","brand":"google-optimize","variant":"main","pair":null,"width":256.0,"height":264.0,"aspect":0.97,"aspect_class":"square","bytes":1145,"shapes":4,"anchors":27,"colors":["#b366f6","#8430ce","#c58af8"],"n_colors":3,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"purple bent bar segments","geometry":["freeform"],"techniques":["stacked-layers"],"type_style":null,"case":null,"mood":["modern","playful"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"google-pay-icon.svg","brand":"google-pay","variant":"icon","pair":"google-pay.svg","width":256.0,"height":218.0,"aspect":1.174,"aspect_class":"square","bytes":1476,"shapes":5,"anchors":38,"colors":["#ea4335","#fbbc04","#34a853","#4285f4"],"n_colors":4,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"interlocking colored rounded bars","geometry":["freeform"],"techniques":["overlap-transparency","color-segments"],"type_style":null,"case":null,"mood":["dynamic","vibrant"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"google-pay.svg","brand":"google-pay","variant":"main","pair":"google-pay-icon.svg","width":512.0,"height":93.0,"aspect":5.505,"aspect_class":"extra-wide","bytes":5711,"shapes":7,"anchors":169,"colors":["#5f6368","#ea4335","#fbbc04","#34a853","#4285f4"],"n_colors":5,"color_families":["blue","gray","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"interlocking colored rounded bars","geometry":["freeform"],"techniques":["overlap-transparency","color-segments"],"type_style":"geometric-sans","case":"titlecase","mood":["friendly","clean"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"google-photos.svg","brand":"google-photos","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":907,"shapes":5,"anchors":24,"colors":["#fbbb05","#e94335","#4285f4","#0f9d58"],"n_colors":4,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"pinwheel of four half-circles","geometry":["radial","circle"],"techniques":["radial-symmetry","color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["playful","vibrant"],"industry":"media-entertainment","exemplary":true,"note":"Pinwheel from four identical half-circles; pure geometric construction."},{"file":"google-play-icon.svg","brand":"google-play","variant":"icon","pair":"google-play.svg","width":256.0,"height":274.0,"aspect":0.934,"aspect_class":"square","bytes":999,"shapes":5,"anchors":22,"colors":["#ffd900","#f43249","#00ee76","#00d3ff"],"n_colors":4,"color_families":["cyan","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"play triangle in color segments","geometry":["triangle"],"techniques":["color-segments","arrow"],"type_style":null,"case":null,"mood":["vibrant","dynamic"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"google-play.svg","brand":"google-play","variant":"main","pair":"google-play-icon.svg","width":512.0,"height":118.0,"aspect":4.339,"aspect_class":"horizontal","bytes":4744,"shapes":6,"anchors":147,"colors":["#ffd900","#f43249","#00ee76","#00d3ff","#808285"],"n_colors":5,"color_families":["cyan","gray","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"play triangle in color segments","geometry":["triangle"],"techniques":["color-segments","arrow"],"type_style":"geometric-sans","case":"titlecase","mood":["vibrant","friendly"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"google-tag-manager.svg","brand":"google-tag-manager","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1036,"shapes":5,"anchors":25,"colors":["#8ab4f8","#4285f4","#246fdb"],"n_colors":3,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"diamond tag outline","geometry":["diamond"],"techniques":["negative-space","overlap-transparency"],"type_style":null,"case":null,"mood":["technical","clean"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"google.svg","brand":"google","variant":"main","pair":"google-icon.svg","width":512.0,"height":168.0,"aspect":3.048,"aspect_class":"horizontal","bytes":3018,"shapes":7,"anchors":76,"colors":["#ff302f","#20b15a","#3686f7","#ffba40"],"n_colors":4,"color_families":["blue","green","orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"multicolor name in geometric sans","geometry":[],"techniques":["color-segments"],"type_style":"geometric-sans","case":"titlecase","mood":["friendly","playful"],"industry":"other","exemplary":false,"note":""},{"file":"gopher.svg","brand":"gopher","variant":"main","pair":null,"width":256.0,"height":348.0,"aspect":0.736,"aspect_class":"tall","bytes":15333,"shapes":21,"anchors":358,"colors":["#f6d2a2","#69d7e2","#000000","#ffffff","#231f20"],"n_colors":5,"color_families":["black","cyan","orange","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"cartoon gopher with big eyes","geometry":["organic"],"techniques":["hand-drawn"],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"programming-language","exemplary":false,"note":""},{"file":"gradle.svg","brand":"gradle","variant":"main","pair":null,"width":256.0,"height":188.0,"aspect":1.362,"aspect_class":"wide","bytes":2088,"shapes":2,"anchors":49,"colors":["#02303a"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"elephant silhouette","geometry":["organic"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["solid","calm"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"grafana.svg","brand":"grafana","variant":"main","pair":null,"width":256.0,"height":279.0,"aspect":0.918,"aspect_class":"square","bytes":9919,"shapes":2,"anchors":244,"colors":["#fff100","#f05a28"],"n_colors":2,"color_families":["orange","yellow"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"spiral inside flame-like cog","geometry":["radial","organic"],"techniques":["gradient","negative-space"],"type_style":null,"case":null,"mood":["energetic","warm"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"grails.svg","brand":"grails","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":8887,"shapes":2,"anchors":229,"colors":["#feb672"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"grail chalice in circle with name","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":"geometric-sans","case":"uppercase","mood":["warm","classic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"graphene.svg","brand":"graphene","variant":"main","pair":null,"width":256.0,"height":302.0,"aspect":0.848,"aspect_class":"square","bytes":1674,"shapes":10,"anchors":84,"colors":["#f25f3f","#ffaa5b","#eb1919"],"n_colors":3,"color_families":["orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"extruded isometric letter G","geometry":["hexagon"],"techniques":["isometric-3d","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"graphql.svg","brand":"graphql","variant":"main","pair":null,"width":256.0,"height":288.0,"aspect":0.889,"aspect_class":"square","bytes":2608,"shapes":2,"anchors":65,"colors":["#e535ab"],"n_colors":1,"color_families":["pink"],"primary_family":"pink","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"node hexagon with inscribed triangle","geometry":["hexagon","triangle"],"techniques":["line-monoline","radial-symmetry","geometric-construction"],"type_style":null,"case":null,"mood":["technical","precise"],"industry":"programming-language","exemplary":true,"note":"Graph nodes and edges as perfect geometric construction."},{"file":"grav.svg","brand":"grav","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4010,"shapes":2,"anchors":90,"colors":["#221e1f"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"floating astronaut in black circle","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["playful","adventurous"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"gravatar.svg","brand":"gravatar","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":753,"shapes":2,"anchors":16,"colors":["#1e8cbe"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"G like power-button symbol","geometry":["circle"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["simple","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"graylog-icon.svg","brand":"graylog","variant":"icon","pair":"graylog.svg","width":256.0,"height":248.0,"aspect":1.032,"aspect_class":"square","bytes":1781,"shapes":3,"anchors":43,"colors":["#ff3633","#a6afbd"],"n_colors":2,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"waveform inside red ring","geometry":["circle"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["technical","alert"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"graylog.svg","brand":"graylog","variant":"main","pair":"graylog-icon.svg","width":512.0,"height":150.0,"aspect":3.413,"aspect_class":"horizontal","bytes":4312,"shapes":4,"anchors":135,"colors":["#a6afbd","#ff3633"],"n_colors":2,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"two-tone name with waveform accent","geometry":[],"techniques":["color-segments","letter-substitution"],"type_style":"geometric-sans","case":"lowercase","mood":["technical","modern"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"gridsome-icon.svg","brand":"gridsome","variant":"icon","pair":"gridsome.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2933,"shapes":6,"anchors":33,"colors":["#1a7d75","#1a8864","#168a81","#31a97f","#27a59b","#64d8a2"],"n_colors":6,"color_families":["cyan","green"],"primary_family":"multi","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"open G ring with dot","geometry":["circle"],"techniques":["gradient","geometric-construction"],"type_style":null,"case":null,"mood":["fresh","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"gridsome.svg","brand":"gridsome","variant":"main","pair":"gridsome-icon.svg","width":512.0,"height":102.0,"aspect":5.02,"aspect_class":"extra-wide","bytes":9296,"shapes":7,"anchors":221,"colors":["#1f344a","#1a7d75","#1a8864","#168a81","#31a97f","#27a59b","#64d8a2"],"n_colors":7,"color_families":["blue","cyan","green"],"primary_family":"multi","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"open G ring with dot","geometry":["circle"],"techniques":["gradient"],"type_style":"geometric-sans","case":"titlecase","mood":["fresh","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"grommet.svg","brand":"grommet","variant":"main","pair":null,"width":512.0,"height":150.0,"aspect":3.413,"aspect_class":"horizontal","bytes":6229,"shapes":3,"anchors":184,"colors":["#7d4cdb"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"purple ring","geometry":["circle"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","simple"],"industry":"framework-library","exemplary":false,"note":""},{"file":"groovehq.svg","brand":"groovehq","variant":"main","pair":null,"width":512.0,"height":132.0,"aspect":3.879,"aspect_class":"horizontal","bytes":3821,"shapes":3,"anchors":101,"colors":["#0ba0be","#000000"],"n_colors":2,"color_families":["black","cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with smile-shaped g descender","geometry":[],"techniques":["hidden-meaning"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","modern"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"grove.svg","brand":"grove","variant":"main","pair":null,"width":256.0,"height":267.0,"aspect":0.959,"aspect_class":"square","bytes":1778,"shapes":5,"anchors":28,"colors":["#92c83e","#4b843d","#ffffff"],"n_colors":3,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":true,"mark_type":"pictorial","symbol_type":null,"subject":"green peaks in speech bubble","geometry":["circle"],"techniques":["speech-bubble","containment"],"type_style":null,"case":null,"mood":["natural","calm"],"industry":"social-communication","exemplary":false,"note":""},{"file":"grpc.svg","brand":"grpc","variant":"main","pair":null,"width":512.0,"height":208.0,"aspect":2.462,"aspect_class":"wide","bytes":5929,"shapes":5,"anchors":151,"colors":["#244b5a","#72c9c9","#02b0ad","#03b6b4","#74cbca"],"n_colors":5,"color_families":["blue","cyan"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"light name with arrow accent on g","geometry":[],"techniques":["arrow"],"type_style":"geometric-sans","case":"mixed","mood":["technical","light"],"industry":"framework-library","exemplary":false,"note":""},{"file":"grunt.svg","brand":"grunt","variant":"main","pair":null,"width":256.0,"height":344.0,"aspect":0.744,"aspect_class":"tall","bytes":28279,"shapes":73,"anchors":684,"colors":["#fba919","#e78724","#fdc168","#ffffff","#c9c9c9","#463014"],"n_colors":6,"color_families":["gray","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"angry boar face","geometry":["organic"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["aggressive","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"gulp.svg","brand":"gulp","variant":"main","pair":null,"width":256.0,"height":566.0,"aspect":0.452,"aspect_class":"tall","bytes":3632,"shapes":6,"anchors":83,"colors":["#d34a47","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"red cup with straw and script name","geometry":["freeform"],"techniques":["containment"],"type_style":"script","case":"titlecase","mood":["playful","retro"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"gunicorn.svg","brand":"gunicorn","variant":"main","pair":null,"width":256.0,"height":156.0,"aspect":1.641,"aspect_class":"wide","bytes":4151,"shapes":3,"anchors":84,"colors":["#499848","#959595","#cccccc"],"n_colors":3,"color_families":["gray","green"],"primary_family":"green","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"green unicorn silhouette","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["playful","simple"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"gusto.svg","brand":"gusto","variant":"main","pair":null,"width":256.0,"height":250.0,"aspect":1.024,"aspect_class":"square","bytes":2457,"shapes":5,"anchors":52,"colors":["#ef0000"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"G with arrow in sketchy circles","geometry":["circle"],"techniques":["hand-drawn","arrow","line-monoline"],"type_style":null,"case":null,"mood":["friendly","energetic"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"gwt.svg","brand":"gwt","variant":"main","pair":null,"width":256.0,"height":270.0,"aspect":0.948,"aspect_class":"square","bytes":2306,"shapes":6,"anchors":74,"colors":["#f93535","#424242"],"n_colors":2,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"red code bracket shapes","geometry":["freeform"],"techniques":["bracket-code","geometric-construction"],"type_style":"grotesque-sans","case":"uppercase","mood":["bold","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"hack.svg","brand":"hack","variant":"main","pair":null,"width":256.0,"height":381.0,"aspect":0.672,"aspect_class":"tall","bytes":694,"shapes":6,"anchors":22,"colors":["#ffffff","#868686","#f7852f"],"n_colors":3,"color_families":["gray","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"slanted gray and orange parallelograms","geometry":["triangle"],"techniques":["geometric-construction","color-segments"],"type_style":null,"case":null,"mood":["technical","sharp"],"industry":"programming-language","exemplary":false,"note":""},{"file":"hacker-one.svg","brand":"hacker-one","variant":"main","pair":null,"width":256.0,"height":478.0,"aspect":0.536,"aspect_class":"tall","bytes":1221,"shapes":2,"anchors":27,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"split h whose shoulder forms 1","geometry":["freeform"],"techniques":["hidden-meaning","negative-space"],"type_style":null,"case":null,"mood":["bold","minimal"],"industry":"security-identity","exemplary":false,"note":""},{"file":"haiku-icon.svg","brand":"haiku","variant":"icon","pair":null,"width":256.0,"height":295.0,"aspect":0.868,"aspect_class":"square","bytes":3091,"shapes":3,"anchors":65,"colors":["#f1cb2b","#d62b5f"],"n_colors":2,"color_families":["red","yellow"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"folded gradient letter H","geometry":["freeform"],"techniques":["gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["vibrant","creative"],"industry":"design-creative","exemplary":false,"note":""},{"file":"haml.svg","brand":"haml","variant":"main","pair":null,"width":256.0,"height":316.0,"aspect":0.81,"aspect_class":"square","bytes":15544,"shapes":4,"anchors":380,"colors":["#ecdfa7","#3f3e29"],"n_colors":2,"color_families":["yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"wooden slingshot","geometry":["organic"],"techniques":["hand-drawn"],"type_style":null,"case":null,"mood":["quirky","rustic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"hanami.svg","brand":"hanami","variant":"main","pair":null,"width":256.0,"height":262.0,"aspect":0.977,"aspect_class":"square","bytes":1170,"shapes":5,"anchors":34,"colors":["#dc3011","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"layered pentagons with gem in circle","geometry":["freeform","circle"],"techniques":["stacked-layers","containment"],"type_style":null,"case":null,"mood":["warm","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"handlebars.svg","brand":"handlebars","variant":"main","pair":null,"width":512.0,"height":124.0,"aspect":4.129,"aspect_class":"horizontal","bytes":2122,"shapes":2,"anchors":39,"colors":["#423426"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"handlebar mustache","geometry":["organic"],"techniques":["mirror-symmetry","hidden-meaning"],"type_style":null,"case":null,"mood":["witty","simple"],"industry":"framework-library","exemplary":true,"note":"Direct visual pun on the name; single memorable shape."},{"file":"hapi.svg","brand":"hapi","variant":"main","pair":null,"width":512.0,"height":351.0,"aspect":1.459,"aspect_class":"wide","bytes":11082,"shapes":5,"anchors":239,"colors":["#9b99a6","#f79727","#787880","#464646"],"n_colors":4,"color_families":["gray","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"curved node link over wordmark","geometry":["freeform"],"techniques":["line-monoline"],"type_style":"humanist-sans","case":"lowercase","mood":["friendly","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"hardhat-icon.svg","brand":"hardhat","variant":"icon","pair":"hardhat.svg","width":256.0,"height":177.0,"aspect":1.446,"aspect_class":"wide","bytes":3094,"shapes":12,"anchors":80,"colors":["#f0d50c","#fff04d","#ffea00","#6e6f70","#0a0a0a"],"n_colors":5,"color_families":["black","gray","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"yellow hard hat with ether diamond","geometry":["organic"],"techniques":["containment"],"type_style":null,"case":null,"mood":["sturdy","bright"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"hardhat.svg","brand":"hardhat","variant":"main","pair":"hardhat-icon.svg","width":512.0,"height":106.0,"aspect":4.83,"aspect_class":"extra-wide","bytes":5614,"shapes":13,"anchors":185,"colors":["#15191f","#f0d50c","#fff04d","#ffea00","#6e6f70","#0a0a0a"],"n_colors":6,"color_families":["black","blue","gray","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"yellow hard hat with ether diamond","geometry":["organic"],"techniques":["containment"],"type_style":"grotesque-sans","case":"titlecase","mood":["sturdy","bright"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"hashnode-icon.svg","brand":"hashnode","variant":"icon","pair":"hashnode.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":807,"shapes":2,"anchors":15,"colors":["#2962ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"rounded diamond with circular hole","geometry":["diamond","circle"],"techniques":["negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["simple","modern"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"hashnode.svg","brand":"hashnode","variant":"main","pair":"hashnode-icon.svg","width":512.0,"height":88.0,"aspect":5.818,"aspect_class":"extra-wide","bytes":4344,"shapes":3,"anchors":137,"colors":["#2962ff","#000000"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"rounded diamond with circular hole","geometry":["diamond"],"techniques":["negative-space"],"type_style":"grotesque-sans","case":"lowercase","mood":["modern","clean"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"haskell-icon.svg","brand":"haskell","variant":"icon","pair":"haskell.svg","width":256.0,"height":181.0,"aspect":1.414,"aspect_class":"wide","bytes":634,"shapes":4,"anchors":27,"colors":["#453a62","#5e5086","#8f4e8b"],"n_colors":3,"color_families":["pink","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"chevron, lambda and equals operator","geometry":["triangle"],"techniques":["hidden-meaning","geometric-construction","color-segments"],"type_style":null,"case":null,"mood":["technical","precise"],"industry":"programming-language","exemplary":true,"note":"Encodes the bind operator and lambda in one geometric mark."},{"file":"haskell.svg","brand":"haskell","variant":"main","pair":"haskell-icon.svg","width":512.0,"height":78.0,"aspect":6.564,"aspect_class":"extra-wide","bytes":6477,"shapes":5,"anchors":198,"colors":["#333333","#453a62","#5e5086","#8f4e8b"],"n_colors":4,"color_families":["gray","pink","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"chevron, lambda and equals operator","geometry":["triangle"],"techniques":["hidden-meaning","geometric-construction"],"type_style":"grotesque-sans","case":"titlecase","mood":["technical","bold"],"industry":"programming-language","exemplary":false,"note":""},{"file":"hasura.svg","brand":"hasura","variant":"main","pair":null,"width":256.0,"height":305.0,"aspect":0.839,"aspect_class":"square","bytes":1801,"shapes":4,"anchors":37,"colors":["#ffc627","#232323"],"n_colors":2,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"horned circle with lambda","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["bold","playful"],"industry":"database-data","exemplary":false,"note":""},{"file":"haxe.svg","brand":"haxe","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1543,"shapes":14,"anchors":65,"colors":["#fbc707","#f68712","#f25c19","#fff200","#f1471d","#fab20b","#f47216","#f89c0e"],"n_colors":8,"color_families":["orange","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"faceted square of orange triangles","geometry":["square","triangle"],"techniques":["color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["energetic","warm"],"industry":"programming-language","exemplary":false,"note":""},{"file":"haxl.svg","brand":"haxl","variant":"main","pair":null,"width":256.0,"height":325.0,"aspect":0.788,"aspect_class":"tall","bytes":646,"shapes":2,"anchors":29,"colors":["#4e69a2"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"X merged with lambda from slanted bars","geometry":["freeform"],"techniques":["geometric-construction","hidden-meaning"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"hbase.svg","brand":"hbase","variant":"main","pair":null,"width":256.0,"height":202.0,"aspect":1.267,"aspect_class":"wide","bytes":5966,"shapes":2,"anchors":129,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"orca whale","geometry":["organic"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["strong","dynamic"],"industry":"database-data","exemplary":false,"note":""},{"file":"headlessui-icon.svg","brand":"headlessui","variant":"icon","pair":"headlessui.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2902,"shapes":3,"anchors":49,"colors":["#66e3ff","#7064f9"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"tilted panel inside rounded square frame","geometry":["rounded-square"],"techniques":["gradient","containment"],"type_style":null,"case":null,"mood":["modern","fresh"],"industry":"framework-library","exemplary":false,"note":""},{"file":"headlessui.svg","brand":"headlessui","variant":"main","pair":"headlessui-icon.svg","width":512.0,"height":90.0,"aspect":5.689,"aspect_class":"extra-wide","bytes":7920,"shapes":5,"anchors":226,"colors":["#111827","#66e3ff","#7064f9"],"n_colors":3,"color_families":["blue","cyan"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"tilted panel inside rounded square frame","geometry":["rounded-square"],"techniques":["gradient","containment"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","clean"],"industry":"framework-library","exemplary":false,"note":""},{"file":"heap.svg","brand":"heap","variant":"main","pair":null,"width":256.0,"height":296.0,"aspect":0.865,"aspect_class":"square","bytes":860,"shapes":2,"anchors":27,"colors":["#f37c27","#ed3774"],"n_colors":2,"color_families":["orange","red"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"hexagon outline with notched segment","geometry":["hexagon"],"techniques":["gradient","negative-space"],"type_style":null,"case":null,"mood":["modern","vibrant"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"helm.svg","brand":"helm","variant":"main","pair":null,"width":256.0,"height":297.0,"aspect":0.862,"aspect_class":"square","bytes":10936,"shapes":3,"anchors":423,"colors":["#0f1689"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"ship wheel around name","geometry":["circle","radial"],"techniques":["radial-symmetry","containment"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","nautical"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"helpscout-icon.svg","brand":"helpscout","variant":"icon","pair":"helpscout.svg","width":256.0,"height":310.0,"aspect":0.826,"aspect_class":"square","bytes":931,"shapes":2,"anchors":21,"colors":["#1292ee"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two pairs of slanted rounded bars","geometry":["freeform"],"techniques":["modular-repetition","motion-lines"],"type_style":null,"case":null,"mood":["friendly","dynamic"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"helpscout.svg","brand":"helpscout","variant":"main","pair":"helpscout-icon.svg","width":512.0,"height":102.0,"aspect":5.02,"aspect_class":"extra-wide","bytes":6357,"shapes":3,"anchors":206,"colors":["#2a3b47","#1292ee"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"two pairs of slanted rounded bars","geometry":["freeform"],"techniques":["modular-repetition"],"type_style":"grotesque-sans","case":"titlecase","mood":["friendly","clean"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"hermes.svg","brand":"hermes","variant":"main","pair":null,"width":256.0,"height":197.0,"aspect":1.299,"aspect_class":"wide","bytes":6723,"shapes":5,"anchors":248,"colors":["#2bb673","#3d3d3d"],"n_colors":2,"color_families":["gray","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"winged letter H","geometry":["freeform"],"techniques":["hidden-meaning"],"type_style":null,"case":null,"mood":["fast","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"heroku-icon.svg","brand":"heroku","variant":"icon","pair":"heroku.svg","width":256.0,"height":285.0,"aspect":0.898,"aspect_class":"square","bytes":1311,"shapes":2,"anchors":49,"colors":["#430098"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"stylized h in rounded square","geometry":["rounded-square"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["technical","calm"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"heroku-redis.svg","brand":"heroku-redis","variant":"main","pair":null,"width":256.0,"height":304.0,"aspect":0.842,"aspect_class":"square","bytes":1218,"shapes":2,"anchors":27,"colors":["#283174"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"R with solid keyhole half","geometry":["freeform"],"techniques":["negative-space","line-monoline"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"database-data","exemplary":false,"note":""},{"file":"heroku.svg","brand":"heroku","variant":"main","pair":"heroku-icon.svg","width":512.0,"height":144.0,"aspect":3.556,"aspect_class":"horizontal","bytes":2778,"shapes":3,"anchors":126,"colors":["#430098"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"stylized h in rounded square","geometry":["rounded-square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","calm"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"hexo.svg","brand":"hexo","variant":"main","pair":null,"width":256.0,"height":295.0,"aspect":0.868,"aspect_class":"square","bytes":776,"shapes":3,"anchors":33,"colors":["#0e83cd","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"letter H in hexagon","geometry":["hexagon"],"techniques":["containment"],"type_style":null,"case":null,"mood":["simple","solid"],"industry":"framework-library","exemplary":false,"note":""},{"file":"hhvm.svg","brand":"hhvm","variant":"main","pair":null,"width":256.0,"height":382.0,"aspect":0.67,"aspect_class":"tall","bytes":779,"shapes":7,"anchors":26,"colors":["#ffffff","#878787","#f7852f"],"n_colors":3,"color_families":["gray","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"slanted gray and orange parallelograms","geometry":["triangle"],"techniques":["geometric-construction","color-segments"],"type_style":null,"case":null,"mood":["technical","sharp"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"hibernate.svg","brand":"hibernate","variant":"main","pair":null,"width":256.0,"height":267.0,"aspect":0.959,"aspect_class":"square","bytes":715,"shapes":5,"anchors":24,"colors":["#59666c","#bcae79"],"n_colors":2,"color_families":["gray","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"hexagonal ring of shaded parallelograms","geometry":["hexagon"],"techniques":["isometric-3d","negative-space","dimensional-shading"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"highcharts.svg","brand":"highcharts","variant":"main","pair":null,"width":256.0,"height":243.0,"aspect":1.053,"aspect_class":"square","bytes":901,"shapes":7,"anchors":37,"colors":["#78758c","#a3edba","#8087e8","#30426b","#6699a1"],"n_colors":5,"color_families":["blue","cyan","gray","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"overlapping translucent triangles","geometry":["triangle"],"techniques":["overlap-transparency"],"type_style":null,"case":null,"mood":["modern","light"],"industry":"framework-library","exemplary":false,"note":""},{"file":"hipercard.svg","brand":"hipercard","variant":"main","pair":null,"width":512.0,"height":223.0,"aspect":2.296,"aspect_class":"wide","bytes":5092,"shapes":3,"anchors":127,"colors":["#b82126","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"italic name in red slanted box","geometry":["freeform"],"techniques":["containment"],"type_style":"humanist-sans","case":"titlecase","mood":["dynamic","bold"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"hoa.svg","brand":"hoa","variant":"main","pair":null,"width":512.0,"height":184.0,"aspect":2.783,"aspect_class":"horizontal","bytes":3096,"shapes":7,"anchors":102,"colors":["#424a52","#fa8a75"],"n_colors":2,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"HOA from modular bracket blocks","geometry":["grid-modular"],"techniques":["modular-repetition","color-segments"],"type_style":"display-custom","case":"uppercase","mood":["technical","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"homebrew.svg","brand":"homebrew","variant":"main","pair":null,"width":164.0,"height":256.0,"aspect":0.641,"aspect_class":"tall","bytes":15783,"shapes":7,"anchors":481,"colors":["#d1d2d3","#fefefe","#faaf41","#ffda95","#010202"],"n_colors":5,"color_families":["black","gray","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"beer mug with apple-stem foam","geometry":["organic"],"techniques":["hand-drawn","hidden-meaning"],"type_style":null,"case":null,"mood":["friendly","warm"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"hoodie.svg","brand":"hoodie","variant":"main","pair":null,"width":512.0,"height":119.0,"aspect":4.303,"aspect_class":"horizontal","bytes":7622,"shapes":12,"anchors":203,"colors":["#e94e1b"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"overlapping outlined letters","geometry":[],"techniques":["line-monoline","overlap-transparency"],"type_style":"display-custom","case":"uppercase","mood":["playful","light"],"industry":"framework-library","exemplary":false,"note":""},{"file":"hosted-graphite.svg","brand":"hosted-graphite","variant":"main","pair":null,"width":256.0,"height":294.0,"aspect":0.871,"aspect_class":"square","bytes":618,"shapes":2,"anchors":22,"colors":["#ec7a51"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"H cut from orange hexagon","geometry":["hexagon"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"hostgator-icon.svg","brand":"hostgator","variant":"icon","pair":"hostgator.svg","width":256.0,"height":355.0,"aspect":0.721,"aspect_class":"tall","bytes":12672,"shapes":42,"anchors":276,"colors":["#2e93ee","#2e578b","#ffcf00","#eca93f","#ff9144","#f1f1f2","#ff6b17","#ebeef2"],"n_colors":8,"color_families":["blue","orange","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"grinning blue alligator","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"hostgator.svg","brand":"hostgator","variant":"main","pair":"hostgator-icon.svg","width":512.0,"height":92.0,"aspect":5.565,"aspect_class":"extra-wide","bytes":16493,"shapes":43,"anchors":410,"colors":["#1f2044","#2e93ee","#2e578b","#ffcf00","#eca93f","#ff9144","#f1f1f2","#ff6b17","#ebeef2"],"n_colors":9,"color_families":["blue","orange","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"grinning blue alligator","geometry":["organic"],"techniques":[],"type_style":"grotesque-sans","case":"mixed","mood":["playful","bold"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"hotjar.svg","brand":"hotjar","variant":"main","pair":null,"width":512.0,"height":246.0,"aspect":2.081,"aspect_class":"wide","bytes":4123,"shapes":3,"anchors":118,"colors":["#1d1d1b","#fd3a5c"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold name with flame accent","geometry":[],"techniques":["letter-substitution"],"type_style":"grotesque-sans","case":"lowercase","mood":["bold","warm"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"houndci.svg","brand":"houndci","variant":"main","pair":null,"width":256.0,"height":251.0,"aspect":1.02,"aspect_class":"square","bytes":734,"shapes":2,"anchors":18,"colors":["#a873d1"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"dog head profile cut into square","geometry":["square"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["clever","calm"],"industry":"developer-tools","exemplary":true,"note":"Dog profile formed purely by negative space in square."},{"file":"html-5.svg","brand":"html-5","variant":"main","pair":null,"width":256.0,"height":361.0,"aspect":0.709,"aspect_class":"tall","bytes":1493,"shapes":11,"anchors":94,"colors":["#e44d26","#f16529","#ebebeb","#000000","#ffffff"],"n_colors":5,"color_families":["black","orange","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"emblem","subject":"shield with numeral 5 under name","geometry":["shield"],"techniques":["containment","dimensional-shading"],"type_style":"grotesque-sans","case":"uppercase","mood":["bold","official"],"industry":"programming-language","exemplary":false,"note":""},{"file":"html5-boilerplate.svg","brand":"html5-boilerplate","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":919,"shapes":7,"anchors":36,"colors":["#222222","#e08524","#466770","#304a51"],"n_colors":4,"color_families":["black","cyan","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"extruded orange star in dark square","geometry":["star","square"],"techniques":["dimensional-shading","containment"],"type_style":null,"case":null,"mood":["bold","retro"],"industry":"framework-library","exemplary":false,"note":""},{"file":"httpie-icon.svg","brand":"httpie","variant":"icon","pair":"httpie.svg","width":256.0,"height":306.0,"aspect":0.837,"aspect_class":"square","bytes":950,"shapes":2,"anchors":19,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"black organic blob pair","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["bold","quirky"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"httpie.svg","brand":"httpie","variant":"main","pair":"httpie-icon.svg","width":512.0,"height":148.0,"aspect":3.459,"aspect_class":"horizontal","bytes":7641,"shapes":3,"anchors":252,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"black organic blob pair","geometry":["organic"],"techniques":[],"type_style":"grotesque-sans","case":"lowercase","mood":["bold","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"hubspot.svg","brand":"hubspot","variant":"main","pair":null,"width":512.0,"height":149.0,"aspect":3.436,"aspect_class":"horizontal","bytes":4529,"shapes":8,"anchors":133,"colors":["#45535e","#f8761f"],"n_colors":2,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with sprocket replacing o","geometry":[],"techniques":["letter-substitution"],"type_style":"humanist-sans","case":"mixed","mood":["friendly","approachable"],"industry":"marketing-analytics","exemplary":true,"note":"Textbook letter substitution: sprocket node graph as the o."},{"file":"huggy.svg","brand":"huggy","variant":"main","pair":null,"width":512.0,"height":72.0,"aspect":7.111,"aspect_class":"extra-wide","bytes":4735,"shapes":3,"anchors":136,"colors":["#050000","#ff0069","#4707ff"],"n_colors":3,"color_families":["black","purple","red"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"dashed pink speed lines","geometry":[],"techniques":["motion-lines"],"type_style":"geometric-sans","case":"uppercase","mood":["energetic","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"hugo.svg","brand":"hugo","variant":"main","pair":null,"width":512.0,"height":134.0,"aspect":3.821,"aspect_class":"horizontal","bytes":250970,"shapes":13,"anchors":16212,"colors":["#ff4088","#c9177e","#ffffff","#0594cb","#0083c0","#33ba91","#00a88a","#ebb951","#fcd804"],"n_colors":9,"color_families":["blue","cyan","green","pink","red","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"letters in colored hexagon badges","geometry":["hexagon"],"techniques":["containment","modular-repetition","color-segments"],"type_style":"rounded-sans","case":"uppercase","mood":["playful","vibrant"],"industry":"framework-library","exemplary":false,"note":""},{"file":"humongous.svg","brand":"humongous","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":3742,"shapes":2,"anchors":76,"colors":["#373737"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"offset heavy letter H","geometry":["freeform"],"techniques":[],"type_style":null,"case":null,"mood":["bold","quirky"],"industry":"database-data","exemplary":false,"note":""},{"file":"hyper.svg","brand":"hyper","variant":"main","pair":null,"width":256.0,"height":224.0,"aspect":1.143,"aspect_class":"square","bytes":1381,"shapes":4,"anchors":39,"colors":["#000000","#ffffff","#ffb300","#dc3939","#ff1bb4"],"n_colors":5,"color_families":["black","pink","red","white","yellow"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"terminal window with bolt prompt","geometry":["rounded-square"],"techniques":["gradient","containment","bracket-code"],"type_style":null,"case":null,"mood":["technical","vibrant"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"hyperapp.svg","brand":"hyperapp","variant":"main","pair":null,"width":512.0,"height":119.0,"aspect":4.303,"aspect_class":"horizontal","bytes":3879,"shapes":3,"anchors":145,"colors":["#000000","#0080ff"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"plus and backslash glyphs","geometry":[],"techniques":["bracket-code"],"type_style":"monospace","case":"lowercase","mood":["technical","minimal"],"industry":"framework-library","exemplary":false,"note":""},{"file":"ibm.svg","brand":"ibm","variant":"main","pair":null,"width":512.0,"height":205.0,"aspect":2.498,"aspect_class":"wide","bytes":2558,"shapes":2,"anchors":193,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"striped IBM letters","geometry":["grid-modular"],"techniques":["modular-repetition","motion-lines"],"type_style":"slab","case":"uppercase","mood":["corporate","iconic"],"industry":"hardware-devices","exemplary":true,"note":"Horizontal stripes unify heavy slab letters; timeless lettermark."},{"file":"ieee.svg","brand":"ieee","variant":"main","pair":null,"width":512.0,"height":150.0,"aspect":3.413,"aspect_class":"horizontal","bytes":3941,"shapes":2,"anchors":132,"colors":["#1a1918"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"diamond with kite arrow emblem","geometry":["diamond"],"techniques":["containment","arrow"],"type_style":"grotesque-sans","case":"uppercase","mood":["official","serious"],"industry":"education","exemplary":false,"note":""},{"file":"ifttt.svg","brand":"ifttt","variant":"main","pair":null,"width":512.0,"height":136.0,"aspect":3.765,"aspect_class":"horizontal","bytes":618,"shapes":2,"anchors":46,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy stencil-like name","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"uppercase","mood":["bold","utilitarian"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"imagemin.svg","brand":"imagemin","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":18813,"shapes":9,"anchors":454,"colors":["#ffffff","#447cad","#ebedf4","#ecf7f9","#dbf0f6","#6cc077","#87c3e8","#bab9d6","#76a1c4"],"n_colors":9,"color_families":["blue","cyan","green","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":true,"mark_type":"pictorial","symbol_type":null,"subject":"landscape photo with compress arrows in circle","geometry":["circle"],"techniques":["containment","arrow"],"type_style":null,"case":null,"mood":["friendly","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"imba-icon.svg","brand":"imba","variant":"icon","pair":"imba.svg","width":256.0,"height":216.0,"aspect":1.185,"aspect_class":"square","bytes":579,"shapes":2,"anchors":7,"colors":["#16cec6"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"swooping cyan wing arrow","geometry":["organic"],"techniques":["arrow","motion-lines"],"type_style":null,"case":null,"mood":["fast","fresh"],"industry":"programming-language","exemplary":false,"note":""},{"file":"imba.svg","brand":"imba","variant":"main","pair":"imba-icon.svg","width":512.0,"height":135.0,"aspect":3.793,"aspect_class":"horizontal","bytes":5714,"shapes":3,"anchors":148,"colors":["#273240","#16cec6"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"swooping cyan wing arrow","geometry":["organic"],"techniques":["arrow"],"type_style":"grotesque-sans","case":"lowercase","mood":["fast","bold"],"industry":"programming-language","exemplary":false,"note":""},{"file":"immer-icon.svg","brand":"immer","variant":"icon","pair":"immer.svg","width":256.0,"height":145.0,"aspect":1.766,"aspect_class":"wide","bytes":2047,"shapes":2,"anchors":43,"colors":["#00e7c3"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"infinity loop with dots","geometry":["organic"],"techniques":["infinity-loop","mirror-symmetry"],"type_style":null,"case":null,"mood":["fresh","simple"],"industry":"framework-library","exemplary":false,"note":""},{"file":"immer.svg","brand":"immer","variant":"main","pair":"immer-icon.svg","width":512.0,"height":314.0,"aspect":1.631,"aspect_class":"wide","bytes":4589,"shapes":2,"anchors":141,"colors":["#00e7c3","#000000"],"n_colors":2,"color_families":["black","cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"infinity loop with dots","geometry":["organic"],"techniques":["infinity-loop","mirror-symmetry"],"type_style":"geometric-sans","case":"lowercase","mood":["fresh","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"immutable.svg","brand":"immutable","variant":"main","pair":null,"width":512.0,"height":73.0,"aspect":7.014,"aspect_class":"extra-wide","bytes":6861,"shapes":3,"anchors":367,"colors":["#fc4349","#2c3e50"],"n_colors":2,"color_families":["blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with offset inline shadow","geometry":[],"techniques":["stacked-layers"],"type_style":"display-custom","case":"uppercase","mood":["retro","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"impala.svg","brand":"impala","variant":"main","pair":null,"width":256.0,"height":613.0,"aspect":0.418,"aspect_class":"tall","bytes":3351,"shapes":2,"anchors":67,"colors":["#2c6791"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"pair of curved antelope horns","geometry":["organic"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["elegant","dynamic"],"industry":"database-data","exemplary":false,"note":""},{"file":"importio.svg","brand":"importio","variant":"main","pair":null,"width":512.0,"height":96.0,"aspect":5.333,"aspect_class":"extra-wide","bytes":2210,"shapes":2,"anchors":95,"colors":["#3138b0"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name in bold display letters","geometry":[],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["technical","playful"],"industry":"database-data","exemplary":false,"note":""},{"file":"infer.svg","brand":"infer","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":773,"shapes":3,"anchors":17,"colors":["#7d29e4","#ffffff"],"n_colors":2,"color_families":["purple","white"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"logic turnstile in purple circle","geometry":["circle"],"techniques":["containment","line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["minimal","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"inferno.svg","brand":"inferno","variant":"main","pair":null,"width":256.0,"height":266.0,"aspect":0.962,"aspect_class":"square","bytes":1573,"shapes":3,"anchors":29,"colors":["#494949","#fb3239"],"n_colors":2,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"flame inside dark ring","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["fiery","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"influxdb.svg","brand":"influxdb","variant":"main","pair":null,"width":256.0,"height":261.0,"aspect":0.981,"aspect_class":"square","bytes":2371,"shapes":2,"anchors":70,"colors":["#292933"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"polyhedron outline in rounded hexagon","geometry":["hexagon"],"techniques":["isometric-3d","line-monoline","geometric-construction"],"type_style":null,"case":null,"mood":["technical","solid"],"industry":"database-data","exemplary":false,"note":""},{"file":"ink.svg","brand":"ink","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2466,"shapes":13,"anchors":80,"colors":["#f6b937","#ffd500","#fff67d","#5acda5","#afe682","#7dd769","#aadc50","#dc4b1e","#aabe55","#db221a","#9e020b","#87d152","#5ca82c","#39be90","#2c8a72"],"n_colors":15,"color_families":["green","red","yellow"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"overlapping multicolor faceted cubes","geometry":["freeform"],"techniques":["overlap-transparency","color-segments"],"type_style":null,"case":null,"mood":["vibrant","creative"],"industry":"framework-library","exemplary":false,"note":""},{"file":"insomnia.svg","brand":"insomnia","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1450,"shapes":4,"anchors":24,"colors":["#ffffff","#4000bf","#7400e1"],"n_colors":3,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"eclipse-like circle in purple ring","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["calm","nocturnal"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"instagram-icon.svg","brand":"instagram","variant":"icon","pair":"instagram.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3067,"shapes":2,"anchors":65,"colors":["#0a0a08"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"camera outline glyph","geometry":["rounded-square","circle"],"techniques":["line-monoline","geometric-construction"],"type_style":null,"case":null,"mood":["simple","friendly"],"industry":"social-communication","exemplary":true,"note":"Camera reduced to three primitives; strong monoline glyph."},{"file":"instagram.svg","brand":"instagram","variant":"main","pair":"instagram-icon.svg","width":512.0,"height":146.0,"aspect":3.507,"aspect_class":"horizontal","bytes":9928,"shapes":3,"anchors":210,"colors":["#343433"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"handwritten script name","geometry":[],"techniques":["hand-drawn"],"type_style":"script","case":"titlecase","mood":["casual","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"intellij-idea.svg","brand":"intellij-idea","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3251,"shapes":7,"anchors":64,"colors":["#000000","#ffffff","#f97a12","#b07b58","#577bae","#1e7ce5","#087cfa","#cb7a3e","#9e7b6a","#757b91","#537bb1","#387ccc","#237ce0","#147cef","#0b7cf7","#fe315d","#cb417e","#9e4e9b","#755bb4","#5365ca","#386ddb","#2374e9","#1478f3","#0b7bf8","#f63462","#df3a71","#c24383","#ad4a91","#1d76ed"],"n_colors":29,"color_families":["black","blue","gray","orange","pink","purple","red","white"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"IJ in black square over gradient shards","geometry":["square"],"techniques":["gradient","overlap-transparency","containment"],"type_style":"grotesque-sans","case":"uppercase","mood":["technical","vibrant"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"intercom-icon.svg","brand":"intercom","variant":"icon","pair":"intercom.svg","width":256.0,"height":263.0,"aspect":0.973,"aspect_class":"square","bytes":3842,"shapes":2,"anchors":92,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"vertical bars forming smiling face","geometry":["rounded-square"],"techniques":["hidden-meaning","containment","modular-repetition"],"type_style":null,"case":null,"mood":["friendly","simple"],"industry":"social-communication","exemplary":true,"note":"Plain bars read as a smiling face; simple dual meaning."},{"file":"intercom.svg","brand":"intercom","variant":"main","pair":"intercom-icon.svg","width":512.0,"height":130.0,"aspect":3.938,"aspect_class":"horizontal","bytes":8156,"shapes":2,"anchors":233,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"vertical bars forming smiling face","geometry":["rounded-square"],"techniques":["hidden-meaning","containment"],"type_style":"geometric-sans","case":"uppercase","mood":["friendly","clean"],"industry":"social-communication","exemplary":false,"note":""},{"file":"internetexplorer.svg","brand":"internetexplorer","variant":"main","pair":null,"width":256.0,"height":252.0,"aspect":1.016,"aspect_class":"square","bytes":2490,"shapes":2,"anchors":52,"colors":["#1ebbee"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"lowercase e with orbit swoosh","geometry":["circle"],"techniques":["overlap-transparency","motion-lines"],"type_style":null,"case":null,"mood":["dynamic","familiar"],"industry":"os-platform","exemplary":false,"note":""},{"file":"invision-icon.svg","brand":"invision","variant":"icon","pair":"invision.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1679,"shapes":4,"anchors":46,"colors":["#ff0066","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"script in lettering in pink square","geometry":["square"],"techniques":["containment"],"type_style":"display-custom","case":"lowercase","mood":["bold","creative"],"industry":"design-creative","exemplary":false,"note":""},{"file":"invision.svg","brand":"invision","variant":"main","pair":"invision-icon.svg","width":512.0,"height":175.0,"aspect":2.926,"aspect_class":"horizontal","bytes":3044,"shapes":4,"anchors":100,"colors":["#ff0066","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"boxed in plus uppercase vision","geometry":[],"techniques":["containment"],"type_style":"display-custom","case":"mixed","mood":["bold","creative"],"industry":"design-creative","exemplary":false,"note":""},{"file":"ionic-icon.svg","brand":"ionic","variant":"icon","pair":"ionic.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1370,"shapes":2,"anchors":31,"colors":["#3880ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"dot in ring with satellite dot","geometry":["circle"],"techniques":["geometric-construction","containment"],"type_style":null,"case":null,"mood":["clean","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"ionic.svg","brand":"ionic","variant":"main","pair":"ionic-icon.svg","width":512.0,"height":173.0,"aspect":2.96,"aspect_class":"horizontal","bytes":2748,"shapes":3,"anchors":78,"colors":["#3880ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"dot in ring with satellite dot","geometry":["circle"],"techniques":["geometric-construction"],"type_style":"geometric-sans","case":"lowercase","mood":["clean","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"ios.svg","brand":"ios","variant":"main","pair":null,"width":257.0,"height":128.0,"aspect":2.008,"aspect_class":"wide","bytes":1590,"shapes":2,"anchors":38,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"camel-case OS name","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"mixed","mood":["clean","neutral"],"industry":"os-platform","exemplary":false,"note":""},{"file":"iron-icon.svg","brand":"iron","variant":"icon","pair":"iron.svg","width":256.0,"height":289.0,"aspect":0.886,"aspect_class":"square","bytes":2093,"shapes":2,"anchors":74,"colors":["#3177bc"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"I-beam letter in hexagon","geometry":["hexagon"],"techniques":["containment","line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["solid","industrial"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"iron.svg","brand":"iron","variant":"main","pair":"iron-icon.svg","width":512.0,"height":173.0,"aspect":2.96,"aspect_class":"horizontal","bytes":3853,"shapes":4,"anchors":117,"colors":["#3177bc","#2e343c"],"n_colors":2,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"I-beam letter in hexagon","geometry":["hexagon"],"techniques":["containment"],"type_style":"geometric-sans","case":"titlecase","mood":["solid","industrial"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"itsalive-icon.svg","brand":"itsalive","variant":"icon","pair":"itsalive.svg","width":256.0,"height":253.0,"aspect":1.012,"aspect_class":"square","bytes":1128,"shapes":2,"anchors":27,"colors":["#5146f9"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"speech bubble with lightning bolt","geometry":["circle"],"techniques":["speech-bubble","negative-space"],"type_style":null,"case":null,"mood":["energetic","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"itsalive.svg","brand":"itsalive","variant":"main","pair":"itsalive-icon.svg","width":512.0,"height":133.0,"aspect":3.85,"aspect_class":"horizontal","bytes":8658,"shapes":2,"anchors":226,"colors":["#5146f9"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"speech bubble with lightning bolt","geometry":["circle"],"techniques":["speech-bubble"],"type_style":"geometric-sans","case":"lowercase","mood":["energetic","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"jade.svg","brand":"jade","variant":"main","pair":null,"width":256.0,"height":388.0,"aspect":0.66,"aspect_class":"tall","bytes":14168,"shapes":3,"anchors":341,"colors":["#569a83","#c1272d"],"n_colors":2,"color_families":["green","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"rabbit in rough stamp with name","geometry":["square"],"techniques":["hand-drawn","negative-space","containment"],"type_style":"display-custom","case":"uppercase","mood":["rustic","traditional"],"industry":"framework-library","exemplary":false,"note":""},{"file":"jamstack-icon.svg","brand":"jamstack","variant":"icon","pair":"jamstack.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":640,"shapes":3,"anchors":21,"colors":["#f0047f","#ffffff"],"n_colors":2,"color_families":["pink","white"],"primary_family":"pink","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"drop-shaped circle with quadrant grid","geometry":["circle","grid-modular"],"techniques":["geometric-construction","negative-space"],"type_style":null,"case":null,"mood":["modern","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"jamstack.svg","brand":"jamstack","variant":"main","pair":"jamstack-icon.svg","width":512.0,"height":98.0,"aspect":5.224,"aspect_class":"extra-wide","bytes":3816,"shapes":4,"anchors":141,"colors":["#ffffff","#f0047f"],"n_colors":2,"color_families":["pink","white"],"primary_family":"pink","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"drop-shaped circle with quadrant grid","geometry":["circle"],"techniques":["geometric-construction","negative-space"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","clean"],"industry":"developer-tools","exemplary":false,"note":"White wordmark invisible on light backgrounds."},{"file":"jasmine.svg","brand":"jasmine","variant":"main","pair":null,"width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":1860,"shapes":12,"anchors":70,"colors":["#8a4182"],"n_colors":1,"color_families":["pink"],"primary_family":"pink","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"radial burst in purple ring","geometry":["circle","radial"],"techniques":["radial-symmetry","containment"],"type_style":null,"case":null,"mood":["fresh","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"java.svg","brand":"java","variant":"main","pair":null,"width":256.0,"height":346.0,"aspect":0.74,"aspect_class":"tall","bytes":2372,"shapes":9,"anchors":45,"colors":["#5382a1","#e76f00"],"n_colors":2,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"steaming coffee cup","geometry":["organic"],"techniques":["motion-lines"],"type_style":null,"case":null,"mood":["warm","classic"],"industry":"programming-language","exemplary":false,"note":""},{"file":"javascript.svg","brand":"javascript","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1236,"shapes":4,"anchors":31,"colors":["#f7df1e","#000000"],"n_colors":2,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"JS in yellow square","geometry":["square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","simple"],"industry":"programming-language","exemplary":false,"note":""},{"file":"jcb.svg","brand":"jcb","variant":"main","pair":null,"width":256.0,"height":198.0,"aspect":1.293,"aspect_class":"wide","bytes":3966,"shapes":7,"anchors":72,"colors":["#ffffff","#007940","#00873f","#40a737","#5cb531","#1f286f","#004e94","#0066b1","#006fbc","#6c2c2f","#882730","#be1833","#dc0436","#e60039"],"n_colors":14,"color_families":["blue","green","red","white"],"primary_family":"multi","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"JCB on three colored panels","geometry":["rounded-square"],"techniques":["color-segments","gradient","containment"],"type_style":"grotesque-sans","case":"uppercase","mood":["corporate","bold"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"jekyll.svg","brand":"jekyll","variant":"main","pair":null,"width":512.0,"height":209.0,"aspect":2.45,"aspect_class":"wide","bytes":14574,"shapes":13,"anchors":300,"colors":["#000000","#333333","#ffffff","#919191","#990000","#e80000","#1a1a1a","#4a4a4c"],"n_colors":8,"color_families":["black","gray","red","white"],"primary_family":"red","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"script name with test tube l","geometry":[],"techniques":["letter-substitution"],"type_style":"script","case":"lowercase","mood":["elegant","quirky"],"industry":"framework-library","exemplary":false,"note":""},{"file":"jelastic-icon.svg","brand":"jelastic","variant":"icon","pair":"jelastic.svg","width":256.0,"height":289.0,"aspect":0.886,"aspect_class":"square","bytes":2049,"shapes":6,"anchors":67,"colors":["#0064c8","#0056b3","#0088fb","#00acff"],"n_colors":4,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric folded shape with diamond hole","geometry":["diamond"],"techniques":["isometric-3d","negative-space","gradient"],"type_style":null,"case":null,"mood":["technical","modern"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"jelastic.svg","brand":"jelastic","variant":"main","pair":"jelastic-icon.svg","width":512.0,"height":124.0,"aspect":4.129,"aspect_class":"horizontal","bytes":7227,"shapes":7,"anchors":221,"colors":["#5e6981","#0987f7","#0064c8","#0056b3","#0088fb","#00acff"],"n_colors":6,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"isometric folded shape with diamond hole","geometry":["diamond"],"techniques":["isometric-3d","gradient"],"type_style":"grotesque-sans","case":"titlecase","mood":["technical","modern"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"jenkins.svg","brand":"jenkins","variant":"main","pair":null,"width":256.0,"height":417.0,"aspect":0.614,"aspect_class":"tall","bytes":33399,"shapes":66,"anchors":900,"colors":["#d33833","#ef3d3a","#231f20","#f0d6b7","#335061","#6d6b6d","#dcd9d8","#f7e4cd","#49728b","#ffffff","#000000","#81b0c4","#1d1919"],"n_colors":13,"color_families":["black","blue","gray","orange","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"butler with bow tie in circle","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["friendly","classic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"jest.svg","brand":"jest","variant":"main","pair":null,"width":256.0,"height":283.0,"aspect":0.905,"aspect_class":"square","bytes":5073,"shapes":3,"anchors":117,"colors":["#99425b","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"jester boot with bells","geometry":["triangle"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["playful","quirky"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"jetbrains.svg","brand":"jetbrains","variant":"main","pair":null,"width":256.0,"height":214.0,"aspect":1.196,"aspect_class":"square","bytes":4737,"shapes":6,"anchors":162,"colors":["#000000","#ffffff","#aa4a9b","#f05922","#ffe42e","#ed417c"],"n_colors":6,"color_families":["black","orange","pink","red","white","yellow"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"name in black square on gradient","geometry":["square"],"techniques":["gradient","containment","overlap-transparency"],"type_style":"grotesque-sans","case":"uppercase","mood":["technical","vibrant"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"jfrog.svg","brand":"jfrog","variant":"main","pair":null,"width":256.0,"height":248.0,"aspect":1.032,"aspect_class":"square","bytes":6947,"shapes":2,"anchors":170,"colors":["#41bf47"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"splash forming frog above name","geometry":["organic"],"techniques":["hidden-meaning"],"type_style":"display-custom","case":"mixed","mood":["lively","fresh"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"jhipster-icon.svg","brand":"jhipster","variant":"icon","pair":"jhipster.svg","width":256.0,"height":104.0,"aspect":2.462,"aspect_class":"wide","bytes":679,"shapes":3,"anchors":9,"colors":["#3474ab","#4289c7"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"blue bow tie","geometry":["organic"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["stylish","simple"],"industry":"framework-library","exemplary":false,"note":""},{"file":"jhipster.svg","brand":"jhipster","variant":"main","pair":"jhipster-icon.svg","width":512.0,"height":108.0,"aspect":4.741,"aspect_class":"extra-wide","bytes":24152,"shapes":4,"anchors":545,"colors":["#343333","#3474ab","#4289c7"],"n_colors":3,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"blue bow tie","geometry":["organic"],"techniques":["mirror-symmetry"],"type_style":"script","case":"mixed","mood":["stylish","quirky"],"industry":"framework-library","exemplary":false,"note":""},{"file":"jira.svg","brand":"jira","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1423,"shapes":4,"anchors":25,"colors":["#2684ff","#0052cc"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"stacked gradient chevron corners","geometry":["freeform"],"techniques":["gradient","stacked-layers","arrow"],"type_style":null,"case":null,"mood":["dynamic","modern"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"joomla.svg","brand":"joomla","variant":"main","pair":null,"width":256.0,"height":258.0,"aspect":0.992,"aspect_class":"square","bytes":2205,"shapes":5,"anchors":52,"colors":["#f9ae41","#ee4035","#4f91cd","#7ac043"],"n_colors":4,"color_families":["blue","green","orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"four interlocking colored hooks","geometry":["radial"],"techniques":["radial-symmetry","color-segments","overlap-transparency"],"type_style":null,"case":null,"mood":["vibrant","connected"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"jquery-mobile.svg","brand":"jquery-mobile","variant":"main","pair":null,"width":256.0,"height":191.0,"aspect":1.34,"aspect_class":"wide","bytes":1703,"shapes":8,"anchors":52,"colors":["#0481a3","#14bef0","#73d8f4","#6aba2f","#b8ec00","#ffffff","#81d958"],"n_colors":7,"color_families":["cyan","green","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"overlapping translucent slanted panels","geometry":["freeform"],"techniques":["overlap-transparency","color-segments"],"type_style":null,"case":null,"mood":["fresh","light"],"industry":"framework-library","exemplary":false,"note":""},{"file":"jquery.svg","brand":"jquery","variant":"main","pair":null,"width":512.0,"height":116.0,"aspect":4.414,"aspect_class":"horizontal","bytes":5797,"shapes":11,"anchors":124,"colors":["#1a1918","#21609b"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"nested swirl arcs","geometry":["organic"],"techniques":["motion-lines"],"type_style":"display-custom","case":"mixed","mood":["dynamic","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"jruby.svg","brand":"jruby","variant":"main","pair":null,"width":257.0,"height":183.0,"aspect":1.404,"aspect_class":"wide","bytes":2315,"shapes":6,"anchors":61,"colors":["#4a0000","#ca1f27","#ffd440"],"n_colors":3,"color_families":["red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red cardinal bird","geometry":["organic"],"techniques":["dimensional-shading"],"type_style":null,"case":null,"mood":["lively","bold"],"industry":"programming-language","exemplary":false,"note":""},{"file":"jsbin.svg","brand":"jsbin","variant":"main","pair":null,"width":256.0,"height":358.0,"aspect":0.715,"aspect_class":"tall","bytes":9583,"shapes":29,"anchors":242,"colors":["#9eaab2","#8e979a","#dbe1e3","#1a2b2f","#1b3134","#213f48","#51c3f1","#ffffff","#f5dd3e","#3b3735"],"n_colors":10,"color_families":["blue","cyan","gray","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"robot trash can with eyes","geometry":["freeform"],"techniques":["dimensional-shading"],"type_style":null,"case":null,"mood":["playful","quirky"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"jsdelivr.svg","brand":"jsdelivr","variant":"main","pair":null,"width":256.0,"height":273.0,"aspect":0.938,"aspect_class":"square","bytes":3790,"shapes":4,"anchors":89,"colors":["#e14337","#f9bd3e","#440401"],"n_colors":3,"color_families":["red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"shield with network globe","geometry":["shield"],"techniques":["dimensional-shading","containment"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"jsdom.svg","brand":"jsdom","variant":"main","pair":null,"width":256.0,"height":287.0,"aspect":0.892,"aspect_class":"square","bytes":1689,"shapes":3,"anchors":43,"colors":["#dbc01d","#383307"],"n_colors":2,"color_families":["yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"branching tree in yellow hexagon","geometry":["hexagon"],"techniques":["containment","hidden-meaning"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"jsfiddle.svg","brand":"jsfiddle","variant":"main","pair":null,"width":256.0,"height":175.0,"aspect":1.463,"aspect_class":"wide","bytes":2625,"shapes":2,"anchors":60,"colors":["#4679a4"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cloud with infinity loop","geometry":["organic"],"techniques":["infinity-loop","negative-space"],"type_style":null,"case":null,"mood":["friendly","calm"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"json.svg","brand":"json","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1478,"shapes":3,"anchors":18,"colors":["#ffffff"],"n_colors":1,"color_families":["white"],"primary_family":"mono","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"shaded interlocking rings in black square","geometry":["square","circle"],"techniques":["gradient","overlap-transparency","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","mysterious"],"industry":"database-data","exemplary":false,"note":""},{"file":"jspm.svg","brand":"jspm","variant":"main","pair":null,"width":256.0,"height":298.0,"aspect":0.859,"aspect_class":"square","bytes":1105,"shapes":7,"anchors":48,"colors":["#feea5f","#e0cc41","#efdb50","#c3c2c2","#b3b3b3","#a5a5a4"],"n_colors":6,"color_families":["gray","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"isometric gray and yellow cube","geometry":["hexagon"],"techniques":["isometric-3d","dimensional-shading"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"jss.svg","brand":"jss","variant":"main","pair":null,"width":256.0,"height":203.0,"aspect":1.261,"aspect_class":"wide","bytes":2065,"shapes":4,"anchors":59,"colors":["#f7df1e","#eeeeee","#000000"],"n_colors":3,"color_families":["black","white","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"JSS over yellow square","geometry":["square"],"techniques":["containment","overlap-transparency"],"type_style":"grotesque-sans","case":"uppercase","mood":["bold","simple"],"industry":"framework-library","exemplary":false,"note":""},{"file":"juju.svg","brand":"juju","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4323,"shapes":3,"anchors":111,"colors":["#dd4813","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"looping line with nodes in orange circle","geometry":["circle"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["technical","warm"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"julia.svg","brand":"julia","variant":"main","pair":null,"width":512.0,"height":330.0,"aspect":1.552,"aspect_class":"wide","bytes":5455,"shapes":6,"anchors":134,"colors":["#ca3c32","#9259a3","#399746","#4d64ae","#1a1a1a"],"n_colors":5,"color_families":["black","blue","green","purple","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with three colored dots","geometry":[],"techniques":["letter-substitution","color-segments"],"type_style":"humanist-sans","case":"lowercase","mood":["friendly","academic"],"industry":"programming-language","exemplary":false,"note":""},{"file":"jupyter.svg","brand":"jupyter","variant":"main","pair":null,"width":256.0,"height":300.0,"aspect":0.853,"aspect_class":"square","bytes":6648,"shapes":7,"anchors":182,"colors":["#4e4e4e","#767677","#f37726","#9e9e9e","#616262"],"n_colors":5,"color_families":["gray","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"name between orange orbit arcs with moons","geometry":["circle"],"techniques":["hidden-meaning","containment"],"type_style":"humanist-sans","case":"lowercase","mood":["academic","warm"],"industry":"developer-tools","exemplary":true,"note":"Orbit arcs and moons evoke Jupiter while framing the name."},{"file":"jwt-icon.svg","brand":"jwt","variant":"icon","pair":"jwt.svg","width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":1406,"shapes":11,"anchors":60,"colors":["#ffffff","#00f2e6","#00b9f1","#d63aff","#fb015b"],"n_colors":5,"color_families":["cyan","purple","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"radial burst of colored shards","geometry":["radial"],"techniques":["radial-symmetry","color-segments"],"type_style":null,"case":null,"mood":["vibrant","technical"],"industry":"security-identity","exemplary":false,"note":""},{"file":"jwt.svg","brand":"jwt","variant":"main","pair":"jwt-icon.svg","width":512.0,"height":172.0,"aspect":2.977,"aspect_class":"horizontal","bytes":2312,"shapes":12,"anchors":99,"colors":["#ffffff","#00f2e6","#00b9f1","#d63aff","#fb015b","#000000"],"n_colors":6,"color_families":["black","cyan","purple","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"radial burst of colored shards","geometry":["radial"],"techniques":["radial-symmetry","color-segments"],"type_style":"display-custom","case":"uppercase","mood":["technical","light"],"industry":"security-identity","exemplary":false,"note":""},{"file":"kafka-icon.svg","brand":"kafka","variant":"icon","pair":"kafka.svg","width":256.0,"height":413.0,"aspect":0.62,"aspect_class":"tall","bytes":4793,"shapes":2,"anchors":136,"colors":["#1a1919"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"linked circle nodes","geometry":["circle"],"techniques":["line-monoline","geometric-construction"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"database-data","exemplary":false,"note":""},{"file":"kafka.svg","brand":"kafka","variant":"main","pair":"kafka-icon.svg","width":512.0,"height":234.0,"aspect":2.188,"aspect_class":"wide","bytes":6465,"shapes":3,"anchors":211,"colors":["#1a1919"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"linked circle nodes","geometry":["circle"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["technical","clean"],"industry":"database-data","exemplary":false,"note":""},{"file":"kaios.svg","brand":"kaios","variant":"main","pair":null,"width":512.0,"height":134.0,"aspect":3.821,"aspect_class":"horizontal","bytes":3002,"shapes":2,"anchors":70,"colors":["#5e3580"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with custom split K","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"mixed","mood":["friendly","modern"],"industry":"os-platform","exemplary":false,"note":""},{"file":"kallithea.svg","brand":"kallithea","variant":"main","pair":null,"width":256.0,"height":709.0,"aspect":0.361,"aspect_class":"tall","bytes":2786,"shapes":2,"anchors":84,"colors":["#587635"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"branching lines ending in circles","geometry":["freeform"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["technical","organic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"karma.svg","brand":"karma","variant":"main","pair":null,"width":256.0,"height":198.0,"aspect":1.293,"aspect_class":"wide","bytes":730,"shapes":5,"anchors":27,"colors":["#429f87","#56c5a8"],"n_colors":2,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"K with lightning zigzag","geometry":["freeform"],"techniques":["geometric-construction","color-segments"],"type_style":null,"case":null,"mood":["energetic","fresh"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"kde.svg","brand":"kde","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1821,"shapes":3,"anchors":58,"colors":["#1d99f3","#fcfcfc"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"K with gear in blue square","geometry":["square"],"techniques":["negative-space","containment","hidden-meaning"],"type_style":null,"case":null,"mood":["technical","friendly"],"industry":"os-platform","exemplary":false,"note":""},{"file":"keen.svg","brand":"keen","variant":"main","pair":null,"width":512.0,"height":111.0,"aspect":4.613,"aspect_class":"extra-wide","bytes":3659,"shapes":5,"anchors":111,"colors":["#f35757","#49c5b1","#00afd7","#546a7e"],"n_colors":4,"color_families":["blue","cyan","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"overlapping outlined triangles","geometry":["triangle"],"techniques":["line-monoline","overlap-transparency"],"type_style":"geometric-sans","case":"titlecase","mood":["light","modern"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"kemal.svg","brand":"kemal","variant":"main","pair":null,"width":256.0,"height":174.0,"aspect":1.471,"aspect_class":"wide","bytes":596,"shapes":4,"anchors":19,"colors":["#ff4f4f","#f92727","#000000"],"n_colors":3,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red two-tone fez hat","geometry":["freeform"],"techniques":["color-segments","hidden-meaning"],"type_style":null,"case":null,"mood":["bold","cultural"],"industry":"framework-library","exemplary":false,"note":""},{"file":"keycdn-icon.svg","brand":"keycdn","variant":"icon","pair":"keycdn.svg","width":256.0,"height":247.0,"aspect":1.036,"aspect_class":"square","bytes":3548,"shapes":3,"anchors":105,"colors":["#2e3234","#047aed"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"keyhole in ring with network nodes","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["technical","secure"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"keycdn.svg","brand":"keycdn","variant":"main","pair":"keycdn-icon.svg","width":512.0,"height":149.0,"aspect":3.436,"aspect_class":"horizontal","bytes":8068,"shapes":5,"anchors":250,"colors":["#2e3234","#047aed"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"keyhole in ring with network nodes","geometry":["circle"],"techniques":["containment"],"type_style":"grotesque-sans","case":"lowercase","mood":["technical","fast"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"keystonejs.svg","brand":"keystonejs","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1201,"shapes":2,"anchors":30,"colors":["#5ae8fa","#2684ff"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white K in gradient rounded square","geometry":["rounded-square"],"techniques":["gradient","containment"],"type_style":null,"case":null,"mood":["modern","clean"],"industry":"framework-library","exemplary":false,"note":""},{"file":"khan_academy-icon.svg","brand":"khan_academy","variant":"icon","pair":"khan_academy.svg","width":256.0,"height":276.0,"aspect":0.928,"aspect_class":"square","bytes":1318,"shapes":4,"anchors":30,"colors":["#14bf96","#ffffff"],"n_colors":2,"color_families":["cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"sprout doubling as person in hexagon","geometry":["hexagon"],"techniques":["negative-space","hidden-meaning","containment"],"type_style":null,"case":null,"mood":["hopeful","friendly"],"industry":"education","exemplary":true,"note":"Leaf sprout reads as a person; negative space dual image."},{"file":"khan_academy.svg","brand":"khan_academy","variant":"main","pair":"khan_academy-icon.svg","width":512.0,"height":82.0,"aspect":6.244,"aspect_class":"extra-wide","bytes":9573,"shapes":5,"anchors":277,"colors":["#000000","#14bf96","#ffffff"],"n_colors":3,"color_families":["black","cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"sprout doubling as person in hexagon","geometry":["hexagon"],"techniques":["negative-space","hidden-meaning"],"type_style":"grotesque-sans","case":"titlecase","mood":["friendly","trustworthy"],"industry":"education","exemplary":false,"note":""},{"file":"kibana.svg","brand":"kibana","variant":"main","pair":null,"width":256.0,"height":342.0,"aspect":0.749,"aspect_class":"tall","bytes":667,"shapes":5,"anchors":18,"colors":["#009b90","#40beb0","#ef5098","#353535"],"n_colors":4,"color_families":["cyan","gray","pink"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"K from colored triangle and arc","geometry":["triangle"],"techniques":["color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["modern","vibrant"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"kickstarter-icon.svg","brand":"kickstarter","variant":"icon","pair":"kickstarter.svg","width":256.0,"height":290.0,"aspect":0.883,"aspect_class":"square","bytes":700,"shapes":2,"anchors":14,"colors":["#05ce78"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"rounded blobby letter K","geometry":["organic"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["friendly","bold"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"kickstarter.svg","brand":"kickstarter","variant":"main","pair":"kickstarter-icon.svg","width":512.0,"height":55.0,"aspect":9.309,"aspect_class":"extra-wide","bytes":4519,"shapes":2,"anchors":125,"colors":["#05ce78"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy rounded uppercase name","geometry":[],"techniques":[],"type_style":"display-custom","case":"uppercase","mood":["bold","playful"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"kinto-icon.svg","brand":"kinto","variant":"icon","pair":"kinto.svg","width":256.0,"height":99.0,"aspect":2.586,"aspect_class":"horizontal","bytes":8908,"shapes":17,"anchors":113,"colors":["#e35702","#eb7808","#feec7f","#f3a21b","#fee97b","#fcdf6e","#facf58","#f6b93a","#fde373","#f6b434","#f7bc3f","#f9c32e","#f19819","#e96c04","#f7b425","#f3a620","#ec8816","#e6720e","#e26208","#e05805","#df5504","#f7bd40","#feea7c","#fce271","#fbd560","#f8c347","#f4ac28","#e66a09","#ef961a"],"n_colors":29,"color_families":["orange","yellow"],"primary_family":"multi","gradients":12,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"gradient cloud with speed trail","geometry":["organic"],"techniques":["gradient","motion-lines"],"type_style":null,"case":null,"mood":["warm","fast"],"industry":"database-data","exemplary":false,"note":""},{"file":"kinto.svg","brand":"kinto","variant":"main","pair":"kinto-icon.svg","width":512.0,"height":100.0,"aspect":5.12,"aspect_class":"extra-wide","bytes":12370,"shapes":18,"anchors":216,"colors":["#333333","#e35702","#eb7808","#feec7f","#f3a21b","#fee97b","#fcdf6e","#facf58","#f6b93a","#fde373","#f6b434","#f7bc3f","#f9c32e","#f19819","#e96c04","#f7b425","#f3a620","#ec8816","#e6720e","#e26208","#e05805","#df5504","#f7bd40","#feea7c","#fce271","#fbd560","#f8c347","#f4ac28","#e66a09","#ef961a"],"n_colors":30,"color_families":["gray","orange","yellow"],"primary_family":"multi","gradients":12,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"gradient cloud with speed trail","geometry":["organic"],"techniques":["gradient","motion-lines"],"type_style":"grotesque-sans","case":"titlecase","mood":["warm","friendly"],"industry":"database-data","exemplary":false,"note":""},{"file":"kirby-icon.svg","brand":"kirby","variant":"icon","pair":"kirby.svg","width":256.0,"height":299.0,"aspect":0.856,"aspect_class":"square","bytes":574,"shapes":2,"anchors":28,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"abstract K in hexagon outline","geometry":["hexagon"],"techniques":["containment","line-monoline","negative-space"],"type_style":null,"case":null,"mood":["minimal","solid"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"kirby.svg","brand":"kirby","variant":"main","pair":"kirby-icon.svg","width":512.0,"height":178.0,"aspect":2.876,"aspect_class":"horizontal","bytes":2253,"shapes":2,"anchors":101,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"abstract K in hexagon outline","geometry":["hexagon"],"techniques":["containment","line-monoline"],"type_style":"grotesque-sans","case":"titlecase","mood":["minimal","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"kissmetrics.svg","brand":"kissmetrics","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":850,"shapes":2,"anchors":33,"colors":["#4551ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"heart containing bar chart","geometry":["organic"],"techniques":["negative-space","hidden-meaning","containment"],"type_style":null,"case":null,"mood":["friendly","clear"],"industry":"marketing-analytics","exemplary":true,"note":"Merges heart and bar chart into one simple silhouette."},{"file":"kitematic.svg","brand":"kitematic","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1159,"shapes":4,"anchors":36,"colors":["#3cb5e8","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"blocky K in blue rounded square","geometry":["rounded-square"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["technical","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"kloudless.svg","brand":"kloudless","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4522,"shapes":12,"anchors":125,"colors":["#3c98ff","#1b5ced","#009b4a","#eb3200","#ebad00"],"n_colors":5,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"multicolor sunburst with center ring","geometry":["radial","star"],"techniques":["radial-symmetry","color-segments"],"type_style":null,"case":null,"mood":["vibrant","energetic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"knex.svg","brand":"knex","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":6280,"shapes":2,"anchors":198,"colors":["#e16426"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange snowflake-like gear burst","geometry":["radial"],"techniques":["radial-symmetry"],"type_style":null,"case":null,"mood":["bold","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"knockout.svg","brand":"knockout","variant":"main","pair":null,"width":512.0,"height":124.0,"aspect":4.129,"aspect_class":"horizontal","bytes":25159,"shapes":2,"anchors":531,"colors":["#e42e16"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"red script name with underline","geometry":[],"techniques":["hand-drawn"],"type_style":"script","case":"titlecase","mood":["retro","energetic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"koa.svg","brand":"koa","variant":"main","pair":null,"width":512.0,"height":275.0,"aspect":1.862,"aspect_class":"wide","bytes":1581,"shapes":2,"anchors":47,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"thin high-contrast serif name","geometry":[],"techniques":[],"type_style":"serif","case":"lowercase","mood":["elegant","minimal"],"industry":"framework-library","exemplary":false,"note":""},{"file":"kong-icon.svg","brand":"kong","variant":"icon","pair":"kong.svg","width":256.0,"height":225.0,"aspect":1.138,"aspect_class":"square","bytes":855,"shapes":5,"anchors":37,"colors":["#169fcc","#14b59a","#1bc263","#16bdcc"],"n_colors":4,"color_families":["cyan","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"geometric gorilla from angular shapes","geometry":["triangle","freeform"],"techniques":["geometric-construction","color-segments","gradient"],"type_style":null,"case":null,"mood":["strong","modern"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"kong.svg","brand":"kong","variant":"main","pair":"kong-icon.svg","width":512.0,"height":167.0,"aspect":3.066,"aspect_class":"horizontal","bytes":2387,"shapes":6,"anchors":115,"colors":["#043558","#169fcc","#14b59a","#1bc263","#16bdcc"],"n_colors":5,"color_families":["blue","cyan","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"geometric gorilla from angular shapes","geometry":["freeform"],"techniques":["geometric-construction","color-segments"],"type_style":"geometric-sans","case":"titlecase","mood":["strong","modern"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"kops.svg","brand":"kops","variant":"main","pair":null,"width":512.0,"height":228.0,"aspect":2.246,"aspect_class":"wide","bytes":8654,"shapes":8,"anchors":198,"colors":["#414042","#27aae1","#ffffff"],"n_colors":3,"color_families":["blue","gray","white"],"primary_family":"blue","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"ship wheel with circular arrow","geometry":["circle","radial"],"techniques":["radial-symmetry","arrow"],"type_style":"geometric-sans","case":"lowercase","mood":["technical","nautical"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"koreio.svg","brand":"koreio","variant":"main","pair":null,"width":256.0,"height":297.0,"aspect":0.862,"aspect_class":"square","bytes":2105,"shapes":15,"anchors":102,"colors":["#c5e3eb","#78abdb","#a4c0c5","#7ba6c1","#98c3e4","#4b7c9e","#f4bc6a","#b48340","#8c3d33","#c47973","#bb6651","#e1938a"],"n_colors":12,"color_families":["blue","cyan","orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"hexagon of translucent colored cubes","geometry":["hexagon"],"techniques":["isometric-3d","overlap-transparency","color-segments"],"type_style":null,"case":null,"mood":["technical","colorful"],"industry":"other","exemplary":false,"note":""},{"file":"kotlin-icon.svg","brand":"kotlin","variant":"icon","pair":"kotlin.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":620,"shapes":2,"anchors":6,"colors":["#e44857","#c711e1","#7f52ff"],"n_colors":3,"color_families":["pink","purple","red"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"gradient square with triangular notch K","geometry":["square","triangle"],"techniques":["gradient","negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["modern","bold"],"industry":"programming-language","exemplary":true,"note":"K implied by one triangular cut; extreme geometric economy."},{"file":"kotlin.svg","brand":"kotlin","variant":"main","pair":"kotlin-icon.svg","width":512.0,"height":112.0,"aspect":4.571,"aspect_class":"extra-wide","bytes":3185,"shapes":3,"anchors":102,"colors":["#000000","#e44857","#c711e1","#7f52ff"],"n_colors":4,"color_families":["black","pink","purple","red"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"gradient square with triangular notch K","geometry":["square","triangle"],"techniques":["gradient","negative-space"],"type_style":"geometric-sans","case":"titlecase","mood":["modern","clean"],"industry":"programming-language","exemplary":false,"note":""},{"file":"kraken.svg","brand":"kraken","variant":"main","pair":null,"width":256.0,"height":229.0,"aspect":1.118,"aspect_class":"square","bytes":4111,"shapes":10,"anchors":56,"colors":["#2e3192","#3e5aa8","#0093d3","#00aeef","#0075be","#f58220","#ed1c24","#ae2538","#a71c20","#ffcb05","#fff200","#f99d1c","#f26522","#c61d23","#61a2d8"],"n_colors":15,"color_families":["blue","orange","red","yellow"],"primary_family":"multi","gradients":9,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"hexagon of multicolor triangular facets","geometry":["hexagon","triangle"],"techniques":["color-segments","geometric-construction","dimensional-shading"],"type_style":null,"case":null,"mood":["vibrant","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"krakenjs.svg","brand":"krakenjs","variant":"main","pair":null,"width":256.0,"height":274.0,"aspect":0.934,"aspect_class":"square","bytes":19202,"shapes":3,"anchors":546,"colors":["#0081c2","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"white kraken in blue hexagon","geometry":["hexagon"],"techniques":["containment","negative-space","mirror-symmetry"],"type_style":null,"case":null,"mood":["playful","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"kubernetes.svg","brand":"kubernetes","variant":"main","pair":null,"width":256.0,"height":249.0,"aspect":1.028,"aspect_class":"square","bytes":10072,"shapes":4,"anchors":268,"colors":["#326de6","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"ship wheel in blue heptagon","geometry":["radial","freeform"],"techniques":["radial-symmetry","containment","hidden-meaning"],"type_style":null,"case":null,"mood":["technical","iconic"],"industry":"cloud-infrastructure","exemplary":true,"note":"Helm metaphor for orchestration; clean radial construction."},{"file":"kustomer.svg","brand":"kustomer","variant":"main","pair":null,"width":512.0,"height":76.0,"aspect":6.737,"aspect_class":"extra-wide","bytes":5826,"shapes":3,"anchors":181,"colors":["#000000","#ff655d"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with chat face replacing O","geometry":[],"techniques":["letter-substitution"],"type_style":"geometric-sans","case":"uppercase","mood":["friendly","modern"],"industry":"social-communication","exemplary":false,"note":""},{"file":"laravel.svg","brand":"laravel","variant":"main","pair":null,"width":256.0,"height":264.0,"aspect":0.97,"aspect_class":"square","bytes":3481,"shapes":2,"anchors":123,"colors":["#ff2d20"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"isometric outlined cubes forming L","geometry":["square"],"techniques":["isometric-3d","line-monoline","geometric-construction"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"framework-library","exemplary":true,"note":"Monoline isometric construction builds letter L from cubes."},{"file":"lastfm.svg","brand":"lastfm","variant":"main","pair":null,"width":512.0,"height":131.0,"aspect":3.908,"aspect_class":"horizontal","bytes":3038,"shapes":7,"anchors":95,"colors":["#d41107"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"custom name with rounded a","geometry":[],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["bold","friendly"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"lateral.svg","brand":"lateral","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":17476,"shapes":15,"anchors":964,"colors":["#115ede","#3582f7","#0d57d9","#1362dd","#6aabd4","#e4f6fe","#a8cce9","#d8e9f8","#84c1f2","#aecee9","#0060ff","#1f66d6","#1f6ae2","#2e7bed"],"n_colors":14,"color_families":["blue"],"primary_family":"blue","gradients":3,"has_mask":true,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"faceted crystal on blue grid square","geometry":["square","triangle"],"techniques":["dimensional-shading","gradient","containment"],"type_style":null,"case":null,"mood":["technical","cool"],"industry":"ai-ml","exemplary":false,"note":""},{"file":"launchrock.svg","brand":"launchrock","variant":"main","pair":null,"width":256.0,"height":271.0,"aspect":0.945,"aspect_class":"square","bytes":1390,"shapes":2,"anchors":35,"colors":["#dc0000"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"rock-on hand gesture","geometry":["organic"],"techniques":["negative-space","hidden-meaning"],"type_style":null,"case":null,"mood":["bold","rebellious"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"leaflet.svg","brand":"leaflet","variant":"main","pair":null,"width":512.0,"height":136.0,"aspect":3.765,"aspect_class":"horizontal","bytes":9235,"shapes":7,"anchors":227,"colors":["#70706f","#3d3d3c","#8ac443","#75b843","#4b9744","#c1db74","#acd259"],"n_colors":7,"color_families":["gray","green"],"primary_family":"green","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"green leaf","geometry":["organic"],"techniques":[],"type_style":"script","case":"titlecase","mood":["natural","light"],"industry":"framework-library","exemplary":false,"note":""},{"file":"leankit-icon.svg","brand":"leankit","variant":"icon","pair":"leankit.svg","width":256.0,"height":283.0,"aspect":0.905,"aspect_class":"square","bytes":1000,"shapes":2,"anchors":33,"colors":["#a4a7ad","#4d515d"],"n_colors":2,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"play triangle cut from gray hexagon","geometry":["hexagon","triangle"],"techniques":["negative-space","arrow","dimensional-shading"],"type_style":null,"case":null,"mood":["calm","technical"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"leankit.svg","brand":"leankit","variant":"main","pair":"leankit-icon.svg","width":512.0,"height":158.0,"aspect":3.241,"aspect_class":"horizontal","bytes":23374,"shapes":4,"anchors":666,"colors":["#202433","#a4a7ad","#4d515d"],"n_colors":3,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"play triangle cut from gray hexagon","geometry":["hexagon"],"techniques":["negative-space","arrow"],"type_style":"geometric-sans","case":"mixed","mood":["calm","corporate"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"lerna.svg","brand":"lerna","variant":"main","pair":null,"width":468.0,"height":424.0,"aspect":1.104,"aspect_class":"square","bytes":320910,"shapes":2,"anchors":10429,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"engraved three-headed hydra","geometry":["organic"],"techniques":["hand-drawn"],"type_style":"serif","case":"titlecase","mood":["classic","mythic"],"industry":"developer-tools","exemplary":false,"note":"Detailed engraving fails at small sizes."},{"file":"less.svg","brand":"less","variant":"main","pair":null,"width":256.0,"height":110.0,"aspect":2.327,"aspect_class":"wide","bytes":4901,"shapes":9,"anchors":102,"colors":["#faf9f8","#2e4f82","#182e4d"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":true,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"name in curly braces on dark block","geometry":["rounded-square"],"techniques":["bracket-code","containment"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","technical"],"industry":"programming-language","exemplary":false,"note":""},{"file":"lets-cloud.svg","brand":"lets-cloud","variant":"main","pair":null,"width":512.0,"height":62.0,"aspect":8.258,"aspect_class":"extra-wide","bytes":11243,"shapes":5,"anchors":274,"colors":["#47545f","#0dabe3","#80d2eb","#00afe6"],"n_colors":4,"color_families":["blue","cyan","gray"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"cloud formed of horizontal speed lines","geometry":["organic"],"techniques":["line-monoline","motion-lines"],"type_style":"geometric-sans","case":"mixed","mood":["light","techy"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"letsencrypt.svg","brand":"letsencrypt","variant":"main","pair":null,"width":256.0,"height":199.0,"aspect":1.286,"aspect_class":"wide","bytes":11784,"shapes":9,"anchors":343,"colors":["#ffa400","#003a70"],"n_colors":2,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"padlock with rising sun rays","geometry":["square"],"techniques":["hidden-meaning"],"type_style":"humanist-sans","case":"titlecase","mood":["trustworthy","friendly","optimistic"],"industry":"security-identity","exemplary":false,"note":""},{"file":"leveldb.svg","brand":"leveldb","variant":"main","pair":null,"width":256.0,"height":329.0,"aspect":0.778,"aspect_class":"tall","bytes":680,"shapes":5,"anchors":28,"colors":["#d4eb95","#96dc75","#317342","#34954c"],"n_colors":4,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"stacked translucent green isometric layers","geometry":["diamond"],"techniques":["isometric-3d","stacked-layers","overlap-transparency"],"type_style":null,"case":null,"mood":["layered","natural"],"industry":"database-data","exemplary":false,"note":""},{"file":"liftweb.svg","brand":"liftweb","variant":"main","pair":null,"width":256.0,"height":318.0,"aspect":0.805,"aspect_class":"square","bytes":1157,"shapes":4,"anchors":33,"colors":["#4861b4","#25336d","#ffffff"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"folded ribbon forming upward arrow","geometry":["rounded-square"],"techniques":["arrow","dimensional-shading"],"type_style":null,"case":null,"mood":["dynamic","uplifting"],"industry":"framework-library","exemplary":false,"note":""},{"file":"lighthouse.svg","brand":"lighthouse","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":12399,"shapes":36,"anchors":213,"colors":["#0535c1","#eaeaea","#ffffff","#000000","#e1e1e1","#eeeeee","#212121","#fff176","#f4481e","#fafafa","#263238","#262626"],"n_colors":12,"color_families":["black","blue","gray","red","white","yellow"],"primary_family":"multi","gradients":10,"has_mask":true,"has_filter":true,"mark_type":"pictorial","symbol_type":null,"subject":"lighthouse with clouds in circle","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["friendly","playful"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"lightstep-icon.svg","brand":"lightstep","variant":"icon","pair":"lightstep.svg","width":256.0,"height":193.0,"aspect":1.326,"aspect_class":"wide","bytes":1486,"shapes":3,"anchors":52,"colors":["#039c49","#121c21"],"n_colors":2,"color_families":["blue","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"wireframe polyhedron lens with green dot","geometry":["freeform"],"techniques":["line-monoline","isometric-3d"],"type_style":null,"case":null,"mood":["technical","precise"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"lightstep.svg","brand":"lightstep","variant":"main","pair":"lightstep-icon.svg","width":512.0,"height":117.0,"aspect":4.376,"aspect_class":"horizontal","bytes":4737,"shapes":3,"anchors":186,"colors":["#039c49","#121c21"],"n_colors":2,"color_families":["blue","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"wireframe polyhedron lens with green dot","geometry":["freeform"],"techniques":["line-monoline","isometric-3d"],"type_style":"geometric-sans","case":"titlecase","mood":["technical","modern"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"lighttpd.svg","brand":"lighttpd","variant":"main","pair":null,"width":256.0,"height":211.0,"aspect":1.213,"aspect_class":"square","bytes":680,"shapes":5,"anchors":23,"colors":["#316682","#8194a6","#d9e2e9","#d7e0e5"],"n_colors":4,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"paper plane","geometry":["triangle"],"techniques":["dimensional-shading"],"type_style":null,"case":null,"mood":["light","fast"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"linkedin-icon.svg","brand":"linkedin","variant":"icon","pair":"linkedin.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1122,"shapes":2,"anchors":34,"colors":["#0a66c2"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"lowercase in inside blue rounded square","geometry":["rounded-square"],"techniques":["containment","negative-space"],"type_style":"grotesque-sans","case":"lowercase","mood":["professional","trustworthy"],"industry":"social-communication","exemplary":false,"note":""},{"file":"linkedin.svg","brand":"linkedin","variant":"main","pair":"linkedin-icon.svg","width":512.0,"height":128.0,"aspect":4.0,"aspect_class":"horizontal","bytes":3043,"shapes":2,"anchors":114,"colors":["#0a66c2"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"Linked with boxed in","geometry":["rounded-square"],"techniques":["containment","negative-space"],"type_style":"grotesque-sans","case":"titlecase","mood":["professional","confident"],"industry":"social-communication","exemplary":false,"note":""},{"file":"linkerd.svg","brand":"linkerd","variant":"main","pair":null,"width":256.0,"height":239.0,"aspect":1.071,"aspect_class":"square","bytes":4101,"shapes":25,"anchors":122,"colors":["#40a0b4","#338090","#45c1a8","#7ce1c0","#a2eacf","#4ad8ac","#4076c4"],"n_colors":7,"color_families":["blue","cyan","green"],"primary_family":"multi","gradients":6,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric striped block with hidden L forms","geometry":["grid-modular"],"techniques":["isometric-3d","gradient","modular-repetition"],"type_style":null,"case":null,"mood":["technical","fresh"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"linode.svg","brand":"linode","variant":"main","pair":null,"width":256.0,"height":307.0,"aspect":0.834,"aspect_class":"square","bytes":8813,"shapes":4,"anchors":267,"colors":["#004711","#00b159","#000000"],"n_colors":3,"color_families":["black","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"stacked green isometric cubes","geometry":["grid-modular"],"techniques":["isometric-3d","modular-repetition","dimensional-shading"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"linux-mint.svg","brand":"linux-mint","variant":"main","pair":null,"width":256.0,"height":230.0,"aspect":1.113,"aspect_class":"square","bytes":4805,"shapes":8,"anchors":147,"colors":["#000000","#ffffff","#52a800","#c7f994","#87cf3e","#3d3d3d"],"n_colors":6,"color_families":["black","gray","green","white"],"primary_family":"green","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"lm letters inside tabbed rounded frame","geometry":["rounded-square"],"techniques":["containment","line-monoline","gradient"],"type_style":"display-custom","case":"lowercase","mood":["fresh","friendly"],"industry":"os-platform","exemplary":false,"note":""},{"file":"linux-tux.svg","brand":"linux-tux","variant":"main","pair":null,"width":256.0,"height":295.0,"aspect":0.868,"aspect_class":"square","bytes":13343,"shapes":29,"anchors":158,"colors":["#000000","#e68c3f","#ffeed7","#bdbfc2","#ffffff","#ffa63f","#ffff00"],"n_colors":7,"color_families":["black","gray","orange","white","yellow"],"primary_family":"multi","gradients":20,"has_mask":false,"has_filter":true,"mark_type":"mascot","symbol_type":null,"subject":"sitting penguin Tux","geometry":["organic"],"techniques":["dimensional-shading","gradient"],"type_style":null,"case":null,"mood":["friendly","playful"],"industry":"os-platform","exemplary":false,"note":"Iconic mascot but too detailed and shaded for small sizes."},{"file":"lit-icon.svg","brand":"lit","variant":"icon","pair":"lit.svg","width":256.0,"height":320.0,"aspect":0.8,"aspect_class":"square","bytes":677,"shapes":5,"anchors":38,"colors":["#00e8ff","#283198","#324fff","#00ffff"],"n_colors":4,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"angular flame from stacked parallelograms","geometry":["triangle"],"techniques":["overlap-transparency","color-segments","geometric-construction","hidden-meaning"],"type_style":null,"case":null,"mood":["energetic","modern"],"industry":"framework-library","exemplary":true,"note":"Flame built from overlapping geometric facets; clever 'lit' pun."},{"file":"lit.svg","brand":"lit","variant":"main","pair":"lit-icon.svg","width":512.0,"height":242.0,"aspect":2.116,"aspect_class":"wide","bytes":1483,"shapes":6,"anchors":74,"colors":["#000000","#00e8ff","#283198","#324fff","#00ffff"],"n_colors":5,"color_families":["black","blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"angular faceted flame","geometry":["freeform"],"techniques":["overlap-transparency","color-segments","geometric-construction"],"type_style":"grotesque-sans","case":"titlecase","mood":["modern","energetic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"litmus.svg","brand":"litmus","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2038,"shapes":11,"anchors":54,"colors":["#6a7a55","#a09440","#afa148","#4c5c59","#48555d","#e3b23b","#903024","#d65841","#e6703e","#f4a83a"],"n_colors":10,"color_families":["gray","green","orange","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"ring of color segments like color wheel","geometry":["circle","radial"],"techniques":["radial-symmetry","color-segments"],"type_style":null,"case":null,"mood":["vibrant","analytical"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"loader.svg","brand":"loader","variant":"main","pair":null,"width":256.0,"height":247.0,"aspect":1.036,"aspect_class":"square","bytes":1083,"shapes":5,"anchors":37,"colors":["#497bbb"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"kettlebell with L cut into it","geometry":["triangle"],"techniques":["negative-space","hidden-meaning","letter-substitution"],"type_style":null,"case":null,"mood":["strong","clever"],"industry":"testing-monitoring","exemplary":true,"note":"Kettlebell weight equals load testing; L carved in negative space."},{"file":"lodash.svg","brand":"lodash","variant":"main","pair":null,"width":256.0,"height":233.0,"aspect":1.099,"aspect_class":"square","bytes":1358,"shapes":4,"anchors":31,"colors":["#000000","#3492ff"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"Lo letters over blue underline bar","geometry":[],"techniques":["geometric-construction"],"type_style":"geometric-sans","case":"titlecase","mood":["minimal","clean"],"industry":"framework-library","exemplary":false,"note":""},{"file":"logentries.svg","brand":"logentries","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3413,"shapes":5,"anchors":71,"colors":["#f47721","#ffffff","#f36d21"],"n_colors":3,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"L from connected nodes with gear","geometry":["rounded-square"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["playful","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"logstash.svg","brand":"logstash","variant":"main","pair":null,"width":256.0,"height":307.0,"aspect":0.834,"aspect_class":"square","bytes":536,"shapes":4,"anchors":16,"colors":["#fec514","#343741","#00bfb3"],"n_colors":3,"color_families":["cyan","gray","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"geometric L from half-round and square","geometry":["square"],"techniques":["geometric-construction","color-segments"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"database-data","exemplary":true,"note":"Letter L composed from simple colored geometric primitives."},{"file":"lookback.svg","brand":"lookback","variant":"main","pair":null,"width":256.0,"height":121.0,"aspect":2.116,"aspect_class":"wide","bytes":1511,"shapes":2,"anchors":34,"colors":["#bc1b23"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"red looping ribbon with central arrow","geometry":["organic"],"techniques":["infinity-loop","arrow"],"type_style":null,"case":null,"mood":["dynamic","bold"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"looker-icon.svg","brand":"looker","variant":"icon","pair":"looker.svg","width":256.0,"height":413.0,"aspect":0.62,"aspect_class":"tall","bytes":2062,"shapes":5,"anchors":45,"colors":["#34a853","#fbbc04","#ea4335","#4285f4"],"n_colors":4,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"chain of connected circles in Google colors","geometry":["circle"],"techniques":["color-segments"],"type_style":null,"case":null,"mood":["playful","connected"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"looker.svg","brand":"looker","variant":"main","pair":"looker-icon.svg","width":512.0,"height":137.0,"aspect":3.737,"aspect_class":"horizontal","bytes":5884,"shapes":6,"anchors":158,"colors":["#34a853","#fbbc04","#ea4335","#4285f4","#5f6368"],"n_colors":5,"color_families":["blue","gray","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"chain of connected colorful circles","geometry":["circle"],"techniques":["color-segments"],"type_style":"geometric-sans","case":"titlecase","mood":["friendly","modern"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"loom.svg","brand":"loom","variant":"main","pair":null,"width":512.0,"height":155.0,"aspect":3.303,"aspect_class":"horizontal","bytes":2360,"shapes":3,"anchors":88,"colors":["#222222","#625df5"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"radiating asterisk burst","geometry":["radial"],"techniques":["radial-symmetry"],"type_style":"geometric-sans","case":"lowercase","mood":["energetic","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"loopback-icon.svg","brand":"loopback","variant":"icon","pair":"loopback.svg","width":256.0,"height":293.0,"aspect":0.874,"aspect_class":"square","bytes":1390,"shapes":2,"anchors":58,"colors":["#3f5dff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"interlocking isometric loops in hexagon","geometry":["hexagon"],"techniques":["isometric-3d","containment","impossible-figure"],"type_style":null,"case":null,"mood":["technical","structured"],"industry":"framework-library","exemplary":false,"note":""},{"file":"loopback.svg","brand":"loopback","variant":"main","pair":"loopback-icon.svg","width":512.0,"height":138.0,"aspect":3.71,"aspect_class":"horizontal","bytes":4269,"shapes":3,"anchors":172,"colors":["#3f5dff","#001956"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"interlocking isometric loops","geometry":["hexagon"],"techniques":["isometric-3d","line-monoline"],"type_style":"geometric-sans","case":"mixed","mood":["technical","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"losant.svg","brand":"losant","variant":"main","pair":null,"width":256.0,"height":146.0,"aspect":1.753,"aspect_class":"wide","bytes":620,"shapes":3,"anchors":22,"colors":["#ff495c","#284fff"],"n_colors":2,"color_families":["blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two interlinked outline diamonds","geometry":["diamond"],"techniques":["overlap-transparency","line-monoline","infinity-loop"],"type_style":null,"case":null,"mood":["connected","technical"],"industry":"hardware-devices","exemplary":false,"note":""},{"file":"lua.svg","brand":"lua","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":8019,"shapes":8,"anchors":249,"colors":["#00007d","#ffffff","#929292"],"n_colors":3,"color_families":["blue","gray","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"moon orbiting planet with Lua text","geometry":["circle"],"techniques":["negative-space","hidden-meaning","containment"],"type_style":"humanist-sans","case":"titlecase","mood":["calm","clever"],"industry":"programming-language","exemplary":true,"note":"Lua means moon; orbit and crescent cut conveyed simply."},{"file":"lucene.net.svg","brand":"lucene.net","variant":"main","pair":null,"width":256.0,"height":146.0,"aspect":1.753,"aspect_class":"wide","bytes":2632,"shapes":5,"anchors":45,"colors":["#0664a8","#02364f"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"swirling blue ribbon loop","geometry":["organic"],"techniques":["infinity-loop","gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["fluid","dynamic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"lucene.svg","brand":"lucene","variant":"main","pair":null,"width":512.0,"height":81.0,"aspect":6.321,"aspect_class":"extra-wide","bytes":35036,"shapes":4,"anchors":784,"colors":["#c1da94","#cbcbcb","#000000"],"n_colors":3,"color_families":["black","gray","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"italic custom lettering with speed wing","geometry":[],"techniques":["motion-lines"],"type_style":"display-custom","case":"titlecase","mood":["retro","quirky"],"industry":"framework-library","exemplary":false,"note":"Dated retro lettering; hard to read at small sizes."},{"file":"lumen.svg","brand":"lumen","variant":"main","pair":null,"width":256.0,"height":515.0,"aspect":0.497,"aspect_class":"tall","bytes":3089,"shapes":2,"anchors":84,"colors":["#e54537"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"diagonal red stripes forming a lamp","geometry":["freeform"],"techniques":["modular-repetition","motion-lines"],"type_style":null,"case":null,"mood":["energetic","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"macOS.svg","brand":"macOS","variant":"main","pair":null,"width":512.0,"height":120.0,"aspect":4.267,"aspect_class":"horizontal","bytes":2810,"shapes":2,"anchors":84,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"macOS set in system sans","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"mixed","mood":["clean","premium"],"industry":"os-platform","exemplary":false,"note":""},{"file":"madge.svg","brand":"madge","variant":"main","pair":null,"width":256.0,"height":372.0,"aspect":0.688,"aspect_class":"tall","bytes":4184,"shapes":8,"anchors":125,"colors":["#c4baff","#6750e5","#a28bca","#dcc6ff","#91c5aa","#3965af","#803fa5","#4b114a"],"n_colors":8,"color_families":["blue","green","pink","purple"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"M from overlapping translucent triangles","geometry":["triangle"],"techniques":["overlap-transparency","geometric-construction"],"type_style":"geometric-sans","case":"uppercase","mood":["mystical","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"maestro.svg","brand":"maestro","variant":"main","pair":null,"width":256.0,"height":199.0,"aspect":1.286,"aspect_class":"wide","bytes":5187,"shapes":5,"anchors":148,"colors":["#6c6bbd","#d32011","#0099df","#110f0d"],"n_colors":4,"color_families":["black","blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"two overlapping red and blue circles","geometry":["circle"],"techniques":["overlap-transparency","mirror-symmetry"],"type_style":"geometric-sans","case":"lowercase","mood":["trustworthy","simple"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"mageia.svg","brand":"mageia","variant":"main","pair":null,"width":512.0,"height":158.0,"aspect":3.241,"aspect_class":"horizontal","bytes":4885,"shapes":14,"anchors":126,"colors":["#262f45","#2397d4"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"cauldron with rising bubbles","geometry":["circle"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["light","magical"],"industry":"os-platform","exemplary":false,"note":""},{"file":"magento.svg","brand":"magento","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1777,"shapes":4,"anchors":49,"colors":["#27140d","#f26724","#fddfdd"],"n_colors":3,"color_families":["orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"isometric folded M in orange circle","geometry":["hexagon","circle"],"techniques":["isometric-3d","containment","geometric-construction"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"mailchimp-freddie.svg","brand":"mailchimp-freddie","variant":"main","pair":null,"width":256.0,"height":291.0,"aspect":0.88,"aspect_class":"square","bytes":91989,"shapes":41,"anchors":2473,"colors":["#59473d","#141c26","#856249","#3478ad","#fce9c9","#4d94c3","#ffffff","#efcfa5","#e1b27e","#face56"],"n_colors":10,"color_families":["blue","orange","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"winking chimp in mail carrier hat","geometry":["organic"],"techniques":["dimensional-shading","hand-drawn"],"type_style":null,"case":null,"mood":["playful","friendly","cheeky"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"mailchimp.svg","brand":"mailchimp","variant":"main","pair":null,"width":512.0,"height":126.0,"aspect":4.063,"aspect_class":"horizontal","bytes":11595,"shapes":7,"anchors":306,"colors":["#0b0b0a","#0b0c0a"],"n_colors":2,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"MailChimp in brush script","geometry":[],"techniques":["hand-drawn"],"type_style":"script","case":"mixed","mood":["playful","casual"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"maildeveloper.svg","brand":"maildeveloper","variant":"main","pair":null,"width":256.0,"height":159.0,"aspect":1.61,"aspect_class":"wide","bytes":1192,"shapes":4,"anchors":32,"colors":["#393e42","#60676f","#303439"],"n_colors":3,"color_families":["gray"],"primary_family":"mono","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"blocky MD letters with shadow","geometry":["square"],"techniques":["geometric-construction","dimensional-shading"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"mailgun-icon.svg","brand":"mailgun","variant":"icon","pair":"mailgun.svg","width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":1749,"shapes":2,"anchors":35,"colors":["#c02428"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"at sign shaped like bullseye target","geometry":["circle"],"techniques":["line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["bold","direct"],"industry":"developer-tools","exemplary":true,"note":"@ sign merged with bullseye target; email plus precision."},{"file":"mailgun.svg","brand":"mailgun","variant":"main","pair":"mailgun-icon.svg","width":512.0,"height":143.0,"aspect":3.58,"aspect_class":"horizontal","bytes":4754,"shapes":3,"anchors":152,"colors":["#c02428","#000000"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"at sign shaped like bullseye target","geometry":["circle"],"techniques":["line-monoline","hidden-meaning"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"mailjet.svg","brand":"mailjet","variant":"main","pair":null,"width":513.0,"height":201.0,"aspect":2.552,"aspect_class":"horizontal","bytes":3414,"shapes":2,"anchors":124,"colors":["#fead0d"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"paper plane with speed trail","geometry":["triangle"],"techniques":["motion-lines"],"type_style":"humanist-sans","case":"lowercase","mood":["fast","friendly"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"malinajs.svg","brand":"malinajs","variant":"main","pair":null,"width":256.0,"height":328.0,"aspect":0.78,"aspect_class":"tall","bytes":5397,"shapes":3,"anchors":165,"colors":["#008000","#ff0000"],"n_colors":2,"color_families":["green","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"raspberry made of red circles","geometry":["circle"],"techniques":["modular-repetition","hidden-meaning"],"type_style":null,"case":null,"mood":["playful","fresh"],"industry":"framework-library","exemplary":false,"note":""},{"file":"manjaro.svg","brand":"manjaro","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":408,"shapes":2,"anchors":17,"colors":["#35bf5c"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"green blocks forming abstract m","geometry":["square"],"techniques":["negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["minimal","solid"],"industry":"os-platform","exemplary":true,"note":"Pure rectangles and gaps build an m; extreme reduction."},{"file":"manuscript.svg","brand":"manuscript","variant":"main","pair":null,"width":256.0,"height":316.0,"aspect":0.81,"aspect_class":"square","bytes":3923,"shapes":3,"anchors":112,"colors":["#ffffff","#3933ff","#944dff"],"n_colors":3,"color_families":["blue","purple","white"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"nested M shapes in blue-violet","geometry":["square"],"techniques":["gradient","stacked-layers","geometric-construction"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"mapbox-icon.svg","brand":"mapbox","variant":"icon","pair":"mapbox.svg","width":256.0,"height":254.0,"aspect":1.008,"aspect_class":"square","bytes":786,"shapes":2,"anchors":20,"colors":["#485160"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"map pin blob with compass star","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["modern","navigational"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"mapbox.svg","brand":"mapbox","variant":"main","pair":"mapbox-icon.svg","width":512.0,"height":114.0,"aspect":4.491,"aspect_class":"horizontal","bytes":5543,"shapes":2,"anchors":194,"colors":["#485160"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"map pin blob with compass star","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"maps-me.svg","brand":"maps-me","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3516,"shapes":13,"anchors":99,"colors":["#4cd960","#ffffff"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"suitcase with map pattern in circle","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["friendly","adventurous"],"industry":"travel-transport","exemplary":false,"note":""},{"file":"mapzen-icon.svg","brand":"mapzen","variant":"icon","pair":"mapzen.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2266,"shapes":2,"anchors":103,"colors":["#54485b"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"compass rose with angular frame lines","geometry":["star","radial"],"techniques":["radial-symmetry","line-monoline"],"type_style":null,"case":null,"mood":["technical","navigational"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"mapzen.svg","brand":"mapzen","variant":"main","pair":"mapzen-icon.svg","width":512.0,"height":150.0,"aspect":3.413,"aspect_class":"horizontal","bytes":4225,"shapes":3,"anchors":185,"colors":["#54485b"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"compass rose with angular frame","geometry":["star","radial"],"techniques":["radial-symmetry","line-monoline"],"type_style":"geometric-sans","case":"titlecase","mood":["technical","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"mariadb-icon.svg","brand":"mariadb","variant":"icon","pair":"mariadb.svg","width":256.0,"height":170.0,"aspect":1.506,"aspect_class":"wide","bytes":3898,"shapes":4,"anchors":81,"colors":["#002b64","#c49a6c"],"n_colors":2,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"sea lion silhouette","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["friendly","natural"],"industry":"database-data","exemplary":false,"note":""},{"file":"mariadb.svg","brand":"mariadb","variant":"main","pair":"mariadb-icon.svg","width":512.0,"height":151.0,"aspect":3.391,"aspect_class":"horizontal","bytes":8152,"shapes":5,"anchors":218,"colors":["#a57242","#002b64","#c49a6c"],"n_colors":3,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"sea lion silhouette","geometry":["organic"],"techniques":[],"type_style":"humanist-sans","case":"mixed","mood":["friendly","approachable"],"industry":"database-data","exemplary":false,"note":""},{"file":"marionette.svg","brand":"marionette","variant":"main","pair":null,"width":256.0,"height":315.0,"aspect":0.813,"aspect_class":"square","bytes":5510,"shapes":16,"anchors":166,"colors":["#939598","#931a2b","#a7a9ac","#bcbec0","#808285","#a81e2c","#ce2227","#a51724"],"n_colors":8,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"M puppet hanging from control bar","geometry":["freeform"],"techniques":["hidden-meaning","dimensional-shading"],"type_style":null,"case":null,"mood":["playful","clever"],"industry":"framework-library","exemplary":false,"note":""},{"file":"markdown.svg","brand":"markdown","variant":"main","pair":null,"width":256.0,"height":158.0,"aspect":1.62,"aspect_class":"wide","bytes":981,"shapes":2,"anchors":39,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"M and down arrow in rounded frame","geometry":["rounded-square"],"techniques":["containment","arrow","letter-substitution"],"type_style":"display-custom","case":"uppercase","mood":["functional","minimal"],"industry":"programming-language","exemplary":true,"note":"M plus down-arrow spells 'markdown' with pure simplicity."},{"file":"marko.svg","brand":"marko","variant":"main","pair":null,"width":256.0,"height":214.0,"aspect":1.196,"aspect_class":"square","bytes":9587,"shapes":17,"anchors":254,"colors":["#272525","#8dc220","#44bfef","#00ac71","#f9bc00","#df1b1c","#8ac23e","#698932","#ffed01","#e02a89","#7f1e4f","#e95506","#88d0f1","#00828b","#2073ba","#8ed0e1"],"n_colors":16,"color_families":["black","blue","cyan","green","orange","pink","red","yellow"],"primary_family":"multi","gradients":10,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"M from colorful chevron brackets","geometry":["triangle"],"techniques":["bracket-code","color-segments","gradient"],"type_style":"humanist-sans","case":"lowercase","mood":["vibrant","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"marvel.svg","brand":"marvel","variant":"main","pair":null,"width":512.0,"height":223.0,"aspect":2.296,"aspect_class":"wide","bytes":4425,"shapes":2,"anchors":91,"colors":["#20b6ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"marvel in brush script with swash","geometry":[],"techniques":["hand-drawn"],"type_style":"script","case":"lowercase","mood":["creative","energetic"],"industry":"design-creative","exemplary":false,"note":""},{"file":"mastercard.svg","brand":"mastercard","variant":"main","pair":null,"width":256.0,"height":199.0,"aspect":1.286,"aspect_class":"wide","bytes":5188,"shapes":5,"anchors":168,"colors":["#000000","#ff5f00","#eb001b","#f79e1b"],"n_colors":4,"color_families":["black","orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"overlapping red and yellow circles","geometry":["circle"],"techniques":["overlap-transparency","mirror-symmetry"],"type_style":"geometric-sans","case":"lowercase","mood":["trustworthy","warm"],"industry":"payments-fintech","exemplary":true,"note":"Two overlapping circles: iconic, reducible, color-driven identity."},{"file":"mastodon-icon.svg","brand":"mastodon","variant":"icon","pair":"mastodon.svg","width":256.0,"height":274.0,"aspect":0.934,"aspect_class":"square","bytes":1647,"shapes":3,"anchors":40,"colors":["#3088d4","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"m inside rounded speech bubble","geometry":["organic"],"techniques":["speech-bubble","negative-space"],"type_style":null,"case":null,"mood":["friendly","social"],"industry":"social-communication","exemplary":false,"note":""},{"file":"mastodon.svg","brand":"mastodon","variant":"main","pair":"mastodon-icon.svg","width":512.0,"height":127.0,"aspect":4.031,"aspect_class":"horizontal","bytes":6420,"shapes":3,"anchors":175,"colors":["#3088d4","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"m inside rounded speech bubble","geometry":["organic"],"techniques":["speech-bubble","negative-space"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","open"],"industry":"social-communication","exemplary":false,"note":""},{"file":"material-ui.svg","brand":"material-ui","variant":"main","pair":null,"width":256.0,"height":204.0,"aspect":1.255,"aspect_class":"wide","bytes":676,"shapes":5,"anchors":33,"colors":["#00b0ff","#0081cb"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"isometric blue blocks forming MU","geometry":["grid-modular"],"techniques":["isometric-3d","geometric-construction","dimensional-shading"],"type_style":null,"case":null,"mood":["structured","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"materializecss.svg","brand":"materializecss","variant":"main","pair":null,"width":256.0,"height":131.0,"aspect":1.954,"aspect_class":"wide","bytes":5636,"shapes":7,"anchors":112,"colors":["#eb7077","#f6a2ad"],"n_colors":2,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"M from folding pink ribbon","geometry":["organic"],"techniques":["overlap-transparency","dimensional-shading"],"type_style":null,"case":null,"mood":["soft","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"matplotlib-icon.svg","brand":"matplotlib","variant":"icon","pair":"matplotlib.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":189810,"shapes":19,"anchors":8369,"colors":["#ffffff","#11557c","#858585","#818181","#004cff","#ceff29","#ff6800","#ffc400","#29ffce","#7dff7a","#000000"],"n_colors":11,"color_families":["black","blue","cyan","gray","green","orange","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"polar bar chart inside circle","geometry":["circle","radial"],"techniques":["radial-symmetry","color-segments","line-monoline"],"type_style":null,"case":null,"mood":["scientific","analytical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"matplotlib.svg","brand":"matplotlib","variant":"main","pair":"matplotlib-icon.svg","width":512.0,"height":103.0,"aspect":4.971,"aspect_class":"extra-wide","bytes":211368,"shapes":21,"anchors":8974,"colors":["#11557c","#ffffff","#858585","#818181","#004cff","#ceff29","#ff6800","#ffc400","#29ffce","#7dff7a","#000000"],"n_colors":11,"color_families":["black","blue","cyan","gray","green","orange","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"polar chart replaces o in name","geometry":[],"techniques":["letter-substitution"],"type_style":"humanist-sans","case":"lowercase","mood":["scientific","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"mattermost-icon.svg","brand":"mattermost","variant":"icon","pair":"mattermost.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1791,"shapes":2,"anchors":46,"colors":["#0058cc"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"open ring with droplet needle inside","geometry":["circle"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["bold","trustworthy"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"mattermost.svg","brand":"mattermost","variant":"main","pair":"mattermost-icon.svg","width":512.0,"height":85.0,"aspect":6.024,"aspect_class":"extra-wide","bytes":13739,"shapes":2,"anchors":348,"colors":["#0058cc"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"open ring with droplet needle","geometry":["circle"],"techniques":["negative-space"],"type_style":"humanist-sans","case":"titlecase","mood":["professional","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"maven.svg","brand":"maven","variant":"main","pair":null,"width":512.0,"height":139.0,"aspect":3.683,"aspect_class":"horizontal","bytes":38876,"shapes":15,"anchors":980,"colors":["#000000","#f69923","#f79a23","#e97826","#9e2064","#c92037","#cd2335","#282662","#662e8d","#9f2064","#cd2032"],"n_colors":11,"color_families":["black","blue","orange","pink","purple","red"],"primary_family":"multi","gradients":14,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"Maven with feather replacing v","geometry":[],"techniques":["letter-substitution"],"type_style":"grotesque-sans","case":"titlecase","mood":["bold","solid"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"maxcdn.svg","brand":"maxcdn","variant":"main","pair":null,"width":512.0,"height":117.0,"aspect":4.376,"aspect_class":"horizontal","bytes":3151,"shapes":4,"anchors":114,"colors":["#ff6600","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"maxcdn lettering in orange slanted box","geometry":["square"],"techniques":["containment","motion-lines"],"type_style":"display-custom","case":"lowercase","mood":["fast","energetic"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"mdn.svg","brand":"mdn","variant":"main","pair":null,"width":256.0,"height":226.0,"aspect":1.133,"aspect_class":"square","bytes":4435,"shapes":9,"anchors":123,"colors":["#ffffff","#f2f2f2","#2075bc","#29aae1","#0a6aa8","#1699c8"],"n_colors":6,"color_families":["blue","white"],"primary_family":"blue","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"dinosaur head on folded map","geometry":["square"],"techniques":["negative-space","dimensional-shading"],"type_style":null,"case":null,"mood":["bold","informative"],"industry":"education","exemplary":false,"note":""},{"file":"mdx.svg","brand":"mdx","variant":"main","pair":null,"width":512.0,"height":212.0,"aspect":2.415,"aspect_class":"wide","bytes":1516,"shapes":6,"anchors":61,"colors":["#ffffff","#eaeaea","#000000","#f9ac00"],"n_colors":4,"color_families":["black","white","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"M arrow X in rounded frame","geometry":["rounded-square"],"techniques":["letter-substitution","arrow","containment"],"type_style":"display-custom","case":"uppercase","mood":["functional","playful"],"industry":"programming-language","exemplary":false,"note":""},{"file":"medium-icon.svg","brand":"medium","variant":"icon","pair":"medium.svg","width":256.0,"height":146.0,"aspect":1.753,"aspect_class":"wide","bytes":852,"shapes":2,"anchors":16,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"circle and two ellipses in sequence","geometry":["circle"],"techniques":["geometric-construction","modular-repetition"],"type_style":null,"case":null,"mood":["minimal","editorial"],"industry":"media-entertainment","exemplary":true,"note":"Three pure ellipses; radical geometric reduction with rhythm."},{"file":"medium.svg","brand":"medium","variant":"main","pair":"medium-icon.svg","width":512.0,"height":78.0,"aspect":6.564,"aspect_class":"extra-wide","bytes":4425,"shapes":2,"anchors":165,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"circle and two ellipses","geometry":["circle"],"techniques":["geometric-construction","modular-repetition"],"type_style":"serif","case":"titlecase","mood":["editorial","refined"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"memcached.svg","brand":"memcached","variant":"main","pair":null,"width":254.0,"height":254.0,"aspect":1.0,"aspect_class":"square","bytes":4176,"shapes":7,"anchors":85,"colors":["#000000","#ffffff","#574c4a","#80716d","#268d83","#2ea19e","#db7c7c","#c83737"],"n_colors":8,"color_families":["black","cyan","gray","red","white"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"teal M with red eyes in rounded tile","geometry":["rounded-square"],"techniques":["containment","hidden-meaning"],"type_style":null,"case":null,"mood":["quirky","technical"],"industry":"database-data","exemplary":false,"note":""},{"file":"memsql-icon.svg","brand":"memsql","variant":"icon","pair":"memsql.svg","width":256.0,"height":184.0,"aspect":1.391,"aspect_class":"wide","bytes":6201,"shapes":6,"anchors":61,"colors":["#ff7bff","#f46bff","#d945ff","#c527ff","#b611ff","#ad04ff","#aa00ff","#a601fb","#9a04f0","#8608de","#690ec5","#4516a4","#311b92","#f268ff","#d843ff","#c426ff"],"n_colors":16,"color_families":["blue","pink","purple"],"primary_family":"multi","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"purple gradient ribbon arcs","geometry":["circle"],"techniques":["gradient","overlap-transparency"],"type_style":null,"case":null,"mood":["vibrant","modern"],"industry":"database-data","exemplary":false,"note":""},{"file":"memsql.svg","brand":"memsql","variant":"main","pair":"memsql-icon.svg","width":512.0,"height":82.0,"aspect":6.244,"aspect_class":"extra-wide","bytes":8422,"shapes":7,"anchors":156,"colors":["#000000","#ff7bff","#f46bff","#d945ff","#c527ff","#b611ff","#ad04ff","#aa00ff"],"n_colors":8,"color_families":["black","pink","purple"],"primary_family":"multi","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"purple gradient ribbon arcs","geometry":["circle"],"techniques":["gradient"],"type_style":"geometric-sans","case":"mixed","mood":["modern","techy"],"industry":"database-data","exemplary":false,"note":""},{"file":"mention.svg","brand":"mention","variant":"main","pair":null,"width":512.0,"height":100.0,"aspect":5.12,"aspect_class":"extra-wide","bytes":4624,"shapes":3,"anchors":183,"colors":["#5a7281","#00a0de"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"white star in blue circle","geometry":["circle","star"],"techniques":["containment","negative-space"],"type_style":"serif","case":"lowercase","mood":["friendly","approachable"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"mercurial.svg","brand":"mercurial","variant":"main","pair":null,"width":256.0,"height":329.0,"aspect":0.778,"aspect_class":"tall","bytes":10053,"shapes":22,"anchors":234,"colors":["#010101","#1b1a1b","#bfbfbf","#000000","#ffffff","#999999","#f3f3f3"],"n_colors":7,"color_families":["black","gray","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"glossy liquid mercury droplets","geometry":["organic"],"techniques":["dimensional-shading","gradient"],"type_style":"humanist-sans","case":"lowercase","mood":["fluid","dated"],"industry":"developer-tools","exemplary":false,"note":"Glossy chrome rendering; poor reduction and dated look."},{"file":"mesos.svg","brand":"mesos","variant":"main","pair":null,"width":256.0,"height":291.0,"aspect":0.88,"aspect_class":"square","bytes":2258,"shapes":25,"anchors":96,"colors":["#ffffff","#00aede"],"n_colors":2,"color_families":["cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"M assembled from cyan triangles","geometry":["triangle","grid-modular"],"techniques":["modular-repetition","geometric-construction","negative-space"],"type_style":null,"case":null,"mood":["structured","modern"],"industry":"cloud-infrastructure","exemplary":true,"note":"M assembled from repeated triangles; modular construction lesson."},{"file":"metabase.svg","brand":"metabase","variant":"main","pair":null,"width":256.0,"height":324.0,"aspect":0.79,"aspect_class":"tall","bytes":5379,"shapes":23,"anchors":110,"colors":["#509ee3"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"dot grid with darker dots forming M","geometry":["grid-modular","circle"],"techniques":["modular-repetition","pixel","hidden-meaning"],"type_style":null,"case":null,"mood":["analytical","friendly"],"industry":"marketing-analytics","exemplary":true,"note":"Letter M emerges from a uniform dot grid via tone only."},{"file":"metamask-icon.svg","brand":"metamask","variant":"icon","pair":"metamask.svg","width":256.0,"height":240.0,"aspect":1.067,"aspect_class":"square","bytes":3902,"shapes":30,"anchors":183,"colors":["#e17726","#e27625","#d5bfb2","#233447","#cc6228","#e27525","#f5841f","#c0ac9d","#161616","#763e1a"],"n_colors":10,"color_families":["black","blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"low-poly fox head","geometry":["freeform"],"techniques":["geometric-construction","color-segments","dimensional-shading"],"type_style":null,"case":null,"mood":["bold","crafty"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"metamask.svg","brand":"metamask","variant":"main","pair":"metamask-icon.svg","width":512.0,"height":96.0,"aspect":5.333,"aspect_class":"extra-wide","bytes":10893,"shapes":31,"anchors":462,"colors":["#161616","#e17726","#e27625","#d5bfb2","#233447","#cc6228","#e27525","#f5841f","#c0ac9d","#763e1a"],"n_colors":10,"color_families":["black","blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"low-poly fox head","geometry":["freeform"],"techniques":["geometric-construction","color-segments"],"type_style":"geometric-sans","case":"uppercase","mood":["techy","confident"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"meteor-icon.svg","brand":"meteor","variant":"icon","pair":"meteor.svg","width":256.0,"height":251.0,"aspect":1.02,"aspect_class":"square","bytes":1456,"shapes":8,"anchors":35,"colors":["#df4f4f"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"diagonal meteor streaks","geometry":["freeform"],"techniques":["motion-lines","modular-repetition"],"type_style":null,"case":null,"mood":["fast","dynamic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"meteor.svg","brand":"meteor","variant":"main","pair":"meteor-icon.svg","width":512.0,"height":124.0,"aspect":4.129,"aspect_class":"horizontal","bytes":2846,"shapes":13,"anchors":100,"colors":["#df4f4f","#26262c"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"METEOR with streaks replacing O","geometry":[],"techniques":["letter-substitution","motion-lines"],"type_style":"geometric-sans","case":"uppercase","mood":["dynamic","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"microcosm.svg","brand":"microcosm","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2307,"shapes":4,"anchors":46,"colors":["#184ae8","#ff6464"],"n_colors":2,"color_families":["blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"blue planet with coral ring","geometry":["circle"],"techniques":["overlap-transparency"],"type_style":null,"case":null,"mood":["playful","cosmic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"microsoft-azure.svg","brand":"microsoft-azure","variant":"main","pair":null,"width":256.0,"height":242.0,"aspect":1.058,"aspect_class":"square","bytes":2393,"shapes":5,"anchors":44,"colors":["#0078d4","#114a8b","#0669bc","#3ccbf4","#2892df"],"n_colors":5,"color_families":["blue","cyan"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"A from overlapping blue gradient shapes","geometry":["triangle"],"techniques":["gradient","overlap-transparency","dimensional-shading"],"type_style":null,"case":null,"mood":["modern","trustworthy"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"microsoft-edge.svg","brand":"microsoft-edge","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4772,"shapes":7,"anchors":76,"colors":["#0c59a4","#114a8b","#1b9de2","#1595df","#0680d7","#0078d4","#35c1f1","#34c1ed","#2fc2df","#2bc3d2","#36c752","#66eb6e"],"n_colors":12,"color_families":["blue","cyan","green"],"primary_family":"multi","gradients":6,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"swirling wave forming e","geometry":["circle"],"techniques":["gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["fluid","modern"],"industry":"os-platform","exemplary":false,"note":""},{"file":"microsoft-onedrive.svg","brand":"microsoft-onedrive","variant":"main","pair":null,"width":256.0,"height":165.0,"aspect":1.552,"aspect_class":"wide","bytes":1248,"shapes":5,"anchors":31,"colors":["#0364b8","#0078d4","#1490df","#28a8ea"],"n_colors":4,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cloud from overlapping blue lobes","geometry":["organic"],"techniques":["overlap-transparency","color-segments"],"type_style":null,"case":null,"mood":["soft","reliable"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"microsoft-power-bi.svg","brand":"microsoft-power-bi","variant":"main","pair":null,"width":256.0,"height":342.0,"aspect":0.749,"aspect_class":"tall","bytes":2036,"shapes":7,"anchors":29,"colors":["#000000","#e6ad10","#c87e0e","#f6d751","#f9e589"],"n_colors":5,"color_families":["black","orange","yellow"],"primary_family":"multi","gradients":3,"has_mask":true,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"three rising yellow bars","geometry":["square"],"techniques":["gradient","stacked-layers"],"type_style":null,"case":null,"mood":["analytical","warm"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"microsoft-teams.svg","brand":"microsoft-teams","variant":"main","pair":null,"width":256.0,"height":239.0,"aspect":1.071,"aspect_class":"square","bytes":3991,"shapes":15,"anchors":109,"colors":["#5059c9","#7b83eb","#000000","#ffffff","#5a62c3","#4d55bd","#3940ab"],"n_colors":7,"color_families":["black","blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"T tile with people silhouettes","geometry":["rounded-square"],"techniques":["overlap-transparency","dimensional-shading","containment"],"type_style":"display-custom","case":"uppercase","mood":["collaborative","professional"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"microsoft-windows.svg","brand":"microsoft-windows","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":560,"shapes":2,"anchors":20,"colors":["#00adef"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"four-pane window in perspective","geometry":["square","grid-modular"],"techniques":["modular-repetition","isometric-3d"],"type_style":null,"case":null,"mood":["clean","iconic"],"industry":"os-platform","exemplary":false,"note":""},{"file":"microsoft.svg","brand":"microsoft","variant":"main","pair":null,"width":512.0,"height":110.0,"aspect":4.655,"aspect_class":"extra-wide","bytes":6268,"shapes":6,"anchors":199,"colors":["#706d6e","#f1511b","#80cc28","#00adef","#fbbc09"],"n_colors":5,"color_families":["blue","gray","green","orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"four colored squares in grid","geometry":["square","grid-modular"],"techniques":["color-segments","modular-repetition"],"type_style":"humanist-sans","case":"titlecase","mood":["trustworthy","balanced"],"industry":"os-platform","exemplary":true,"note":"Four colored squares; maximal simplicity with a clear system."},{"file":"middleman.svg","brand":"middleman","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1249,"shapes":8,"anchors":57,"colors":["#f1c761","#000000","#ffffff"],"n_colors":3,"color_families":["black","white","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"3D boxy MM in yellow tile","geometry":["rounded-square"],"techniques":["containment","dimensional-shading","isometric-3d"],"type_style":"display-custom","case":"uppercase","mood":["solid","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"milligram.svg","brand":"milligram","variant":"main","pair":null,"width":256.0,"height":370.0,"aspect":0.692,"aspect_class":"tall","bytes":1309,"shapes":2,"anchors":26,"colors":["#9b4dca"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"outlined purple water drop","geometry":["organic"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["light","minimal"],"industry":"framework-library","exemplary":false,"note":""},{"file":"mint-lang.svg","brand":"mint-lang","variant":"main","pair":null,"width":512.0,"height":111.0,"aspect":4.613,"aspect_class":"extra-wide","bytes":6109,"shapes":4,"anchors":150,"colors":["#444444","#3ac155","#0cb3ff"],"n_colors":3,"color_families":["blue","gray","green"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"stylized green mint leaf","geometry":["organic"],"techniques":["gradient"],"type_style":"geometric-sans","case":"titlecase","mood":["fresh","clean"],"industry":"programming-language","exemplary":false,"note":""},{"file":"mio.svg","brand":"mio","variant":"main","pair":null,"width":512.0,"height":229.0,"aspect":2.236,"aspect_class":"wide","bytes":4237,"shapes":6,"anchors":116,"colors":["#963398","#1ebdbf","#492670","#ffffff","#3e1b67"],"n_colors":5,"color_families":["cyan","pink","purple","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"purple speech bubble with dots","geometry":["square"],"techniques":["speech-bubble","dimensional-shading"],"type_style":"geometric-sans","case":"titlecase","mood":["friendly","conversational"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"mist.svg","brand":"mist","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2263,"shapes":10,"anchors":30,"colors":["#e9e9e9","#a4a4a4","#121212","#171717","#212121","#010101","#ffffff","#c2c1c1","#a2a2a1","#b3b3b3"],"n_colors":10,"color_families":["black","gray","white"],"primary_family":"mono","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"swirling dark wave strips in circle","geometry":["circle"],"techniques":["stacked-layers","motion-lines","containment"],"type_style":null,"case":null,"mood":["mysterious","fluid"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"mithril.svg","brand":"mithril","variant":"main","pair":null,"width":256.0,"height":246.0,"aspect":1.041,"aspect_class":"square","bytes":2271,"shapes":2,"anchors":50,"colors":["#010002"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three overlapping outlined rings","geometry":["circle"],"techniques":["line-monoline","overlap-transparency","radial-symmetry"],"type_style":null,"case":null,"mood":["minimal","balanced"],"industry":"framework-library","exemplary":false,"note":""},{"file":"mixmax.svg","brand":"mixmax","variant":"main","pair":null,"width":256.0,"height":203.0,"aspect":1.261,"aspect_class":"wide","bytes":674,"shapes":6,"anchors":25,"colors":["#e55cff","#24235c"],"n_colors":2,"color_families":["blue","pink"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"M from pink bars and navy slants","geometry":["square"],"techniques":["color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"mixpanel.svg","brand":"mixpanel","variant":"main","pair":null,"width":512.0,"height":168.0,"aspect":3.048,"aspect_class":"horizontal","bytes":5539,"shapes":12,"anchors":140,"colors":["#33547d"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"thin lowercase name with three dots","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["light","analytical"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"mlab.svg","brand":"mlab","variant":"main","pair":null,"width":512.0,"height":183.0,"aspect":2.798,"aspect_class":"horizontal","bytes":5796,"shapes":8,"anchors":177,"colors":["#232b32","#eca52e","#4273a5","#152331","#5488b5","#87b4d5","#f8c41b","#f9ac18"],"n_colors":8,"color_families":["blue","orange","yellow"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"glowing vacuum tube","geometry":["freeform"],"techniques":["dimensional-shading"],"type_style":"geometric-sans","case":"mixed","mood":["technical","friendly"],"industry":"database-data","exemplary":false,"note":""},{"file":"mobx.svg","brand":"mobx","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1359,"shapes":6,"anchors":58,"colors":["#ea6618","#d65813","#e05e11","#de5c16","#ffffff"],"n_colors":5,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"brackets and v forming M in orange tile","geometry":["rounded-square"],"techniques":["bracket-code","letter-substitution","containment"],"type_style":"display-custom","case":null,"mood":["technical","clever"],"industry":"framework-library","exemplary":true,"note":"]v[ reads as M; code brackets double as letter strokes."},{"file":"mocha.svg","brand":"mocha","variant":"main","pair":null,"width":256.0,"height":291.0,"aspect":0.88,"aspect_class":"square","bytes":6599,"shapes":3,"anchors":207,"colors":["#8d6748","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"hexagon badge with coffee cup and MOCHA","geometry":["hexagon"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["warm","crafted"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"mockflow-icon.svg","brand":"mockflow","variant":"icon","pair":"mockflow.svg","width":256.0,"height":220.0,"aspect":1.164,"aspect_class":"square","bytes":621,"shapes":5,"anchors":22,"colors":["#7957ff","#1b7ce2","#f845c6"],"n_colors":3,"color_families":["blue","pink"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"MF from colored triangles","geometry":["triangle"],"techniques":["color-segments","overlap-transparency","geometric-construction"],"type_style":null,"case":null,"mood":["vibrant","modern"],"industry":"design-creative","exemplary":false,"note":""},{"file":"mockflow.svg","brand":"mockflow","variant":"main","pair":"mockflow-icon.svg","width":512.0,"height":77.0,"aspect":6.649,"aspect_class":"extra-wide","bytes":3786,"shapes":6,"anchors":168,"colors":["#111111","#7957ff","#1b7ce2","#f845c6"],"n_colors":4,"color_families":["black","blue","pink"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"lettermark","subject":"MF from colored triangles","geometry":["triangle"],"techniques":["color-segments","overlap-transparency"],"type_style":"geometric-sans","case":"mixed","mood":["modern","friendly"],"industry":"design-creative","exemplary":false,"note":""},{"file":"modernizr.svg","brand":"modernizr","variant":"main","pair":null,"width":256.0,"height":123.0,"aspect":2.081,"aspect_class":"wide","bytes":412,"shapes":3,"anchors":13,"colors":["#d91b77"],"n_colors":1,"color_families":["pink"],"primary_family":"pink","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"stepped blocks beside half circle","geometry":["square","circle"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"modx-icon.svg","brand":"modx","variant":"icon","pair":"modx.svg","width":256.0,"height":266.0,"aspect":0.962,"aspect_class":"square","bytes":670,"shapes":5,"anchors":22,"colors":["#00b5de","#00decc","#ff5529","#ff9640"],"n_colors":4,"color_families":["cyan","orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"angular colored shards forming X pinwheel","geometry":["triangle"],"techniques":["color-segments","radial-symmetry","geometric-construction"],"type_style":null,"case":null,"mood":["dynamic","vibrant"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"modx.svg","brand":"modx","variant":"main","pair":"modx-icon.svg","width":512.0,"height":141.0,"aspect":3.631,"aspect_class":"horizontal","bytes":1582,"shapes":5,"anchors":73,"colors":["#00b5de","#00decc","#ff5529","#ff9640","#102c53"],"n_colors":5,"color_families":["blue","cyan","orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"angular colored shards forming X","geometry":["triangle"],"techniques":["color-segments","geometric-construction"],"type_style":"geometric-sans","case":"uppercase","mood":["dynamic","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"moltin-icon.svg","brand":"moltin","variant":"icon","pair":"moltin.svg","width":256.0,"height":291.0,"aspect":0.88,"aspect_class":"square","bytes":3354,"shapes":6,"anchors":69,"colors":["#ffffff","#999999","#e67417","#e62f17","#f2bb30"],"n_colors":5,"color_families":["gray","orange","red","white","yellow"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange wavy heart shape in hexagon","geometry":["hexagon"],"techniques":["gradient","containment"],"type_style":null,"case":null,"mood":["warm","friendly"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"moltin.svg","brand":"moltin","variant":"main","pair":"moltin-icon.svg","width":512.0,"height":162.0,"aspect":3.16,"aspect_class":"horizontal","bytes":5183,"shapes":7,"anchors":144,"colors":["#3d3d3d","#ffffff","#999999","#e67417","#e62f17","#f2bb30"],"n_colors":6,"color_families":["gray","orange","red","white","yellow"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"orange wavy shape in hexagon","geometry":["hexagon"],"techniques":["gradient","containment"],"type_style":"humanist-sans","case":"lowercase","mood":["warm","friendly"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"momentjs.svg","brand":"momentjs","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1035,"shapes":3,"anchors":24,"colors":["#376660","#529990"],"n_colors":2,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"simple clock face","geometry":["circle"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["calm","simple"],"industry":"framework-library","exemplary":false,"note":""},{"file":"monday-icon.svg","brand":"monday","variant":"icon","pair":"monday.svg","width":256.0,"height":156.0,"aspect":1.641,"aspect_class":"wide","bytes":1227,"shapes":4,"anchors":23,"colors":["#f62b54","#ffcc00","#00ca72"],"n_colors":3,"color_families":["green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two slanted pills and a dot","geometry":[],"techniques":["color-segments","modular-repetition"],"type_style":null,"case":null,"mood":["playful","energetic"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"monday.svg","brand":"monday","variant":"main","pair":"monday-icon.svg","width":512.0,"height":95.0,"aspect":5.389,"aspect_class":"extra-wide","bytes":5179,"shapes":5,"anchors":164,"colors":["#f62b54","#ffcc00","#00ca72","#333333"],"n_colors":4,"color_families":["gray","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"two slanted pills and a dot","geometry":[],"techniques":["color-segments"],"type_style":"geometric-sans","case":"lowercase","mood":["playful","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"monero.svg","brand":"monero","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":839,"shapes":3,"anchors":27,"colors":["#ff6600","#4c4c4c"],"n_colors":2,"color_families":["gray","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"M cut into orange and gray circle","geometry":["circle"],"techniques":["negative-space","color-segments","containment"],"type_style":null,"case":null,"mood":["bold","secure"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"mongodb.svg","brand":"mongodb","variant":"main","pair":null,"width":512.0,"height":146.0,"aspect":3.507,"aspect_class":"horizontal","bytes":13204,"shapes":9,"anchors":292,"colors":["#8e714e","#442d22","#ffffff","#a6a385","#499d4a","#58aa50"],"n_colors":6,"color_families":["green","orange","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"green leaf","geometry":["organic"],"techniques":["gradient"],"type_style":"serif","case":"mixed","mood":["natural","approachable"],"industry":"database-data","exemplary":false,"note":""},{"file":"mono.svg","brand":"mono","variant":"main","pair":null,"width":256.0,"height":329.0,"aspect":0.778,"aspect_class":"tall","bytes":6641,"shapes":6,"anchors":156,"colors":["#1a1918"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"stylized monkey head in black square","geometry":["square"],"techniques":["negative-space","containment"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","quirky"],"industry":"framework-library","exemplary":false,"note":""},{"file":"moon.svg","brand":"moon","variant":"main","pair":null,"width":256.0,"height":301.0,"aspect":0.85,"aspect_class":"square","bytes":979,"shapes":2,"anchors":9,"colors":["#41a7ef","#813dde","#8f2ee2","#a11ce6"],"n_colors":4,"color_families":["blue","purple"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"gradient crescent moon","geometry":["circle"],"techniques":["gradient","negative-space"],"type_style":null,"case":null,"mood":["calm","dreamy"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"mootools.svg","brand":"mootools","variant":"main","pair":null,"width":512.0,"height":109.0,"aspect":4.697,"aspect_class":"extra-wide","bytes":5436,"shapes":5,"anchors":129,"colors":["#414347","#6e788c"],"n_colors":2,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"lettering with wrench replacing l","geometry":[],"techniques":["letter-substitution","dimensional-shading"],"type_style":"display-custom","case":"lowercase","mood":["playful","dated"],"industry":"framework-library","exemplary":false,"note":""},{"file":"morpheus-icon.svg","brand":"morpheus","variant":"icon","pair":"morpheus.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1348,"shapes":3,"anchors":33,"colors":["#3db5e6","#d8292f"],"n_colors":2,"color_families":["blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"M as pulse line splitting circle","geometry":["circle"],"techniques":["negative-space","color-segments","hidden-meaning"],"type_style":null,"case":null,"mood":["dynamic","technical"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"morpheus.svg","brand":"morpheus","variant":"main","pair":"morpheus-icon.svg","width":512.0,"height":106.0,"aspect":4.83,"aspect_class":"extra-wide","bytes":4512,"shapes":4,"anchors":143,"colors":["#3db5e6","#d8292f"],"n_colors":2,"color_families":["blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"M as pulse line splitting circle","geometry":["circle"],"techniques":["negative-space","color-segments"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","modern"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"mozilla.svg","brand":"mozilla","variant":"main","pair":null,"width":512.0,"height":165.0,"aspect":3.103,"aspect_class":"horizontal","bytes":2591,"shapes":2,"anchors":106,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"moz://a in black box","geometry":["square"],"techniques":["letter-substitution","containment","hidden-meaning"],"type_style":"slab","case":"lowercase","mood":["bold","witty"],"industry":"open-source-community","exemplary":true,"note":"URL syntax :// substitutes letters; clever, ownable type idea."},{"file":"mparticle-icon.svg","brand":"mparticle","variant":"icon","pair":"mparticle.svg","width":256.0,"height":214.0,"aspect":1.196,"aspect_class":"square","bytes":603,"shapes":2,"anchors":30,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"checkered pattern of slanted black blocks","geometry":["grid-modular"],"techniques":["modular-repetition","motion-lines"],"type_style":null,"case":null,"mood":["bold","dynamic"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"mparticle.svg","brand":"mparticle","variant":"main","pair":"mparticle-icon.svg","width":512.0,"height":108.0,"aspect":4.741,"aspect_class":"extra-wide","bytes":3855,"shapes":2,"anchors":160,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"checkered slanted black blocks","geometry":["grid-modular"],"techniques":["modular-repetition"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","modern"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"multipass.svg","brand":"multipass","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1997,"shapes":3,"anchors":44,"colors":["#e95420","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"M from connected nodes in orange circle","geometry":["circle"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["technical","friendly"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"mysql-icon.svg","brand":"mysql","variant":"icon","pair":"mysql.svg","width":256.0,"height":252.0,"aspect":1.016,"aspect_class":"square","bytes":4285,"shapes":3,"anchors":91,"colors":["#00546b"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"outlined leaping dolphin","geometry":["organic"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["fluid","friendly"],"industry":"database-data","exemplary":false,"note":""},{"file":"mysql.svg","brand":"mysql","variant":"main","pair":"mysql-icon.svg","width":512.0,"height":349.0,"aspect":1.467,"aspect_class":"wide","bytes":7635,"shapes":4,"anchors":215,"colors":["#00758f","#f29111"],"n_colors":2,"color_families":["cyan","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"outlined leaping dolphin","geometry":["organic"],"techniques":["line-monoline"],"type_style":"humanist-sans","case":"mixed","mood":["friendly","approachable"],"industry":"database-data","exemplary":false,"note":""},{"file":"naiveui.svg","brand":"naiveui","variant":"main","pair":null,"width":256.0,"height":312.0,"aspect":0.821,"aspect_class":"square","bytes":2992,"shapes":4,"anchors":75,"colors":["#4c9717","#5fbc21"],"n_colors":2,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"N from folded green ribbon","geometry":["freeform"],"techniques":["dimensional-shading","overlap-transparency"],"type_style":null,"case":null,"mood":["fresh","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"namecheap.svg","brand":"namecheap","variant":"main","pair":null,"width":256.0,"height":142.0,"aspect":1.803,"aspect_class":"wide","bytes":3146,"shapes":6,"anchors":80,"colors":["#ff5000","#ff8c44","#d4202c","#d82d2b","#e25226","#eb7123","#f28920","#f69a1e","#f9a41d","#faa71d"],"n_colors":10,"color_families":["orange","red"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"N from orange gradient ribbon","geometry":["freeform"],"techniques":["gradient","overlap-transparency"],"type_style":null,"case":null,"mood":["warm","friendly"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"nanonets.svg","brand":"nanonets","variant":"main","pair":null,"width":256.0,"height":206.0,"aspect":1.243,"aspect_class":"square","bytes":2346,"shapes":2,"anchors":52,"colors":["#546fff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"connected nodes zigzagging into N","geometry":["freeform"],"techniques":["line-monoline","modular-repetition"],"type_style":null,"case":null,"mood":["technical","connected"],"industry":"ai-ml","exemplary":false,"note":""},{"file":"nativescript.svg","brand":"nativescript","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1583,"shapes":2,"anchors":42,"colors":["#3c5afd"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"N flanked by curly braces in tile","geometry":["rounded-square"],"techniques":["bracket-code","negative-space","containment"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"nats-icon.svg","brand":"nats","variant":"icon","pair":"nats.svg","width":256.0,"height":266.0,"aspect":0.962,"aspect_class":"square","bytes":674,"shapes":6,"anchors":35,"colors":["#34a574","#27aae1","#8dc63f","#375c93","#ffffff"],"n_colors":5,"color_families":["blue","green","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"N on colored quadrants with speech tail","geometry":["square"],"techniques":["color-segments","speech-bubble","negative-space"],"type_style":null,"case":null,"mood":["bold","communicative"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"nats.svg","brand":"nats","variant":"main","pair":"nats-icon.svg","width":512.0,"height":125.0,"aspect":4.096,"aspect_class":"horizontal","bytes":1966,"shapes":6,"anchors":81,"colors":["#27aae1","#34a574","#375c93","#8dc63f","#ffffff"],"n_colors":5,"color_families":["blue","green","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"NATS letters in colored boxes","geometry":["square"],"techniques":["color-segments","speech-bubble","containment"],"type_style":"display-custom","case":"uppercase","mood":["bold","modular"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"neat.svg","brand":"neat","variant":"main","pair":null,"width":256.0,"height":258.0,"aspect":0.992,"aspect_class":"square","bytes":738,"shapes":4,"anchors":17,"colors":["#53aee0","#3d81a6","#2b5b75"],"n_colors":3,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"blue triangles forming folded shape","geometry":["triangle"],"techniques":["color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["clean","crisp"],"industry":"framework-library","exemplary":false,"note":""},{"file":"neo4j.svg","brand":"neo4j","variant":"main","pair":null,"width":512.0,"height":170.0,"aspect":3.012,"aspect_class":"horizontal","bytes":3594,"shapes":4,"anchors":104,"colors":["#000000","#018bff"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"neo4j with graph node connector","geometry":[],"techniques":["hidden-meaning"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","connected"],"industry":"database-data","exemplary":false,"note":""},{"file":"neovim.svg","brand":"neovim","variant":"main","pair":null,"width":512.0,"height":148.0,"aspect":3.459,"aspect_class":"horizontal","bytes":7442,"shapes":12,"anchors":178,"colors":["#000000","#444444","#16b0ed","#0f59b2","#7db643","#367533","#88c649","#439240"],"n_colors":8,"color_families":["black","blue","gray","green"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"N from green-blue gradient facets","geometry":["freeform"],"techniques":["gradient","dimensional-shading"],"type_style":"geometric-sans","case":"lowercase","mood":["technical","fresh"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"nestjs.svg","brand":"nestjs","variant":"main","pair":null,"width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":12997,"shapes":2,"anchors":278,"colors":["#e0234e"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red cat head silhouette","geometry":["organic"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["fierce","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"netbeans.svg","brand":"netbeans","variant":"main","pair":null,"width":256.0,"height":271.0,"aspect":0.945,"aspect_class":"square","bytes":7452,"shapes":21,"anchors":154,"colors":["#e92200"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"hand-drawn wireframe cube","geometry":["diamond"],"techniques":["isometric-3d","line-monoline","hand-drawn"],"type_style":null,"case":null,"mood":["sketchy","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"netflix-icon.svg","brand":"netflix","variant":"icon","pair":"netflix.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4842,"shapes":10,"anchors":137,"colors":["#000000","#b1060f","#e50914"],"n_colors":3,"color_families":["black","red"],"primary_family":"red","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"red folded ribbon N on black","geometry":["square"],"techniques":["dimensional-shading","gradient","containment"],"type_style":null,"case":null,"mood":["cinematic","bold"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"netflix.svg","brand":"netflix","variant":"main","pair":"netflix-icon.svg","width":512.0,"height":138.0,"aspect":3.71,"aspect_class":"horizontal","bytes":1479,"shapes":2,"anchors":71,"colors":["#db202c"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"NETFLIX condensed with curved baseline","geometry":[],"techniques":[],"type_style":"display-custom","case":"uppercase","mood":["bold","cinematic"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"netlify.svg","brand":"netlify","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":7027,"shapes":2,"anchors":195,"colors":["#20c6b7","#4d9abf"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"teal diamond with network cut lines","geometry":["diamond"],"techniques":["negative-space","line-monoline"],"type_style":null,"case":null,"mood":["technical","connected"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"new-relic.svg","brand":"new-relic","variant":"main","pair":null,"width":256.0,"height":208.0,"aspect":1.231,"aspect_class":"square","bytes":6018,"shapes":12,"anchors":179,"colors":["#37808c","#9bd3cd","#1b1a19"],"n_colors":3,"color_families":["black","cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"New Relic text in teal oval","geometry":["circle"],"techniques":["containment","stacked-layers"],"type_style":"humanist-sans","case":"titlecase","mood":["dated","friendly"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"nextjs-icon.svg","brand":"nextjs","variant":"icon","pair":"nextjs.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2161,"shapes":2,"anchors":51,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"N with fading extended diagonal in circle","geometry":["circle"],"techniques":["negative-space","gradient","containment"],"type_style":null,"case":null,"mood":["minimal","sharp"],"industry":"framework-library","exemplary":false,"note":""},{"file":"nextjs.svg","brand":"nextjs","variant":"main","pair":"nextjs-icon.svg","width":512.0,"height":309.0,"aspect":1.657,"aspect_class":"wide","bytes":1804,"shapes":2,"anchors":74,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"thin NEXT with extended X stroke","geometry":[],"techniques":["ligature","geometric-construction"],"type_style":"geometric-sans","case":"uppercase","mood":["minimal","sharp"],"industry":"framework-library","exemplary":true,"note":"Hairline custom letters with an extended X stroke; distinctive type customisation."},{"file":"nginx.svg","brand":"nginx","variant":"main","pair":null,"width":256.0,"height":291.0,"aspect":0.88,"aspect_class":"square","bytes":1181,"shapes":3,"anchors":30,"colors":["#009639","#ffffff"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white N in green hexagon","geometry":["hexagon"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["solid","reliable"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"nightwatch.svg","brand":"nightwatch","variant":"main","pair":null,"width":256.0,"height":328.0,"aspect":0.78,"aspect_class":"tall","bytes":4756,"shapes":9,"anchors":107,"colors":["#794422","#502d17","#ffffff","#ff7f2b","#b1dfec","#000000"],"n_colors":6,"color_families":["black","cyan","orange","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"wide-eyed owl character","geometry":["organic"],"techniques":["dimensional-shading"],"type_style":null,"case":null,"mood":["playful","watchful"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"nim-lang.svg","brand":"nim-lang","variant":"main","pair":null,"width":512.0,"height":141.0,"aspect":3.631,"aspect_class":"horizontal","bytes":1927,"shapes":4,"anchors":62,"colors":["#000000","#f3d400","#ffe953"],"n_colors":3,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"yellow crown","geometry":["freeform"],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["regal","playful"],"industry":"programming-language","exemplary":false,"note":""},{"file":"nocodb.svg","brand":"nocodb","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3237,"shapes":5,"anchors":74,"colors":["#0381fd","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"bug-like face with circuit legs in tile","geometry":["rounded-square"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["friendly","technical"],"industry":"database-data","exemplary":false,"note":""},{"file":"nodal.svg","brand":"nodal","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":847,"shapes":5,"anchors":32,"colors":["#138ee2","#00bdff","#00e1ff"],"n_colors":3,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"isometric folded cyan N","geometry":["freeform"],"techniques":["isometric-3d","color-segments"],"type_style":null,"case":null,"mood":["fresh","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"node-sass.svg","brand":"node-sass","variant":"main","pair":null,"width":256.0,"height":293.0,"aspect":0.874,"aspect_class":"square","bytes":5606,"shapes":2,"anchors":132,"colors":["#8cc84b"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"Sass script in green hexagon","geometry":["hexagon"],"techniques":["containment"],"type_style":"script","case":"titlecase","mood":["stylish","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"nodebots.svg","brand":"nodebots","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1734,"shapes":6,"anchors":45,"colors":["#f7df1e","#2e2e2c"],"n_colors":2,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"small robot face in yellow square","geometry":["square"],"techniques":["containment"],"type_style":null,"case":null,"mood":["playful","cute"],"industry":"hardware-devices","exemplary":false,"note":""},{"file":"nodejs-icon.svg","brand":"nodejs","variant":"icon","pair":"nodejs.svg","width":256.0,"height":289.0,"aspect":0.886,"aspect_class":"square","bytes":2297,"shapes":2,"anchors":59,"colors":["#539e43"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"JS inside outlined green hexagon","geometry":["hexagon"],"techniques":["containment","line-monoline"],"type_style":"display-custom","case":"uppercase","mood":["technical","solid"],"industry":"framework-library","exemplary":false,"note":""},{"file":"nodejs.svg","brand":"nodejs","variant":"main","pair":"nodejs-icon.svg","width":512.0,"height":314.0,"aspect":1.631,"aspect_class":"wide","bytes":9336,"shapes":12,"anchors":203,"colors":["#539e43","#333333","#41873f","#418b3d","#419637","#3fa92d","#3fae2a","#54a044","#66b848","#6cc04a"],"n_colors":10,"color_families":["gray","green"],"primary_family":"green","gradients":5,"has_mask":true,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"node with hexagon o and JS badge","geometry":["hexagon"],"techniques":["letter-substitution","containment"],"type_style":"display-custom","case":"lowercase","mood":["technical","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"nodemon.svg","brand":"nodemon","variant":"main","pair":null,"width":256.0,"height":292.0,"aspect":0.877,"aspect_class":"square","bytes":1739,"shapes":3,"anchors":46,"colors":["#76d04b","#4f4d3f"],"n_colors":2,"color_families":["gray","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"horned demon n in green hexagon","geometry":["hexagon"],"techniques":["hidden-meaning","containment"],"type_style":null,"case":null,"mood":["playful","mischievous"],"industry":"developer-tools","exemplary":true,"note":"Two horns turn an n into a demon; one witty idea."},{"file":"nodeos.svg","brand":"nodeos","variant":"main","pair":null,"width":256.0,"height":274.0,"aspect":0.934,"aspect_class":"square","bytes":1014,"shapes":5,"anchors":49,"colors":["#0000aa","#00aaaa"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"stacked n diamond and OS letters","geometry":["diamond"],"techniques":["geometric-construction"],"type_style":"display-custom","case":"mixed","mood":["bold","technical"],"industry":"os-platform","exemplary":false,"note":""},{"file":"nodewebkit.svg","brand":"nodewebkit","variant":"main","pair":null,"width":256.0,"height":290.0,"aspect":0.883,"aspect_class":"square","bytes":3137,"shapes":7,"anchors":84,"colors":["#3d3b47","#cccccc","#eff3f3","#0977f7"],"n_colors":4,"color_families":["blue","gray","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"compass needle in dark hexagon","geometry":["hexagon"],"techniques":["containment"],"type_style":null,"case":null,"mood":["technical","navigational"],"industry":"framework-library","exemplary":false,"note":""},{"file":"nomad.svg","brand":"nomad","variant":"main","pair":null,"width":256.0,"height":300.0,"aspect":0.853,"aspect_class":"square","bytes":869,"shapes":5,"anchors":29,"colors":["#449b82","#9bdb9c","#56cdad","#ffffff"],"n_colors":4,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"N on isometric green hexagon cube","geometry":["hexagon"],"techniques":["isometric-3d","dimensional-shading","negative-space"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"noysi.svg","brand":"noysi","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1258,"shapes":5,"anchors":36,"colors":["#17b6a7","#ffffff"],"n_colors":2,"color_families":["cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"N cut by diagonal in teal tile","geometry":["rounded-square"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["clean","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"npm-icon.svg","brand":"npm","variant":"icon","pair":"npm.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":360,"shapes":3,"anchors":14,"colors":["#c12127","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white n in red square","geometry":["square"],"techniques":["negative-space","containment","geometric-construction"],"type_style":null,"case":null,"mood":["bold","utilitarian"],"industry":"developer-tools","exemplary":true,"note":"n carved from a solid square; pure negative-space simplicity."},{"file":"npm.svg","brand":"npm","variant":"main","pair":"npm-icon.svg","width":512.0,"height":165.0,"aspect":3.103,"aspect_class":"horizontal","bytes":542,"shapes":2,"anchors":34,"colors":["#c12127"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"blocky red npm lettering","geometry":[],"techniques":["geometric-construction"],"type_style":"display-custom","case":"lowercase","mood":["bold","utilitarian"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"nuclide.svg","brand":"nuclide","variant":"main","pair":null,"width":256.0,"height":308.0,"aspect":0.831,"aspect_class":"square","bytes":1708,"shapes":5,"anchors":52,"colors":["#7d4f8f","#3f2a70","#5a2a79"],"n_colors":3,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"purple slabs with orbiting ellipse","geometry":["freeform"],"techniques":["overlap-transparency","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","cosmic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"numpy.svg","brand":"numpy","variant":"main","pair":null,"width":256.0,"height":274.0,"aspect":0.934,"aspect_class":"square","bytes":1270,"shapes":3,"anchors":53,"colors":["#4dabcf","#4d77cf"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"isometric cubes forming N and P","geometry":["grid-modular"],"techniques":["isometric-3d","modular-repetition","dimensional-shading"],"type_style":null,"case":null,"mood":["scientific","structured"],"industry":"framework-library","exemplary":false,"note":""},{"file":"nuxt-icon.svg","brand":"nuxt","variant":"icon","pair":"nuxt.svg","width":256.0,"height":172.0,"aspect":1.488,"aspect_class":"wide","bytes":722,"shapes":3,"anchors":15,"colors":["#80eec0","#00dc82"],"n_colors":2,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two green overlapping triangles","geometry":["triangle"],"techniques":["color-segments","overlap-transparency"],"type_style":null,"case":null,"mood":["fresh","simple"],"industry":"framework-library","exemplary":false,"note":""},{"file":"nuxt.svg","brand":"nuxt","variant":"main","pair":"nuxt-icon.svg","width":512.0,"height":95.0,"aspect":5.389,"aspect_class":"extra-wide","bytes":2904,"shapes":4,"anchors":121,"colors":["#000000","#80eec0","#00dc82"],"n_colors":3,"color_families":["black","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"two green triangles like mountains","geometry":["triangle"],"techniques":["color-segments"],"type_style":"geometric-sans","case":"mixed","mood":["fresh","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"nx.svg","brand":"nx","variant":"main","pair":null,"width":256.0,"height":160.0,"aspect":1.6,"aspect_class":"wide","bytes":2951,"shapes":4,"anchors":106,"colors":["#012f55","#96d8e9","#48c4e5"],"n_colors":3,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"N with curling wave x","geometry":[],"techniques":["ligature"],"type_style":"display-custom","case":"mixed","mood":["bold","dynamic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"oauth.svg","brand":"oauth","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":10836,"shapes":45,"anchors":379,"colors":["#ffffff","#000000"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"A in circle ringed by OAUTH text","geometry":["circle"],"techniques":["containment","radial-symmetry"],"type_style":"geometric-sans","case":"uppercase","mood":["secure","official"],"industry":"security-identity","exemplary":false,"note":""},{"file":"ocaml.svg","brand":"ocaml","variant":"main","pair":null,"width":512.0,"height":141.0,"aspect":3.631,"aspect_class":"horizontal","bytes":14019,"shapes":10,"anchors":316,"colors":["#ffffff","#484444","#f29100","#ec670f"],"n_colors":4,"color_families":["gray","orange","white"],"primary_family":"orange","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"white camel in orange box","geometry":["rounded-square"],"techniques":["negative-space","containment"],"type_style":"geometric-sans","case":"mixed","mood":["warm","quirky"],"industry":"programming-language","exemplary":false,"note":""},{"file":"octodns.svg","brand":"octodns","variant":"main","pair":null,"width":256.0,"height":239.0,"aspect":1.071,"aspect_class":"square","bytes":6729,"shapes":10,"anchors":181,"colors":["#af81e0","#9069c4","#825aba","#ffffff"],"n_colors":4,"color_families":["purple","white"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"octagonal network of linked rings","geometry":["radial","circle"],"techniques":["radial-symmetry","line-monoline","overlap-transparency"],"type_style":null,"case":null,"mood":["connected","technical"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"octopus-deploy.svg","brand":"octopus-deploy","variant":"main","pair":null,"width":256.0,"height":271.0,"aspect":0.945,"aspect_class":"square","bytes":1195,"shapes":2,"anchors":21,"colors":["#2f93e0"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"blue octopus silhouette","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["friendly","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"olark.svg","brand":"olark","variant":"main","pair":null,"width":512.0,"height":323.0,"aspect":1.585,"aspect_class":"wide","bytes":5199,"shapes":2,"anchors":130,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"Olark script with speech tail underline","geometry":[],"techniques":["hand-drawn","speech-bubble"],"type_style":"script","case":"titlecase","mood":["friendly","conversational"],"industry":"social-communication","exemplary":false,"note":""},{"file":"onesignal.svg","brand":"onesignal","variant":"main","pair":null,"width":256.0,"height":236.0,"aspect":1.085,"aspect_class":"square","bytes":1856,"shapes":2,"anchors":53,"colors":["#e44a49"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"broadcast signal rings in red circle","geometry":["circle"],"techniques":["negative-space","line-monoline","containment"],"type_style":null,"case":null,"mood":["bold","alert"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"open-graph.svg","brand":"open-graph","variant":"main","pair":null,"width":256.0,"height":209.0,"aspect":1.225,"aspect_class":"square","bytes":5764,"shapes":6,"anchors":150,"colors":["#b8c6c9","#759bc5","#343532"],"n_colors":3,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"globe grid in hexagon with nodes","geometry":["hexagon"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["technical","connected"],"industry":"social-communication","exemplary":false,"note":""},{"file":"open-zeppelin-icon.svg","brand":"open-zeppelin","variant":"icon","pair":"open-zeppelin.svg","width":256.0,"height":284.0,"aspect":0.901,"aspect_class":"square","bytes":574,"shapes":4,"anchors":17,"colors":["#63d2f9","#4e5ee4","#63b0f9"],"n_colors":3,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"Z from blue parallelograms","geometry":["square"],"techniques":["color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["secure","modern"],"industry":"security-identity","exemplary":false,"note":""},{"file":"open-zeppelin.svg","brand":"open-zeppelin","variant":"main","pair":"open-zeppelin-icon.svg","width":512.0,"height":80.0,"aspect":6.4,"aspect_class":"extra-wide","bytes":4848,"shapes":5,"anchors":180,"colors":["#63d2f9","#4e5ee4","#63b0f9","#282846"],"n_colors":4,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"Z from blue parallelograms","geometry":["square"],"techniques":["color-segments","geometric-construction"],"type_style":"geometric-sans","case":"mixed","mood":["modern","trustworthy"],"industry":"security-identity","exemplary":false,"note":""},{"file":"openai-icon.svg","brand":"openai","variant":"icon","pair":"openai.svg","width":256.0,"height":260.0,"aspect":0.985,"aspect_class":"square","bytes":2615,"shapes":2,"anchors":80,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"hexagonal knot of interlocking strokes","geometry":["hexagon","radial"],"techniques":["radial-symmetry","modular-repetition","line-monoline","impossible-figure"],"type_style":null,"case":null,"mood":["intelligent","balanced"],"industry":"ai-ml","exemplary":true,"note":"One rounded module rotated six times forms an interlaced knot."},{"file":"openai.svg","brand":"openai","variant":"main","pair":"openai-icon.svg","width":512.0,"height":126.0,"aspect":4.063,"aspect_class":"horizontal","bytes":4840,"shapes":3,"anchors":176,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"hexagonal knot of interlocking strokes","geometry":["hexagon","radial"],"techniques":["radial-symmetry","modular-repetition"],"type_style":"geometric-sans","case":"mixed","mood":["intelligent","clean"],"industry":"ai-ml","exemplary":false,"note":""},{"file":"opencart.svg","brand":"opencart","variant":"main","pair":null,"width":512.0,"height":100.0,"aspect":5.12,"aspect_class":"extra-wide","bytes":8169,"shapes":2,"anchors":185,"colors":["#04b6f0","#3ecaf0"],"n_colors":2,"color_families":["cyan"],"primary_family":"cyan","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"shopping cart from line and dots","geometry":[],"techniques":["line-monoline"],"type_style":"rounded-sans","case":"lowercase","mood":["friendly","casual"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"opencollective.svg","brand":"opencollective","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":970,"shapes":3,"anchors":19,"colors":["#b8d3f4","#7fadf2"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"open ring C with lighter segment","geometry":["circle"],"techniques":["negative-space","color-segments"],"type_style":null,"case":null,"mood":["open","friendly"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"opencv.svg","brand":"opencv","variant":"main","pair":null,"width":256.0,"height":317.0,"aspect":0.808,"aspect_class":"square","bytes":7081,"shapes":5,"anchors":157,"colors":["#ff0101","#0101ff","#01ff01","#050505"],"n_colors":4,"color_families":["black","blue","green","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"three RGB open rings in triangle","geometry":["circle","triangle"],"techniques":["color-segments","radial-symmetry","negative-space"],"type_style":"geometric-sans","case":"mixed","mood":["technical","vivid"],"industry":"ai-ml","exemplary":false,"note":""},{"file":"openframeworks.svg","brand":"openframeworks","variant":"main","pair":null,"width":256.0,"height":135.0,"aspect":1.896,"aspect_class":"wide","bytes":559,"shapes":2,"anchors":19,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"solid circle and blocky F","geometry":["circle","square"],"techniques":["geometric-construction"],"type_style":"display-custom","case":"uppercase","mood":["bold","graphic"],"industry":"framework-library","exemplary":true,"note":"O and F from primitive circle and blocks; bold geometric reduction."},{"file":"opengl.svg","brand":"opengl","variant":"main","pair":null,"width":512.0,"height":224.0,"aspect":2.286,"aspect_class":"wide","bytes":6926,"shapes":2,"anchors":173,"colors":["#5586a4"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"OpenGL text with orbiting swoosh","geometry":["circle"],"techniques":["containment","motion-lines"],"type_style":"humanist-sans","case":"mixed","mood":["dated","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"openjs-foundation-icon.svg","brand":"openjs-foundation","variant":"icon","pair":"openjs-foundation.svg","width":256.0,"height":296.0,"aspect":0.865,"aspect_class":"square","bytes":2295,"shapes":2,"anchors":120,"colors":["#0075c9","#80bc00","#fde021"],"n_colors":3,"color_families":["blue","green","yellow"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"gradient hexagon with all diagonals connected","geometry":["hexagon"],"techniques":["line-monoline","gradient","geometric-construction","radial-symmetry"],"type_style":null,"case":null,"mood":["connected","inclusive"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"openjs-foundation.svg","brand":"openjs-foundation","variant":"main","pair":"openjs-foundation-icon.svg","width":512.0,"height":161.0,"aspect":3.18,"aspect_class":"horizontal","bytes":10056,"shapes":4,"anchors":410,"colors":["#54565a","#0075c9","#80bc00","#fde021"],"n_colors":4,"color_families":["blue","gray","green","yellow"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"gradient hexagon with connected diagonals","geometry":["hexagon"],"techniques":["line-monoline","gradient","geometric-construction"],"type_style":"humanist-sans","case":"titlecase","mood":["inclusive","calm"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"openlayers.svg","brand":"openlayers","variant":"main","pair":null,"width":256.0,"height":259.0,"aspect":0.988,"aspect_class":"square","bytes":1446,"shapes":5,"anchors":35,"colors":["#015965","#e5e5e5","#35bbce","#ffffff"],"n_colors":4,"color_families":["cyan","gray","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"stacked rounded diamond layers","geometry":["diamond"],"techniques":["stacked-layers","isometric-3d","gradient"],"type_style":null,"case":null,"mood":["layered","fresh"],"industry":"framework-library","exemplary":false,"note":""},{"file":"openshift.svg","brand":"openshift","variant":"main","pair":null,"width":256.0,"height":237.0,"aspect":1.08,"aspect_class":"square","bytes":3579,"shapes":13,"anchors":108,"colors":["#da2430","#e82429","#c22035","#ac223b","#b92135"],"n_colors":5,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"red ring with offset slanted segments","geometry":["circle"],"techniques":["color-segments","dimensional-shading"],"type_style":null,"case":null,"mood":["bold","dynamic"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"opensource.svg","brand":"opensource","variant":"main","pair":null,"width":256.0,"height":248.0,"aspect":1.032,"aspect_class":"square","bytes":4166,"shapes":4,"anchors":98,"colors":["#3da639","#1d531d"],"n_colors":2,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"green ring with keyhole opening","geometry":["circle"],"techniques":["negative-space","hidden-meaning"],"type_style":null,"case":null,"mood":["open","trustworthy"],"industry":"open-source-community","exemplary":true,"note":"Keyhole notch opens the ring; open-source idea in one gesture."},{"file":"openstack-icon.svg","brand":"openstack","variant":"icon","pair":"openstack.svg","width":256.0,"height":251.0,"aspect":1.02,"aspect_class":"square","bytes":843,"shapes":2,"anchors":36,"colors":["#da1a32"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"red tile split by white rectangle","geometry":["rounded-square"],"techniques":["negative-space","containment","modular-repetition"],"type_style":null,"case":null,"mood":["solid","structured"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"openstack.svg","brand":"openstack","variant":"main","pair":"openstack-icon.svg","width":512.0,"height":94.0,"aspect":5.447,"aspect_class":"extra-wide","bytes":4873,"shapes":3,"anchors":183,"colors":["#da1a32","#4e4540"],"n_colors":2,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"red tile split by white rectangle","geometry":["rounded-square"],"techniques":["negative-space","containment"],"type_style":"humanist-sans","case":"lowercase","mood":["solid","approachable"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"opentelemetry-icon.svg","brand":"opentelemetry","variant":"icon","pair":"opentelemetry.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1966,"shapes":3,"anchors":52,"colors":["#f5a800","#425cc7"],"n_colors":2,"color_families":["blue","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"geometric telescope","geometry":["freeform"],"techniques":["geometric-construction","color-segments"],"type_style":null,"case":null,"mood":["curious","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"opentelemetry.svg","brand":"opentelemetry","variant":"main","pair":"opentelemetry-icon.svg","width":512.0,"height":180.0,"aspect":2.844,"aspect_class":"horizontal","bytes":6059,"shapes":3,"anchors":217,"colors":["#f5a800","#425cc7"],"n_colors":2,"color_families":["blue","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"geometric telescope","geometry":["freeform"],"techniques":["geometric-construction","color-segments"],"type_style":"geometric-sans","case":"mixed","mood":["technical","friendly"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"opera.svg","brand":"opera","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1704,"shapes":3,"anchors":25,"colors":["#ff1b2d","#fa1a2c","#ed1528","#d60e21","#b70519","#a70014","#9c0000","#ff4b4b"],"n_colors":8,"color_families":["red"],"primary_family":"red","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"red shaded O ring","geometry":["circle"],"techniques":["gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"os-platform","exemplary":false,"note":""},{"file":"opsgenie.svg","brand":"opsgenie","variant":"main","pair":null,"width":256.0,"height":305.0,"aspect":0.839,"aspect_class":"square","bytes":1739,"shapes":4,"anchors":23,"colors":["#2684ff","#0052cc"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"person figure with V-shaped body","geometry":["circle"],"techniques":["gradient","overlap-transparency"],"type_style":null,"case":null,"mood":["friendly","alert"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"optimizely.svg","brand":"optimizely","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3523,"shapes":4,"anchors":93,"colors":["#080738","#0037ff"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"overlapping blue rings with stripes","geometry":["circle"],"techniques":["overlap-transparency","modular-repetition"],"type_style":null,"case":null,"mood":["dynamic","bold"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"oracle.svg","brand":"oracle","variant":"main","pair":null,"width":512.0,"height":67.0,"aspect":7.642,"aspect_class":"extra-wide","bytes":1969,"shapes":2,"anchors":76,"colors":["#ea1b22"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"ORACLE in wide rounded capitals","geometry":[],"techniques":[],"type_style":"display-custom","case":"uppercase","mood":["corporate","solid"],"industry":"database-data","exemplary":false,"note":""},{"file":"oreilly.svg","brand":"oreilly","variant":"main","pair":null,"width":512.0,"height":93.0,"aspect":5.505,"aspect_class":"extra-wide","bytes":1794,"shapes":3,"anchors":78,"colors":["#221f20","#d31242"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"O'REILLY in bold capitals","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"uppercase","mood":["authoritative","plain"],"industry":"education","exemplary":false,"note":""},{"file":"origami.svg","brand":"origami","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2480,"shapes":9,"anchors":30,"colors":["#e8f5ff","#64a4d8","#4492d2","#51c3f7","#046cf4","#ffffff","#5cb5ff","#7ac2ff","#cbe7ff"],"n_colors":9,"color_families":["blue","white"],"primary_family":"blue","gradients":4,"has_mask":true,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"folded paper facets in blue circle","geometry":["circle"],"techniques":["gradient","dimensional-shading","overlap-transparency"],"type_style":null,"case":null,"mood":["crafted","light"],"industry":"design-creative","exemplary":false,"note":""},{"file":"origin.svg","brand":"origin","variant":"main","pair":null,"width":256.0,"height":344.0,"aspect":0.744,"aspect_class":"tall","bytes":1818,"shapes":2,"anchors":29,"colors":["#ff9900","#f05a22"],"n_colors":2,"color_families":["orange"],"primary_family":"orange","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange ring with flaring swirl tail","geometry":["circle"],"techniques":["gradient","negative-space"],"type_style":null,"case":null,"mood":["energetic","warm"],"industry":"gaming","exemplary":false,"note":""},{"file":"oshw.svg","brand":"oshw","variant":"main","pair":null,"width":256.0,"height":269.0,"aspect":0.952,"aspect_class":"square","bytes":11127,"shapes":19,"anchors":344,"colors":["#0099b0"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"gear with keyhole notch","geometry":["circle","radial"],"techniques":["negative-space","hidden-meaning","radial-symmetry"],"type_style":"humanist-sans","case":"lowercase","mood":["open","technical"],"industry":"hardware-devices","exemplary":true,"note":"Gear with keyhole notch fuses hardware and openness."},{"file":"osquery.svg","brand":"osquery","variant":"main","pair":null,"width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":991,"shapes":9,"anchors":40,"colors":["#a596ff","#000000"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"black and purple chevrons in pinwheel","geometry":["diamond","radial"],"techniques":["radial-symmetry","color-segments","arrow"],"type_style":null,"case":null,"mood":["sharp","technical"],"industry":"security-identity","exemplary":false,"note":""},{"file":"packer.svg","brand":"packer","variant":"main","pair":null,"width":256.0,"height":413.0,"aspect":0.62,"aspect_class":"tall","bytes":546,"shapes":3,"anchors":13,"colors":["#1daeff","#1d94dd"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"slanted blue blocks forming P","geometry":["freeform"],"techniques":["dimensional-shading","color-segments"],"type_style":null,"case":null,"mood":["solid","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"pagekit.svg","brand":"pagekit","variant":"main","pair":null,"width":256.0,"height":320.0,"aspect":0.8,"aspect_class":"square","bytes":331,"shapes":2,"anchors":13,"colors":["#212121"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"square frame with notch forming P","geometry":["square"],"techniques":["negative-space","line-monoline","geometric-construction"],"type_style":null,"case":null,"mood":["minimal","bold"],"industry":"developer-tools","exemplary":true,"note":"A single square outline with one notch reads as P."},{"file":"pagekite.svg","brand":"pagekite","variant":"main","pair":null,"width":256.0,"height":285.0,"aspect":0.898,"aspect_class":"square","bytes":779,"shapes":4,"anchors":19,"colors":["#e80022","#b6b1b1","#748282"],"n_colors":3,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"red and gray chevrons like a kite","geometry":["freeform"],"techniques":["arrow","color-segments","stacked-layers"],"type_style":null,"case":null,"mood":["dynamic","dated"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"pagerduty-icon.svg","brand":"pagerduty","variant":"icon","pair":"pagerduty.svg","width":256.0,"height":372.0,"aspect":0.688,"aspect_class":"tall","bytes":724,"shapes":2,"anchors":21,"colors":["#06ac38"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"green D bowl above small square","geometry":["square"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["bold","urgent"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"pagerduty.svg","brand":"pagerduty","variant":"main","pair":"pagerduty-icon.svg","width":512.0,"height":106.0,"aspect":4.83,"aspect_class":"extra-wide","bytes":4287,"shapes":2,"anchors":148,"colors":["#06ac38"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"PagerDuty in green custom sans","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"mixed","mood":["friendly","urgent"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"panda.svg","brand":"panda","variant":"main","pair":null,"width":256.0,"height":203.0,"aspect":1.261,"aspect_class":"wide","bytes":4555,"shapes":14,"anchors":100,"colors":["#090b08","#ffffff","#e7ebe0","#e1dedc","#f1efee","#d3d0cd"],"n_colors":6,"color_families":["black","gray","green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"cute panda face","geometry":["circle"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["cute","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"parcel-icon.svg","brand":"parcel","variant":"icon","pair":"parcel.svg","width":256.0,"height":193.0,"aspect":1.326,"aspect_class":"wide","bytes":19958,"shapes":27,"anchors":592,"colors":["#e8b67f","#d2a679","#bf9064","#bd8f63","#322214","#cd9c6b","#d4a271","#deb37e","#dbad77","#d7aa77","#f8ce93","#c37a44","#bb713d","#a05728","#964e23","#e9b880","#e4af76","#c37a45","#d08d55","#dea167","#e8af73","#ecb477","#af6938","#9a5227","#8d4520","#af6a38","#b87542","#d59c66","#743f1a","#322314","#c69866","#ba8c5e","#b5875b","#845f35","#91673c","#976a40","#986b40","#ab8157","#a9794b","#ae7f53","#ac7d50","#b2875d"],"n_colors":42,"color_families":["orange"],"primary_family":"orange","gradients":14,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"open cardboard box","geometry":["freeform"],"techniques":["dimensional-shading","isometric-3d"],"type_style":null,"case":null,"mood":["realistic","warm"],"industry":"developer-tools","exemplary":false,"note":"Illustrative box rendering; too detailed for a scalable mark."},{"file":"parcel.svg","brand":"parcel","variant":"main","pair":"parcel-icon.svg","width":512.0,"height":105.0,"aspect":4.876,"aspect_class":"extra-wide","bytes":3198,"shapes":2,"anchors":180,"colors":["#be4248"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"PARCEL in condensed inline capitals","geometry":[],"techniques":["line-monoline"],"type_style":"display-custom","case":"uppercase","mood":["retro","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"parse.svg","brand":"parse","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":990,"shapes":2,"anchors":24,"colors":["#169cee"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"looping p stroke in blue circle","geometry":["circle"],"techniques":["line-monoline","negative-space","containment"],"type_style":null,"case":null,"mood":["friendly","fluid"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"parsehub.svg","brand":"parsehub","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":828,"shapes":3,"anchors":20,"colors":["#21bbd1","#20222d"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"dark p with teal circle bowl","geometry":["rounded-square"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"database-data","exemplary":false,"note":""},{"file":"partytown-icon.svg","brand":"partytown","variant":"icon","pair":"partytown.svg","width":256.0,"height":268.0,"aspect":0.955,"aspect_class":"square","bytes":6153,"shapes":12,"anchors":138,"colors":["#ff37ad","#fcc954","#2890e9","#f0a420","#2e6ac9"],"n_colors":5,"color_families":["blue","orange","pink","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"party popper with confetti","geometry":["freeform"],"techniques":["color-segments"],"type_style":null,"case":null,"mood":["festive","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"partytown.svg","brand":"partytown","variant":"main","pair":"partytown-icon.svg","width":512.0,"height":107.0,"aspect":4.785,"aspect_class":"extra-wide","bytes":16341,"shapes":13,"anchors":427,"colors":["#ff37ad","#fcc954","#2890e9","#f0a420","#2e6ac9"],"n_colors":5,"color_families":["blue","orange","pink","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"party popper with confetti","geometry":["freeform"],"techniques":["color-segments"],"type_style":"geometric-sans","case":"titlecase","mood":["festive","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"passbolt-icon.svg","brand":"passbolt","variant":"icon","pair":"passbolt.svg","width":256.0,"height":233.0,"aspect":1.099,"aspect_class":"square","bytes":1778,"shapes":2,"anchors":60,"colors":["#d40000"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"key cut into red diamond","geometry":["diamond"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["secure","bold"],"industry":"security-identity","exemplary":false,"note":""},{"file":"passbolt.svg","brand":"passbolt","variant":"main","pair":"passbolt-icon.svg","width":512.0,"height":90.0,"aspect":5.689,"aspect_class":"extra-wide","bytes":6470,"shapes":3,"anchors":216,"colors":["#d40000","#000000"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"key cut into red diamond","geometry":["diamond"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"lowercase","mood":["secure","confident"],"industry":"security-identity","exemplary":false,"note":""},{"file":"passport.svg","brand":"passport","variant":"main","pair":null,"width":256.0,"height":320.0,"aspect":0.8,"aspect_class":"square","bytes":601,"shapes":5,"anchors":22,"colors":["#d6ff00","#34e27a","#00b9f1","#ffffff"],"n_colors":4,"color_families":["cyan","green","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"ring of colored segments forming P","geometry":["circle"],"techniques":["color-segments","negative-space"],"type_style":null,"case":null,"mood":["vibrant","friendly"],"industry":"security-identity","exemplary":false,"note":""},{"file":"patreon.svg","brand":"patreon","variant":"main","pair":null,"width":256.0,"height":247.0,"aspect":1.036,"aspect_class":"square","bytes":482,"shapes":2,"anchors":10,"colors":["#ff424d"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"circle beside vertical bar forming P","geometry":["circle"],"techniques":["geometric-construction","negative-space"],"type_style":null,"case":null,"mood":["bold","minimal"],"industry":"payments-fintech","exemplary":true,"note":"P reduced to a bar and a circle; simplest possible construction."},{"file":"paypal.svg","brand":"paypal","variant":"main","pair":null,"width":256.0,"height":302.0,"aspect":0.848,"aspect_class":"square","bytes":2508,"shapes":5,"anchors":64,"colors":["#27346a","#2790c3","#1f264f"],"n_colors":3,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"two overlapping italic P letters","geometry":[],"techniques":["overlap-transparency","color-segments"],"type_style":"display-custom","case":"uppercase","mood":["trustworthy","dynamic"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"peer5.svg","brand":"peer5","variant":"main","pair":null,"width":256.0,"height":291.0,"aspect":0.88,"aspect_class":"square","bytes":901,"shapes":5,"anchors":35,"colors":["#e44d26","#ef6429","#ebebeb","#fefefe"],"n_colors":4,"color_families":["orange","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"P on orange shield like HTML5 badge","geometry":["shield"],"techniques":["containment","dimensional-shading"],"type_style":null,"case":null,"mood":["bold","derivative"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"pepperoni.svg","brand":"pepperoni","variant":"main","pair":null,"width":256.0,"height":245.0,"aspect":1.045,"aspect_class":"square","bytes":13288,"shapes":55,"anchors":276,"colors":["#d18f00","#e94f35","#f39200","#4b5b5c","#3a4949","#aa2322","#441a0d","#d89687","#914f00","#9f5600","#b76200","#c66900","#cb6c00","#fbba00","#fdc000","#ffd500","#ffe300","#ffeb00","#ffed00"],"n_colors":19,"color_families":["gray","orange","red","yellow"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"pizza slice as rocket","geometry":["triangle"],"techniques":["hidden-meaning","motion-lines"],"type_style":null,"case":null,"mood":["playful","fun"],"industry":"framework-library","exemplary":false,"note":""},{"file":"percona.svg","brand":"percona","variant":"main","pair":null,"width":256.0,"height":250.0,"aspect":1.024,"aspect_class":"square","bytes":1292,"shapes":3,"anchors":21,"colors":["#fcb42f","#fbb32f","#c11511","#c11411"],"n_colors":4,"color_families":["orange","red"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"P with yellow bowl in gradient circle","geometry":["circle"],"techniques":["gradient","negative-space","containment"],"type_style":null,"case":null,"mood":["warm","bold"],"industry":"database-data","exemplary":false,"note":""},{"file":"percy-icon.svg","brand":"percy","variant":"icon","pair":"percy.svg","width":256.0,"height":205.0,"aspect":1.249,"aspect_class":"square","bytes":3192,"shapes":2,"anchors":93,"colors":["#5c007b"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"purple hedgehog silhouette","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["playful","spiky"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"percy.svg","brand":"percy","variant":"main","pair":"percy-icon.svg","width":512.0,"height":142.0,"aspect":3.606,"aspect_class":"horizontal","bytes":8230,"shapes":2,"anchors":226,"colors":["#5c007b"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"purple hedgehog silhouette","geometry":["organic"],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["playful","friendly"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"perf-rocks.svg","brand":"perf-rocks","variant":"main","pair":null,"width":512.0,"height":99.0,"aspect":5.172,"aspect_class":"extra-wide","bytes":7824,"shapes":2,"anchors":230,"colors":["#3b4c60"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"PERF ROCKS with lightning bolt divider","geometry":[],"techniques":["letter-substitution"],"type_style":"geometric-sans","case":"uppercase","mood":["energetic","bold"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"perl.svg","brand":"perl","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4055,"shapes":8,"anchors":82,"colors":["#3a3c5b","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"onion in dark circle","geometry":["circle"],"techniques":["negative-space","line-monoline","containment"],"type_style":null,"case":null,"mood":["classic","technical"],"industry":"programming-language","exemplary":false,"note":""},{"file":"phalcon.svg","brand":"phalcon","variant":"main","pair":null,"width":256.0,"height":292.0,"aspect":0.877,"aspect_class":"square","bytes":4123,"shapes":29,"anchors":195,"colors":["#73b08f","#c5e4d3","#76c39b","#000000"],"n_colors":4,"color_families":["black","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"low-poly green falcon","geometry":["freeform"],"techniques":["geometric-construction","color-segments"],"type_style":null,"case":null,"mood":["fast","sharp"],"industry":"framework-library","exemplary":false,"note":""},{"file":"phoenix.svg","brand":"phoenix","variant":"main","pair":null,"width":256.0,"height":175.0,"aspect":1.463,"aspect_class":"wide","bytes":5188,"shapes":2,"anchors":118,"colors":["#fd4f00"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"flaming phoenix bird","geometry":["organic"],"techniques":["motion-lines"],"type_style":null,"case":null,"mood":["fiery","dynamic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"phonegap-bot.svg","brand":"phonegap-bot","variant":"main","pair":null,"width":256.0,"height":216.0,"aspect":1.185,"aspect_class":"square","bytes":30232,"shapes":87,"anchors":707,"colors":["#333333","#676767","#36a3c9","#010101","#50c8ec","#ffffff","#f3f3f3","#cdcccc","#e6e6e5","#b4b4b4","#fdfeff"],"n_colors":11,"color_families":["black","blue","cyan","gray","white"],"primary_family":"multi","gradients":41,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"isometric gray robot","geometry":["freeform"],"techniques":["isometric-3d","dimensional-shading"],"type_style":null,"case":null,"mood":["playful","mechanical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"phonegap.svg","brand":"phonegap","variant":"main","pair":null,"width":256.0,"height":279.0,"aspect":0.918,"aspect_class":"square","bytes":3308,"shapes":6,"anchors":71,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"stacked phone outlines like brackets","geometry":["rounded-square"],"techniques":["stacked-layers","negative-space","bracket-code"],"type_style":null,"case":null,"mood":["bold","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"php-alt.svg","brand":"php-alt","variant":"main","pair":null,"width":512.0,"height":258.0,"aspect":1.984,"aspect_class":"wide","bytes":1982,"shapes":2,"anchors":59,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"php in heavy italic lettering","geometry":[],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["bold","classic"],"industry":"programming-language","exemplary":false,"note":""},{"file":"php.svg","brand":"php","variant":"main","pair":null,"width":256.0,"height":135.0,"aspect":1.896,"aspect_class":"wide","bytes":3822,"shapes":8,"anchors":136,"colors":["#6181b6","#ffffff","#000004","#4c6b97","#231f20"],"n_colors":5,"color_families":["black","blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"php lettering in blue oval","geometry":["circle"],"techniques":["containment"],"type_style":"display-custom","case":"lowercase","mood":["classic","friendly"],"industry":"programming-language","exemplary":false,"note":""},{"file":"phpstorm.svg","brand":"phpstorm","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2280,"shapes":6,"anchors":65,"colors":["#000000","#ffffff","#765af8","#b345f1","#fa3293","#ff318c","#8655f6","#9f4cf3","#ae47f2"],"n_colors":9,"color_families":["black","blue","pink","purple","white"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"PS in black square on gradient shape","geometry":["square"],"techniques":["containment","gradient","overlap-transparency"],"type_style":"geometric-sans","case":"uppercase","mood":["vibrant","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"pinterest.svg","brand":"pinterest","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1441,"shapes":2,"anchors":27,"colors":["#cb1f27"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"P shaped like a pin in red circle","geometry":["circle"],"techniques":["negative-space","containment","hidden-meaning"],"type_style":null,"case":null,"mood":["bold","friendly"],"industry":"social-communication","exemplary":true,"note":"P letter doubles as a map pin; subtle hidden meaning."},{"file":"pipedrive.svg","brand":"pipedrive","variant":"main","pair":null,"width":512.0,"height":117.0,"aspect":4.376,"aspect_class":"horizontal","bytes":8305,"shapes":25,"anchors":267,"colors":["#525254","#231f1f","#3b3b3c"],"n_colors":3,"color_families":["black","gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"pipedrive in bold lowercase","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"lowercase","mood":["solid","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"pipefy.svg","brand":"pipefy","variant":"main","pair":null,"width":256.0,"height":88.0,"aspect":2.909,"aspect_class":"horizontal","bytes":5048,"shapes":2,"anchors":134,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"pipefy with custom p and y","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["modern","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"pivotal_tracker.svg","brand":"pivotal_tracker","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1559,"shapes":3,"anchors":54,"colors":["#ed7d1a","#5282b0"],"n_colors":2,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange pinwheel segments in blue ring","geometry":["circle","radial"],"techniques":["radial-symmetry","color-segments","containment"],"type_style":null,"case":null,"mood":["energetic","organized"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"pixijs.svg","brand":"pixijs","variant":"main","pair":null,"width":512.0,"height":180.0,"aspect":2.844,"aspect_class":"horizontal","bytes":2458,"shapes":2,"anchors":74,"colors":["#ea1e63"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"PixiJS in heavy magenta lettering","geometry":[],"techniques":["ligature"],"type_style":"display-custom","case":"mixed","mood":["bold","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"pkg.svg","brand":"pkg","variant":"main","pair":null,"width":256.0,"height":229.0,"aspect":1.118,"aspect_class":"square","bytes":886,"shapes":2,"anchors":18,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"black pyramid with center line","geometry":["triangle"],"techniques":["mirror-symmetry","negative-space"],"type_style":null,"case":null,"mood":["solid","minimal"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"planless-icon.svg","brand":"planless","variant":"icon","pair":"planless.svg","width":256.0,"height":330.0,"aspect":0.776,"aspect_class":"tall","bytes":1571,"shapes":5,"anchors":33,"colors":["#f7ce12","#f0572a","#2abde1","#1c519f"],"n_colors":4,"color_families":["blue","cyan","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"P from colored rounded shapes","geometry":["freeform"],"techniques":["color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["vibrant","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"planless.svg","brand":"planless","variant":"main","pair":"planless-icon.svg","width":512.0,"height":108.0,"aspect":4.741,"aspect_class":"extra-wide","bytes":14732,"shapes":5,"anchors":373,"colors":["#111111","#f7ce12","#f0572a","#2abde1","#1c519f"],"n_colors":5,"color_families":["black","blue","cyan","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"P from colored rounded shapes","geometry":["freeform"],"techniques":["color-segments"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"plastic-scm.svg","brand":"plastic-scm","variant":"main","pair":null,"width":256.0,"height":285.0,"aspect":0.898,"aspect_class":"square","bytes":3341,"shapes":4,"anchors":113,"colors":["#ff4300","#ff5b00","#dc2f03"],"n_colors":3,"color_families":["orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"P with cube in isometric orange hexagon","geometry":["hexagon"],"techniques":["isometric-3d","containment","line-monoline"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"platformio.svg","brand":"platformio","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2778,"shapes":5,"anchors":66,"colors":["#ff7f00","#ffffff","#e57200"],"n_colors":3,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"alien ant head in orange ring","geometry":["circle"],"techniques":["containment","mirror-symmetry"],"type_style":null,"case":null,"mood":["playful","quirky"],"industry":"hardware-devices","exemplary":false,"note":""},{"file":"play.svg","brand":"play","variant":"main","pair":null,"width":512.0,"height":266.0,"aspect":1.925,"aspect_class":"wide","bytes":3382,"shapes":4,"anchors":92,"colors":["#92d13d","#49691f"],"n_colors":2,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"green chevron play arrow","geometry":["triangle"],"techniques":["arrow","dimensional-shading"],"type_style":"humanist-sans","case":"lowercase","mood":["friendly","energetic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"playwright.svg","brand":"playwright","variant":"main","pair":null,"width":256.0,"height":192.0,"aspect":1.333,"aspect_class":"wide","bytes":5194,"shapes":8,"anchors":138,"colors":["#2d4552","#e2574c","#2ead33","#d65348","#1d8d22","#c04b41"],"n_colors":6,"color_families":["blue","green","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red and green theater masks","geometry":["organic"],"techniques":["overlap-transparency","hidden-meaning"],"type_style":null,"case":null,"mood":["dramatic","playful"],"industry":"testing-monitoring","exemplary":true,"note":"Theater masks literalize the name; memorable dual-mask idea."},{"file":"pm2.svg","brand":"pm2","variant":"main","pair":null,"width":512.0,"height":88.0,"aspect":5.818,"aspect_class":"extra-wide","bytes":3374,"shapes":7,"anchors":80,"colors":["#1fd3ef","#5d5d5d"],"n_colors":2,"color_families":["cyan","gray"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"PM2 name with equals-sign speed lines","geometry":[],"techniques":["motion-lines","line-monoline"],"type_style":"geometric-sans","case":"uppercase","mood":["fast","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"pnpm.svg","brand":"pnpm","variant":"main","pair":null,"width":512.0,"height":368.0,"aspect":1.391,"aspect_class":"wide","bytes":6457,"shapes":3,"anchors":191,"colors":["#f9ad00","#4e4e4e"],"n_colors":2,"color_families":["gray","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"square block grid beside name","geometry":["grid-modular","square"],"techniques":["modular-repetition","color-segments"],"type_style":"rounded-sans","case":"lowercase","mood":["orderly","bold"],"industry":"developer-tools","exemplary":false,"note":"Grid of blocks hints at package structure"},{"file":"poeditor.svg","brand":"poeditor","variant":"main","pair":null,"width":256.0,"height":207.0,"aspect":1.237,"aspect_class":"square","bytes":2091,"shapes":10,"anchors":61,"colors":["#ffffff","#24c1ce","#3dd0ad","#404953","#ffda00","#3a4287"],"n_colors":6,"color_families":["blue","cyan","gray","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"stylized parrot head, speech-bubble body","geometry":["rounded-square","organic"],"techniques":["negative-space","speech-bubble","color-segments"],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"polymer.svg","brand":"polymer","variant":"main","pair":null,"width":256.0,"height":178.0,"aspect":1.438,"aspect_class":"wide","bytes":2512,"shapes":23,"anchors":100,"colors":["#ff4081","#ffffff","#000000","#536dfe","#303f9f","#3f51b5","#7986cb"],"n_colors":7,"color_families":["black","blue","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"zigzag chain of faceted triangles","geometry":["triangle","hexagon"],"techniques":["modular-repetition","color-segments","gradient"],"type_style":null,"case":null,"mood":["dynamic","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"postcss.svg","brand":"postcss","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":43137,"shapes":4,"anchors":995,"colors":["#dd3735"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"alchemical circle, triangle and square","geometry":["circle","triangle","square"],"techniques":["containment","hand-drawn","geometric-construction"],"type_style":null,"case":null,"mood":["mystical","raw"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"postgraphile.svg","brand":"postgraphile","variant":"main","pair":null,"width":256.0,"height":247.0,"aspect":1.036,"aspect_class":"square","bytes":3749,"shapes":26,"anchors":167,"colors":["#468bcc","#4ba8ff","#ffffff","#082744","#166ebf","#0b457f","#0c3861"],"n_colors":7,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"low-poly blue elephant head","geometry":["freeform"],"techniques":["dimensional-shading","color-segments"],"type_style":null,"case":null,"mood":["technical","strong"],"industry":"database-data","exemplary":false,"note":""},{"file":"postgresql.svg","brand":"postgresql","variant":"main","pair":null,"width":256.0,"height":264.0,"aspect":0.97,"aspect_class":"square","bytes":9284,"shapes":6,"anchors":204,"colors":["#000000","#336791","#ffffff"],"n_colors":3,"color_families":["black","blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"outlined elephant head Slonik","geometry":["organic"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["sturdy","friendly"],"industry":"database-data","exemplary":false,"note":""},{"file":"postman-icon.svg","brand":"postman","variant":"icon","pair":"postman.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":8617,"shapes":22,"anchors":240,"colors":["#ff6c37","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"rocket-man figure in orange circle","geometry":["circle"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["energetic","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"postman.svg","brand":"postman","variant":"main","pair":"postman-icon.svg","width":512.0,"height":156.0,"aspect":3.282,"aspect_class":"horizontal","bytes":14258,"shapes":23,"anchors":397,"colors":["#ff6c37","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"rocket-man circle beside spaced wordmark","geometry":["circle"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["energetic","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"pouchdb.svg","brand":"pouchdb","variant":"main","pair":null,"width":256.0,"height":330.0,"aspect":0.776,"aspect_class":"tall","bytes":1547,"shapes":12,"anchors":55,"colors":["#6ccb94","#5dbd85","#64c48c","#6ecc95","#5ebe86","#76d29c","#74d09b","#58b880","#5fbf87"],"n_colors":9,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"low-poly green animal head","geometry":["freeform","triangle"],"techniques":["color-segments","dimensional-shading"],"type_style":null,"case":null,"mood":["friendly","modern"],"industry":"database-data","exemplary":false,"note":""},{"file":"preact.svg","brand":"preact","variant":"main","pair":null,"width":256.0,"height":296.0,"aspect":0.865,"aspect_class":"square","bytes":1830,"shapes":5,"anchors":40,"colors":["#673ab8","#ffffff"],"n_colors":2,"color_families":["purple","white"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"atom orbits inside purple hexagon","geometry":["hexagon","radial"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["technical","compact"],"industry":"framework-library","exemplary":false,"note":""},{"file":"precursor.svg","brand":"precursor","variant":"main","pair":null,"width":256.0,"height":299.0,"aspect":0.856,"aspect_class":"square","bytes":663,"shapes":2,"anchors":16,"colors":["#333333"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"P built from open arc and bar","geometry":["circle"],"techniques":["geometric-construction","negative-space"],"type_style":null,"case":null,"mood":["minimal","bold"],"industry":"design-creative","exemplary":true,"note":"P constructed from open arc and bar, pure geometry"},{"file":"prerender-icon.svg","brand":"prerender","variant":"icon","pair":"prerender.svg","width":256.0,"height":192.0,"aspect":1.333,"aspect_class":"wide","bytes":621,"shapes":5,"anchors":26,"colors":["#f0da50","#4bc69a","#5d7b8c"],"n_colors":3,"color_families":["blue","green","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"interlocking color blocks forming r and d","geometry":["rounded-square"],"techniques":["color-segments","negative-space"],"type_style":null,"case":null,"mood":["modern","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"prerender.svg","brand":"prerender","variant":"main","pair":"prerender-icon.svg","width":512.0,"height":81.0,"aspect":6.321,"aspect_class":"extra-wide","bytes":6798,"shapes":6,"anchors":246,"colors":["#5d7b8c","#f0da50","#4bc69a"],"n_colors":3,"color_families":["blue","green","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"block icon beside PRERENDER.IO name","geometry":["rounded-square"],"techniques":["color-segments"],"type_style":"geometric-sans","case":"uppercase","mood":["modern","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"prestashop.svg","brand":"prestashop","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":30368,"shapes":44,"anchors":732,"colors":["#a5dbe8","#525353","#000000","#aa9678","#c4b6a1","#786453","#ffffff","#bbbcbd","#676a6a","#909393","#e3dddb","#fcb03f","#9f2254","#df0067","#8b7460"],"n_colors":15,"color_families":["black","cyan","gray","orange","pink","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"puffin bird inside blue circle","geometry":["circle"],"techniques":["containment","dimensional-shading"],"type_style":null,"case":null,"mood":["friendly","playful"],"industry":"ecommerce-retail","exemplary":false,"note":"Detailed illustration, weak at small sizes"},{"file":"presto.svg","brand":"presto","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":5121,"shapes":23,"anchors":114,"colors":["#000000","#669cfe","#3fe7fe","#ffffff","#6a9efe"],"n_colors":5,"color_families":["black","blue","cyan","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"dot grid fading in speed pattern","geometry":["rounded-square","grid-modular"],"techniques":["modular-repetition","motion-lines","containment"],"type_style":null,"case":null,"mood":["fast","technical"],"industry":"database-data","exemplary":false,"note":""},{"file":"prettier.svg","brand":"prettier","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":10664,"shapes":42,"anchors":369,"colors":["#56b3b4","#ea5e5e","#bf85bf","#f7ba3e","#d0d4d8"],"n_colors":5,"color_families":["cyan","gray","pink","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"rows of colored lines like formatted code","geometry":["grid-modular"],"techniques":["modular-repetition","color-segments","hidden-meaning"],"type_style":null,"case":null,"mood":["orderly","clean"],"industry":"developer-tools","exemplary":true,"note":"Directly visualises tidy formatted code lines"},{"file":"prisma.svg","brand":"prisma","variant":"main","pair":null,"width":256.0,"height":310.0,"aspect":0.826,"aspect_class":"square","bytes":929,"shapes":2,"anchors":21,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"prism triangle with inner facet","geometry":["triangle"],"techniques":["negative-space","isometric-3d"],"type_style":null,"case":null,"mood":["sharp","minimal"],"industry":"database-data","exemplary":true,"note":"Single-stroke prism, strong simple silhouette"},{"file":"prismic-icon.svg","brand":"prismic","variant":"icon","pair":"prismic.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":4884,"shapes":5,"anchors":137,"colors":["#e55638","#f4c942","#7b8fea","#d97ee8"],"n_colors":4,"color_families":["blue","pink","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"overlapping rounded square outlines","geometry":["rounded-square"],"techniques":["overlap-transparency","gradient","color-segments"],"type_style":null,"case":null,"mood":["colorful","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"prismic.svg","brand":"prismic","variant":"main","pair":"prismic-icon.svg","width":512.0,"height":132.0,"aspect":3.879,"aspect_class":"horizontal","bytes":13642,"shapes":2,"anchors":358,"colors":["#212735"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"interlocking squares icon plus name","geometry":["rounded-square"],"techniques":["overlap-transparency"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","clean"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"processwire.svg","brand":"processwire","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3106,"shapes":2,"anchors":63,"colors":["#eb1d61"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"P drawn as continuous spiral stroke","geometry":["circle"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["friendly","fluid"],"industry":"developer-tools","exemplary":true,"note":"P drawn in one continuous stroke, very economical"},{"file":"productboard-icon.svg","brand":"productboard","variant":"icon","pair":"productboard.svg","width":256.0,"height":168.0,"aspect":1.524,"aspect_class":"wide","bytes":491,"shapes":4,"anchors":13,"colors":["#ff2638","#ffc600","#0079f2"],"n_colors":3,"color_families":["blue","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three color triangles forming chevron","geometry":["triangle","diamond"],"techniques":["color-segments","arrow"],"type_style":null,"case":null,"mood":["dynamic","bright"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"productboard.svg","brand":"productboard","variant":"main","pair":"productboard-icon.svg","width":512.0,"height":64.0,"aspect":8.0,"aspect_class":"extra-wide","bytes":8808,"shapes":4,"anchors":260,"colors":["#ff2638","#ffc600","#0079f2","#000c2c"],"n_colors":4,"color_families":["blue","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"color chevron icon plus name","geometry":["triangle"],"techniques":["color-segments","arrow"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","dynamic"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"producthunt.svg","brand":"producthunt","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":939,"shapes":3,"anchors":19,"colors":["#ffffff","#da552f","#d04b25"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white P in orange circle","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["friendly","bold"],"industry":"social-communication","exemplary":false,"note":""},{"file":"progress.svg","brand":"progress","variant":"main","pair":null,"width":256.0,"height":277.0,"aspect":0.924,"aspect_class":"square","bytes":511,"shapes":2,"anchors":18,"colors":["#5ce500"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric green arrow of stacked planes","geometry":["freeform"],"techniques":["isometric-3d","arrow","stacked-layers"],"type_style":null,"case":null,"mood":["forward","energetic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"prometheus.svg","brand":"prometheus","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":1480,"shapes":2,"anchors":35,"colors":["#da4e31"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"torch flame in red circle","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["bold","warm"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"promises.svg","brand":"promises","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3255,"shapes":3,"anchors":97,"colors":["#fbde34","#524739"],"n_colors":2,"color_families":["orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"word then in yellow square","geometry":["square"],"techniques":["containment","hidden-meaning"],"type_style":"grotesque-sans","case":"lowercase","mood":["simple","witty"],"industry":"framework-library","exemplary":false,"note":"Uses the API keyword then as identity"},{"file":"proofy.svg","brand":"proofy","variant":"main","pair":null,"width":256.0,"height":261.0,"aspect":0.981,"aspect_class":"square","bytes":1463,"shapes":4,"anchors":48,"colors":["#13c779","#ffffff","#231f1f"],"n_colors":3,"color_families":["black","green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"envelope check inside green shield","geometry":["shield"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["trustworthy","clean"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"prospect.svg","brand":"prospect","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1466,"shapes":3,"anchors":35,"colors":["#9933cc","#ffffff"],"n_colors":2,"color_families":["purple","white"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"white carrot in purple rounded square","geometry":["rounded-square"],"techniques":["containment"],"type_style":null,"case":null,"mood":["playful","bold"],"industry":"other","exemplary":false,"note":""},{"file":"protactor.svg","brand":"protactor","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1505,"shapes":4,"anchors":43,"colors":["#e23237","#b52e31","#ffffff"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"protractor half-dial in red circle","geometry":["circle"],"techniques":["containment","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"protoio.svg","brand":"protoio","variant":"main","pair":null,"width":512.0,"height":135.0,"aspect":3.793,"aspect_class":"horizontal","bytes":2531,"shapes":2,"anchors":72,"colors":["#3e4245"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"proto.io name in rounded geometric type","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["clean","friendly"],"industry":"design-creative","exemplary":false,"note":""},{"file":"protonet.svg","brand":"protonet","variant":"main","pair":null,"width":512.0,"height":120.0,"aspect":4.267,"aspect_class":"horizontal","bytes":4369,"shapes":2,"anchors":156,"colors":["#e15b29"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"orange hexagon beside PROTONET name","geometry":["hexagon"],"techniques":[],"type_style":"grotesque-sans","case":"uppercase","mood":["solid","technical"],"industry":"hardware-devices","exemplary":false,"note":""},{"file":"prott.svg","brand":"prott","variant":"main","pair":null,"width":512.0,"height":197.0,"aspect":2.599,"aspect_class":"horizontal","bytes":3117,"shapes":2,"anchors":86,"colors":["#3e3e3e"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"custom prott type with joined tt","geometry":[],"techniques":["ligature"],"type_style":"display-custom","case":"lowercase","mood":["friendly","bold"],"industry":"design-creative","exemplary":false,"note":""},{"file":"pug.svg","brand":"pug","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":7871,"shapes":27,"anchors":191,"colors":["#f2f2f2","#ed1c24","#c1272d","#ff931e","#ffb81e","#f7bd89","#fbd5a0","#000000","#ffffff","#4d4d4d","#808080"],"n_colors":11,"color_families":["black","gray","orange","red","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"pug dog face in grey circle","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["playful","cute"],"industry":"framework-library","exemplary":false,"note":""},{"file":"pumpkindb.svg","brand":"pumpkindb","variant":"main","pair":null,"width":256.0,"height":326.0,"aspect":0.785,"aspect_class":"tall","bytes":3366,"shapes":14,"anchors":67,"colors":["#d04b06","#c65c14","#f17008","#8f6646","#f48d39","#f7f3f0","#160c06","#f9f6f4"],"n_colors":8,"color_families":["black","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"orange pumpkin with single eye","geometry":["organic"],"techniques":["dimensional-shading"],"type_style":null,"case":null,"mood":["playful","quirky"],"industry":"database-data","exemplary":false,"note":""},{"file":"puppet-icon.svg","brand":"puppet","variant":"icon","pair":"puppet.svg","width":256.0,"height":395.0,"aspect":0.648,"aspect_class":"tall","bytes":528,"shapes":2,"anchors":28,"colors":["#ffae1a"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange squares linked by angled strings","geometry":["square"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["technical","structured"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"puppet.svg","brand":"puppet","variant":"main","pair":"puppet-icon.svg","width":512.0,"height":181.0,"aspect":2.829,"aspect_class":"horizontal","bytes":2988,"shapes":3,"anchors":123,"colors":["#ffae1a","#000000"],"n_colors":2,"color_families":["black","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"node-and-string icon plus bold name","geometry":["square"],"techniques":["geometric-construction"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"puppeteer.svg","brand":"puppeteer","variant":"main","pair":null,"width":256.0,"height":383.0,"aspect":0.668,"aspect_class":"tall","bytes":9344,"shapes":7,"anchors":334,"colors":["#dfdedf","#ffffff","#000000","#00d8a2"],"n_colors":4,"color_families":["black","cyan","gray","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"marionette control over browser window with name","geometry":["square"],"techniques":["containment","hidden-meaning","line-monoline"],"type_style":"geometric-sans","case":"titlecase","mood":["playful","technical"],"industry":"developer-tools","exemplary":false,"note":"Literal puppet-controls-browser metaphor"},{"file":"puppy-linux.svg","brand":"puppy-linux","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":8722,"shapes":9,"anchors":209,"colors":["#000000","#141414","#ffffff","#fffdff"],"n_colors":4,"color_families":["black","white"],"primary_family":"mono","gradients":5,"has_mask":false,"has_filter":true,"mark_type":"mascot","symbol_type":null,"subject":"outlined cartoon puppy face","geometry":["organic"],"techniques":["line-monoline","hand-drawn"],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"os-platform","exemplary":false,"note":""},{"file":"purescript-icon.svg","brand":"purescript","variant":"icon","pair":"purescript.svg","width":256.0,"height":158.0,"aspect":1.62,"aspect_class":"wide","bytes":878,"shapes":2,"anchors":33,"colors":["#1d222d"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"equals lines between angle brackets","geometry":[],"techniques":["bracket-code","mirror-symmetry"],"type_style":null,"case":null,"mood":["technical","minimal"],"industry":"programming-language","exemplary":false,"note":""},{"file":"purescript.svg","brand":"purescript","variant":"main","pair":"purescript-icon.svg","width":512.0,"height":86.0,"aspect":5.953,"aspect_class":"extra-wide","bytes":5306,"shapes":2,"anchors":196,"colors":["#1d222d"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"bracket symbol plus spaced uppercase name","geometry":[],"techniques":["bracket-code"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","clean"],"industry":"programming-language","exemplary":false,"note":""},{"file":"pushbullet.svg","brand":"pushbullet","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1673,"shapes":7,"anchors":34,"colors":["#67bf79","#ffffff","#4cb36b","#3ea16f"],"n_colors":4,"color_families":["green","white"],"primary_family":"green","gradients":1,"has_mask":true,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"bar and half-disc bullet in green circle","geometry":["circle"],"techniques":["containment","dimensional-shading","negative-space"],"type_style":null,"case":null,"mood":["friendly","simple"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"pusher-icon.svg","brand":"pusher","variant":"icon","pair":"pusher.svg","width":256.0,"height":396.0,"aspect":0.646,"aspect_class":"tall","bytes":2748,"shapes":2,"anchors":76,"colors":["#300d4f"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric stacked stripes forming a P","geometry":["freeform"],"techniques":["isometric-3d","modular-repetition","line-monoline"],"type_style":null,"case":null,"mood":["technical","dynamic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"pusher.svg","brand":"pusher","variant":"main","pair":"pusher-icon.svg","width":512.0,"height":135.0,"aspect":3.793,"aspect_class":"horizontal","bytes":8209,"shapes":2,"anchors":251,"colors":["#300d4f"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"striped isometric icon plus PUSHER name","geometry":["freeform"],"techniques":["isometric-3d"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"pwa.svg","brand":"pwa","variant":"main","pair":null,"width":512.0,"height":193.0,"aspect":2.653,"aspect_class":"horizontal","bytes":1108,"shapes":4,"anchors":42,"colors":["#3d3d3d","#5a0fc8"],"n_colors":2,"color_families":["gray","purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"PWA letters with purple W","geometry":[],"techniques":["color-segments","overlap-transparency"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"pycharm.svg","brand":"pycharm","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3748,"shapes":8,"anchors":71,"colors":["#000000","#ffffff","#21d789","#07c3f2","#fcf84a","#a7eb62","#5fe077","#32da84","#20d68c","#1ed497","#19d1a9","#13ccc2","#0bc6e1","#24d788","#2fd886","#41da82","#5adc7d","#7ae077","#a1e36e","#cfe865","#f1eb5e","#5add7d","#79e077","#7ce076","#8ce173","#b2e56b","#ecf451","#c2e964"],"n_colors":28,"color_families":["black","cyan","green","white","yellow"],"primary_family":"multi","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"PC in black square over gradient shapes","geometry":["square","freeform"],"techniques":["containment","gradient","overlap-transparency"],"type_style":"geometric-sans","case":"uppercase","mood":["vibrant","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"python.svg","brand":"python","variant":"main","pair":null,"width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":1948,"shapes":3,"anchors":40,"colors":["#387eb8","#366994","#ffe052","#ffc331"],"n_colors":4,"color_families":["blue","yellow"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"two interlocking snakes, blue and yellow","geometry":["organic"],"techniques":["radial-symmetry","color-segments","negative-space"],"type_style":null,"case":null,"mood":["friendly","balanced"],"industry":"programming-language","exemplary":true,"note":"Rotational symmetry of two snakes, memorable and simple"},{"file":"pytorch.svg","brand":"pytorch","variant":"main","pair":null,"width":256.0,"height":310.0,"aspect":0.826,"aspect_class":"square","bytes":855,"shapes":2,"anchors":17,"colors":["#ee4c2c"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"open flame-like ring with dot","geometry":["circle"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["energetic","minimal"],"industry":"ai-ml","exemplary":false,"note":""},{"file":"pyup.svg","brand":"pyup","variant":"main","pair":null,"width":256.0,"height":296.0,"aspect":0.865,"aspect_class":"square","bytes":1132,"shapes":4,"anchors":57,"colors":["#4f859a","#2e6371","#1bafce"],"n_colors":3,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"isometric blocks forming letter p","geometry":["hexagon"],"techniques":["isometric-3d","dimensional-shading"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"security-identity","exemplary":false,"note":""},{"file":"q.svg","brand":"q","variant":"main","pair":null,"width":256.0,"height":295.0,"aspect":0.868,"aspect_class":"square","bytes":8470,"shapes":10,"anchors":217,"colors":["#b7a634","#f9df34","#524739","#524839"],"n_colors":4,"color_families":["orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"then chain-link inside yellow hexagon","geometry":["hexagon"],"techniques":["containment","line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["technical","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"qlik.svg","brand":"qlik","variant":"main","pair":null,"width":512.0,"height":151.0,"aspect":3.391,"aspect_class":"horizontal","bytes":3079,"shapes":4,"anchors":88,"colors":["#54565b","#009848"],"n_colors":2,"color_families":["gray","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"Qlik name with green Q symbol","geometry":["circle"],"techniques":[],"type_style":"geometric-sans","case":"titlecase","mood":["modern","bold"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"qt.svg","brand":"qt","variant":"main","pair":null,"width":256.0,"height":192.0,"aspect":1.333,"aspect_class":"wide","bytes":1687,"shapes":3,"anchors":56,"colors":["#41cd52","#ffffff"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"Qt letters in cut-corner green shape","geometry":["freeform"],"techniques":["containment"],"type_style":"geometric-sans","case":"mixed","mood":["bold","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"quarkus-icon.svg","brand":"quarkus","variant":"icon","pair":"quarkus.svg","width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":1397,"shapes":4,"anchors":61,"colors":["#4695eb","#ff004a","#091313"],"n_colors":3,"color_families":["black","blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"cube pinwheel inside blue frame","geometry":["rounded-square"],"techniques":["containment","isometric-3d","color-segments","negative-space"],"type_style":null,"case":null,"mood":["technical","busy"],"industry":"framework-library","exemplary":false,"note":""},{"file":"quarkus.svg","brand":"quarkus","variant":"main","pair":"quarkus-icon.svg","width":512.0,"height":77.0,"aspect":6.649,"aspect_class":"extra-wide","bytes":5161,"shapes":5,"anchors":188,"colors":["#091313","#4695eb","#ff004a"],"n_colors":3,"color_families":["black","blue","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"frame icon plus spaced QUARKUS name","geometry":["rounded-square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","clean"],"industry":"framework-library","exemplary":false,"note":""},{"file":"quay.svg","brand":"quay","variant":"main","pair":null,"width":256.0,"height":236.0,"aspect":1.085,"aspect_class":"square","bytes":760,"shapes":3,"anchors":35,"colors":["#40b4e5","#003764"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"interlocking blue chevron brackets","geometry":["diamond"],"techniques":["bracket-code","overlap-transparency","mirror-symmetry"],"type_style":null,"case":null,"mood":["technical","dynamic"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"quobyte.svg","brand":"quobyte","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":2560,"shapes":2,"anchors":54,"colors":["#274e85"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"Q as thick circular ring with tail","geometry":["circle"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["solid","simple"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"quora.svg","brand":"quora","variant":"main","pair":null,"width":512.0,"height":142.0,"aspect":3.606,"aspect_class":"horizontal","bytes":3325,"shapes":2,"anchors":98,"colors":["#b92b27"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"Quora in red bold serif","geometry":[],"techniques":[],"type_style":"serif","case":"titlecase","mood":["intellectual","classic"],"industry":"social-communication","exemplary":false,"note":""},{"file":"r-lang.svg","brand":"r-lang","variant":"main","pair":null,"width":256.0,"height":193.0,"aspect":1.326,"aspect_class":"wide","bytes":1363,"shapes":3,"anchors":29,"colors":["#2165b6","#c9cbce","#7b7a81"],"n_colors":3,"color_families":["blue","gray"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"blue R over grey ellipse ring","geometry":["circle"],"techniques":["overlap-transparency","gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["academic","solid"],"industry":"programming-language","exemplary":false,"note":""},{"file":"rabbitmq-icon.svg","brand":"rabbitmq","variant":"icon","pair":"rabbitmq.svg","width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":1770,"shapes":2,"anchors":44,"colors":["#ff6600"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"blocky rabbit-ear silhouette with square hole","geometry":["square","grid-modular"],"techniques":["negative-space","hidden-meaning","geometric-construction"],"type_style":null,"case":null,"mood":["bold","simple"],"industry":"cloud-infrastructure","exemplary":true,"note":"Rabbit reduced to rectangles, strong geometric abstraction"},{"file":"rabbitmq.svg","brand":"rabbitmq","variant":"main","pair":"rabbitmq-icon.svg","width":512.0,"height":87.0,"aspect":5.885,"aspect_class":"extra-wide","bytes":5392,"shapes":4,"anchors":185,"colors":["#a9b5af","#ff6600"],"n_colors":2,"color_families":["gray","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"blocky rabbit icon plus condensed name","geometry":["square"],"techniques":["negative-space"],"type_style":"grotesque-sans","case":"mixed","mood":["technical","bold"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"rackspace.svg","brand":"rackspace","variant":"main","pair":null,"width":512.0,"height":103.0,"aspect":4.971,"aspect_class":"extra-wide","bytes":5152,"shapes":2,"anchors":148,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"rackspace in bold italic lowercase","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"lowercase","mood":["energetic","confident"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"rails.svg","brand":"rails","variant":"main","pair":null,"width":512.0,"height":180.0,"aspect":2.844,"aspect_class":"horizontal","bytes":3151,"shapes":3,"anchors":125,"colors":["#cc0000"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"rail track arc over bold RAILS","geometry":["circle"],"techniques":["motion-lines"],"type_style":"display-custom","case":"uppercase","mood":["bold","energetic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"ramda.svg","brand":"ramda","variant":"main","pair":null,"width":256.0,"height":306.0,"aspect":0.837,"aspect_class":"square","bytes":3740,"shapes":2,"anchors":75,"colors":["#11100e"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"lambda shaped into ram head with horn","geometry":["organic"],"techniques":["hidden-meaning","letter-substitution","negative-space"],"type_style":null,"case":null,"mood":["clever","bold"],"industry":"framework-library","exemplary":true,"note":"Lambda doubles as ram: name pun made visual"},{"file":"raml.svg","brand":"raml","variant":"main","pair":null,"width":512.0,"height":147.0,"aspect":3.483,"aspect_class":"horizontal","bytes":2448,"shapes":2,"anchors":76,"colors":["#75c9e1"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"RAML in thin light-blue strokes","geometry":[],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"uppercase","mood":["light","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"rancher-icon.svg","brand":"rancher","variant":"icon","pair":"rancher.svg","width":256.0,"height":121.0,"aspect":2.116,"aspect_class":"wide","bytes":1764,"shapes":2,"anchors":55,"colors":["#0075a8"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"blocky blue bull silhouette","geometry":["freeform"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["sturdy","bold"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"rancher.svg","brand":"rancher","variant":"main","pair":"rancher-icon.svg","width":512.0,"height":78.0,"aspect":6.564,"aspect_class":"extra-wide","bytes":4452,"shapes":3,"anchors":174,"colors":["#0075a8","#59595b"],"n_colors":2,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"bull silhouette plus RANCHER name","geometry":["freeform"],"techniques":[],"type_style":"grotesque-sans","case":"uppercase","mood":["sturdy","bold"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"raphael.svg","brand":"raphael","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2998,"shapes":4,"anchors":75,"colors":["#f89938","#3399ff","#333333"],"n_colors":3,"color_families":["blue","gray","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange curves and blue dot in rounded diamond","geometry":["diamond","rounded-square"],"techniques":["containment","color-segments"],"type_style":null,"case":null,"mood":["playful","artistic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"raspberry-pi.svg","brand":"raspberry-pi","variant":"main","pair":null,"width":256.0,"height":327.0,"aspect":0.783,"aspect_class":"tall","bytes":7381,"shapes":15,"anchors":167,"colors":["#000000","#75a928","#bc1142"],"n_colors":3,"color_families":["black","green","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"outlined raspberry with green leaves","geometry":["organic"],"techniques":["modular-repetition","line-monoline"],"type_style":null,"case":null,"mood":["friendly","playful"],"industry":"hardware-devices","exemplary":false,"note":""},{"file":"rax.svg","brand":"rax","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":601,"shapes":2,"anchors":15,"colors":["#f76927"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"R from chevron stroke and arc","geometry":["freeform"],"techniques":["geometric-construction","negative-space"],"type_style":null,"case":null,"mood":["dynamic","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"react-query-icon.svg","brand":"react-query","variant":"icon","pair":"react-query.svg","width":256.0,"height":230.0,"aspect":1.113,"aspect_class":"square","bytes":6798,"shapes":5,"anchors":192,"colors":["#00435b","#002b3b","#ff4154","#ffd94c"],"n_colors":4,"color_families":["blue","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red atom orbits around yellow hexagon","geometry":["radial","hexagon"],"techniques":["radial-symmetry","overlap-transparency"],"type_style":null,"case":null,"mood":["vibrant","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"react-query.svg","brand":"react-query","variant":"main","pair":"react-query-icon.svg","width":512.0,"height":100.0,"aspect":5.12,"aspect_class":"extra-wide","bytes":12997,"shapes":6,"anchors":384,"colors":["#00435b","#002b3b","#ff4154","#ffd94c"],"n_colors":4,"color_families":["blue","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"atom-flower icon plus React Query name","geometry":["radial"],"techniques":["radial-symmetry"],"type_style":"geometric-sans","case":"titlecase","mood":["vibrant","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"react-router.svg","brand":"react-router","variant":"main","pair":null,"width":256.0,"height":140.0,"aspect":1.829,"aspect_class":"wide","bytes":1659,"shapes":3,"anchors":33,"colors":["#000000","#d0021b"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"dots joined by red route path","geometry":["circle"],"techniques":["hidden-meaning","negative-space"],"type_style":null,"case":null,"mood":["playful","minimal"],"industry":"framework-library","exemplary":false,"note":""},{"file":"react-spring.svg","brand":"react-spring","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":9252,"shapes":5,"anchors":207,"colors":["#ffffff","#1b1a22","#ff6d6d"],"n_colors":3,"color_families":["black","red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"scribbled coil over red circle","geometry":["circle","organic"],"techniques":["hand-drawn","motion-lines"],"type_style":null,"case":null,"mood":["loose","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"react-styleguidist.svg","brand":"react-styleguidist","variant":"main","pair":null,"width":256.0,"height":174.0,"aspect":1.471,"aspect_class":"wide","bytes":24492,"shapes":40,"anchors":543,"colors":["#053949","#00d8fe","#000000","#043849","#ffffff","#063a49"],"n_colors":6,"color_families":["black","cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"blue cartoon octopus","geometry":["organic"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"react.svg","brand":"react","variant":"main","pair":null,"width":256.0,"height":228.0,"aspect":1.123,"aspect_class":"square","bytes":5389,"shapes":2,"anchors":123,"colors":["#00d8ff"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"atom with three elliptical orbits","geometry":["radial","circle"],"techniques":["radial-symmetry","line-monoline","geometric-construction"],"type_style":null,"case":null,"mood":["technical","iconic"],"industry":"framework-library","exemplary":true,"note":"Iconic radial construction, works as single-color line mark"},{"file":"reactivex.svg","brand":"reactivex","variant":"main","pair":null,"width":256.0,"height":247.0,"aspect":1.036,"aspect_class":"square","bytes":3845,"shapes":6,"anchors":48,"colors":["#ff0090","#f80090","#4d008e","#57008e","#5c008e","#f70090","#e50090","#d6008f","#c10090","#b2008f","#f60090"],"n_colors":11,"color_families":["pink","purple"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"curling electric eel in pink gradient","geometry":["circle","organic"],"techniques":["gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["dynamic","vivid"],"industry":"framework-library","exemplary":false,"note":""},{"file":"realm.svg","brand":"realm","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3553,"shapes":11,"anchors":66,"colors":["#ffffff","#fcc397","#fc9f95","#f77c88","#f25192","#d34ca3","#9a50a5","#59569e","#39477f"],"n_colors":9,"color_families":["blue","orange","pink","red","white"],"primary_family":"multi","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"sunset wave layers inside circle","geometry":["circle"],"techniques":["containment","stacked-layers","color-segments"],"type_style":null,"case":null,"mood":["calm","warm"],"industry":"database-data","exemplary":false,"note":""},{"file":"reapp.svg","brand":"reapp","variant":"main","pair":null,"width":256.0,"height":338.0,"aspect":0.757,"aspect_class":"tall","bytes":839,"shapes":3,"anchors":24,"colors":["#27ccf5","#22e071"],"n_colors":2,"color_families":["cyan","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two offset bracket shapes blue and green","geometry":["rounded-square"],"techniques":["color-segments","negative-space"],"type_style":null,"case":null,"mood":["fresh","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"reasonml-icon.svg","brand":"reasonml","variant":"icon","pair":"reasonml.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":767,"shapes":3,"anchors":35,"colors":["#dd4b39","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"RE set in red square corner","geometry":["square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","solid"],"industry":"programming-language","exemplary":false,"note":""},{"file":"reasonml.svg","brand":"reasonml","variant":"main","pair":"reasonml-icon.svg","width":512.0,"height":192.0,"aspect":2.667,"aspect_class":"horizontal","bytes":2017,"shapes":4,"anchors":82,"colors":["#dd4b39","#333333","#ffffff"],"n_colors":3,"color_families":["gray","red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"REASON with RE boxed in red","geometry":["square"],"techniques":["containment","color-segments"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","solid"],"industry":"programming-language","exemplary":false,"note":""},{"file":"reddit-icon.svg","brand":"reddit","variant":"icon","pair":"reddit.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2160,"shapes":3,"anchors":47,"colors":["#ff4500","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"Snoo alien head in orange circle","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"reddit.svg","brand":"reddit","variant":"main","pair":"reddit-icon.svg","width":511.0,"height":176.0,"aspect":2.903,"aspect_class":"horizontal","bytes":5721,"shapes":5,"anchors":156,"colors":["#ff4500","#222222","#ffffff"],"n_colors":3,"color_families":["black","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"Snoo circle plus reddit lowercase name","geometry":["circle"],"techniques":["containment"],"type_style":"rounded-sans","case":"lowercase","mood":["playful","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"redhat-icon.svg","brand":"redhat","variant":"icon","pair":"redhat.svg","width":256.0,"height":194.0,"aspect":1.32,"aspect_class":"wide","bytes":1612,"shapes":3,"anchors":33,"colors":["#ee0000","#000000"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red fedora with black band","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["confident","iconic"],"industry":"os-platform","exemplary":true,"note":"Single object, flat, instantly recognisable silhouette"},{"file":"redhat.svg","brand":"redhat","variant":"main","pair":"redhat-icon.svg","width":512.0,"height":121.0,"aspect":4.231,"aspect_class":"horizontal","bytes":4116,"shapes":4,"anchors":135,"colors":["#ee0000","#000000"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"fedora icon plus Red Hat name","geometry":["organic"],"techniques":[],"type_style":"geometric-sans","case":"titlecase","mood":["confident","modern"],"industry":"os-platform","exemplary":false,"note":""},{"file":"redis.svg","brand":"redis","variant":"main","pair":null,"width":256.0,"height":220.0,"aspect":1.164,"aspect_class":"square","bytes":3627,"shapes":12,"anchors":90,"colors":["#912626","#c6302b","#ffffff","#621b1c","#9a2928"],"n_colors":5,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"stacked red isometric layers with shapes","geometry":["freeform"],"techniques":["isometric-3d","stacked-layers","dimensional-shading"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"database-data","exemplary":false,"note":""},{"file":"redsmin.svg","brand":"redsmin","variant":"main","pair":null,"width":256.0,"height":344.0,"aspect":0.744,"aspect_class":"tall","bytes":2692,"shapes":12,"anchors":91,"colors":["#ee3a43","#cf3239","#af272b","#7a1313"],"n_colors":4,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"isometric hexagonal R in red shades","geometry":["hexagon"],"techniques":["isometric-3d","dimensional-shading"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"redux-observable.svg","brand":"redux-observable","variant":"main","pair":null,"width":256.0,"height":250.0,"aspect":1.024,"aspect_class":"square","bytes":22367,"shapes":25,"anchors":297,"colors":["#b1278f","#af278e","#a8258a","#9e2383","#ec178d","#ea178d","#e3188c","#d81a8a","#c71d88","#b12085","#cb1c8c","#772888","#512e87","#ba258e","#b5258d","#a5278b","#8b2987","#7a2a85","#e21a8d","#952584","#df1a8d","#d51c8c","#c51e8a","#af2187"],"n_colors":24,"color_families":["pink","purple"],"primary_family":"multi","gradients":24,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"purple fish creatures forming a ring","geometry":["circle","organic"],"techniques":["gradient","radial-symmetry"],"type_style":null,"case":null,"mood":["dynamic","vivid"],"industry":"framework-library","exemplary":false,"note":""},{"file":"redux-saga.svg","brand":"redux-saga","variant":"main","pair":null,"width":256.0,"height":157.0,"aspect":1.631,"aspect_class":"wide","bytes":4267,"shapes":3,"anchors":88,"colors":["#999999","#89d96d"],"n_colors":2,"color_families":["gray","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"interlocking grey and green loops with nodes","geometry":["circle"],"techniques":["line-monoline","overlap-transparency"],"type_style":null,"case":null,"mood":["technical","light"],"industry":"framework-library","exemplary":false,"note":""},{"file":"redux.svg","brand":"redux","variant":"main","pair":null,"width":256.0,"height":244.0,"aspect":1.049,"aspect_class":"square","bytes":2317,"shapes":2,"anchors":51,"colors":["#764abc"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three purple looping strokes with dots","geometry":["radial"],"techniques":["line-monoline","radial-symmetry"],"type_style":null,"case":null,"mood":["fluid","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"redwoodjs.svg","brand":"redwoodjs","variant":"main","pair":null,"width":256.0,"height":277.0,"aspect":0.924,"aspect_class":"square","bytes":4670,"shapes":3,"anchors":122,"colors":["#ffffff","#bf4722"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"diamond tiles forming redwood cone","geometry":["diamond","hexagon"],"techniques":["modular-repetition","negative-space"],"type_style":null,"case":null,"mood":["natural","structured"],"industry":"framework-library","exemplary":false,"note":""},{"file":"reindex.svg","brand":"reindex","variant":"main","pair":null,"width":256.0,"height":266.0,"aspect":0.962,"aspect_class":"square","bytes":2459,"shapes":5,"anchors":66,"colors":["#62bbe7","#78cbc8"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"stacked chevron lines with node dots","geometry":["freeform"],"techniques":["line-monoline","stacked-layers","modular-repetition"],"type_style":null,"case":null,"mood":["technical","light"],"industry":"database-data","exemplary":false,"note":""},{"file":"relay.svg","brand":"relay","variant":"main","pair":null,"width":256.0,"height":151.0,"aspect":1.695,"aspect_class":"wide","bytes":1049,"shapes":2,"anchors":23,"colors":["#f26b00"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange S-shaped route with end nodes","geometry":[],"techniques":["line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["simple","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"release.svg","brand":"release","variant":"main","pair":null,"width":256.0,"height":290.0,"aspect":0.883,"aspect_class":"square","bytes":1853,"shapes":2,"anchors":57,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"outlined cube with play triangle","geometry":["hexagon","square"],"techniques":["isometric-3d","line-monoline","arrow"],"type_style":null,"case":null,"mood":["technical","minimal"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"remix-icon.svg","brand":"remix","variant":"icon","pair":"remix.svg","width":256.0,"height":297.0,"aspect":0.862,"aspect_class":"square","bytes":1872,"shapes":2,"anchors":83,"colors":["#121212"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"heavy R with detached stem pieces","geometry":["square"],"techniques":["negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"remix.svg","brand":"remix","variant":"main","pair":"remix-icon.svg","width":512.0,"height":128.0,"aspect":4.0,"aspect_class":"horizontal","bytes":3721,"shapes":2,"anchors":159,"colors":["#121212"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy custom Remix type, split R","geometry":[],"techniques":["negative-space"],"type_style":"display-custom","case":"titlecase","mood":["bold","modern"],"industry":"framework-library","exemplary":false,"note":"Custom cut in R gives an ownable detail"},{"file":"require.svg","brand":"require","variant":"main","pair":null,"width":256.0,"height":283.0,"aspect":0.905,"aspect_class":"square","bytes":11143,"shapes":24,"anchors":309,"colors":["#43a5eb","#f34b41","#fefb1f","#000000","#4c4c4c"],"n_colors":5,"color_families":["black","blue","gray","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"archery target with arrow and arched name","geometry":["circle","radial"],"techniques":["radial-symmetry","arrow"],"type_style":"display-custom","case":"uppercase","mood":["playful","precise"],"industry":"framework-library","exemplary":false,"note":""},{"file":"rescript-icon.svg","brand":"rescript","variant":"icon","pair":"rescript.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1545,"shapes":2,"anchors":37,"colors":["#d44140"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"r from bar and dot in red square","geometry":["rounded-square"],"techniques":["containment","geometric-construction"],"type_style":null,"case":null,"mood":["simple","bold"],"industry":"programming-language","exemplary":true,"note":"Letter r reduced to a bar and a dot"},{"file":"rescript.svg","brand":"rescript","variant":"main","pair":"rescript-icon.svg","width":512.0,"height":121.0,"aspect":4.231,"aspect_class":"horizontal","bytes":11661,"shapes":2,"anchors":302,"colors":["#d44140"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"r square icon plus rescript name","geometry":["rounded-square"],"techniques":["containment"],"type_style":"geometric-sans","case":"lowercase","mood":["simple","modern"],"industry":"programming-language","exemplary":false,"note":""},{"file":"rest-li.svg","brand":"rest-li","variant":"main","pair":null,"width":512.0,"height":224.0,"aspect":2.286,"aspect_class":"wide","bytes":7863,"shapes":2,"anchors":169,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"black winged horse head","geometry":["organic"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["powerful","dramatic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"rethinkdb.svg","brand":"rethinkdb","variant":"main","pair":null,"width":512.0,"height":82.0,"aspect":6.244,"aspect_class":"extra-wide","bytes":8630,"shapes":2,"anchors":288,"colors":["#204956"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"RethinkDB in dark teal slab serif","geometry":[],"techniques":[],"type_style":"slab","case":"mixed","mood":["solid","academic"],"industry":"database-data","exemplary":false,"note":""},{"file":"retool-icon.svg","brand":"retool","variant":"icon","pair":"retool.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":900,"shapes":2,"anchors":27,"colors":["#262626"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three offset stacked rounded bars","geometry":["rounded-square"],"techniques":["stacked-layers","modular-repetition"],"type_style":null,"case":null,"mood":["solid","minimal"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"retool.svg","brand":"retool","variant":"main","pair":"retool-icon.svg","width":512.0,"height":110.0,"aspect":4.655,"aspect_class":"extra-wide","bytes":2900,"shapes":3,"anchors":100,"colors":["#262626"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"stacked bars icon plus bold Retool","geometry":["rounded-square"],"techniques":["stacked-layers"],"type_style":"geometric-sans","case":"titlecase","mood":["solid","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"riak.svg","brand":"riak","variant":"main","pair":null,"width":256.0,"height":254.0,"aspect":1.008,"aspect_class":"square","bytes":2655,"shapes":7,"anchors":52,"colors":["#3d4c67","#f6861a"],"n_colors":2,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"curved lines fanning to surrounding dots","geometry":["radial"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["technical","connected"],"industry":"database-data","exemplary":false,"note":""},{"file":"riot.svg","brand":"riot","variant":"main","pair":null,"width":256.0,"height":248.0,"aspect":1.032,"aspect_class":"square","bytes":989,"shapes":2,"anchors":27,"colors":["#ed1846"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"blocky red R with notch cutouts","geometry":["square"],"techniques":["negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["bold","energetic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"rocket-chat-icon.svg","brand":"rocket-chat","variant":"icon","pair":"rocket-chat.svg","width":256.0,"height":230.0,"aspect":1.113,"aspect_class":"square","bytes":2191,"shapes":2,"anchors":45,"colors":["#f5455c"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red speech bubble with three dots","geometry":["organic"],"techniques":["speech-bubble"],"type_style":null,"case":null,"mood":["friendly","chatty"],"industry":"social-communication","exemplary":false,"note":""},{"file":"rocket-chat.svg","brand":"rocket-chat","variant":"main","pair":"rocket-chat-icon.svg","width":512.0,"height":87.0,"aspect":5.885,"aspect_class":"extra-wide","bytes":6904,"shapes":2,"anchors":201,"colors":["#f5455c"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"speech bubble plus rocket.chat name","geometry":["organic"],"techniques":["speech-bubble"],"type_style":"rounded-sans","case":"lowercase","mood":["friendly","modern"],"industry":"social-communication","exemplary":false,"note":""},{"file":"rocksdb.svg","brand":"rocksdb","variant":"main","pair":null,"width":256.0,"height":210.0,"aspect":1.219,"aspect_class":"square","bytes":9219,"shapes":29,"anchors":205,"colors":["#000000","#f7be01","#303144"],"n_colors":3,"color_families":["black","blue","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cheetah leaping up steps in black tile","geometry":["rounded-square"],"techniques":["containment"],"type_style":null,"case":null,"mood":["fast","energetic"],"industry":"database-data","exemplary":false,"note":""},{"file":"rocky-linux-icon.svg","brand":"rocky-linux","variant":"icon","pair":"rocky-linux.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":597,"shapes":2,"anchors":13,"colors":["#10b981"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"green circle cut by mountain chevron","geometry":["circle"],"techniques":["negative-space","hidden-meaning"],"type_style":null,"case":null,"mood":["clean","confident"],"industry":"os-platform","exemplary":true,"note":"Mountain peak carved from circle with one cut"},{"file":"rocky-linux.svg","brand":"rocky-linux","variant":"main","pair":"rocky-linux-icon.svg","width":512.0,"height":95.0,"aspect":5.389,"aspect_class":"extra-wide","bytes":5683,"shapes":3,"anchors":182,"colors":["#10b981","#000000"],"n_colors":2,"color_families":["black","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"mountain circle plus Rocky Linux name","geometry":["circle"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"titlecase","mood":["clean","confident"],"industry":"os-platform","exemplary":false,"note":""},{"file":"rollbar-icon.svg","brand":"rollbar","variant":"icon","pair":"rollbar.svg","width":256.0,"height":214.0,"aspect":1.196,"aspect_class":"square","bytes":2053,"shapes":2,"anchors":62,"colors":["#3c72ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"blue outlined sheared quarter-cylinder","geometry":["freeform"],"techniques":["isometric-3d","line-monoline"],"type_style":null,"case":null,"mood":["technical","light"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"rollbar.svg","brand":"rollbar","variant":"main","pair":"rollbar-icon.svg","width":512.0,"height":112.0,"aspect":4.571,"aspect_class":"extra-wide","bytes":6280,"shapes":3,"anchors":189,"colors":["#3c72ff","#343f55"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"outlined 3D icon plus bold Rollbar","geometry":["freeform"],"techniques":["isometric-3d","line-monoline"],"type_style":"geometric-sans","case":"titlecase","mood":["technical","solid"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"rollupjs.svg","brand":"rollupjs","variant":"main","pair":null,"width":256.0,"height":335.0,"aspect":0.764,"aspect_class":"tall","bytes":4512,"shapes":7,"anchors":57,"colors":["#ff6533","#ff5633","#ff4333","#ff3733","#ff3333","#bf3338","#fbb040","#fb8840","#ffffff"],"n_colors":9,"color_families":["orange","red","white"],"primary_family":"multi","gradients":6,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"red R with rolling paper curl","geometry":["freeform"],"techniques":["gradient","overlap-transparency","hidden-meaning"],"type_style":null,"case":null,"mood":["dynamic","warm"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"rome-icon.svg","brand":"rome","variant":"icon","pair":"rome.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1747,"shapes":3,"anchors":55,"colors":["#27272a","#ffc905"],"n_colors":2,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"Roman arches, yellow inner arch","geometry":["freeform"],"techniques":["mirror-symmetry","containment"],"type_style":null,"case":null,"mood":["classic","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"rome.svg","brand":"rome","variant":"main","pair":"rome-icon.svg","width":512.0,"height":127.0,"aspect":4.031,"aspect_class":"horizontal","bytes":9152,"shapes":4,"anchors":247,"colors":["#27272a","#ffc905"],"n_colors":2,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"arch icon plus Rome serif name","geometry":["freeform"],"techniques":["mirror-symmetry"],"type_style":"serif","case":"titlecase","mood":["classic","solid"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"rsa.svg","brand":"rsa","variant":"main","pair":null,"width":256.0,"height":129.0,"aspect":1.984,"aspect_class":"wide","bytes":1583,"shapes":5,"anchors":50,"colors":["#d9222a","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"RSA white type in red box","geometry":["square"],"techniques":["containment","letter-substitution"],"type_style":"geometric-sans","case":"uppercase","mood":["secure","bold"],"industry":"security-identity","exemplary":false,"note":""},{"file":"rsmq.svg","brand":"rsmq","variant":"main","pair":null,"width":256.0,"height":176.0,"aspect":1.455,"aspect_class":"wide","bytes":1721,"shapes":7,"anchors":66,"colors":["#b2271b","#d82a1f"],"n_colors":2,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"red vertical bars in folded perspective","geometry":["square"],"techniques":["modular-repetition","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"rubocop.svg","brand":"rubocop","variant":"main","pair":null,"width":256.0,"height":302.0,"aspect":0.848,"aspect_class":"square","bytes":1924,"shapes":3,"anchors":68,"colors":["#0a0b09","#d7252c"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"robot cop helmet with red visor","geometry":["organic"],"techniques":["mirror-symmetry","negative-space"],"type_style":null,"case":null,"mood":["strict","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"ruby.svg","brand":"ruby","variant":"main","pair":null,"width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":7656,"shapes":18,"anchors":79,"colors":["#ffffff","#9e1209","#fb7655","#e42b1e","#990000","#871101","#911209","#e57252","#de3b20","#a60003","#e4714e","#be1a0d","#a80d00","#e46342","#c82410","#c81f11","#bf0905","#de4024","#bf190b","#bd0012","#c82f1c","#820c01","#a31601","#b31301","#e82609","#8c0c01","#990c00","#a80d0e","#7e110b","#9e0c00","#79130d","#9e120b","#7e0e08","#a30c00","#800e08","#8b2114","#9e100a","#b3100c","#b31000","#910f08","#791c12"],"n_colors":41,"color_families":["red","white"],"primary_family":"red","gradients":16,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"faceted red gemstone","geometry":["diamond"],"techniques":["dimensional-shading","gradient"],"type_style":null,"case":null,"mood":["precious","warm"],"industry":"programming-language","exemplary":false,"note":""},{"file":"rubygems.svg","brand":"rubygems","variant":"main","pair":null,"width":256.0,"height":293.0,"aspect":0.874,"aspect_class":"square","bytes":648,"shapes":3,"anchors":24,"colors":["#d34231"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"gem inside red hexagon outline","geometry":["hexagon","diamond"],"techniques":["containment"],"type_style":null,"case":null,"mood":["solid","simple"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"rubymine.svg","brand":"rubymine","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2513,"shapes":6,"anchors":70,"colors":["#000000","#ffffff","#ff1f51","#ff3648","#ff593b","#ff7231","#ff812b","#ff8629","#9039d0"],"n_colors":9,"color_families":["black","orange","purple","red","white"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"RM in black square over gradient shapes","geometry":["square","freeform"],"techniques":["containment","gradient","overlap-transparency"],"type_style":"geometric-sans","case":"uppercase","mood":["vibrant","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"rum.svg","brand":"rum","variant":"main","pair":null,"width":512.0,"height":197.0,"aspect":2.599,"aspect_class":"horizontal","bytes":2550,"shapes":2,"anchors":91,"colors":["#883030","#ff6565"],"n_colors":2,"color_families":["red"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"RUM in thin type wrapped in brackets","geometry":[],"techniques":["bracket-code","line-monoline"],"type_style":"grotesque-sans","case":"uppercase","mood":["light","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"runscope.svg","brand":"runscope","variant":"main","pair":null,"width":256.0,"height":267.0,"aspect":0.959,"aspect_class":"square","bytes":2549,"shapes":4,"anchors":67,"colors":["#0a0b09","#3e64a0"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"partial gear ring around blue dot","geometry":["circle"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["technical","solid"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"rust.svg","brand":"rust","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":8608,"shapes":2,"anchors":246,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"R inside black gear cog","geometry":["circle","radial"],"techniques":["containment","radial-symmetry"],"type_style":null,"case":null,"mood":["industrial","solid"],"industry":"programming-language","exemplary":false,"note":""},{"file":"rxdb.svg","brand":"rxdb","variant":"main","pair":null,"width":256.0,"height":187.0,"aspect":1.369,"aspect_class":"wide","bytes":3008,"shapes":4,"anchors":141,"colors":["#5f2688","#8d1f89","#e6008d"],"n_colors":3,"color_families":["pink","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"pixelated gradient stacked bars plus RxDB","geometry":["square"],"techniques":["pixel","stacked-layers","gradient"],"type_style":"geometric-sans","case":"mixed","mood":["vivid","technical"],"industry":"database-data","exemplary":false,"note":""},{"file":"safari.svg","brand":"safari","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":52294,"shapes":137,"anchors":1385,"colors":["#f3f3f3","#ffffff","#e2e2e2","#000000","#cd151e","#fa5153","#acacac","#eeeeee","#dbdbda","#2abce1","#2abbe1","#3375f8"],"n_colors":12,"color_families":["black","blue","cyan","gray","red","white"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":true,"mark_type":"pictorial","symbol_type":null,"subject":"blue compass dial with needle","geometry":["circle","radial"],"techniques":["radial-symmetry","gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["precise","polished"],"industry":"os-platform","exemplary":false,"note":""},{"file":"sagui.svg","brand":"sagui","variant":"main","pair":null,"width":256.0,"height":221.0,"aspect":1.158,"aspect_class":"square","bytes":4290,"shapes":2,"anchors":96,"colors":["#753f8c"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"purple sitting monkey","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["playful","cute"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"sails.svg","brand":"sails","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":471,"shapes":3,"anchors":8,"colors":["#28a3b2"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"two teal sails side by side","geometry":["triangle","organic"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["calm","simple"],"industry":"framework-library","exemplary":false,"note":""},{"file":"salesforce.svg","brand":"salesforce","variant":"main","pair":null,"width":256.0,"height":180.0,"aspect":1.422,"aspect_class":"wide","bytes":12022,"shapes":12,"anchors":288,"colors":["#00a1e0","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"salesforce name inside blue cloud","geometry":["organic"],"techniques":["containment"],"type_style":"humanist-sans","case":"lowercase","mood":["friendly","approachable"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"sameroom.svg","brand":"sameroom","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1722,"shapes":7,"anchors":37,"colors":["#78787a","#ffffff","#1b94b8","#000000"],"n_colors":4,"color_families":["black","cyan","gray","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"grey square face with eyes and smile","geometry":["rounded-square"],"techniques":[],"type_style":null,"case":null,"mood":["friendly","playful"],"industry":"social-communication","exemplary":false,"note":""},{"file":"samsung.svg","brand":"samsung","variant":"main","pair":null,"width":512.0,"height":79.0,"aspect":6.481,"aspect_class":"extra-wide","bytes":9698,"shapes":2,"anchors":394,"colors":["#1428a0"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"SAMSUNG wide type, A without crossbar","geometry":[],"techniques":["letter-substitution"],"type_style":"display-custom","case":"uppercase","mood":["corporate","modern"],"industry":"hardware-devices","exemplary":false,"note":""},{"file":"sanity.svg","brand":"sanity","variant":"main","pair":null,"width":512.0,"height":104.0,"aspect":4.923,"aspect_class":"extra-wide","bytes":2192,"shapes":11,"anchors":90,"colors":["#f37368","#f7a199","#f04939"],"n_colors":3,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"SANITY in coral red bold caps","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"uppercase","mood":["bold","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"sass-doc.svg","brand":"sass-doc","variant":"main","pair":null,"width":256.0,"height":216.0,"aspect":1.185,"aspect_class":"square","bytes":10651,"shapes":3,"anchors":242,"colors":["#5c4863","#dd5a6f"],"n_colors":2,"color_families":["purple","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"sass DOC under code comment marks","geometry":[],"techniques":["bracket-code"],"type_style":"geometric-sans","case":"mixed","mood":["technical","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"sass.svg","brand":"sass","variant":"main","pair":null,"width":256.0,"height":192.0,"aspect":1.333,"aspect_class":"wide","bytes":5722,"shapes":2,"anchors":121,"colors":["#cd6799"],"n_colors":1,"color_families":["pink"],"primary_family":"pink","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"Sass in flowing pink script","geometry":[],"techniques":[],"type_style":"script","case":"titlecase","mood":["elegant","playful"],"industry":"programming-language","exemplary":false,"note":""},{"file":"saucelabs.svg","brand":"saucelabs","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1288,"shapes":2,"anchors":34,"colors":["#e12826"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"lightning bolt cut into red circle","geometry":["circle"],"techniques":["containment","negative-space","line-monoline"],"type_style":null,"case":null,"mood":["energetic","fast"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"scala.svg","brand":"scala","variant":"main","pair":null,"width":256.0,"height":416.0,"aspect":0.615,"aspect_class":"tall","bytes":1910,"shapes":6,"anchors":29,"colors":["#4f4f4f","#c40000","#ff0000"],"n_colors":3,"color_families":["gray","red"],"primary_family":"red","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"red spiral staircase of stacked bands","geometry":["freeform"],"techniques":["stacked-layers","dimensional-shading","gradient"],"type_style":null,"case":null,"mood":["bold","dynamic"],"industry":"programming-language","exemplary":false,"note":""},{"file":"scaledrone.svg","brand":"scaledrone","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":918,"shapes":3,"anchors":12,"colors":["#6466bb","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"purple disc with gradient crescent","geometry":["circle"],"techniques":["gradient"],"type_style":null,"case":null,"mood":["smooth","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"scribd-icon.svg","brand":"scribd","variant":"icon","pair":"scribd.svg","width":256.0,"height":316.0,"aspect":0.81,"aspect_class":"square","bytes":1916,"shapes":2,"anchors":43,"colors":["#1e7b85"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"teal S made of two hooks","geometry":["organic"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["friendly","fluid"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"scribd.svg","brand":"scribd","variant":"main","pair":"scribd-icon.svg","width":512.0,"height":114.0,"aspect":4.491,"aspect_class":"horizontal","bytes":4383,"shapes":3,"anchors":130,"colors":["#00293f","#1e7b85"],"n_colors":2,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"hook S icon plus spaced SCRIBD","geometry":["organic"],"techniques":[],"type_style":"geometric-sans","case":"uppercase","mood":["clean","literate"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"section-icon.svg","brand":"section","variant":"icon","pair":"section.svg","width":256.0,"height":431.0,"aspect":0.594,"aspect_class":"tall","bytes":735,"shapes":4,"anchors":32,"colors":["#00a86b","#038754"],"n_colors":2,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"nested green outlined building frames","geometry":["square"],"techniques":["line-monoline","stacked-layers","isometric-3d"],"type_style":null,"case":null,"mood":["structured","technical"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"section.svg","brand":"section","variant":"main","pair":"section-icon.svg","width":512.0,"height":171.0,"aspect":2.994,"aspect_class":"horizontal","bytes":3342,"shapes":5,"anchors":126,"colors":["#00a86b","#038754","#000000"],"n_colors":3,"color_families":["black","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"frame icon plus Section name","geometry":["square"],"techniques":["line-monoline"],"type_style":"grotesque-sans","case":"titlecase","mood":["structured","clean"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"segment-icon.svg","brand":"segment","variant":"icon","pair":"segment.svg","width":256.0,"height":265.0,"aspect":0.966,"aspect_class":"square","bytes":2703,"shapes":2,"anchors":81,"colors":["#4fb58b"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"arcs, bars and dots forming S","geometry":["circle"],"techniques":["line-monoline","hidden-meaning","negative-space"],"type_style":null,"case":null,"mood":["clean","technical"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"segment.svg","brand":"segment","variant":"main","pair":"segment-icon.svg","width":512.0,"height":105.0,"aspect":4.876,"aspect_class":"extra-wide","bytes":9506,"shapes":2,"anchors":312,"colors":["#4fb58b"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"arc-S icon plus segment name","geometry":["circle"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["clean","friendly"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"selenium.svg","brand":"selenium","variant":"main","pair":null,"width":256.0,"height":269.0,"aspect":0.952,"aspect_class":"square","bytes":2869,"shapes":2,"anchors":68,"colors":["#2cb134"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"Se with check mark in green square","geometry":["square"],"techniques":["containment"],"type_style":"geometric-sans","case":"mixed","mood":["reliable","bold"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"semantic-release.svg","brand":"semantic-release","variant":"main","pair":null,"width":256.0,"height":295.0,"aspect":0.868,"aspect_class":"square","bytes":1973,"shapes":2,"anchors":54,"colors":["#494949"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"shutter pinwheel inside hexagon","geometry":["hexagon","radial"],"techniques":["radial-symmetry","negative-space","containment"],"type_style":null,"case":null,"mood":["technical","precise"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"semantic-ui.svg","brand":"semantic-ui","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1091,"shapes":3,"anchors":22,"colors":["#34bdb2","#ffffff"],"n_colors":2,"color_families":["cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white S in teal square","geometry":["square"],"techniques":["containment"],"type_style":null,"case":null,"mood":["simple","clean"],"industry":"framework-library","exemplary":false,"note":""},{"file":"semantic-web.svg","brand":"semantic-web","variant":"main","pair":null,"width":512.0,"height":157.0,"aspect":3.261,"aspect_class":"horizontal","bytes":10456,"shapes":5,"anchors":297,"colors":["#015a9c","#86ba0c","#ef7c00","#bd1789"],"n_colors":4,"color_families":["blue","green","orange","pink"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"tri-color isometric cube plus two-line name","geometry":["hexagon"],"techniques":["isometric-3d","color-segments"],"type_style":"geometric-sans","case":"titlecase","mood":["academic","colorful"],"industry":"other","exemplary":false,"note":""},{"file":"semaphoreci.svg","brand":"semaphoreci","variant":"main","pair":null,"width":256.0,"height":160.0,"aspect":1.6,"aspect_class":"wide","bytes":846,"shapes":3,"anchors":21,"colors":["#f06332","#029d74"],"n_colors":2,"color_families":["green","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange and green chevrons forming wave","geometry":["freeform"],"techniques":["color-segments"],"type_style":null,"case":null,"mood":["dynamic","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"sencha.svg","brand":"sencha","variant":"main","pair":null,"width":256.0,"height":388.0,"aspect":0.66,"aspect_class":"tall","bytes":8839,"shapes":6,"anchors":224,"colors":["#7cba3d","#c5d83e","#aace36","#2fa042","#79a933","#70a333","#559332","#277b2f","#005f27","#005020","#79ab35","#00aa4b"],"n_colors":12,"color_families":["green"],"primary_family":"green","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"green leaf-like S curve","geometry":["organic"],"techniques":["gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["fresh","fluid"],"industry":"framework-library","exemplary":false,"note":""},{"file":"sendgrid-icon.svg","brand":"sendgrid","variant":"icon","pair":"sendgrid.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":738,"shapes":7,"anchors":36,"colors":["#9dd6e3","#3f72ab","#00a9d1","#2191c4"],"n_colors":4,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"blue squares in staggered pixel grid","geometry":["grid-modular","square"],"techniques":["modular-repetition","pixel","color-segments"],"type_style":null,"case":null,"mood":["technical","orderly"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"sendgrid.svg","brand":"sendgrid","variant":"main","pair":"sendgrid-icon.svg","width":512.0,"height":90.0,"aspect":5.689,"aspect_class":"extra-wide","bytes":3943,"shapes":8,"anchors":144,"colors":["#212f38","#9dd6e3","#3f72ab","#00a9d1","#2191c4"],"n_colors":5,"color_families":["blue","cyan"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"pixel grid icon plus SendGrid name","geometry":["grid-modular"],"techniques":["pixel","color-segments"],"type_style":"grotesque-sans","case":"mixed","mood":["technical","solid"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"seneca.svg","brand":"seneca","variant":"main","pair":null,"width":256.0,"height":200.0,"aspect":1.28,"aspect_class":"wide","bytes":1386,"shapes":2,"anchors":37,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"black ionic column capital and shaft","geometry":["freeform"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["classic","solid"],"industry":"framework-library","exemplary":false,"note":""},{"file":"sensu-icon.svg","brand":"sensu","variant":"icon","pair":"sensu.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":854,"shapes":2,"anchors":22,"colors":["#73cc58"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"nested arcs inside green diamond outline","geometry":["diamond"],"techniques":["containment","negative-space","line-monoline"],"type_style":null,"case":null,"mood":["technical","fresh"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"sensu.svg","brand":"sensu","variant":"main","pair":"sensu-icon.svg","width":512.0,"height":174.0,"aspect":2.943,"aspect_class":"horizontal","bytes":5421,"shapes":3,"anchors":142,"colors":["#2b335b","#73cc58"],"n_colors":2,"color_families":["blue","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"diamond arcs icon plus Sensu name","geometry":["diamond"],"techniques":["containment"],"type_style":"geometric-sans","case":"titlecase","mood":["technical","friendly"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"sentry-icon.svg","brand":"sentry","variant":"icon","pair":"sentry.svg","width":256.0,"height":227.0,"aspect":1.128,"aspect_class":"square","bytes":1497,"shapes":2,"anchors":36,"colors":["#362d59"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"triangle glyph with concentric inner arcs","geometry":["triangle"],"techniques":["line-monoline","negative-space","hidden-meaning"],"type_style":null,"case":null,"mood":["watchful","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"sentry.svg","brand":"sentry","variant":"main","pair":"sentry-icon.svg","width":512.0,"height":113.0,"aspect":4.531,"aspect_class":"extra-wide","bytes":2867,"shapes":2,"anchors":112,"colors":["#362d59"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"arc triangle icon plus SENTRY","geometry":["triangle"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","solid"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"sequelize.svg","brand":"sequelize","variant":"main","pair":null,"width":256.0,"height":296.0,"aspect":0.865,"aspect_class":"square","bytes":3686,"shapes":28,"anchors":195,"colors":["#2f406a","#2379bd","#03afef"],"n_colors":3,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"stacked cubes inside blue isometric hexagon","geometry":["hexagon"],"techniques":["isometric-3d","containment","modular-repetition"],"type_style":null,"case":null,"mood":["structured","technical"],"industry":"database-data","exemplary":false,"note":""},{"file":"serverless.svg","brand":"serverless","variant":"main","pair":null,"width":256.0,"height":204.0,"aspect":1.255,"aspect_class":"wide","bytes":550,"shapes":2,"anchors":30,"colors":["#f26d61"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"coral bars split by slanted gaps","geometry":["square"],"techniques":["modular-repetition","negative-space"],"type_style":null,"case":null,"mood":["bold","dynamic"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"sherlock-icon.svg","brand":"sherlock","variant":"icon","pair":"sherlock.svg","width":256.0,"height":299.0,"aspect":0.856,"aspect_class":"square","bytes":9315,"shapes":4,"anchors":234,"colors":["#ffc700","#150007"],"n_colors":2,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"line-drawn detective with cap and pipe","geometry":["circle"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["quirky","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"sherlock.svg","brand":"sherlock","variant":"main","pair":"sherlock-icon.svg","width":512.0,"height":115.0,"aspect":4.452,"aspect_class":"horizontal","bytes":13755,"shapes":5,"anchors":378,"colors":["#000000","#ffc700","#150007"],"n_colors":3,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"detective icon plus bold SHERLOCK","geometry":["circle"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"uppercase","mood":["quirky","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"shields.svg","brand":"shields","variant":"main","pair":null,"width":256.0,"height":75.0,"aspect":3.413,"aspect_class":"horizontal","bytes":6360,"shapes":11,"anchors":180,"colors":["#000000","#ffffff"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"Shields IO split badge","geometry":["rounded-square"],"techniques":["containment","color-segments"],"type_style":"humanist-sans","case":"mixed","mood":["technical","simple"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"shipit.svg","brand":"shipit","variant":"main","pair":null,"width":512.0,"height":135.0,"aspect":3.793,"aspect_class":"horizontal","bytes":6939,"shapes":6,"anchors":176,"colors":["#464462","#464563","#e88826","#f7a81f"],"n_colors":4,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"orange sailboat plus SHIPIT name","geometry":["triangle"],"techniques":[],"type_style":"geometric-sans","case":"uppercase","mood":["confident","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"shippable.svg","brand":"shippable","variant":"main","pair":null,"width":512.0,"height":118.0,"aspect":4.339,"aspect_class":"horizontal","bytes":7831,"shapes":3,"anchors":207,"colors":["#000000","#238189"],"n_colors":2,"color_families":["black","cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy tight shippable lowercase","geometry":[],"techniques":[],"type_style":"grotesque-sans","case":"lowercase","mood":["bold","confident"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"shogun.svg","brand":"shogun","variant":"main","pair":null,"width":512.0,"height":178.0,"aspect":2.876,"aspect_class":"horizontal","bytes":5376,"shapes":2,"anchors":143,"colors":["#5d50c6"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"shogun in purple with macron o","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["modern","friendly"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"shopify.svg","brand":"shopify","variant":"main","pair":null,"width":256.0,"height":292.0,"aspect":0.877,"aspect_class":"square","bytes":2429,"shapes":4,"anchors":52,"colors":["#95bf46","#5e8e3e","#ffffff"],"n_colors":3,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"green shopping bag with S","geometry":["freeform"],"techniques":["dimensional-shading","containment"],"type_style":null,"case":null,"mood":["friendly","approachable"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"sidekick.svg","brand":"sidekick","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1085,"shapes":2,"anchors":18,"colors":["#e57e41"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange ring with notch cut","geometry":["circle"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["friendly","warm"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"sidekiq-icon.svg","brand":"sidekiq","variant":"icon","pair":"sidekiq.svg","width":256.0,"height":280.0,"aspect":0.914,"aspect_class":"square","bytes":8463,"shapes":3,"anchors":175,"colors":["#991b21","#000000"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red karate high-kick silhouette","geometry":["organic"],"techniques":["motion-lines"],"type_style":null,"case":null,"mood":["energetic","strong"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"sidekiq.svg","brand":"sidekiq","variant":"main","pair":"sidekiq-icon.svg","width":512.0,"height":188.0,"aspect":2.723,"aspect_class":"horizontal","bytes":14771,"shapes":4,"anchors":356,"colors":["#991b21","#000000"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"kicking figure plus Sidekiq name","geometry":["organic"],"techniques":[],"type_style":"humanist-sans","case":"titlecase","mood":["energetic","light"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"signal.svg","brand":"signal","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2984,"shapes":2,"anchors":99,"colors":["#3a76f0"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"blue speech bubble with dashed outer ring","geometry":["circle"],"techniques":["speech-bubble","containment"],"type_style":null,"case":null,"mood":["trustworthy","calm"],"industry":"social-communication","exemplary":false,"note":""},{"file":"sinatra.svg","brand":"sinatra","variant":"main","pair":null,"width":256.0,"height":174.0,"aspect":1.471,"aspect_class":"wide","bytes":5100,"shapes":8,"anchors":63,"colors":["#cec7bc","#afadae","#f3efe9","#eeeae3","#e1dbd2","#cdc5b7","#b4aa98","#d7d0c6","#cdc7bb","#c7c2b5","#cbc6ba","#d7d1c7","#e6dfd6","#e7e3d9","#e5dfd3","#dfd5c6","#b2a797","#c7bdae","#d6cebf","#e2dcd0","#f7f5ee","#e6e1d6","#d8d1c3","#d0c8b9","#cec5b5","#262222","#2f2c2c","#424143","#4a4a4c","#383536"],"n_colors":30,"color_families":["black","gray","orange","white","yellow"],"primary_family":"multi","gradients":6,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"realistic white fedora hat","geometry":["organic"],"techniques":["dimensional-shading","gradient"],"type_style":null,"case":null,"mood":["classic","suave"],"industry":"framework-library","exemplary":false,"note":"Photoreal rendering, weak as a scalable mark"},{"file":"sitepoint.svg","brand":"sitepoint","variant":"main","pair":null,"width":256.0,"height":307.0,"aspect":0.834,"aspect_class":"square","bytes":1004,"shapes":3,"anchors":28,"colors":["#07508b","#e57b25"],"n_colors":2,"color_families":["blue","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange and blue chevrons forming S","geometry":["freeform"],"techniques":["bracket-code","color-segments","arrow"],"type_style":null,"case":null,"mood":["dynamic","technical"],"industry":"education","exemplary":false,"note":""},{"file":"skaffolder.svg","brand":"skaffolder","variant":"main","pair":null,"width":512.0,"height":77.0,"aspect":6.649,"aspect_class":"extra-wide","bytes":3758,"shapes":3,"anchors":136,"colors":["#0a0a0a","#ff6b35"],"n_colors":2,"color_families":["black","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"Skaffolder with bracket-arrow ending","geometry":[],"techniques":["bracket-code"],"type_style":"geometric-sans","case":"titlecase","mood":["technical","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"sketch.svg","brand":"sketch","variant":"main","pair":null,"width":256.0,"height":232.0,"aspect":1.103,"aspect_class":"square","bytes":1046,"shapes":10,"anchors":39,"colors":["#fdb300","#eb6c00","#fdad00","#fdd231","#feeeb7"],"n_colors":5,"color_families":["orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"faceted yellow-orange diamond gem","geometry":["diamond"],"techniques":["dimensional-shading","color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["precious","bright"],"industry":"design-creative","exemplary":true,"note":"Clean faceted construction, shading by flat color only"},{"file":"skylight.svg","brand":"skylight","variant":"main","pair":null,"width":256.0,"height":289.0,"aspect":0.886,"aspect_class":"square","bytes":1954,"shapes":10,"anchors":80,"colors":["#bac4c5","#ed1a3b","#c2315d","#94407e","#577f9f","#00aec5","#93c483","#fcde11","#f78e36"],"n_colors":9,"color_families":["blue","cyan","gray","green","orange","pink","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"color pinwheel star in grey hexagon","geometry":["hexagon","radial"],"techniques":["color-segments","radial-symmetry","containment"],"type_style":null,"case":null,"mood":["colorful","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"skype.svg","brand":"skype","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2908,"shapes":2,"anchors":67,"colors":["#00aff0"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white S in blue cloud-circle","geometry":["organic","circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["friendly","soft"],"industry":"social-communication","exemplary":false,"note":""},{"file":"slack-icon.svg","brand":"slack","variant":"icon","pair":"slack.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1884,"shapes":5,"anchors":52,"colors":["#e01e5a","#36c5f0","#2eb67d","#ecb22e"],"n_colors":4,"color_families":["cyan","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"four-color rounded bars forming hash pinwheel","geometry":["radial","rounded-square"],"techniques":["modular-repetition","radial-symmetry","color-segments","hidden-meaning"],"type_style":null,"case":null,"mood":["friendly","colorful"],"industry":"productivity-collaboration","exemplary":true,"note":"Modular pieces form hashtag and pinwheel"},{"file":"slack.svg","brand":"slack","variant":"main","pair":"slack-icon.svg","width":512.0,"height":130.0,"aspect":3.938,"aspect_class":"horizontal","bytes":3513,"shapes":6,"anchors":109,"colors":["#000000","#e01e5a","#36c5f0","#2eb67d","#ecb22e"],"n_colors":5,"color_families":["black","cyan","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"hash pinwheel plus bold slack name","geometry":["radial"],"techniques":["modular-repetition","color-segments"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","confident"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"slides.svg","brand":"slides","variant":"main","pair":null,"width":256.0,"height":248.0,"aspect":1.032,"aspect_class":"square","bytes":1962,"shapes":5,"anchors":45,"colors":["#512833","#934358","#e5637c","#ffffff"],"n_colors":4,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"S on stack of offset slide squares","geometry":["square"],"techniques":["stacked-layers","containment"],"type_style":null,"case":null,"mood":["simple","warm"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"slim.svg","brand":"slim","variant":"main","pair":null,"width":256.0,"height":274.0,"aspect":0.934,"aspect_class":"square","bytes":2569,"shapes":2,"anchors":52,"colors":["#729544","#93bd5a"],"n_colors":2,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white S curve splitting green circle","geometry":["circle"],"techniques":["negative-space","color-segments"],"type_style":null,"case":null,"mood":["fresh","simple"],"industry":"framework-library","exemplary":false,"note":""},{"file":"smartling.svg","brand":"smartling","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2559,"shapes":2,"anchors":52,"colors":["#f26c5d"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"concentric broken red rings","geometry":["circle","radial"],"techniques":["line-monoline","radial-symmetry"],"type_style":null,"case":null,"mood":["dynamic","technical"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"smashingmagazine.svg","brand":"smashingmagazine","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2043,"shapes":3,"anchors":42,"colors":["#ef4d37","#f8953e","#f36e3e"],"n_colors":3,"color_families":["orange","red"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"S on skewed orange tile","geometry":["rounded-square"],"techniques":["gradient","containment"],"type_style":null,"case":null,"mood":["energetic","bold"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"snap-svg.svg","brand":"snap-svg","variant":"main","pair":null,"width":256.0,"height":425.0,"aspect":0.602,"aspect_class":"tall","bytes":2230,"shapes":6,"anchors":38,"colors":["#002e3b","#002639","#00bc85","#149d91","#004473","#00345f"],"n_colors":6,"color_families":["blue","cyan","green"],"primary_family":"multi","gradients":5,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"isometric hexagon ring with trailing tail","geometry":["hexagon"],"techniques":["isometric-3d","color-segments","negative-space"],"type_style":null,"case":null,"mood":["technical","structured"],"industry":"framework-library","exemplary":false,"note":""},{"file":"snowflake-icon.svg","brand":"snowflake","variant":"icon","pair":"snowflake.svg","width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":3755,"shapes":2,"anchors":119,"colors":["#29b5e8"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"snowflake of six arrowed arms","geometry":["radial"],"techniques":["radial-symmetry","modular-repetition","arrow"],"type_style":null,"case":null,"mood":["crisp","cool"],"industry":"database-data","exemplary":false,"note":""},{"file":"snowflake.svg","brand":"snowflake","variant":"main","pair":"snowflake-icon.svg","width":512.0,"height":116.0,"aspect":4.414,"aspect_class":"horizontal","bytes":15131,"shapes":3,"anchors":442,"colors":["#29b5e8"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"snowflake icon plus light lowercase name","geometry":["radial"],"techniques":["radial-symmetry"],"type_style":"geometric-sans","case":"lowercase","mood":["crisp","clean"],"industry":"database-data","exemplary":false,"note":""},{"file":"snowpack.svg","brand":"snowpack","variant":"main","pair":null,"width":256.0,"height":205.0,"aspect":1.249,"aspect_class":"square","bytes":692,"shapes":2,"anchors":16,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"black mountain with snow-cap cutout","geometry":["triangle"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["bold","minimal"],"industry":"developer-tools","exemplary":true,"note":"Mountain and snow cap from one triangle and one cut"},{"file":"snupps.svg","brand":"snupps","variant":"main","pair":null,"width":256.0,"height":301.0,"aspect":0.85,"aspect_class":"square","bytes":1475,"shapes":2,"anchors":31,"colors":["#ff6c0c"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"orange S shaped as speech bubble","geometry":["freeform"],"techniques":["speech-bubble","letter-substitution"],"type_style":null,"case":null,"mood":["bold","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"snyk.svg","brand":"snyk","variant":"main","pair":null,"width":256.0,"height":419.0,"aspect":0.611,"aspect_class":"tall","bytes":9925,"shapes":27,"anchors":320,"colors":["#ffffff","#3b3b63","#dbdbdb","#c6c6c6","#53537a","#bc9375","#073251","#c49a7e","#d8b7a0","#333152"],"n_colors":10,"color_families":["blue","gray","orange","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"stern doberman dog head","geometry":["organic"],"techniques":["mirror-symmetry","dimensional-shading"],"type_style":null,"case":null,"mood":["alert","protective"],"industry":"security-identity","exemplary":false,"note":""},{"file":"socket.io.svg","brand":"socket.io","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1042,"shapes":4,"anchors":20,"colors":["#010101","#ffffff"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"lightning bolt inside black ring","geometry":["circle"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["fast","minimal"],"industry":"framework-library","exemplary":true,"note":"Bolt in ring: simple, scalable, single-color"},{"file":"solarwinds.svg","brand":"solarwinds","variant":"main","pair":null,"width":512.0,"height":117.0,"aspect":4.376,"aspect_class":"horizontal","bytes":4819,"shapes":3,"anchors":153,"colors":["#444444","#f99d1c"],"n_colors":2,"color_families":["gray","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"lowercase name with orange wind swoosh","geometry":["freeform"],"techniques":["motion-lines"],"type_style":"geometric-sans","case":"lowercase","mood":["light","corporate"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"solid.svg","brand":"solid","variant":"main","pair":null,"width":256.0,"height":230.0,"aspect":1.113,"aspect_class":"square","bytes":1835,"shapes":6,"anchors":53,"colors":["#ffffff","#7c4dff","#f7f7f7","#444444"],"n_colors":4,"color_families":["gray","purple","white"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white S in purple hexagon","geometry":["hexagon"],"techniques":["containment","dimensional-shading"],"type_style":null,"case":null,"mood":["solid","modern"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"solidity.svg","brand":"solidity","variant":"main","pair":null,"width":256.0,"height":398.0,"aspect":0.643,"aspect_class":"tall","bytes":867,"shapes":7,"anchors":30,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"split grey octahedron of triangles","geometry":["triangle","diamond"],"techniques":["color-segments","isometric-3d"],"type_style":null,"case":null,"mood":["technical","geometric"],"industry":"programming-language","exemplary":false,"note":""},{"file":"solidjs-icon.svg","brand":"solidjs","variant":"icon","pair":"solidjs.svg","width":256.0,"height":239.0,"aspect":1.071,"aspect_class":"square","bytes":2775,"shapes":7,"anchors":45,"colors":["#76b3e1","#518ac8","#dcf2fd","#4377bb","#1f3b77","#315aa9","#1a336b"],"n_colors":7,"color_families":["blue"],"primary_family":"blue","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"blue 3D slabs forming an S","geometry":["freeform"],"techniques":["isometric-3d","gradient","stacked-layers"],"type_style":null,"case":null,"mood":["solid","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"solidjs.svg","brand":"solidjs","variant":"main","pair":"solidjs-icon.svg","width":512.0,"height":214.0,"aspect":2.393,"aspect_class":"wide","bytes":4150,"shapes":8,"anchors":92,"colors":["#000000","#76b3e1","#518ac8","#dcf2fd","#4377bb","#1f3b77","#315aa9","#1a336b"],"n_colors":8,"color_families":["black","blue"],"primary_family":"blue","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"slab S icon plus spaced SOLID","geometry":["freeform"],"techniques":["isometric-3d"],"type_style":"geometric-sans","case":"uppercase","mood":["clean","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"solr.svg","brand":"solr","variant":"main","pair":null,"width":256.0,"height":130.0,"aspect":1.969,"aspect_class":"wide","bytes":5887,"shapes":6,"anchors":152,"colors":["#201f26","#c7402b"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"thin Solr name with red sunburst","geometry":["radial"],"techniques":["radial-symmetry"],"type_style":"geometric-sans","case":"titlecase","mood":["light","warm"],"industry":"database-data","exemplary":false,"note":""},{"file":"sonarqube.svg","brand":"sonarqube","variant":"main","pair":null,"width":512.0,"height":125.0,"aspect":4.096,"aspect_class":"horizontal","bytes":5127,"shapes":3,"anchors":157,"colors":["#070707","#499cd2"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"bold lowercase name with sonar arcs","geometry":["circle"],"techniques":["motion-lines","line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["technical","confident"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"soundcloud.svg","brand":"soundcloud","variant":"main","pair":null,"width":256.0,"height":145.0,"aspect":1.766,"aspect_class":"wide","bytes":12758,"shapes":16,"anchors":255,"colors":["#f04923","#f6871f","#f57e20","#f36621"],"n_colors":4,"color_families":["orange","red"],"primary_family":"multi","gradients":14,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"waveform-bar cloud above SOUNDCLOUD","geometry":["organic"],"techniques":["gradient","modular-repetition","hidden-meaning"],"type_style":"geometric-sans","case":"uppercase","mood":["warm","energetic"],"industry":"media-entertainment","exemplary":true,"note":"Cloud built from sound bars fuses both halves of name"},{"file":"sourcegraph.svg","brand":"sourcegraph","variant":"main","pair":null,"width":256.0,"height":262.0,"aspect":0.977,"aspect_class":"square","bytes":1077,"shapes":4,"anchors":24,"colors":["#f96316","#b200f8","#00b4f2"],"n_colors":3,"color_families":["blue","orange","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three crossing colored rounded bars","geometry":["radial"],"techniques":["color-segments","overlap-transparency"],"type_style":null,"case":null,"mood":["vibrant","dynamic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"sourcetrail.svg","brand":"sourcetrail","variant":"main","pair":null,"width":256.0,"height":247.0,"aspect":1.036,"aspect_class":"square","bytes":2202,"shapes":2,"anchors":47,"colors":["#027ac3"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"blue anteater silhouette","geometry":["organic"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["friendly","curious"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"sourcetree.svg","brand":"sourcetree","variant":"main","pair":null,"width":256.0,"height":322.0,"aspect":0.795,"aspect_class":"tall","bytes":1424,"shapes":3,"anchors":24,"colors":["#2684ff","#0052cc"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"blue pin shape with round hole","geometry":["circle"],"techniques":["gradient","negative-space"],"type_style":null,"case":null,"mood":["simple","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"spark.svg","brand":"spark","variant":"main","pair":null,"width":256.0,"height":258.0,"aspect":0.992,"aspect_class":"square","bytes":2001,"shapes":8,"anchors":35,"colors":["#ffa64d"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"orange comet with fading trails","geometry":["circle","organic"],"techniques":["motion-lines","gradient","overlap-transparency"],"type_style":null,"case":null,"mood":["fast","energetic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"sparkcentral.svg","brand":"sparkcentral","variant":"main","pair":null,"width":256.0,"height":292.0,"aspect":0.877,"aspect_class":"square","bytes":1807,"shapes":3,"anchors":36,"colors":["#253351","#4690dc"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"rounded bars forming asterisk figure","geometry":["radial"],"techniques":["color-segments","mirror-symmetry"],"type_style":null,"case":null,"mood":["friendly","balanced"],"industry":"social-communication","exemplary":false,"note":""},{"file":"sparkpost.svg","brand":"sparkpost","variant":"main","pair":null,"width":512.0,"height":134.0,"aspect":3.821,"aspect_class":"horizontal","bytes":3468,"shapes":3,"anchors":137,"colors":["#55555a","#fa6423"],"n_colors":2,"color_families":["gray","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"SPARKPOST with flame replacing O","geometry":[],"techniques":["letter-substitution"],"type_style":"geometric-sans","case":"uppercase","mood":["energetic","technical"],"industry":"marketing-analytics","exemplary":true,"note":"Flame-for-O substitution adds one memorable accent"},{"file":"speakerdeck.svg","brand":"speakerdeck","variant":"main","pair":null,"width":256.0,"height":160.0,"aspect":1.6,"aspect_class":"wide","bytes":1065,"shapes":2,"anchors":33,"colors":["#009287"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"rounded teal S and bracket forming SD","geometry":["rounded-square"],"techniques":["geometric-construction","negative-space"],"type_style":"display-custom","case":"uppercase","mood":["bold","modern"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"speedcurve.svg","brand":"speedcurve","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2098,"shapes":2,"anchors":39,"colors":["#4295c2"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"double paperclip-like blue loops","geometry":["organic"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["fluid","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"spidermonkey-icon.svg","brand":"spidermonkey","variant":"icon","pair":"spidermonkey.svg","width":256.0,"height":213.0,"aspect":1.202,"aspect_class":"square","bytes":2701,"shapes":2,"anchors":60,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"black monkey silhouette forming an S","geometry":["organic"],"techniques":["hidden-meaning","letter-substitution"],"type_style":null,"case":null,"mood":["playful","clever"],"industry":"developer-tools","exemplary":true,"note":"Monkey silhouette doubles as the letter S"},{"file":"spidermonkey.svg","brand":"spidermonkey","variant":"main","pair":"spidermonkey-icon.svg","width":512.0,"height":73.0,"aspect":7.014,"aspect_class":"extra-wide","bytes":8637,"shapes":2,"anchors":325,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"SpiderMonkey serif with monkey S","geometry":[],"techniques":["letter-substitution"],"type_style":"serif","case":"mixed","mood":["classic","quirky"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"spinnaker.svg","brand":"spinnaker","variant":"main","pair":null,"width":256.0,"height":297.0,"aspect":0.862,"aspect_class":"square","bytes":9137,"shapes":12,"anchors":222,"colors":["#149cb5","#2b3990","#1e62a7","#1485bc","#0ba1cc","#05b4d7","#01c0de","#00c4e0"],"n_colors":8,"color_families":["blue","cyan"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"gradient blue sail above name","geometry":["triangle","organic"],"techniques":["gradient","overlap-transparency"],"type_style":"humanist-sans","case":"titlecase","mood":["dynamic","fresh"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"splunk.svg","brand":"splunk","variant":"main","pair":null,"width":512.0,"height":153.0,"aspect":3.346,"aspect_class":"horizontal","bytes":4953,"shapes":2,"anchors":140,"colors":["#0c1724"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"splunk followed by prompt chevron","geometry":[],"techniques":["bracket-code"],"type_style":"geometric-sans","case":"lowercase","mood":["technical","bold"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"spotify-icon.svg","brand":"spotify","variant":"icon","pair":"spotify.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1362,"shapes":2,"anchors":29,"colors":["#1ed760"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three sound-wave arcs in green circle","geometry":["circle"],"techniques":["containment","motion-lines"],"type_style":null,"case":null,"mood":["bold","friendly"],"industry":"media-entertainment","exemplary":true,"note":"Three arcs in a circle: minimal and instantly readable"},{"file":"spotify.svg","brand":"spotify","variant":"main","pair":"spotify-icon.svg","width":512.0,"height":160.0,"aspect":3.2,"aspect_class":"horizontal","bytes":5844,"shapes":2,"anchors":166,"colors":["#1ed760"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"wave circle plus bold Spotify name","geometry":["circle"],"techniques":["containment","motion-lines"],"type_style":"geometric-sans","case":"titlecase","mood":["bold","friendly"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"spree.svg","brand":"spree","variant":"main","pair":null,"width":512.0,"height":209.0,"aspect":2.45,"aspect_class":"wide","bytes":6738,"shapes":7,"anchors":172,"colors":["#0066cc","#99cc00"],"n_colors":2,"color_families":["blue","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"smiling cart with arrow plus spree","geometry":["freeform"],"techniques":["arrow","hidden-meaning"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","playful"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"spring-icon.svg","brand":"spring","variant":"icon","pair":"spring.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2609,"shapes":3,"anchors":62,"colors":["#6db33f","#ffffff"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"leaf cut from green circle with dot","geometry":["circle","organic"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["fresh","natural"],"industry":"framework-library","exemplary":false,"note":""},{"file":"spring.svg","brand":"spring","variant":"main","pair":"spring-icon.svg","width":512.0,"height":139.0,"aspect":3.683,"aspect_class":"horizontal","bytes":7112,"shapes":4,"anchors":205,"colors":["#6db33f","#ffffff"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"leaf circle plus green spring name","geometry":["circle"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"lowercase","mood":["fresh","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"sqlite.svg","brand":"sqlite","variant":"main","pair":null,"width":512.0,"height":228.0,"aspect":2.246,"aspect_class":"wide","bytes":8037,"shapes":5,"anchors":199,"colors":["#003b57","#0f80cc","#97d9f6"],"n_colors":3,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"feather quill on blue square plus SQLite serif","geometry":["square"],"techniques":["gradient","overlap-transparency"],"type_style":"serif","case":"mixed","mood":["classic","dated"],"industry":"database-data","exemplary":false,"note":"Gradient square plus serif feels dated"},{"file":"square.svg","brand":"square","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":980,"shapes":3,"anchors":28,"colors":["#2e3b4e"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"small square inside rounded dark square","geometry":["rounded-square","square"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["minimal","trustworthy"],"industry":"payments-fintech","exemplary":true,"note":"Name made literal with two nested squares"},{"file":"squarespace.svg","brand":"squarespace","variant":"main","pair":null,"width":256.0,"height":204.0,"aspect":1.255,"aspect_class":"wide","bytes":1769,"shapes":2,"anchors":42,"colors":["#1a1918"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two interlocking black link loops","geometry":["organic"],"techniques":["line-monoline","overlap-transparency","modular-repetition"],"type_style":null,"case":null,"mood":["elegant","bold"],"industry":"design-creative","exemplary":true,"note":"Interlocking modular strokes, strong single-color mark"},{"file":"stackbit-icon.svg","brand":"stackbit","variant":"icon","pair":"stackbit.svg","width":256.0,"height":209.0,"aspect":1.225,"aspect_class":"square","bytes":1417,"shapes":2,"anchors":36,"colors":["#3eb0fd"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"outlined isometric stacked layer squares","geometry":["diamond"],"techniques":["isometric-3d","stacked-layers","line-monoline"],"type_style":null,"case":null,"mood":["technical","light"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"stackbit.svg","brand":"stackbit","variant":"main","pair":"stackbit-icon.svg","width":512.0,"height":79.0,"aspect":6.481,"aspect_class":"extra-wide","bytes":3968,"shapes":4,"anchors":150,"colors":["#ffffff","#3eb2fd","#3eb0fd"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"layer icon plus white STACKBIT wordmark","geometry":["diamond"],"techniques":["isometric-3d","stacked-layers"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","clean"],"industry":"developer-tools","exemplary":false,"note":"White wordmark invisible on light backgrounds"},{"file":"stackoverflow-icon.svg","brand":"stackoverflow","variant":"icon","pair":"stackoverflow.svg","width":256.0,"height":304.0,"aspect":0.842,"aspect_class":"square","bytes":738,"shapes":3,"anchors":34,"colors":["#bcbbbb","#f48023"],"n_colors":2,"color_families":["gray","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"orange bars fanning out of grey tray","geometry":["freeform"],"techniques":["stacked-layers","hidden-meaning"],"type_style":null,"case":null,"mood":["friendly","energetic"],"industry":"developer-tools","exemplary":true,"note":"Literally depicts a stack overflowing its tray"},{"file":"stackoverflow.svg","brand":"stackoverflow","variant":"main","pair":"stackoverflow-icon.svg","width":512.0,"height":114.0,"aspect":4.491,"aspect_class":"horizontal","bytes":6587,"shapes":20,"anchors":232,"colors":["#0a0b09","#b58f52","#c78431","#e9812c","#e5712a","#9d8469","#797b7b"],"n_colors":7,"color_families":["black","gray","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"overflowing tray plus stackoverflow name","geometry":["freeform"],"techniques":["stacked-layers","hidden-meaning"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"stackshare.svg","brand":"stackshare","variant":"main","pair":null,"width":256.0,"height":228.0,"aspect":1.123,"aspect_class":"square","bytes":1938,"shapes":3,"anchors":49,"colors":["#0090f9","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"branching node graph in blue rounded square","geometry":["rounded-square"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["technical","clean"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"statuspage.svg","brand":"statuspage","variant":"main","pair":null,"width":256.0,"height":189.0,"aspect":1.354,"aspect_class":"wide","bytes":1164,"shapes":3,"anchors":16,"colors":["#2684ff","#0052cc"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"blue arc floating over circle","geometry":["circle"],"techniques":["gradient","negative-space"],"type_style":null,"case":null,"mood":["calm","modern"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"stdlib-icon.svg","brand":"stdlib","variant":"icon","pair":"stdlib.svg","width":256.0,"height":286.0,"aspect":0.895,"aspect_class":"square","bytes":6161,"shapes":11,"anchors":122,"colors":["#f0ad3e","#00aeef","#a4681d","#e18f2f","#006991","#008bbf"],"n_colors":6,"color_families":["blue","orange"],"primary_family":"multi","gradients":6,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"intertwined blue and orange S strands","geometry":["organic"],"techniques":["overlap-transparency","gradient","color-segments"],"type_style":null,"case":null,"mood":["dynamic","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"stdlib.svg","brand":"stdlib","variant":"main","pair":"stdlib-icon.svg","width":512.0,"height":159.0,"aspect":3.22,"aspect_class":"horizontal","bytes":9694,"shapes":13,"anchors":227,"colors":["#f0ad3e","#00aeef","#a4681d","#e18f2f","#006991","#008bbf"],"n_colors":6,"color_families":["blue","orange"],"primary_family":"multi","gradients":6,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"twisted strands icon plus stdlib name","geometry":["organic"],"techniques":["color-segments"],"type_style":"geometric-sans","case":"lowercase","mood":["technical","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"steam.svg","brand":"steam","variant":"main","pair":null,"width":256.0,"height":259.0,"aspect":0.988,"aspect_class":"square","bytes":1737,"shapes":2,"anchors":39,"colors":["#1a1918"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"piston linkage inside black circle","geometry":["circle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["mechanical","bold"],"industry":"gaming","exemplary":true,"note":"Steam-engine linkage in negative space, strong silhouette"},{"file":"stenciljs-icon.svg","brand":"stenciljs","variant":"icon","pair":"stenciljs.svg","width":256.0,"height":197.0,"aspect":1.299,"aspect_class":"wide","bytes":446,"shapes":2,"anchors":15,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three slanted black parallelogram bars","geometry":["freeform"],"techniques":["modular-repetition","motion-lines"],"type_style":null,"case":null,"mood":["fast","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"stenciljs.svg","brand":"stenciljs","variant":"main","pair":"stenciljs-icon.svg","width":512.0,"height":107.0,"aspect":4.785,"aspect_class":"extra-wide","bytes":2477,"shapes":2,"anchors":90,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"slanted bars icon plus bold stencil","geometry":["freeform"],"techniques":["motion-lines"],"type_style":"geometric-sans","case":"lowercase","mood":["bold","fast"],"industry":"framework-library","exemplary":false,"note":""},{"file":"stetho.svg","brand":"stetho","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3208,"shapes":4,"anchors":82,"colors":["#4caf50","#ffffff"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"stethoscope with gear in green circle","geometry":["circle"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["friendly","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"stickermule.svg","brand":"stickermule","variant":"main","pair":null,"width":256.0,"height":149.0,"aspect":1.718,"aspect_class":"wide","bytes":10561,"shapes":4,"anchors":289,"colors":["#4c2418","#e26029"],"n_colors":2,"color_families":["orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"brown mule standing on stickermule name","geometry":["organic"],"techniques":["color-segments"],"type_style":"rounded-sans","case":"lowercase","mood":["playful","friendly"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"stimulus.svg","brand":"stimulus","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1555,"shapes":2,"anchors":59,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"white stream waves inside black square","geometry":["square"],"techniques":["negative-space","containment","arrow"],"type_style":null,"case":null,"mood":["bold","dynamic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"stitch.svg","brand":"stitch","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":910,"shapes":2,"anchors":34,"colors":["#ffc600"],"n_colors":1,"color_families":["yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"dashed seam line in yellow square","geometry":["square"],"techniques":["containment","negative-space","hidden-meaning"],"type_style":null,"case":null,"mood":["simple","bright"],"industry":"database-data","exemplary":false,"note":""},{"file":"stoplight.svg","brand":"stoplight","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2728,"shapes":4,"anchors":86,"colors":["#ffffff","#3880f0"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"line-drawn robot in blue circle","geometry":["circle"],"techniques":["line-monoline","containment"],"type_style":null,"case":null,"mood":["friendly","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"storybook-icon.svg","brand":"storybook","variant":"icon","pair":"storybook.svg","width":256.0,"height":319.0,"aspect":0.803,"aspect_class":"square","bytes":2084,"shapes":4,"anchors":34,"colors":["#ff4785","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white S on pink bookmarked book","geometry":["rounded-square"],"techniques":["containment","hidden-meaning"],"type_style":null,"case":null,"mood":["playful","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"storybook.svg","brand":"storybook","variant":"main","pair":"storybook-icon.svg","width":512.0,"height":103.0,"aspect":4.971,"aspect_class":"extra-wide","bytes":7640,"shapes":5,"anchors":195,"colors":["#333333","#ff4785","#ffffff"],"n_colors":3,"color_families":["gray","red","white"],"primary_family":"red","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"book S icon plus Storybook name","geometry":["rounded-square"],"techniques":["containment"],"type_style":"geometric-sans","case":"titlecase","mood":["friendly","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"strapi-icon.svg","brand":"strapi","variant":"icon","pair":"strapi.svg","width":256.0,"height":252.0,"aspect":1.016,"aspect_class":"square","bytes":994,"shapes":4,"anchors":31,"colors":["#8e75ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"folded purple ribbon shape","geometry":["square","triangle"],"techniques":["overlap-transparency","isometric-3d"],"type_style":null,"case":null,"mood":["modern","light"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"strapi.svg","brand":"strapi","variant":"main","pair":"strapi-icon.svg","width":512.0,"height":133.0,"aspect":3.85,"aspect_class":"horizontal","bytes":6627,"shapes":4,"anchors":188,"colors":["#8e75ff","#2f2e8b"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"folded ribbon icon plus strapi name","geometry":["square"],"techniques":["overlap-transparency"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"strider.svg","brand":"strider","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1620,"shapes":6,"anchors":56,"colors":["#006eaf","#00a7e1","#5bc9ec","#ffffff","#013a78"],"n_colors":5,"color_families":["blue","cyan","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"white radiating lines splitting blue circle","geometry":["circle","radial"],"techniques":["color-segments","radial-symmetry"],"type_style":null,"case":null,"mood":["dynamic","cool"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"stripe.svg","brand":"stripe","variant":"main","pair":null,"width":512.0,"height":214.0,"aspect":2.393,"aspect_class":"wide","bytes":2231,"shapes":2,"anchors":74,"colors":["#6772e5"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy purple stripe lowercase","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["confident","modern"],"industry":"payments-fintech","exemplary":true,"note":"Tight custom lowercase, wordmark carries the brand alone"},{"file":"struts.svg","brand":"struts","variant":"main","pair":null,"width":256.0,"height":290.0,"aspect":0.883,"aspect_class":"square","bytes":1460,"shapes":11,"anchors":69,"colors":["#202a5a","#2c448a","#283a79","#3558a7","#416fb5","#477fc1"],"n_colors":6,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"isometric blue S block","geometry":["hexagon"],"techniques":["isometric-3d","dimensional-shading"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"styleci.svg","brand":"styleci","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":778,"shapes":3,"anchors":21,"colors":["#e44041","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"white CI in red square","geometry":["square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","simple"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"stylefmt.svg","brand":"stylefmt","variant":"main","pair":null,"width":256.0,"height":154.0,"aspect":1.662,"aspect_class":"wide","bytes":2576,"shapes":5,"anchors":65,"colors":["#000000","#1c96d4","#c61a41","#eeb034"],"n_colors":4,"color_families":["black","blue","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"magic wand between code brackets with sparkles","geometry":[],"techniques":["bracket-code","line-monoline"],"type_style":null,"case":null,"mood":["playful","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"stylelint.svg","brand":"stylelint","variant":"main","pair":null,"width":256.0,"height":245.0,"aspect":1.045,"aspect_class":"square","bytes":2171,"shapes":2,"anchors":68,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"tuxedo shirt front with bow tie","geometry":["triangle"],"techniques":["negative-space","mirror-symmetry"],"type_style":null,"case":null,"mood":["elegant","witty"],"industry":"developer-tools","exemplary":true,"note":"Tuxedo metaphor for 'style'; shirt formed by negative space."},{"file":"stylis.svg","brand":"stylis","variant":"main","pair":null,"width":512.0,"height":201.0,"aspect":2.547,"aspect_class":"horizontal","bytes":2382,"shapes":2,"anchors":88,"colors":["#745dc0","#5497d8"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"italic bold name with extended y","geometry":[],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["dynamic","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"stylus.svg","brand":"stylus","variant":"main","pair":null,"width":512.0,"height":315.0,"aspect":1.625,"aspect_class":"wide","bytes":4828,"shapes":2,"anchors":101,"colors":["#333333"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"brush script name","geometry":[],"techniques":["hand-drawn"],"type_style":"script","case":"lowercase","mood":["expressive","fluid"],"industry":"programming-language","exemplary":false,"note":""},{"file":"sublimetext-icon.svg","brand":"sublimetext","variant":"icon","pair":"sublimetext.svg","width":256.0,"height":332.0,"aspect":0.771,"aspect_class":"tall","bytes":1315,"shapes":4,"anchors":27,"colors":["#ff9800","#ff9700","#f48e00","#d06f00"],"n_colors":4,"color_families":["orange"],"primary_family":"orange","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"S built from slanted folded ribbons","geometry":["freeform"],"techniques":["stacked-layers","dimensional-shading","gradient"],"type_style":null,"case":null,"mood":["bold","energetic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"sublimetext.svg","brand":"sublimetext","variant":"main","pair":"sublimetext-icon.svg","width":512.0,"height":62.0,"aspect":8.258,"aspect_class":"extra-wide","bytes":9790,"shapes":4,"anchors":323,"colors":["#ffffff","#ff9800","#ff9700","#f48e00","#d06f00"],"n_colors":5,"color_families":["orange","white"],"primary_family":"orange","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"folded ribbon S beside name","geometry":["freeform"],"techniques":["dimensional-shading","gradient"],"type_style":"geometric-sans","case":"titlecase","mood":["bold","modern"],"industry":"developer-tools","exemplary":false,"note":"Wordmark filled white; disappears on light backgrounds."},{"file":"subversion.svg","brand":"subversion","variant":"main","pair":null,"width":256.0,"height":186.0,"aspect":1.376,"aspect_class":"wide","bytes":2352,"shapes":2,"anchors":56,"colors":["#809cc8"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"sweeping S curves cut through blue rectangle","geometry":["square"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["technical","fluid"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"sugarss.svg","brand":"sugarss","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":137907,"shapes":535,"anchors":2764,"colors":["#2dcc9f","#d0f5f5","#c8eeee","#9deeee","#f0ffff","#94b3ca","#ff8aff","#733335","#cdeeee","#ddf5f5","#c2f5f5","#249e7c"],"n_colors":12,"color_families":["blue","cyan","green","pink","red","white"],"primary_family":"multi","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"smiling sugar cube character","geometry":["circle","square"],"techniques":["containment"],"type_style":null,"case":null,"mood":["playful","cute"],"industry":"framework-library","exemplary":false,"note":""},{"file":"supabase-icon.svg","brand":"supabase","variant":"icon","pair":"supabase.svg","width":256.0,"height":263.0,"aspect":0.973,"aspect_class":"square","bytes":1253,"shapes":4,"anchors":18,"colors":["#3ecf8e","#249361"],"n_colors":2,"color_families":["green"],"primary_family":"green","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"split lightning bolt","geometry":["freeform"],"techniques":["gradient"],"type_style":null,"case":null,"mood":["fast","modern"],"industry":"database-data","exemplary":true,"note":"Bolt split into two offset halves; minimal, memorable."},{"file":"supabase.svg","brand":"supabase","variant":"main","pair":"supabase-icon.svg","width":512.0,"height":99.0,"aspect":5.172,"aspect_class":"extra-wide","bytes":8894,"shapes":5,"anchors":294,"colors":["#1f1f1f","#3ecf8e","#249361"],"n_colors":3,"color_families":["black","green"],"primary_family":"green","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"split lightning bolt with name","geometry":["freeform"],"techniques":["gradient"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","clean"],"industry":"database-data","exemplary":false,"note":""},{"file":"surge.svg","brand":"surge","variant":"main","pair":null,"width":256.0,"height":380.0,"aspect":0.674,"aspect_class":"tall","bytes":10970,"shapes":31,"anchors":325,"colors":["#564740","#483a34","#aad9bd","#f7e3d6","#faf1eb","#63c199","#c5e4d0","#fbf9f6","#a8e1c2"],"n_colors":9,"color_families":["gray","green","orange","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"walrus face with tusks","geometry":["organic"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["friendly","quirky"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"survicate.svg","brand":"survicate","variant":"main","pair":null,"width":256.0,"height":202.0,"aspect":1.267,"aspect_class":"wide","bytes":822,"shapes":4,"anchors":23,"colors":["#29292b","#e8a824"],"n_colors":2,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"angular face with check-mark smile","geometry":["triangle"],"techniques":["mirror-symmetry","hidden-meaning"],"type_style":null,"case":null,"mood":["friendly","smart"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"suse.svg","brand":"suse","variant":"main","pair":null,"width":512.0,"height":238.0,"aspect":2.151,"aspect_class":"wide","bytes":7228,"shapes":4,"anchors":232,"colors":["#0d2c40","#02d35f"],"n_colors":2,"color_families":["blue","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"green chameleon above bold name","geometry":["organic"],"techniques":[],"type_style":"geometric-sans","case":"uppercase","mood":["friendly","confident"],"industry":"os-platform","exemplary":false,"note":""},{"file":"susy.svg","brand":"susy","variant":"main","pair":null,"width":256.0,"height":228.0,"aspect":1.123,"aspect_class":"square","bytes":1763,"shapes":2,"anchors":46,"colors":["#ff0080"],"n_colors":1,"color_families":["pink"],"primary_family":"pink","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"serif S between angle brackets","geometry":[],"techniques":["bracket-code"],"type_style":"serif","case":"uppercase","mood":["playful","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"svelte-icon.svg","brand":"svelte","variant":"icon","pair":"svelte.svg","width":256.0,"height":308.0,"aspect":0.831,"aspect_class":"square","bytes":2585,"shapes":3,"anchors":60,"colors":["#ff3e00","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"S from interlocking rounded links","geometry":["organic"],"techniques":["negative-space","line-monoline"],"type_style":null,"case":null,"mood":["bold","energetic"],"industry":"framework-library","exemplary":true,"note":"S drawn as two interlocking rounded links; strong negative space."},{"file":"svelte.svg","brand":"svelte","variant":"main","pair":"svelte-icon.svg","width":512.0,"height":125.0,"aspect":4.096,"aspect_class":"horizontal","bytes":4882,"shapes":4,"anchors":150,"colors":["#4a4a55","#ff3e00","#ffffff"],"n_colors":3,"color_families":["gray","red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"interlocking S beside tracked name","geometry":["organic"],"techniques":["negative-space"],"type_style":"geometric-sans","case":"uppercase","mood":["modern","clean"],"industry":"framework-library","exemplary":false,"note":""},{"file":"svg.svg","brand":"svg","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3131,"shapes":3,"anchors":73,"colors":["#000000","#ffb13b"],"n_colors":2,"color_families":["black","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"eight-armed asterisk with node dots","geometry":["radial","circle"],"techniques":["radial-symmetry"],"type_style":null,"case":null,"mood":["bold","playful"],"industry":"design-creative","exemplary":false,"note":""},{"file":"swagger.svg","brand":"swagger","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3961,"shapes":4,"anchors":87,"colors":["#ffffff","#49a32b"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"curly braces with dots in circle","geometry":["circle"],"techniques":["bracket-code","containment"],"type_style":null,"case":null,"mood":["technical","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"swift.svg","brand":"swift","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2421,"shapes":4,"anchors":55,"colors":["#ffffff","#faae42","#ef3e31","#e39f3a","#d33929"],"n_colors":5,"color_families":["orange","red","white"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"swift bird in rounded square","geometry":["rounded-square"],"techniques":["negative-space","gradient","containment"],"type_style":null,"case":null,"mood":["fast","sleek"],"industry":"programming-language","exemplary":true,"note":"Name-literal bird in negative space; simple swoosh construction."},{"file":"swiftype.svg","brand":"swiftype","variant":"main","pair":null,"width":256.0,"height":315.0,"aspect":0.813,"aspect_class":"square","bytes":1230,"shapes":3,"anchors":29,"colors":["#f55341","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"lightning bolt in rounded blob","geometry":["rounded-square","organic"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["fast","energetic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"symfony.svg","brand":"symfony","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":2605,"shapes":3,"anchors":54,"colors":["#1a171b","#ffffff"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"calligraphic sf ligature in black circle","geometry":["circle"],"techniques":["ligature","containment","negative-space"],"type_style":"script","case":"lowercase","mood":["elegant","classic"],"industry":"framework-library","exemplary":false,"note":""},{"file":"sysdig-icon.svg","brand":"sysdig","variant":"icon","pair":null,"width":256.0,"height":317.0,"aspect":0.808,"aspect_class":"square","bytes":2494,"shapes":2,"anchors":62,"colors":["#00abc7"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"shovel drawn in parallel strokes","geometry":["freeform"],"techniques":["line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["technical","clever"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"t3.svg","brand":"t3","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":4281,"shapes":13,"anchors":98,"colors":["#4d37b9","#ffffff","#b300e3","#4e00bf","#0ebbf0","#93e477","#dde6ec","#fe4545","#feb900","#47e8e2"],"n_colors":10,"color_families":["blue","cyan","green","purple","red","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"T3 in circle ringed by dots","geometry":["circle","radial"],"techniques":["containment","radial-symmetry"],"type_style":"geometric-sans","case":"uppercase","mood":["modern","playful"],"industry":"framework-library","exemplary":false,"note":""},{"file":"tableau-icon.svg","brand":"tableau","variant":"icon","pair":"tableau.svg","width":256.0,"height":251.0,"aspect":1.02,"aspect_class":"square","bytes":1568,"shapes":10,"anchors":126,"colors":["#7099a6","#eb912c","#59879b","#e8762c","#5b6591","#c72035","#1f447e"],"n_colors":7,"color_families":["blue","cyan","orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"cluster of colored plus signs","geometry":["grid-modular"],"techniques":["modular-repetition","color-segments"],"type_style":null,"case":null,"mood":["analytical","vibrant"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"tableau.svg","brand":"tableau","variant":"main","pair":"tableau-icon.svg","width":512.0,"height":109.0,"aspect":4.697,"aspect_class":"extra-wide","bytes":11191,"shapes":11,"anchors":376,"colors":["#7099a6","#eb912c","#59879b","#e8762c","#5b6591","#c72035","#1f447e"],"n_colors":7,"color_families":["blue","cyan","orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"plus-sign cluster with +ableau name","geometry":["grid-modular"],"techniques":["letter-substitution","modular-repetition","color-segments"],"type_style":"geometric-sans","case":"lowercase","mood":["analytical","clean"],"industry":"marketing-analytics","exemplary":true,"note":"t replaced by plus sign, echoing symbol; coherent system."},{"file":"taiga.svg","brand":"taiga","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1337,"shapes":10,"anchors":45,"colors":["#a295ae","#5d6f6d","#8cd592","#665e74","#3c3647","#837193","#a2f4ac","#7ea685"],"n_colors":8,"color_families":["gray","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"rotated translucent squares forming flower","geometry":["square","radial"],"techniques":["overlap-transparency","radial-symmetry"],"type_style":null,"case":null,"mood":["organic","calm"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"tailwindcss-icon.svg","brand":"tailwindcss","variant":"icon","pair":"tailwindcss.svg","width":256.0,"height":154.0,"aspect":1.662,"aspect_class":"wide","bytes":1176,"shapes":2,"anchors":18,"colors":["#2298bd","#0ed7b5"],"n_colors":2,"color_families":["cyan"],"primary_family":"cyan","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two stacked wind waves","geometry":["organic"],"techniques":["modular-repetition","gradient"],"type_style":null,"case":null,"mood":["fluid","fresh"],"industry":"framework-library","exemplary":true,"note":"Two repeated wave strokes; minimal, memorable, name-literal."},{"file":"tailwindcss.svg","brand":"tailwindcss","variant":"main","pair":"tailwindcss-icon.svg","width":512.0,"height":64.0,"aspect":8.0,"aspect_class":"extra-wide","bytes":4898,"shapes":3,"anchors":152,"colors":["#2d3748","#2298bd","#0ed7b5"],"n_colors":3,"color_families":["blue","cyan"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"double wave beside name","geometry":["organic"],"techniques":["modular-repetition"],"type_style":"geometric-sans","case":"lowercase","mood":["fresh","clean"],"industry":"framework-library","exemplary":false,"note":""},{"file":"tapcart-icon.svg","brand":"tapcart","variant":"icon","pair":"tapcart.svg","width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":1434,"shapes":2,"anchors":33,"colors":["#373aaf"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"concentric arcs like tap ripple","geometry":["circle"],"techniques":["line-monoline","modular-repetition"],"type_style":null,"case":null,"mood":["modern","dynamic"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"tapcart.svg","brand":"tapcart","variant":"main","pair":"tapcart-icon.svg","width":512.0,"height":114.0,"aspect":4.491,"aspect_class":"horizontal","bytes":5763,"shapes":3,"anchors":163,"colors":["#373aaf","#000000"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"concentric arcs beside name","geometry":["circle"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","friendly"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"targetprocess.svg","brand":"targetprocess","variant":"main","pair":null,"width":256.0,"height":267.0,"aspect":0.959,"aspect_class":"square","bytes":5881,"shapes":14,"anchors":212,"colors":["#1a1a1a","#649791","#efc519","#a21c3d","#068cba","#531210","#509f4e","#106e66","#92beaf","#4b635b","#b9bc63","#e38b25"],"n_colors":12,"color_families":["black","blue","cyan","gray","green","orange","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"colored rounded bars in radial cluster","geometry":["radial","hexagon"],"techniques":["modular-repetition","color-segments"],"type_style":null,"case":null,"mood":["vibrant","organized"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"taskade-icon.svg","brand":"taskade","variant":"icon","pair":"taskade.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":13787,"shapes":4,"anchors":292,"colors":["#ffffff","#2f2f2f"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"fluffy sheep face","geometry":["circle","organic"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["cute","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"taskade.svg","brand":"taskade","variant":"main","pair":"taskade-icon.svg","width":512.0,"height":141.0,"aspect":3.631,"aspect_class":"horizontal","bytes":22484,"shapes":4,"anchors":506,"colors":["#ffffff","#2f2f2f","#000000"],"n_colors":3,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"sheep face beside name","geometry":["circle"],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","clean"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"tastejs.svg","brand":"tastejs","variant":"main","pair":null,"width":256.0,"height":389.0,"aspect":0.658,"aspect_class":"tall","bytes":85360,"shapes":210,"anchors":1558,"colors":["#7f1e0b","#ad1813","#590d00","#250000","#e04c89","#ce4920","#c62619","#020202","#8c0000","#4a0100","#ffffff","#660300","#920b04","#af2419","#95110a","#6e0301","#3fb5ba","#fe980e","#6caf11","#fbb316","#cb9257","#fbb040","#ea6709","#e6e7e8","#a7a9ac","#ff8b6c","#b32000","#c7392e","#f28567","#bf441e","#b11a0a","#ddc48c","#6aac10","#64a10f","#59900c","#52840a","#9c1710","#96003a","#cebc99","#d8caaf","#e6ddcc","#f1ece2","#f9f7f3","#fefdfc","#faf8f4","#f2eee5","#e8e0d0","#dbceb5","#961307","#8c1306","#7a0400","#710300","#700300","#770501","#991000","#b08bab","#a07f9b","#7e647b","#644f61","#51414f","#463844","#423540","#a33665","#7d002f","#361221","#ffada6","#85211b","#a6261a","#ab2015","#b82c1e","#b3174b","#2b0011","#3ed8bb","#f6d62c","#f6d60e","#ff5906","#2cab98","#81c819","#71b612","#e3c091","#7f5327"],"n_colors":81,"color_families":["black","cyan","gray","green","orange","pink","red","white","yellow"],"primary_family":"multi","gradients":80,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"red monster licking a popsicle","geometry":["organic"],"techniques":["dimensional-shading"],"type_style":null,"case":null,"mood":["playful","wacky"],"industry":"open-source-community","exemplary":false,"note":"Detailed illustration; poor scalability at small sizes."},{"file":"tauri.svg","brand":"tauri","variant":"main","pair":null,"width":256.0,"height":289.0,"aspect":0.886,"aspect_class":"square","bytes":1844,"shapes":5,"anchors":37,"colors":["#ffc131","#24c8db"],"n_colors":2,"color_families":["cyan","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two interlocking arcs with dots","geometry":["circle"],"techniques":["radial-symmetry","color-segments"],"type_style":null,"case":null,"mood":["dynamic","modern"],"industry":"framework-library","exemplary":false,"note":""},{"file":"tealium.svg","brand":"tealium","variant":"main","pair":null,"width":256.0,"height":405.0,"aspect":0.632,"aspect_class":"tall","bytes":2773,"shapes":3,"anchors":60,"colors":["#1d7dc0","#969aa2"],"n_colors":2,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"diagonal rows of growing dots","geometry":["circle","grid-modular"],"techniques":["modular-repetition"],"type_style":null,"case":null,"mood":["technical","flowing"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"teamgrid.svg","brand":"teamgrid","variant":"main","pair":null,"width":256.0,"height":163.0,"aspect":1.571,"aspect_class":"wide","bytes":620,"shapes":2,"anchors":30,"colors":["#3c7dd0"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"row of vertical hexagonal bars","geometry":["grid-modular"],"techniques":["modular-repetition"],"type_style":null,"case":null,"mood":["rhythmic","orderly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"teamwork-icon.svg","brand":"teamwork","variant":"icon","pair":"teamwork.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1364,"shapes":4,"anchors":30,"colors":["#ffffff","#1d1c39","#ff22b1"],"n_colors":3,"color_families":["blue","pink","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"lowercase t with pink dot","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","modern"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"teamwork.svg","brand":"teamwork","variant":"main","pair":"teamwork-icon.svg","width":512.0,"height":69.0,"aspect":7.42,"aspect_class":"extra-wide","bytes":6321,"shapes":3,"anchors":183,"colors":["#1d1c39","#ff22b1"],"n_colors":2,"color_families":["blue","pink"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold name with pink period","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","confident"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"telegram.svg","brand":"telegram","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1131,"shapes":5,"anchors":26,"colors":["#40b3e0","#ffffff","#d2e5f1","#b5cfe4"],"n_colors":4,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"paper plane in blue circle","geometry":["circle","triangle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["fast","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"tensorflow.svg","brand":"tensorflow","variant":"main","pair":null,"width":256.0,"height":274.0,"aspect":0.934,"aspect_class":"square","bytes":1008,"shapes":4,"anchors":53,"colors":["#e55b2d","#ed8e24","#f8bf3c"],"n_colors":3,"color_families":["orange","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"isometric blocks reading as T and F","geometry":["freeform"],"techniques":["isometric-3d","dimensional-shading","hidden-meaning"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"ai-ml","exemplary":true,"note":"One isometric form reads as T and F from different sides."},{"file":"terminal.svg","brand":"terminal","variant":"main","pair":null,"width":256.0,"height":210.0,"aspect":1.219,"aspect_class":"square","bytes":1405,"shapes":3,"anchors":38,"colors":["#000000","#ffffff"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"terminal window with prompt cursor","geometry":["square"],"techniques":["bracket-code","containment"],"type_style":null,"case":null,"mood":["technical","minimal"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"terraform-icon.svg","brand":"terraform","variant":"icon","pair":"terraform.svg","width":256.0,"height":291.0,"aspect":0.88,"aspect_class":"square","bytes":536,"shapes":3,"anchors":19,"colors":["#4040b2","#5c4ee5"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"isometric parallelograms forming a T","geometry":["freeform"],"techniques":["isometric-3d","modular-repetition","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","solid"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"terraform.svg","brand":"terraform","variant":"main","pair":"terraform-icon.svg","width":512.0,"height":123.0,"aspect":4.163,"aspect_class":"horizontal","bytes":3498,"shapes":4,"anchors":144,"colors":["#000000","#4040b2","#5c4ee5"],"n_colors":3,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"isometric T blocks beside name","geometry":["freeform"],"techniques":["isometric-3d"],"type_style":"geometric-sans","case":"titlecase","mood":["technical","confident"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"terser-icon.svg","brand":"terser","variant":"icon","pair":"terser.svg","width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":1493,"shapes":8,"anchors":73,"colors":["#00b3e3","#ffc843","#ff4338","#002f32","#ff350f","#008c3c","#00250d"],"n_colors":7,"color_families":["black","cyan","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"overlapping colored bars forming asterisk","geometry":["radial"],"techniques":["overlap-transparency","color-segments","radial-symmetry"],"type_style":null,"case":null,"mood":["vibrant","energetic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"terser.svg","brand":"terser","variant":"main","pair":"terser-icon.svg","width":512.0,"height":157.0,"aspect":3.261,"aspect_class":"horizontal","bytes":3415,"shapes":23,"anchors":125,"colors":["#ff6b00","#05ce7c","#055600","#da1800","#da3ab3","#00b3e3","#00299f","#ff4338"],"n_colors":8,"color_families":["blue","cyan","green","orange","pink","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name in overlapping multicolor letters","geometry":[],"techniques":["overlap-transparency","color-segments"],"type_style":"display-custom","case":"lowercase","mood":["vibrant","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"testing-library.svg","brand":"testing-library","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":37745,"shapes":215,"anchors":729,"colors":["#4b1313","#302d3b","#6f828a","#9e1c20","#f389a4","#e34e70","#f7b3c5","#facfda","#e33332","#e03330","#d52e2c","#c32827","#a91f23","#89181a","#640e0e","#f7b0c2","#f6a4b6","#f390a5","#e7728b","#dc4d6c","#da4b6a"],"n_colors":21,"color_families":["gray","red"],"primary_family":"red","gradients":8,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"red cartoon octopus","geometry":["organic"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["playful","friendly"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"testlodge.svg","brand":"testlodge","variant":"main","pair":null,"width":256.0,"height":219.0,"aspect":1.169,"aspect_class":"square","bytes":1504,"shapes":13,"anchors":66,"colors":["#c5cf21","#70b540","#006d69","#008ca9"],"n_colors":4,"color_families":["cyan","green","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"faceted low-poly letter T","geometry":["triangle"],"techniques":["geometric-construction","color-segments","dimensional-shading"],"type_style":null,"case":null,"mood":["crisp","modern"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"threejs.svg","brand":"threejs","variant":"main","pair":null,"width":256.0,"height":259.0,"aspect":0.988,"aspect_class":"square","bytes":1671,"shapes":2,"anchors":77,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"triangle subdivided into wireframe mesh","geometry":["triangle","grid-modular"],"techniques":["line-monoline","geometric-construction","isometric-3d"],"type_style":null,"case":null,"mood":["technical","precise"],"industry":"framework-library","exemplary":true,"note":"Subdivided triangle mesh signals 3D in pure line geometry."},{"file":"tidal-icon.svg","brand":"tidal","variant":"icon","pair":"tidal.svg","width":256.0,"height":171.0,"aspect":1.497,"aspect_class":"wide","bytes":582,"shapes":2,"anchors":19,"colors":["#0a0b09"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"four diamonds in tight cluster","geometry":["diamond","grid-modular"],"techniques":["modular-repetition","negative-space"],"type_style":null,"case":null,"mood":["minimal","bold"],"industry":"media-entertainment","exemplary":true,"note":"Four identical diamonds; extreme simplicity, scales perfectly."},{"file":"tidal.svg","brand":"tidal","variant":"main","pair":"tidal-icon.svg","width":512.0,"height":68.0,"aspect":7.529,"aspect_class":"extra-wide","bytes":1235,"shapes":3,"anchors":65,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"diamond cluster with tracked name","geometry":["diamond"],"techniques":["modular-repetition"],"type_style":"geometric-sans","case":"uppercase","mood":["minimal","premium"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"tiktok-icon.svg","brand":"tiktok","variant":"icon","pair":"tiktok.svg","width":256.0,"height":290.0,"aspect":0.883,"aspect_class":"square","bytes":2504,"shapes":4,"anchors":69,"colors":["#ff004f","#000000","#00f2ea"],"n_colors":3,"color_families":["black","cyan","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"music note with cyan-red glitch offset","geometry":["freeform"],"techniques":["stacked-layers","hidden-meaning"],"type_style":null,"case":null,"mood":["energetic","youthful"],"industry":"social-communication","exemplary":true,"note":"Chromatic offset layers evoke motion; note doubles as d."},{"file":"tiktok.svg","brand":"tiktok","variant":"main","pair":"tiktok-icon.svg","width":512.0,"height":150.0,"aspect":3.413,"aspect_class":"horizontal","bytes":4159,"shapes":7,"anchors":149,"colors":["#ff004f","#000000","#00f2ea"],"n_colors":3,"color_families":["black","cyan","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"glitch music note beside name","geometry":["freeform"],"techniques":["stacked-layers"],"type_style":"display-custom","case":"mixed","mood":["energetic","bold"],"industry":"social-communication","exemplary":false,"note":""},{"file":"tnw.svg","brand":"tnw","variant":"main","pair":null,"width":512.0,"height":125.0,"aspect":4.096,"aspect_class":"horizontal","bytes":1351,"shapes":2,"anchors":63,"colors":["#ff4422"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"custom heavy connected TNW letters","geometry":[],"techniques":["ligature"],"type_style":"display-custom","case":"uppercase","mood":["bold","loud"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"todoist-icon.svg","brand":"todoist","variant":"icon","pair":"todoist.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1759,"shapes":5,"anchors":42,"colors":["#e44332","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"stacked check strokes in red square","geometry":["rounded-square"],"techniques":["stacked-layers","containment","negative-space"],"type_style":null,"case":null,"mood":["organized","energetic"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"todoist.svg","brand":"todoist","variant":"main","pair":"todoist-icon.svg","width":512.0,"height":130.0,"aspect":3.938,"aspect_class":"horizontal","bytes":10027,"shapes":6,"anchors":256,"colors":["#e44332","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"stacked checks beside name","geometry":["rounded-square"],"techniques":["stacked-layers","containment"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","organized"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"todomvc.svg","brand":"todomvc","variant":"main","pair":null,"width":256.0,"height":230.0,"aspect":1.113,"aspect_class":"square","bytes":1696,"shapes":3,"anchors":94,"colors":["#383838","#af2f2f"],"n_colors":2,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"check mark in dashed box","geometry":["rounded-square"],"techniques":["containment"],"type_style":null,"case":null,"mood":["simple","functional"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"tomcat.svg","brand":"tomcat","variant":"main","pair":null,"width":256.0,"height":182.0,"aspect":1.407,"aspect_class":"wide","bytes":6343,"shapes":7,"anchors":206,"colors":["#d1a41a","#ffdc76","#000000"],"n_colors":3,"color_families":["black","yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"leaping cartoon tomcat","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["playful","retro"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"toml.svg","brand":"toml","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":531,"shapes":4,"anchors":27,"colors":["#9c4221","#000000"],"n_colors":2,"color_families":["black","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"bold T inside square brackets","geometry":["square"],"techniques":["bracket-code","containment"],"type_style":"grotesque-sans","case":"uppercase","mood":["technical","sturdy"],"industry":"programming-language","exemplary":false,"note":""},{"file":"tor.svg","brand":"tor","variant":"main","pair":null,"width":512.0,"height":310.0,"aspect":1.652,"aspect_class":"wide","bytes":7236,"shapes":7,"anchors":175,"colors":["#68b044","#f5f8de","#7e4798","#010101"],"n_colors":4,"color_families":["black","green","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with onion replacing o","geometry":[],"techniques":["letter-substitution","hidden-meaning"],"type_style":"display-custom","case":"titlecase","mood":["trustworthy","bold"],"industry":"security-identity","exemplary":true,"note":"Onion substitutes the o, explaining onion routing at a glance."},{"file":"torus.svg","brand":"torus","variant":"main","pair":null,"width":256.0,"height":130.0,"aspect":1.969,"aspect_class":"wide","bytes":1484,"shapes":3,"anchors":18,"colors":["#a34cb4","#954db2","#3c52a1","#19549b","#ff0264","#fe744a","#fdbc39","#fddf31"],"n_colors":8,"color_families":["blue","pink","purple","red","yellow"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"gradient 3D ring","geometry":["circle"],"techniques":["gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["modern","vibrant"],"industry":"security-identity","exemplary":false,"note":""},{"file":"traackr.svg","brand":"traackr","variant":"main","pair":null,"width":512.0,"height":120.0,"aspect":4.267,"aspect_class":"horizontal","bytes":5905,"shapes":2,"anchors":180,"colors":["#250e62"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"dot-grid T shape beside name","geometry":["grid-modular","circle"],"techniques":["modular-repetition"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","confident"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"trac.svg","brand":"trac","variant":"main","pair":null,"width":256.0,"height":307.0,"aspect":0.834,"aspect_class":"square","bytes":2364,"shapes":9,"anchors":48,"colors":["#c00000"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"red animal paw print","geometry":["organic"],"techniques":["hidden-meaning"],"type_style":null,"case":null,"mood":["bold","simple"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"travis-ci-monochrome.svg","brand":"travis-ci-monochrome","variant":"main","pair":null,"width":256.0,"height":253.0,"aspect":1.012,"aspect_class":"square","bytes":9498,"shapes":5,"anchors":254,"colors":["#403e42"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"mustached builder with T hard hat","geometry":["organic"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["friendly","quirky"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"travis-ci.svg","brand":"travis-ci","variant":"main","pair":null,"width":256.0,"height":254.0,"aspect":1.008,"aspect_class":"square","bytes":33726,"shapes":44,"anchors":831,"colors":["#0e0f0d","#e1c5a2","#a89983","#ffffff","#e0d896","#d7c184","#9f8f78","#6e6a67","#93232c","#731b2a"],"n_colors":10,"color_families":["black","gray","orange","red","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"mustached builder with T hard hat","geometry":["organic"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["friendly","quirky"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"treasuredata-icon.svg","brand":"treasuredata","variant":"icon","pair":"treasuredata.svg","width":256.0,"height":174.0,"aspect":1.471,"aspect_class":"wide","bytes":2935,"shapes":5,"anchors":48,"colors":["#8855ff","#00b6ff","#ffffff","#009fff","#4036c1","#539eff"],"n_colors":6,"color_families":["blue","purple","white"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"faceted gradient gemstone","geometry":["diamond"],"techniques":["gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["premium","modern"],"industry":"database-data","exemplary":false,"note":""},{"file":"treasuredata.svg","brand":"treasuredata","variant":"main","pair":"treasuredata-icon.svg","width":512.0,"height":50.0,"aspect":10.24,"aspect_class":"extra-wide","bytes":8346,"shapes":6,"anchors":260,"colors":["#2e40aa","#8855ff","#00b6ff","#ffffff","#009fff","#4036c1","#539eff"],"n_colors":7,"color_families":["blue","purple","white"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"small gem beside tracked name","geometry":["diamond"],"techniques":["gradient"],"type_style":"geometric-sans","case":"uppercase","mood":["premium","clean"],"industry":"database-data","exemplary":false,"note":""},{"file":"treehouse.svg","brand":"treehouse","variant":"main","pair":null,"width":256.0,"height":274.0,"aspect":0.934,"aspect_class":"square","bytes":2415,"shapes":2,"anchors":59,"colors":["#5fcf80"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"white tree branch in green hexagon","geometry":["hexagon"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["friendly","growing"],"industry":"education","exemplary":false,"note":""},{"file":"trello.svg","brand":"trello","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1124,"shapes":4,"anchors":27,"colors":["#ffffff","#0091e6","#0079bf"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"kanban board with two cards","geometry":["rounded-square"],"techniques":["containment","negative-space","gradient"],"type_style":null,"case":null,"mood":["organized","simple"],"industry":"productivity-collaboration","exemplary":true,"note":"Product's own board UI reduced to two bars; instantly explanatory."},{"file":"truffle-icon.svg","brand":"truffle","variant":"icon","pair":"truffle.svg","width":256.0,"height":253.0,"aspect":1.012,"aspect_class":"square","bytes":2738,"shapes":5,"anchors":53,"colors":["#5e464d","#ffffff","#3fe0c5"],"n_colors":3,"color_families":["cyan","gray","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"chocolate truffle with swirl top","geometry":["circle"],"techniques":["dimensional-shading"],"type_style":null,"case":null,"mood":["sweet","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"truffle.svg","brand":"truffle","variant":"main","pair":"truffle-icon.svg","width":512.0,"height":539.0,"aspect":0.95,"aspect_class":"square","bytes":4613,"shapes":6,"anchors":151,"colors":["#5e464d","#ffffff","#3fe0c5"],"n_colors":3,"color_families":["cyan","gray","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"chocolate truffle above tracked name","geometry":["circle"],"techniques":[],"type_style":"display-custom","case":"uppercase","mood":["sweet","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"tsnode.svg","brand":"tsnode","variant":"main","pair":null,"width":512.0,"height":190.0,"aspect":2.695,"aspect_class":"horizontal","bytes":5659,"shapes":10,"anchors":152,"colors":["#2261a8","#ffffff","#333333"],"n_colors":3,"color_families":["blue","gray","white"],"primary_family":"blue","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"combination","symbol_type":"lettermark","subject":"TS hexagon with node, hexagon o","geometry":["hexagon"],"techniques":["containment","letter-substitution"],"type_style":"display-custom","case":"mixed","mood":["technical","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"tsu.svg","brand":"tsu","variant":"main","pair":null,"width":256.0,"height":171.0,"aspect":1.497,"aspect_class":"wide","bytes":4383,"shapes":2,"anchors":89,"colors":["#5cd39b"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy chunky name with macron","geometry":[],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["bold","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"tsuru.svg","brand":"tsuru","variant":"main","pair":null,"width":256.0,"height":193.0,"aspect":1.326,"aspect_class":"wide","bytes":1029,"shapes":2,"anchors":30,"colors":["#33dd99"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"origami crane of flat triangles","geometry":["triangle"],"techniques":["geometric-construction","hidden-meaning"],"type_style":null,"case":null,"mood":["light","elegant"],"industry":"cloud-infrastructure","exemplary":true,"note":"Name-literal origami crane from flat triangles; clean construction."},{"file":"tumblr-icon.svg","brand":"tumblr","variant":"icon","pair":"tumblr.svg","width":256.0,"height":446.0,"aspect":0.574,"aspect_class":"tall","bytes":660,"shapes":2,"anchors":17,"colors":["#303d4d"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"heavy lowercase t","geometry":[],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["bold","casual"],"industry":"social-communication","exemplary":false,"note":""},{"file":"tumblr.svg","brand":"tumblr","variant":"main","pair":"tumblr-icon.svg","width":512.0,"height":108.0,"aspect":4.741,"aspect_class":"extra-wide","bytes":4326,"shapes":2,"anchors":145,"colors":["#303d4d"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy name with trailing period","geometry":[],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["bold","casual"],"industry":"social-communication","exemplary":false,"note":""},{"file":"tunein.svg","brand":"tunein","variant":"main","pair":null,"width":512.0,"height":225.0,"aspect":2.276,"aspect_class":"wide","bytes":4205,"shapes":2,"anchors":147,"colors":["#14d8cc"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"TUNE and IN in offset boxes","geometry":["square"],"techniques":["containment","overlap-transparency"],"type_style":"display-custom","case":"uppercase","mood":["bold","fresh"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"tuple.svg","brand":"tuple","variant":"main","pair":null,"width":512.0,"height":191.0,"aspect":2.681,"aspect_class":"horizontal","bytes":1266,"shapes":4,"anchors":67,"colors":["#1f2e41","#bfc6f1","#4652af"],"n_colors":3,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"paired offset parallelograms beside name","geometry":["freeform"],"techniques":["overlap-transparency","isometric-3d"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","solid"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"turborepo-icon.svg","brand":"turborepo","variant":"icon","pair":"turborepo.svg","width":256.0,"height":318.0,"aspect":0.805,"aspect_class":"square","bytes":4165,"shapes":8,"anchors":64,"colors":["#000000","#1e90ff","#ff1e56"],"n_colors":3,"color_families":["black","blue","red"],"primary_family":"multi","gradients":6,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"black ring inside segmented gradient arc","geometry":["circle","radial"],"techniques":["gradient","color-segments","motion-lines"],"type_style":null,"case":null,"mood":["fast","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"turborepo.svg","brand":"turborepo","variant":"main","pair":"turborepo-icon.svg","width":512.0,"height":115.0,"aspect":4.452,"aspect_class":"horizontal","bytes":9160,"shapes":8,"anchors":229,"colors":["#000000","#1e90ff","#ff1e56"],"n_colors":3,"color_families":["black","blue","red"],"primary_family":"multi","gradients":6,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold name with ring replacing O","geometry":[],"techniques":["letter-substitution","gradient"],"type_style":"grotesque-sans","case":"uppercase","mood":["fast","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"turret.svg","brand":"turret","variant":"main","pair":null,"width":256.0,"height":384.0,"aspect":0.667,"aspect_class":"tall","bytes":391,"shapes":2,"anchors":25,"colors":["#195de6"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"chess rook castle tower","geometry":["freeform"],"techniques":["mirror-symmetry"],"type_style":null,"case":null,"mood":["solid","strong"],"industry":"other","exemplary":false,"note":""},{"file":"twilio-icon.svg","brand":"twilio","variant":"icon","pair":"twilio.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1338,"shapes":2,"anchors":30,"colors":["#f12e45"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"four dots in red ring","geometry":["circle"],"techniques":["containment","modular-repetition","mirror-symmetry"],"type_style":null,"case":null,"mood":["friendly","bold"],"industry":"social-communication","exemplary":false,"note":""},{"file":"twilio.svg","brand":"twilio","variant":"main","pair":"twilio-icon.svg","width":512.0,"height":155.0,"aspect":3.303,"aspect_class":"horizontal","bytes":4223,"shapes":2,"anchors":133,"colors":["#f12e45"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"four-dot ring beside name","geometry":["circle"],"techniques":["containment"],"type_style":"display-custom","case":"lowercase","mood":["bold","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"twitch.svg","brand":"twitch","variant":"main","pair":null,"width":256.0,"height":268.0,"aspect":0.955,"aspect_class":"square","bytes":565,"shapes":2,"anchors":30,"colors":["#5a3e85"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"glitch speech bubble with eyes","geometry":["freeform"],"techniques":["speech-bubble","negative-space"],"type_style":null,"case":null,"mood":["playful","bold"],"industry":"media-entertainment","exemplary":true,"note":"Speech bubble with two eyes: chat and character in one shape."},{"file":"twitter.svg","brand":"twitter","variant":"main","pair":null,"width":256.0,"height":209.0,"aspect":1.225,"aspect_class":"square","bytes":1284,"shapes":2,"anchors":22,"colors":["#55acee"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"blue bird in flight","geometry":["organic","circle"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["friendly","light"],"industry":"social-communication","exemplary":true,"note":"Bird constructed entirely from overlapping circle arcs."},{"file":"typeform-icon.svg","brand":"typeform","variant":"icon","pair":"typeform.svg","width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":1363,"shapes":2,"anchors":36,"colors":["#262627"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"T inside hand-drawn circle","geometry":["circle","organic"],"techniques":["hand-drawn","line-monoline","containment"],"type_style":"grotesque-sans","case":"uppercase","mood":["human","minimal"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"typeform.svg","brand":"typeform","variant":"main","pair":"typeform-icon.svg","width":512.0,"height":302.0,"aspect":1.695,"aspect_class":"wide","bytes":4355,"shapes":2,"anchors":139,"colors":["#262627"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"hand-drawn circle overlapping name","geometry":["circle","organic"],"techniques":["hand-drawn","line-monoline"],"type_style":"grotesque-sans","case":"titlecase","mood":["human","minimal"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"typescript-icon.svg","brand":"typescript","variant":"icon","pair":"typescript.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1905,"shapes":4,"anchors":55,"colors":["#007acc","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"TS in blue square","geometry":["square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","solid"],"industry":"programming-language","exemplary":false,"note":""},{"file":"typescript.svg","brand":"typescript","variant":"main","pair":"typescript-icon.svg","width":512.0,"height":125.0,"aspect":4.096,"aspect_class":"horizontal","bytes":5859,"shapes":2,"anchors":181,"colors":["#007acc"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"light camel-case name","geometry":[],"techniques":[],"type_style":"humanist-sans","case":"mixed","mood":["technical","clean"],"industry":"programming-language","exemplary":false,"note":""},{"file":"typo3-icon.svg","brand":"typo3","variant":"icon","pair":"typo3.svg","width":256.0,"height":260.0,"aspect":0.985,"aspect_class":"square","bytes":823,"shapes":2,"anchors":17,"colors":["#f49700"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"bent orange cone with notch","geometry":["organic"],"techniques":[],"type_style":null,"case":null,"mood":["bold","warm"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"typo3.svg","brand":"typo3","variant":"main","pair":"typo3-icon.svg","width":512.0,"height":137.0,"aspect":3.737,"aspect_class":"horizontal","bytes":2569,"shapes":3,"anchors":81,"colors":["#f49700","#000000"],"n_colors":2,"color_families":["black","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"orange cone beside condensed name","geometry":["organic"],"techniques":[],"type_style":"grotesque-sans","case":"uppercase","mood":["technical","plain"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"ubuntu.svg","brand":"ubuntu","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2207,"shapes":3,"anchors":49,"colors":["#dd4814","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"circle of three friends in orange disc","geometry":["circle","radial"],"techniques":["radial-symmetry","negative-space","containment","hidden-meaning"],"type_style":null,"case":null,"mood":["friendly","communal"],"industry":"os-platform","exemplary":true,"note":"Three abstract figures form a ring; radial symmetry carries 'community'."},{"file":"udacity-icon.svg","brand":"udacity","variant":"icon","pair":"udacity.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2744,"shapes":2,"anchors":73,"colors":["#2015ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"folded ribbon U outline","geometry":["freeform"],"techniques":["line-monoline","dimensional-shading"],"type_style":null,"case":null,"mood":["modern","dynamic"],"industry":"education","exemplary":false,"note":""},{"file":"udacity.svg","brand":"udacity","variant":"main","pair":"udacity-icon.svg","width":512.0,"height":97.0,"aspect":5.278,"aspect_class":"extra-wide","bytes":4387,"shapes":3,"anchors":155,"colors":["#2015ff","#0b0b0b"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"ribbon U beside tracked name","geometry":["freeform"],"techniques":["line-monoline"],"type_style":"geometric-sans","case":"uppercase","mood":["modern","clean"],"industry":"education","exemplary":false,"note":""},{"file":"udemy-icon.svg","brand":"udemy","variant":"icon","pair":"udemy.svg","width":256.0,"height":497.0,"aspect":0.515,"aspect_class":"tall","bytes":718,"shapes":3,"anchors":21,"colors":["#a435f0","#000000"],"n_colors":2,"color_families":["black","purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"U under purple chevron cap","geometry":["freeform"],"techniques":["hidden-meaning"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"education","exemplary":false,"note":""},{"file":"udemy.svg","brand":"udemy","variant":"main","pair":"udemy-icon.svg","width":512.0,"height":193.0,"aspect":2.653,"aspect_class":"horizontal","bytes":2946,"shapes":3,"anchors":99,"colors":["#a435f0","#000000"],"n_colors":2,"color_families":["black","purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold name with chevron over u","geometry":[],"techniques":["hidden-meaning"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","confident"],"industry":"education","exemplary":false,"note":""},{"file":"uikit.svg","brand":"uikit","variant":"main","pair":null,"width":256.0,"height":297.0,"aspect":0.862,"aspect_class":"square","bytes":497,"shapes":2,"anchors":18,"colors":["#2396f3"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"broken isometric hexagon outline","geometry":["hexagon"],"techniques":["isometric-3d","negative-space"],"type_style":null,"case":null,"mood":["technical","clean"],"industry":"framework-library","exemplary":false,"note":""},{"file":"umu.svg","brand":"umu","variant":"main","pair":null,"width":256.0,"height":346.0,"aspect":0.74,"aspect_class":"tall","bytes":1871,"shapes":2,"anchors":36,"colors":["#ffbd2b"],"n_colors":1,"color_families":["yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"giraffe silhouette in yellow square","geometry":["square"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["playful","warm"],"industry":"education","exemplary":false,"note":""},{"file":"unbounce-icon.svg","brand":"unbounce","variant":"icon","pair":"unbounce.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1430,"shapes":2,"anchors":33,"colors":["#303030"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"slashed circle in dark disc","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["bold","modern"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"unbounce.svg","brand":"unbounce","variant":"main","pair":"unbounce-icon.svg","width":512.0,"height":102.0,"aspect":5.02,"aspect_class":"extra-wide","bytes":6763,"shapes":2,"anchors":197,"colors":["#303030"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"slashed circle beside name","geometry":["circle"],"techniques":["containment"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","confident"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"undertow.svg","brand":"undertow","variant":"main","pair":null,"width":256.0,"height":146.0,"aspect":1.753,"aspect_class":"wide","bytes":1751,"shapes":5,"anchors":34,"colors":["#8f9495","#496b8c","#4a5d75","#4b73a2"],"n_colors":4,"color_families":["blue","gray"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"grey U riding a wave swoosh","geometry":["organic"],"techniques":["motion-lines"],"type_style":null,"case":null,"mood":["fluid","calm"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"unionpay.svg","brand":"unionpay","variant":"main","pair":null,"width":256.0,"height":160.0,"aspect":1.6,"aspect_class":"wide","bytes":12293,"shapes":5,"anchors":400,"colors":["#e21836","#00447c","#007b84","#fefefe"],"n_colors":4,"color_families":["blue","cyan","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"name over three colored parallelograms","geometry":["freeform"],"techniques":["color-segments","containment","stacked-layers"],"type_style":"display-custom","case":"mixed","mood":["established","trustworthy"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"unitjs.svg","brand":"unitjs","variant":"main","pair":null,"width":256.0,"height":269.0,"aspect":0.952,"aspect_class":"square","bytes":1428,"shapes":7,"anchors":50,"colors":["#a4d43a","#62655d","#3f4238","#f7f7f7"],"n_colors":4,"color_families":["gray","green","white"],"primary_family":"green","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"check mark hexagon with arrow","geometry":["hexagon"],"techniques":["containment","arrow","dimensional-shading"],"type_style":null,"case":null,"mood":["reliable","technical"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"unito-icon.svg","brand":"unito","variant":"icon","pair":"unito.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1517,"shapes":2,"anchors":37,"colors":["#3aafa9"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"monoline un ligature in teal circle","geometry":["circle"],"techniques":["ligature","line-monoline","containment"],"type_style":null,"case":null,"mood":["connected","calm"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"unito.svg","brand":"unito","variant":"main","pair":"unito-icon.svg","width":512.0,"height":163.0,"aspect":3.141,"aspect_class":"horizontal","bytes":3310,"shapes":3,"anchors":103,"colors":["#0c0c0c","#3aafa9"],"n_colors":2,"color_families":["black","cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"lettermark","subject":"un ligature circle beside name","geometry":["circle"],"techniques":["ligature","line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","clean"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"unity.svg","brand":"unity","variant":"main","pair":null,"width":256.0,"height":263.0,"aspect":0.973,"aspect_class":"square","bytes":717,"shapes":2,"anchors":29,"colors":["#222c37"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"cube implied by three arrow shapes","geometry":["triangle"],"techniques":["negative-space","isometric-3d","radial-symmetry"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"gaming","exemplary":true,"note":"Cube emerges from negative space between three angular pieces."},{"file":"unocss.svg","brand":"unocss","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":981,"shapes":4,"anchors":21,"colors":["#333333"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three primitive shapes in grid","geometry":["grid-modular","circle","square"],"techniques":["geometric-construction","modular-repetition"],"type_style":null,"case":null,"mood":["minimal","modular"],"industry":"framework-library","exemplary":false,"note":""},{"file":"unrealengine-icon.svg","brand":"unrealengine","variant":"icon","pair":"unrealengine.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":5023,"shapes":2,"anchors":195,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"calligraphic U in circle","geometry":["circle"],"techniques":["containment"],"type_style":"display-custom","case":"uppercase","mood":["powerful","classic"],"industry":"gaming","exemplary":false,"note":""},{"file":"unrealengine.svg","brand":"unrealengine","variant":"main","pair":"unrealengine-icon.svg","width":256.0,"height":210.0,"aspect":1.219,"aspect_class":"square","bytes":12777,"shapes":4,"anchors":517,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"U circle above extended name","geometry":["circle"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["powerful","bold"],"industry":"gaming","exemplary":false,"note":""},{"file":"upcase.svg","brand":"upcase","variant":"main","pair":null,"width":512.0,"height":108.0,"aspect":4.741,"aspect_class":"extra-wide","bytes":4214,"shapes":3,"anchors":115,"colors":["#5f5f5f","#487bf6","#0093cb"],"n_colors":3,"color_families":["blue","gray"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with caret replacing A","geometry":[],"techniques":["letter-substitution","arrow"],"type_style":"geometric-sans","case":"uppercase","mood":["clean","upward"],"industry":"education","exemplary":false,"note":""},{"file":"upwork.svg","brand":"upwork","variant":"main","pair":null,"width":512.0,"height":153.0,"aspect":3.346,"aspect_class":"horizontal","bytes":2169,"shapes":3,"anchors":78,"colors":["#6fda44","#000000"],"n_colors":2,"color_families":["black","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with custom green up ligature","geometry":[],"techniques":["ligature"],"type_style":"display-custom","case":"lowercase","mood":["friendly","confident"],"industry":"other","exemplary":false,"note":""},{"file":"user-testing-icon.svg","brand":"user-testing","variant":"icon","pair":"user-testing.svg","width":256.0,"height":330.0,"aspect":0.776,"aspect_class":"tall","bytes":1645,"shapes":2,"anchors":41,"colors":["#315cfd"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"U in blue speech bubble","geometry":["rounded-square"],"techniques":["speech-bubble","containment","negative-space"],"type_style":"geometric-sans","case":"uppercase","mood":["friendly","clear"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"user-testing.svg","brand":"user-testing","variant":"main","pair":"user-testing-icon.svg","width":512.0,"height":136.0,"aspect":3.765,"aspect_class":"horizontal","bytes":14762,"shapes":2,"anchors":384,"colors":["#315cfd"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"User in speech bubble, then Testing","geometry":[],"techniques":["speech-bubble","containment"],"type_style":"humanist-sans","case":"titlecase","mood":["friendly","clear"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"uservoice-icon.svg","brand":"uservoice","variant":"icon","pair":"uservoice.svg","width":256.0,"height":320.0,"aspect":0.8,"aspect_class":"square","bytes":2165,"shapes":2,"anchors":73,"colors":["#ff6720"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"orange U with dotted left stroke","geometry":["freeform"],"techniques":["modular-repetition"],"type_style":null,"case":null,"mood":["energetic","friendly"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"uservoice.svg","brand":"uservoice","variant":"main","pair":"uservoice-icon.svg","width":512.0,"height":128.0,"aspect":4.0,"aspect_class":"horizontal","bytes":6851,"shapes":3,"anchors":228,"colors":["#ff6720","#464653"],"n_colors":2,"color_families":["gray","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"dotted U beside name","geometry":["freeform"],"techniques":["modular-repetition"],"type_style":"geometric-sans","case":"uppercase","mood":["friendly","solid"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"uwsgi.svg","brand":"uwsgi","variant":"main","pair":null,"width":512.0,"height":161.0,"aspect":3.18,"aspect_class":"horizontal","bytes":5346,"shapes":18,"anchors":155,"colors":["#aec84d","#141215","#252326","#000000","#ffffff"],"n_colors":5,"color_families":["black","green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"condensed name with green u","geometry":[],"techniques":["color-segments"],"type_style":"grotesque-sans","case":"mixed","mood":["technical","plain"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"v8-ignition.svg","brand":"v8-ignition","variant":"main","pair":null,"width":256.0,"height":304.0,"aspect":0.842,"aspect_class":"square","bytes":3569,"shapes":16,"anchors":133,"colors":["#4285f4","#263238","#ffffff","#424242","#9e9e9e","#e8e8e8","#231f20"],"n_colors":7,"color_families":["black","blue","gray","white"],"primary_family":"blue","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"lightning bolt in circle with funnel","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["technical","energetic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"v8-turbofan.svg","brand":"v8-turbofan","variant":"main","pair":null,"width":256.0,"height":214.0,"aspect":1.196,"aspect_class":"square","bytes":5889,"shapes":20,"anchors":168,"colors":["#424242","#ffffff","#afafaf","#4285f4","#263238","#e8e8e8","#d6d6d6","#231f20"],"n_colors":8,"color_families":["black","blue","gray","white"],"primary_family":"blue","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"fan in blue circle on V frame","geometry":["circle"],"techniques":["containment","radial-symmetry"],"type_style":null,"case":null,"mood":["technical","fast"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"v8.svg","brand":"v8","variant":"main","pair":null,"width":256.0,"height":227.0,"aspect":1.128,"aspect_class":"square","bytes":3717,"shapes":10,"anchors":157,"colors":["#9e9e9e","#424242","#ffffff","#263238","#4285f4"],"n_colors":5,"color_families":["blue","gray","white"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"blue 8 over grey V","geometry":[],"techniques":["stacked-layers"],"type_style":"display-custom","case":"uppercase","mood":["technical","bold"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"vaadin.svg","brand":"vaadin","variant":"main","pair":null,"width":512.0,"height":124.0,"aspect":4.129,"aspect_class":"horizontal","bytes":5097,"shapes":3,"anchors":151,"colors":["#000000","#00b4f0"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"name with bracket-arrow glyph","geometry":[],"techniques":["bracket-code"],"type_style":"display-custom","case":"lowercase","mood":["friendly","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"vaddy.svg","brand":"vaddy","variant":"main","pair":null,"width":256.0,"height":254.0,"aspect":1.008,"aspect_class":"square","bytes":1388,"shapes":2,"anchors":23,"colors":["#8fc53b","#48a23c"],"n_colors":2,"color_families":["green"],"primary_family":"green","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"green ring around dot like eye","geometry":["circle"],"techniques":["gradient","containment"],"type_style":null,"case":null,"mood":["watchful","fresh"],"industry":"security-identity","exemplary":false,"note":""},{"file":"vagrant-icon.svg","brand":"vagrant","variant":"icon","pair":"vagrant.svg","width":256.0,"height":266.0,"aspect":0.962,"aspect_class":"square","bytes":998,"shapes":3,"anchors":54,"colors":["#1159cc","#127eff"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"isometric 3D letter V","geometry":["freeform"],"techniques":["isometric-3d","dimensional-shading"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"vagrant.svg","brand":"vagrant","variant":"main","pair":"vagrant-icon.svg","width":512.0,"height":139.0,"aspect":3.683,"aspect_class":"horizontal","bytes":4306,"shapes":4,"anchors":173,"colors":["#000000","#1159cc","#127eff"],"n_colors":3,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"3D V beside name","geometry":["freeform"],"techniques":["isometric-3d"],"type_style":"geometric-sans","case":"titlecase","mood":["solid","confident"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"vault-icon.svg","brand":"vault","variant":"icon","pair":"vault.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":870,"shapes":2,"anchors":60,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"inverted triangle with keypad dot grid","geometry":["triangle","grid-modular"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["secure","stark"],"industry":"security-identity","exemplary":false,"note":""},{"file":"vault.svg","brand":"vault","variant":"main","pair":"vault-icon.svg","width":512.0,"height":184.0,"aspect":2.783,"aspect_class":"horizontal","bytes":2287,"shapes":2,"anchors":127,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"keypad triangle beside name","geometry":["triangle"],"techniques":["containment","negative-space"],"type_style":"geometric-sans","case":"titlecase","mood":["secure","bold"],"industry":"security-identity","exemplary":false,"note":""},{"file":"vector-timber.svg","brand":"vector-timber","variant":"main","pair":null,"width":256.0,"height":151.0,"aspect":1.695,"aspect_class":"wide","bytes":422,"shapes":2,"anchors":12,"colors":["#10e7ff"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"V from two slanted cyan strokes","geometry":["freeform"],"techniques":["modular-repetition","motion-lines"],"type_style":null,"case":null,"mood":["fast","sharp"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"vercel-icon.svg","brand":"vercel","variant":"icon","pair":"vercel.svg","width":256.0,"height":222.0,"aspect":1.153,"aspect_class":"square","bytes":304,"shapes":2,"anchors":4,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"solid black equilateral triangle","geometry":["triangle"],"techniques":["geometric-construction"],"type_style":null,"case":null,"mood":["minimal","confident"],"industry":"hosting-cdn","exemplary":true,"note":"A single equilateral triangle; reduction to the absolute minimum."},{"file":"vercel.svg","brand":"vercel","variant":"main","pair":"vercel-icon.svg","width":512.0,"height":116.0,"aspect":4.414,"aspect_class":"horizontal","bytes":2063,"shapes":2,"anchors":65,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"triangle beside name","geometry":["triangle"],"techniques":[],"type_style":"geometric-sans","case":"titlecase","mood":["minimal","confident"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"verdaccio-icon.svg","brand":"verdaccio","variant":"icon","pair":"verdaccio.svg","width":256.0,"height":216.0,"aspect":1.185,"aspect_class":"square","bytes":627,"shapes":4,"anchors":27,"colors":["#405236","#cd4000","#4a5e3f"],"n_colors":3,"color_families":["green","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"dark green V with speed lines","geometry":["freeform"],"techniques":["motion-lines","dimensional-shading"],"type_style":null,"case":null,"mood":["fast","sturdy"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"verdaccio.svg","brand":"verdaccio","variant":"main","pair":"verdaccio-icon.svg","width":512.0,"height":96.0,"aspect":5.333,"aspect_class":"extra-wide","bytes":7221,"shapes":6,"anchors":203,"colors":["#405236","#0f5200","#cd4000","#4a5e3f"],"n_colors":4,"color_families":["green","orange"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"speed-line V beside italic name","geometry":["freeform"],"techniques":["motion-lines"],"type_style":"humanist-sans","case":"titlecase","mood":["light","fast"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"vernemq.svg","brand":"vernemq","variant":"main","pair":null,"width":256.0,"height":230.0,"aspect":1.113,"aspect_class":"square","bytes":3245,"shapes":7,"anchors":53,"colors":["#ffffff","#54beaf","#25488d","#0e2e62","#08154e"],"n_colors":5,"color_families":["blue","cyan","white"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"V of two hinged rounded bars","geometry":["freeform"],"techniques":["gradient","line-monoline"],"type_style":null,"case":null,"mood":["technical","connected"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"vim.svg","brand":"vim","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":9564,"shapes":21,"anchors":443,"colors":["#019833","#66fe98","#45fe02","#017d17","#005d04","#000000","#fefefe","#808080","#cccccc"],"n_colors":9,"color_families":["black","gray","green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"beveled V and im on green diamond","geometry":["diamond"],"techniques":["dimensional-shading","containment"],"type_style":"display-custom","case":"titlecase","mood":["retro","technical"],"industry":"developer-tools","exemplary":false,"note":"Dated bevel and chrome effects; busy at small sizes."},{"file":"vimeo-icon.svg","brand":"vimeo","variant":"icon","pair":"vimeo.svg","width":256.0,"height":223.0,"aspect":1.148,"aspect_class":"square","bytes":1112,"shapes":2,"anchors":19,"colors":["#32b8e8"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"flowing script lowercase v","geometry":["organic"],"techniques":[],"type_style":"script","case":"lowercase","mood":["friendly","creative"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"vimeo.svg","brand":"vimeo","variant":"main","pair":"vimeo-icon.svg","width":512.0,"height":146.0,"aspect":3.507,"aspect_class":"horizontal","bytes":6157,"shapes":6,"anchors":131,"colors":["#1ab7eb"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"flowing brush-script name","geometry":[],"techniques":["hand-drawn"],"type_style":"script","case":"lowercase","mood":["friendly","creative"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"visa.svg","brand":"visa","variant":"main","pair":null,"width":256.0,"height":83.0,"aspect":3.084,"aspect_class":"horizontal","bytes":1626,"shapes":2,"anchors":45,"colors":["#222357","#254aa5"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy italic custom name","geometry":[],"techniques":[],"type_style":"display-custom","case":"uppercase","mood":["trustworthy","dynamic"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"visaelectron.svg","brand":"visaelectron","variant":"main","pair":null,"width":256.0,"height":114.0,"aspect":2.246,"aspect_class":"wide","bytes":3956,"shapes":2,"anchors":146,"colors":["#1a1f71"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"italic VISA over Electron","geometry":[],"techniques":[],"type_style":"display-custom","case":"mixed","mood":["trustworthy","dynamic"],"industry":"payments-fintech","exemplary":false,"note":""},{"file":"visual-studio-code.svg","brand":"visual-studio-code","variant":"main","pair":null,"width":256.0,"height":254.0,"aspect":1.008,"aspect_class":"square","bytes":3271,"shapes":6,"anchors":59,"colors":["#0065a9","#007acc","#1f9cf0","#ffffff"],"n_colors":4,"color_families":["blue","white"],"primary_family":"blue","gradients":1,"has_mask":true,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"folded ribbon forming angle bracket","geometry":["freeform"],"techniques":["gradient","dimensional-shading","bracket-code"],"type_style":null,"case":null,"mood":["technical","modern"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"visual-studio.svg","brand":"visual-studio","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3245,"shapes":5,"anchors":95,"colors":["#52218a","#6c33af","#854cc7","#b179f1","#ffffff"],"n_colors":5,"color_families":["purple","white"],"primary_family":"purple","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"folded purple ribbon infinity loop","geometry":["freeform"],"techniques":["infinity-loop","gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","polished"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"vitejs.svg","brand":"vitejs","variant":"main","pair":null,"width":256.0,"height":257.0,"aspect":0.996,"aspect_class":"square","bytes":1709,"shapes":3,"anchors":29,"colors":["#41d1ff","#bd34fe","#ffea83","#ffdd35","#ffa800"],"n_colors":5,"color_families":["cyan","orange","purple","yellow"],"primary_family":"multi","gradients":2,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"gradient V with lightning bolt","geometry":["triangle"],"techniques":["gradient","overlap-transparency","hidden-meaning"],"type_style":null,"case":null,"mood":["fast","vibrant"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"vitest.svg","brand":"vitest","variant":"main","pair":null,"width":256.0,"height":234.0,"aspect":1.094,"aspect_class":"square","bytes":2549,"shapes":4,"anchors":58,"colors":["#fcc72b","#729b1b"],"n_colors":2,"color_families":["green","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"check-mark V with lightning bolt","geometry":["freeform"],"techniques":["hidden-meaning","color-segments"],"type_style":null,"case":null,"mood":["fast","reliable"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"vivaldi-icon.svg","brand":"vivaldi","variant":"icon","pair":"vivaldi.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3568,"shapes":4,"anchors":70,"colors":["#ef3939","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"V in white circle on red square","geometry":["rounded-square","circle"],"techniques":["containment","dimensional-shading","negative-space"],"type_style":null,"case":null,"mood":["bold","friendly"],"industry":"os-platform","exemplary":false,"note":""},{"file":"vivaldi.svg","brand":"vivaldi","variant":"main","pair":"vivaldi-icon.svg","width":512.0,"height":88.0,"aspect":5.818,"aspect_class":"extra-wide","bytes":4465,"shapes":5,"anchors":127,"colors":["#333333","#ef3939","#ffffff"],"n_colors":3,"color_families":["gray","red","white"],"primary_family":"red","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"V badge beside tracked name","geometry":["rounded-square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["bold","confident"],"industry":"os-platform","exemplary":false,"note":""},{"file":"vlang.svg","brand":"vlang","variant":"main","pair":null,"width":256.0,"height":253.0,"aspect":1.012,"aspect_class":"square","bytes":2501,"shapes":5,"anchors":24,"colors":["#536b8a","#000000","#5d87bf"],"n_colors":3,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":true,"has_filter":true,"mark_type":"letterform","symbol_type":null,"subject":"V from two slanted blue planks","geometry":["freeform"],"techniques":["color-segments","dimensional-shading"],"type_style":null,"case":null,"mood":["simple","technical"],"industry":"programming-language","exemplary":false,"note":""},{"file":"void.svg","brand":"void","variant":"main","pair":null,"width":256.0,"height":211.0,"aspect":1.213,"aspect_class":"square","bytes":4967,"shapes":8,"anchors":124,"colors":["#abc2ab","#478061","#000000"],"n_colors":3,"color_families":["black","green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"italic VOID across broken green ring","geometry":["circle"],"techniques":["overlap-transparency"],"type_style":"display-custom","case":"uppercase","mood":["bold","technical"],"industry":"os-platform","exemplary":false,"note":""},{"file":"vue.svg","brand":"vue","variant":"main","pair":null,"width":256.0,"height":221.0,"aspect":1.158,"aspect_class":"square","bytes":510,"shapes":4,"anchors":23,"colors":["#41b883","#35495e"],"n_colors":2,"color_families":["blue","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"nested green and navy chevrons","geometry":["triangle"],"techniques":["stacked-layers","mirror-symmetry","negative-space"],"type_style":null,"case":null,"mood":["clean","friendly"],"industry":"framework-library","exemplary":true,"note":"Two nested chevrons make a V; flat geometry, instantly recognisable."},{"file":"vuetifyjs.svg","brand":"vuetifyjs","variant":"main","pair":null,"width":256.0,"height":293.0,"aspect":0.874,"aspect_class":"square","bytes":482,"shapes":5,"anchors":14,"colors":["#1697f6","#1867c0","#7bc6ff","#aeddff"],"n_colors":4,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"V from light blue parallelograms","geometry":["triangle"],"techniques":["color-segments","geometric-construction"],"type_style":null,"case":null,"mood":["clean","light"],"industry":"framework-library","exemplary":false,"note":""},{"file":"vueuse.svg","brand":"vueuse","variant":"main","pair":null,"width":256.0,"height":277.0,"aspect":0.924,"aspect_class":"square","bytes":792,"shapes":3,"anchors":23,"colors":["#35495e","#41b883"],"n_colors":2,"color_families":["blue","green"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"U from nested green and navy bars","geometry":["freeform"],"techniques":["stacked-layers","mirror-symmetry"],"type_style":null,"case":null,"mood":["clean","friendly"],"industry":"framework-library","exemplary":false,"note":""},{"file":"vulkan.svg","brand":"vulkan","variant":"main","pair":null,"width":512.0,"height":147.0,"aspect":3.483,"aspect_class":"horizontal","bytes":4549,"shapes":2,"anchors":136,"colors":["#a41e22"],"n_colors":1,"color_families":["red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"red name under swoosh arc","geometry":[],"techniques":["motion-lines"],"type_style":"display-custom","case":"titlecase","mood":["powerful","dynamic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"vultr.svg","brand":"vultr","variant":"main","pair":null,"width":512.0,"height":102.0,"aspect":5.02,"aspect_class":"extra-wide","bytes":4075,"shapes":3,"anchors":112,"colors":["#1e88e5","#2b2a29"],"n_colors":2,"color_families":["black","blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"thin tracked name with accent flag","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"uppercase","mood":["clean","technical"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"vwo.svg","brand":"vwo","variant":"main","pair":null,"width":512.0,"height":170.0,"aspect":3.012,"aspect_class":"horizontal","bytes":1091,"shapes":4,"anchors":32,"colors":["#bf3078","#802050","#26134d"],"n_colors":3,"color_families":["pink","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"monoline gradient VWO letters","geometry":[],"techniques":["line-monoline","gradient"],"type_style":"display-custom","case":"uppercase","mood":["modern","vibrant"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"w3c.svg","brand":"w3c","variant":"main","pair":null,"width":256.0,"height":137.0,"aspect":1.869,"aspect_class":"wide","bytes":2465,"shapes":5,"anchors":69,"colors":["#005a9c","#221b0a"],"n_colors":2,"color_families":["blue","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"custom W3C letterforms","geometry":[],"techniques":[],"type_style":"display-custom","case":"uppercase","mood":["institutional","classic"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"waffle-icon.svg","brand":"waffle","variant":"icon","pair":"waffle.svg","width":256.0,"height":168.0,"aspect":1.524,"aspect_class":"wide","bytes":65602,"shapes":47,"anchors":689,"colors":["#ffae47","#fcc062","#da7d17","#f7931e","#000000","#9c703e","#784a25","#71401b","#472810","#7b4d27","#683f1e"],"n_colors":11,"color_families":["black","orange"],"primary_family":"orange","gradients":19,"has_mask":true,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"isometric waffle with melting chocolate","geometry":["diamond","grid-modular"],"techniques":["isometric-3d","dimensional-shading"],"type_style":null,"case":null,"mood":["playful","sweet"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"waffle.svg","brand":"waffle","variant":"main","pair":"waffle-icon.svg","width":256.0,"height":347.0,"aspect":0.738,"aspect_class":"tall","bytes":2043,"shapes":2,"anchors":99,"colors":["#ffd150"],"n_colors":1,"color_families":["yellow"],"primary_family":"yellow","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"waffle grid diamond dripping syrup","geometry":["diamond","grid-modular"],"techniques":["negative-space","modular-repetition"],"type_style":null,"case":null,"mood":["playful","sweet"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"wagtail.svg","brand":"wagtail","variant":"main","pair":null,"width":256.0,"height":316.0,"aspect":0.81,"aspect_class":"square","bytes":2461,"shapes":2,"anchors":74,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"wagtail bird silhouette","geometry":["organic"],"techniques":["negative-space"],"type_style":null,"case":null,"mood":["elegant","simple"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"wakatime.svg","brand":"wakatime","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1208,"shapes":2,"anchors":32,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"monoline w check inside clock ring","geometry":["circle"],"techniques":["containment","line-monoline","hidden-meaning"],"type_style":null,"case":null,"mood":["minimal","precise"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"watchman.svg","brand":"watchman","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2415,"shapes":5,"anchors":52,"colors":["#4356e6","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":true,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"eye with hexagon iris in circle","geometry":["circle","hexagon"],"techniques":["containment","negative-space","mirror-symmetry"],"type_style":null,"case":null,"mood":["watchful","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"wearos.svg","brand":"wearos","variant":"main","pair":null,"width":256.0,"height":196.0,"aspect":1.306,"aspect_class":"wide","bytes":1341,"shapes":5,"anchors":26,"colors":["#00a94b","#ff4131","#ffbc00","#0085f7"],"n_colors":4,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"colored slanted bars and dots forming W","geometry":["freeform"],"techniques":["color-segments"],"type_style":null,"case":null,"mood":["playful","modern"],"industry":"os-platform","exemplary":false,"note":""},{"file":"weave.svg","brand":"weave","variant":"main","pair":null,"width":256.0,"height":261.0,"aspect":0.981,"aspect_class":"square","bytes":1104,"shapes":5,"anchors":31,"colors":["#ff4b19","#00d2ff","#556991"],"n_colors":3,"color_families":["blue","cyan","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"W woven from colored stripes","geometry":["freeform"],"techniques":["overlap-transparency","color-segments","hidden-meaning"],"type_style":null,"case":null,"mood":["dynamic","vibrant"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"web-fundamentals.svg","brand":"web-fundamentals","variant":"main","pair":null,"width":256.0,"height":254.0,"aspect":1.008,"aspect_class":"square","bytes":777,"shapes":3,"anchors":32,"colors":["#1c70e7","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"outlined six-arm asterisk","geometry":["radial","star"],"techniques":["radial-symmetry","line-monoline"],"type_style":null,"case":null,"mood":["friendly","technical"],"industry":"education","exemplary":false,"note":""},{"file":"web.dev-icon.svg","brand":"web.dev","variant":"icon","pair":"web.dev.svg","width":256.0,"height":218.0,"aspect":1.174,"aspect_class":"square","bytes":1212,"shapes":4,"anchors":26,"colors":["#00c9db","#0d55ff","#7000f2"],"n_colors":3,"color_families":["blue","cyan","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"prompt chevron with gradient underscore","geometry":["freeform"],"techniques":["bracket-code","gradient"],"type_style":null,"case":null,"mood":["technical","modern"],"industry":"education","exemplary":false,"note":""},{"file":"web.dev.svg","brand":"web.dev","variant":"main","pair":"web.dev-icon.svg","width":512.0,"height":96.0,"aspect":5.333,"aspect_class":"extra-wide","bytes":3455,"shapes":4,"anchors":117,"colors":["#00c9db","#0d55ff","#7000f2","#5f6368"],"n_colors":4,"color_families":["blue","cyan","gray","purple"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"abstract","subject":"prompt chevron beside name","geometry":["freeform"],"techniques":["bracket-code"],"type_style":"geometric-sans","case":"lowercase","mood":["clean","technical"],"industry":"education","exemplary":false,"note":""},{"file":"web3js.svg","brand":"web3js","variant":"main","pair":null,"width":256.0,"height":240.0,"aspect":1.067,"aspect_class":"square","bytes":3103,"shapes":4,"anchors":83,"colors":["#808285","#bcbec0","#f16822"],"n_colors":3,"color_families":["gray","orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"isometric 3D W3JS letters","geometry":["freeform"],"techniques":["isometric-3d","dimensional-shading"],"type_style":"display-custom","case":"uppercase","mood":["technical","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"webassembly.svg","brand":"webassembly","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":866,"shapes":2,"anchors":41,"colors":["#654ff0"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"WA in notched purple square","geometry":["square"],"techniques":["containment","negative-space"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","solid"],"industry":"programming-language","exemplary":false,"note":""},{"file":"webcomponents.svg","brand":"webcomponents","variant":"main","pair":null,"width":256.0,"height":209.0,"aspect":1.225,"aspect_class":"square","bytes":2016,"shapes":9,"anchors":40,"colors":["#166da5","#8fdb69","#010101","#2a3b8f","#29abe2","#b4d44e","#e7f716"],"n_colors":7,"color_families":["black","blue","green","yellow"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"faceted hexagonal C of polygons","geometry":["hexagon"],"techniques":["dimensional-shading","gradient","color-segments"],"type_style":null,"case":null,"mood":["technical","modular"],"industry":"framework-library","exemplary":false,"note":""},{"file":"webdriverio.svg","brand":"webdriverio","variant":"main","pair":null,"width":512.0,"height":275.0,"aspect":1.862,"aspect_class":"wide","bytes":21366,"shapes":5,"anchors":689,"colors":["#000000","#ea5906","#f2f2f2"],"n_colors":3,"color_families":["black","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"mascot","subject":"orange robot above thin name","geometry":["square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","playful"],"industry":"testing-monitoring","exemplary":false,"note":""},{"file":"webflow.svg","brand":"webflow","variant":"main","pair":null,"width":512.0,"height":129.0,"aspect":3.969,"aspect_class":"horizontal","bytes":3706,"shapes":2,"anchors":94,"colors":["#4353ff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold italic custom name","geometry":[],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["dynamic","confident"],"industry":"design-creative","exemplary":false,"note":""},{"file":"webhint-icon.svg","brand":"webhint","variant":"icon","pair":"webhint.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2018,"shapes":2,"anchors":50,"colors":["#4700a3"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"narwhal in purple ring","geometry":["circle"],"techniques":["containment"],"type_style":null,"case":null,"mood":["friendly","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"webhint.svg","brand":"webhint","variant":"main","pair":"webhint-icon.svg","width":256.0,"height":302.0,"aspect":0.848,"aspect_class":"square","bytes":8211,"shapes":6,"anchors":241,"colors":["#ffffff","#4700a3","#18186d","#4046dd"],"n_colors":4,"color_families":["blue","purple","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"narwhal ring above name","geometry":["circle"],"techniques":["containment"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","clean"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"webhooks.svg","brand":"webhooks","variant":"main","pair":null,"width":256.0,"height":239.0,"aspect":1.071,"aspect_class":"square","bytes":2522,"shapes":4,"anchors":49,"colors":["#c73a63","#4b4b4b","#4a4a4a"],"n_colors":3,"color_families":["gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"three hooked nodes in triangular loop","geometry":["triangle","circle"],"techniques":["radial-symmetry","line-monoline","color-segments"],"type_style":null,"case":null,"mood":["connected","technical"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"webix-icon.svg","brand":"webix","variant":"icon","pair":"webix.svg","width":256.0,"height":213.0,"aspect":1.202,"aspect_class":"square","bytes":5175,"shapes":16,"anchors":68,"colors":["#5b2e6e","#67337a","#723986","#623274","#542c65","#8a519f","#8a53a0","#8a529f","#5c2e6d","#6d377b","#612e74","#7f4395","#582c6a","#743983","#723a85","#8c519c","#66397a","#9f69ab","#5d306e","#9f6aaa"],"n_colors":20,"color_families":["purple"],"primary_family":"purple","gradients":13,"has_mask":true,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"faceted purple W","geometry":["triangle"],"techniques":["dimensional-shading","geometric-construction"],"type_style":null,"case":null,"mood":["technical","bold"],"industry":"framework-library","exemplary":false,"note":""},{"file":"webix.svg","brand":"webix","variant":"main","pair":"webix-icon.svg","width":512.0,"height":165.0,"aspect":3.103,"aspect_class":"horizontal","bytes":8704,"shapes":16,"anchors":164,"colors":["#5b2e6e","#000000","#67337a","#723986","#623274","#542c65","#8a519f","#8a53a0","#8a529f","#5c2e6d","#6d377b","#612e74","#7f4395","#582c6a","#743983","#723a85","#8c519c","#66397a","#9f69ab","#5d306e","#9f6aaa"],"n_colors":21,"color_families":["black","purple"],"primary_family":"purple","gradients":13,"has_mask":true,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"faceted W beside name","geometry":["triangle"],"techniques":["dimensional-shading"],"type_style":"display-custom","case":"lowercase","mood":["friendly","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"webmin.svg","brand":"webmin","variant":"main","pair":null,"width":256.0,"height":281.0,"aspect":0.911,"aspect_class":"square","bytes":4199,"shapes":2,"anchors":91,"colors":["#97beef"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"light blue three-lobed propeller shape","geometry":["organic"],"techniques":["radial-symmetry"],"type_style":null,"case":null,"mood":["soft","friendly"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"webpack.svg","brand":"webpack","variant":"main","pair":null,"width":256.0,"height":290.0,"aspect":0.883,"aspect_class":"square","bytes":1067,"shapes":4,"anchors":54,"colors":["#ffffff","#8ed6fb","#1c78c0"],"n_colors":3,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"cube inside isometric hexagon shell","geometry":["hexagon"],"techniques":["isometric-3d","containment","dimensional-shading"],"type_style":null,"case":null,"mood":["technical","solid"],"industry":"developer-tools","exemplary":true,"note":"Cube in cube reads as 'package'; clean isometric construction."},{"file":"webplatform.svg","brand":"webplatform","variant":"main","pair":null,"width":256.0,"height":254.0,"aspect":1.008,"aspect_class":"square","bytes":2899,"shapes":13,"anchors":78,"colors":["#2db2c4","#e45026","#694ea0","#801434","#d02f28","#263d81","#f99d22","#ffffff"],"n_colors":8,"color_families":["blue","cyan","orange","purple","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"W of overlapping jointed color bars","geometry":["freeform"],"techniques":["overlap-transparency","color-segments","line-monoline"],"type_style":null,"case":null,"mood":["vibrant","open"],"industry":"education","exemplary":false,"note":""},{"file":"webrtc.svg","brand":"webrtc","variant":"main","pair":null,"width":256.0,"height":249.0,"aspect":1.028,"aspect_class":"square","bytes":2892,"shapes":12,"anchors":62,"colors":["#ff6600","#ffcc00","#0089cc","#009939","#bf0000","#fc0007","#1cd306","#0f7504","#0c5e87","#6b0001","#ffffff"],"n_colors":11,"color_families":["blue","green","orange","red","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"speech bubble on colored circle flower","geometry":["circle","radial"],"techniques":["speech-bubble","color-segments","radial-symmetry"],"type_style":null,"case":null,"mood":["vibrant","friendly"],"industry":"social-communication","exemplary":false,"note":""},{"file":"websocket.svg","brand":"websocket","variant":"main","pair":null,"width":256.0,"height":193.0,"aspect":1.326,"aspect_class":"wide","bytes":744,"shapes":2,"anchors":39,"colors":["#231f20"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"interlocking angular black strokes","geometry":["freeform"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["technical","stark"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"webstorm.svg","brand":"webstorm","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1998,"shapes":6,"anchors":62,"colors":["#000000","#ffffff","#00cdd7","#2086d7","#fff045"],"n_colors":5,"color_families":["black","blue","cyan","white","yellow"],"primary_family":"multi","gradients":3,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"WS in black square on gradient shard","geometry":["square"],"techniques":["containment","gradient"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","vibrant"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"webtask.svg","brand":"webtask","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":552,"shapes":6,"anchors":25,"colors":["#5f3237","#e56e62","#ed955b","#f9e862","#ffffff"],"n_colors":5,"color_families":["orange","red","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"offset nested colored squares","geometry":["square"],"techniques":["stacked-layers","color-segments"],"type_style":null,"case":null,"mood":["warm","modular"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"webtorrent.svg","brand":"webtorrent","variant":"main","pair":null,"width":256.0,"height":295.0,"aspect":0.868,"aspect_class":"square","bytes":3129,"shapes":4,"anchors":66,"colors":["#eb324b","#333943","#252a32"],"n_colors":3,"color_families":["black","gray","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"heart in dark hexagon with shadow","geometry":["hexagon"],"techniques":["containment","dimensional-shading"],"type_style":null,"case":null,"mood":["warm","friendly"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"weebly.svg","brand":"weebly","variant":"main","pair":null,"width":256.0,"height":197.0,"aspect":1.299,"aspect_class":"wide","bytes":1650,"shapes":2,"anchors":41,"colors":["#3192e7"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"rounded outlined blue W","geometry":["organic"],"techniques":["line-monoline"],"type_style":null,"case":null,"mood":["friendly","simple"],"industry":"design-creative","exemplary":false,"note":""},{"file":"whalar.svg","brand":"whalar","variant":"main","pair":null,"width":256.0,"height":252.0,"aspect":1.016,"aspect_class":"square","bytes":791,"shapes":2,"anchors":14,"colors":["#03cacf"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"whale tail in teal circle","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["calm","fresh"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"whatsapp.svg","brand":"whatsapp","variant":"main","pair":null,"width":256.0,"height":259.0,"aspect":0.988,"aspect_class":"square","bytes":3056,"shapes":3,"anchors":74,"colors":["#00e676","#ffffff"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"phone handset inside speech bubble","geometry":["circle"],"techniques":["speech-bubble","negative-space","containment"],"type_style":null,"case":null,"mood":["friendly","approachable"],"industry":"social-communication","exemplary":true,"note":"Phone plus speech bubble fuses call and chat in one silhouette."},{"file":"whatwg.svg","brand":"whatwg","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1019,"shapes":4,"anchors":29,"colors":["#ffffff","#3c790a"],"n_colors":2,"color_families":["green","white"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"question mark in green ring","geometry":["circle"],"techniques":["containment","line-monoline"],"type_style":null,"case":null,"mood":["curious","simple"],"industry":"open-source-community","exemplary":false,"note":""},{"file":"wicket-icon.svg","brand":"wicket","variant":"icon","pair":"wicket.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":581,"shapes":3,"anchors":15,"colors":["#ff9925","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"W shaped as crown in orange circle","geometry":["circle"],"techniques":["containment","negative-space","hidden-meaning"],"type_style":null,"case":null,"mood":["regal","warm"],"industry":"framework-library","exemplary":false,"note":""},{"file":"wicket.svg","brand":"wicket","variant":"main","pair":"wicket-icon.svg","width":512.0,"height":76.0,"aspect":6.737,"aspect_class":"extra-wide","bytes":4531,"shapes":4,"anchors":227,"colors":["#ff9925","#ffffff","#111111"],"n_colors":3,"color_families":["black","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"crown W between condensed words","geometry":["circle"],"techniques":["containment"],"type_style":"grotesque-sans","case":"uppercase","mood":["bold","sturdy"],"industry":"framework-library","exemplary":false,"note":""},{"file":"wifi.svg","brand":"wifi","variant":"main","pair":null,"width":256.0,"height":192.0,"aspect":1.333,"aspect_class":"wide","bytes":1767,"shapes":2,"anchors":71,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"Wi Fi in yin-yang style oval","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":"geometric-sans","case":"mixed","mood":["bold","universal"],"industry":"hardware-devices","exemplary":false,"note":""},{"file":"wildfly.svg","brand":"wildfly","variant":"main","pair":null,"width":512.0,"height":152.0,"aspect":3.368,"aspect_class":"horizontal","bytes":59324,"shapes":14,"anchors":1476,"colors":["#293644","#ffffff","#e1eef4","#d4dfe5","#dfeef6"],"n_colors":5,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"sketched dragonfly after name","geometry":["organic"],"techniques":["line-monoline"],"type_style":"humanist-sans","case":"mixed","mood":["light","technical"],"industry":"cloud-infrastructure","exemplary":false,"note":""},{"file":"wire.svg","brand":"wire","variant":"main","pair":null,"width":512.0,"height":174.0,"aspect":2.943,"aspect_class":"horizontal","bytes":1784,"shapes":2,"anchors":56,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"thin continuous monoline name","geometry":[],"techniques":["line-monoline"],"type_style":"display-custom","case":"lowercase","mood":["minimal","elegant"],"industry":"social-communication","exemplary":true,"note":"Single-weight wire-like strokes literally embody the name."},{"file":"wix.svg","brand":"wix","variant":"main","pair":null,"width":512.0,"height":202.0,"aspect":2.535,"aspect_class":"horizontal","bytes":2748,"shapes":2,"anchors":75,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"heavy custom name with small i","geometry":[],"techniques":[],"type_style":"display-custom","case":"mixed","mood":["bold","playful"],"industry":"design-creative","exemplary":false,"note":""},{"file":"wmr.svg","brand":"wmr","variant":"main","pair":null,"width":256.0,"height":376.0,"aspect":0.681,"aspect_class":"tall","bytes":46364,"shapes":83,"anchors":1436,"colors":["#ffffff","#371a45","#22a7f0","#220f2d","#000000","#ce2e2e","#6b184e","#33aef1","#f92323","#848484"],"n_colors":10,"color_families":["black","blue","gray","pink","purple","red","white"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"astronaut working on laptop","geometry":["organic"],"techniques":["dimensional-shading"],"type_style":null,"case":null,"mood":["playful","detailed"],"industry":"developer-tools","exemplary":false,"note":"Detailed illustration; does not reduce to a small mark."},{"file":"woocommerce-icon.svg","brand":"woocommerce","variant":"icon","pair":"woocommerce.svg","width":256.0,"height":153.0,"aspect":1.673,"aspect_class":"wide","bytes":3597,"shapes":2,"anchors":80,"colors":["#7f54b3"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"Woo inside purple speech bubble","geometry":["rounded-square"],"techniques":["speech-bubble","containment"],"type_style":"display-custom","case":"titlecase","mood":["friendly","playful"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"woocommerce.svg","brand":"woocommerce","variant":"main","pair":"woocommerce-icon.svg","width":512.0,"height":104.0,"aspect":4.923,"aspect_class":"extra-wide","bytes":6816,"shapes":3,"anchors":203,"colors":["#7f54b3","#000000"],"n_colors":2,"color_families":["black","purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"emblem","subject":"Woo bubble beside COMMERCE","geometry":["rounded-square"],"techniques":["speech-bubble","containment"],"type_style":"display-custom","case":"mixed","mood":["friendly","bold"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"woopra.svg","brand":"woopra","variant":"main","pair":null,"width":512.0,"height":121.0,"aspect":4.231,"aspect_class":"horizontal","bytes":3943,"shapes":2,"anchors":110,"colors":["#020202"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with oo as infinity loop","geometry":[],"techniques":["infinity-loop","ligature"],"type_style":"geometric-sans","case":"lowercase","mood":["modern","clever"],"industry":"marketing-analytics","exemplary":false,"note":""},{"file":"wordpress-icon.svg","brand":"wordpress","variant":"icon","pair":"wordpress.svg","width":256.0,"height":255.0,"aspect":1.004,"aspect_class":"square","bytes":2080,"shapes":2,"anchors":49,"colors":["#464342"],"n_colors":1,"color_families":["gray"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"serif W in ringed circle","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":"serif","case":"uppercase","mood":["established","classic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"wordpress.svg","brand":"wordpress","variant":"main","pair":"wordpress-icon.svg","width":512.0,"height":117.0,"aspect":4.376,"aspect_class":"horizontal","bytes":6933,"shapes":4,"anchors":235,"colors":["#00749a","#464342"],"n_colors":2,"color_families":["cyan","gray"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"W circle beside small-caps serif name","geometry":["circle"],"techniques":["containment"],"type_style":"serif","case":"mixed","mood":["established","classic"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"workboard.svg","brand":"workboard","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":672,"shapes":3,"anchors":25,"colors":["#51bbd6","#ffffff"],"n_colors":2,"color_families":["cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"B built from chevrons in blue circle","geometry":["circle"],"techniques":["containment","arrow","negative-space"],"type_style":null,"case":null,"mood":["modern","directional"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"workplace.svg","brand":"workplace","variant":"main","pair":null,"width":512.0,"height":123.0,"aspect":4.163,"aspect_class":"horizontal","bytes":10000,"shapes":2,"anchors":259,"colors":["#20252d"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with w enclosed in ring","geometry":[],"techniques":["containment","letter-substitution"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","modern"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"wpengine.svg","brand":"wpengine","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":970,"shapes":2,"anchors":57,"colors":["#40bac8"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"grid of teal tiles around diamond gap","geometry":["grid-modular","square"],"techniques":["negative-space","modular-repetition"],"type_style":null,"case":null,"mood":["solid","technical"],"industry":"hosting-cdn","exemplary":false,"note":""},{"file":"wufoo.svg","brand":"wufoo","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":900,"shapes":4,"anchors":25,"colors":["#d46a59","#d04f41","#ffffff"],"n_colors":3,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"slanted white W in red circle","geometry":["circle"],"techniques":["containment","dimensional-shading"],"type_style":null,"case":null,"mood":["bold","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"xamarin.svg","brand":"xamarin","variant":"main","pair":null,"width":256.0,"height":228.0,"aspect":1.123,"aspect_class":"square","bytes":1431,"shapes":2,"anchors":39,"colors":["#3498db"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"X in blue hexagon","geometry":["hexagon"],"techniques":["containment"],"type_style":null,"case":null,"mood":["technical","clean"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"xampp.svg","brand":"xampp","variant":"main","pair":null,"width":256.0,"height":258.0,"aspect":0.992,"aspect_class":"square","bytes":3883,"shapes":3,"anchors":76,"colors":["#fb7a24","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"white looped knot in orange square","geometry":["rounded-square"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["bold","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"xcart.svg","brand":"xcart","variant":"main","pair":null,"width":512.0,"height":156.0,"aspect":3.282,"aspect_class":"horizontal","bytes":6108,"shapes":16,"anchors":195,"colors":["#000000","#f29221","#ffffff","#b14c26"],"n_colors":4,"color_families":["black","orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"cart icon in orange square with name","geometry":["rounded-square"],"techniques":["containment"],"type_style":"grotesque-sans","case":"uppercase","mood":["bold","commercial"],"industry":"ecommerce-retail","exemplary":false,"note":""},{"file":"xero.svg","brand":"xero","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3343,"shapes":3,"anchors":85,"colors":["#1fc0e7","#ffffff"],"n_colors":2,"color_families":["cyan","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"emblem","symbol_type":null,"subject":"thin name inside blue circle","geometry":["circle"],"techniques":["containment","line-monoline"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","clean"],"industry":"finance-banking","exemplary":false,"note":""},{"file":"xplenty.svg","brand":"xplenty","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1135,"shapes":4,"anchors":26,"colors":["#ffffff","#3f3f3f","#0ab3e5"],"n_colors":3,"color_families":["cyan","gray","white"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"mountain peaks in ring","geometry":["circle"],"techniques":["containment","negative-space"],"type_style":null,"case":null,"mood":["calm","solid"],"industry":"database-data","exemplary":false,"note":""},{"file":"xstate.svg","brand":"xstate","variant":"main","pair":null,"width":512.0,"height":160.0,"aspect":3.2,"aspect_class":"horizontal","bytes":1883,"shapes":3,"anchors":81,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold X followed by tracked STATE","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"uppercase","mood":["technical","clean"],"industry":"framework-library","exemplary":false,"note":""},{"file":"xtend.svg","brand":"xtend","variant":"main","pair":null,"width":256.0,"height":212.0,"aspect":1.208,"aspect_class":"square","bytes":1058,"shapes":2,"anchors":34,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"X with leading chevron arrows","geometry":["freeform"],"techniques":["arrow","motion-lines"],"type_style":null,"case":null,"mood":["dynamic","bold"],"industry":"programming-language","exemplary":false,"note":""},{"file":"xwiki-icon.svg","brand":"xwiki","variant":"icon","pair":"xwiki.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1950,"shapes":6,"anchors":57,"colors":["#70b700","#ff7700","#ff0000","#0087cb","#505052"],"n_colors":5,"color_families":["blue","gray","green","orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"grey X with four colored ticks","geometry":["radial"],"techniques":["color-segments","radial-symmetry"],"type_style":null,"case":null,"mood":["collaborative","bright"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"xwiki.svg","brand":"xwiki","variant":"main","pair":"xwiki-icon.svg","width":512.0,"height":172.0,"aspect":2.977,"aspect_class":"horizontal","bytes":3597,"shapes":7,"anchors":117,"colors":["#70b700","#ff7700","#ff0000","#0087cb","#505052"],"n_colors":5,"color_families":["blue","gray","green","orange","red"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"ticked X beside thin WIKI","geometry":["radial"],"techniques":["color-segments"],"type_style":"geometric-sans","case":"uppercase","mood":["light","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"yahoo.svg","brand":"yahoo","variant":"main","pair":null,"width":512.0,"height":143.0,"aspect":3.58,"aspect_class":"horizontal","bytes":2173,"shapes":2,"anchors":67,"colors":["#5f01d1"],"n_colors":1,"color_families":["purple"],"primary_family":"purple","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold purple name with exclamation","geometry":[],"techniques":[],"type_style":"display-custom","case":"lowercase","mood":["playful","loud"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"yaml.svg","brand":"yaml","variant":"main","pair":null,"width":512.0,"height":176.0,"aspect":2.909,"aspect_class":"horizontal","bytes":1093,"shapes":7,"anchors":55,"colors":["#ffffff","#000000"],"n_colors":2,"color_families":["black","white"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"geometric stencil YAML letters","geometry":[],"techniques":["geometric-construction","negative-space"],"type_style":"display-custom","case":"uppercase","mood":["technical","stark"],"industry":"programming-language","exemplary":false,"note":""},{"file":"yammer.svg","brand":"yammer","variant":"main","pair":null,"width":256.0,"height":218.0,"aspect":1.174,"aspect_class":"square","bytes":1610,"shapes":2,"anchors":34,"colors":["#265495"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"blue y with radiating lines","geometry":["freeform"],"techniques":["motion-lines"],"type_style":null,"case":null,"mood":["friendly","social"],"industry":"social-communication","exemplary":false,"note":""},{"file":"yandex-ru.svg","brand":"yandex-ru","variant":"main","pair":null,"width":512.0,"height":201.0,"aspect":2.547,"aspect_class":"horizontal","bytes":3560,"shapes":3,"anchors":115,"colors":["#ff0000","#000000"],"n_colors":2,"color_families":["black","red"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"Cyrillic name with red first letter","geometry":[],"techniques":["color-segments"],"type_style":"grotesque-sans","case":"titlecase","mood":["bold","local"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"yarn.svg","brand":"yarn","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":3398,"shapes":3,"anchors":71,"colors":["#368fb9","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"outlined cat in blue circle","geometry":["circle"],"techniques":["line-monoline","containment","hidden-meaning"],"type_style":null,"case":null,"mood":["friendly","playful"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"ycombinator.svg","brand":"ycombinator","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":824,"shapes":3,"anchors":23,"colors":["#fb651e","#ffffff"],"n_colors":2,"color_families":["orange","white"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white Y in orange square","geometry":["square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["simple","confident"],"industry":"finance-banking","exemplary":false,"note":""},{"file":"yeoman.svg","brand":"yeoman","variant":"main","pair":null,"width":256.0,"height":278.0,"aspect":0.921,"aspect_class":"square","bytes":12906,"shapes":41,"anchors":467,"colors":["#020202","#050505","#dd002a","#f4cf8c","#d8af6f","#930023","#b27d30","#ffffff","#c98c28","#cea063","#ffb000","#4f1907"],"n_colors":12,"color_families":["black","orange","red","white","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"mascot","symbol_type":null,"subject":"mustached beefeater guard saluting","geometry":["organic"],"techniques":["dimensional-shading"],"type_style":null,"case":null,"mood":["quirky","friendly"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"yii.svg","brand":"yii","variant":"main","pair":null,"width":256.0,"height":274.0,"aspect":0.934,"aspect_class":"square","bytes":3833,"shapes":5,"anchors":95,"colors":["#73b723","#d8ee61","#98c9ea","#026fb2","#086eb6","#d73721","#f7d768","#d4c883","#a1d1a7"],"n_colors":9,"color_families":["blue","green","red","yellow"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"Y from three gradient petals","geometry":["organic"],"techniques":["gradient","overlap-transparency"],"type_style":null,"case":null,"mood":["fresh","vibrant"],"industry":"framework-library","exemplary":false,"note":""},{"file":"youtrack.svg","brand":"youtrack","variant":"main","pair":null,"width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":2110,"shapes":5,"anchors":56,"colors":["#0cb0f2","#000000","#ffffff","#905cfb","#a554e6","#d641b5","#f43597","#ff318c"],"n_colors":8,"color_families":["black","blue","pink","purple","white"],"primary_family":"multi","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"YT in black square on gradient X","geometry":["square"],"techniques":["containment","gradient","color-segments"],"type_style":"geometric-sans","case":"uppercase","mood":["technical","vibrant"],"industry":"developer-tools","exemplary":false,"note":""},{"file":"youtube-icon.svg","brand":"youtube","variant":"icon","pair":"youtube.svg","width":256.0,"height":180.0,"aspect":1.422,"aspect_class":"wide","bytes":833,"shapes":3,"anchors":15,"colors":["#ff0000","#ffffff"],"n_colors":2,"color_families":["red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"play triangle in red rounded screen","geometry":["rounded-square","triangle"],"techniques":["negative-space","containment"],"type_style":null,"case":null,"mood":["bold","iconic"],"industry":"media-entertainment","exemplary":true,"note":"Universal play symbol in a TV-shaped container; radical simplicity."},{"file":"youtube.svg","brand":"youtube","variant":"main","pair":"youtube-icon.svg","width":512.0,"height":116.0,"aspect":4.414,"aspect_class":"horizontal","bytes":5375,"shapes":3,"anchors":178,"colors":["#ff0000","#ffffff","#282828"],"n_colors":3,"color_families":["black","red","white"],"primary_family":"red","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"pictorial","subject":"play button beside condensed name","geometry":["rounded-square"],"techniques":["containment","negative-space"],"type_style":"grotesque-sans","case":"mixed","mood":["bold","familiar"],"industry":"media-entertainment","exemplary":false,"note":""},{"file":"zapier-icon.svg","brand":"zapier","variant":"icon","pair":"zapier.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1705,"shapes":2,"anchors":53,"colors":["#ff4a00"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"orange asterisk with square center","geometry":["radial","star"],"techniques":["radial-symmetry","negative-space"],"type_style":null,"case":null,"mood":["energetic","bold"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"zapier.svg","brand":"zapier","variant":"main","pair":"zapier-icon.svg","width":512.0,"height":234.0,"aspect":2.188,"aspect_class":"wide","bytes":8169,"shapes":2,"anchors":212,"colors":["#ff4a00"],"n_colors":1,"color_families":["orange"],"primary_family":"orange","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"name with asterisk dotting the i","geometry":[],"techniques":["letter-substitution"],"type_style":"geometric-sans","case":"lowercase","mood":["friendly","energetic"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"zend-framework.svg","brand":"zend-framework","variant":"main","pair":null,"width":256.0,"height":124.0,"aspect":2.065,"aspect_class":"wide","bytes":836,"shapes":5,"anchors":24,"colors":["#6fb643"],"n_colors":1,"color_families":["green"],"primary_family":"green","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"lettermark","symbol_type":null,"subject":"green Z and speed-striped F","geometry":[],"techniques":["motion-lines","ligature"],"type_style":"display-custom","case":"uppercase","mood":["fast","technical"],"industry":"framework-library","exemplary":false,"note":""},{"file":"zendesk-icon.svg","brand":"zendesk","variant":"icon","pair":"zendesk.svg","width":256.0,"height":195.0,"aspect":1.313,"aspect_class":"wide","bytes":569,"shapes":2,"anchors":16,"colors":["#03363d"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"Z from two triangles and semicircles","geometry":["triangle","circle"],"techniques":["geometric-construction","negative-space","mirror-symmetry"],"type_style":null,"case":null,"mood":["balanced","calm"],"industry":"productivity-collaboration","exemplary":true,"note":"Z built from two triangles and two semicircles; pure geometric construction."},{"file":"zendesk.svg","brand":"zendesk","variant":"main","pair":"zendesk-icon.svg","width":512.0,"height":99.0,"aspect":5.172,"aspect_class":"extra-wide","bytes":3293,"shapes":2,"anchors":107,"colors":["#03363d"],"n_colors":1,"color_families":["cyan"],"primary_family":"cyan","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"lowercase name in dark green","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"lowercase","mood":["calm","friendly"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"zenhub-icon.svg","brand":"zenhub","variant":"icon","pair":"zenhub.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":434,"shapes":3,"anchors":16,"colors":["#5e60ba","#ffffff"],"n_colors":2,"color_families":["blue","white"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"white Z in purple square","geometry":["square"],"techniques":["containment"],"type_style":"geometric-sans","case":"uppercase","mood":["simple","solid"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"zenhub.svg","brand":"zenhub","variant":"main","pair":"zenhub-icon.svg","width":512.0,"height":112.0,"aspect":4.571,"aspect_class":"extra-wide","bytes":1971,"shapes":2,"anchors":78,"colors":["#323f48"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"bold camel-case name","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"mixed","mood":["confident","technical"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"zeplin.svg","brand":"zeplin","variant":"main","pair":null,"width":256.0,"height":205.0,"aspect":1.249,"aspect_class":"square","bytes":3262,"shapes":9,"anchors":82,"colors":["#fdbd39","#f69833","#fecf33","#ee6723"],"n_colors":4,"color_families":["orange","yellow"],"primary_family":"multi","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"pictorial","symbol_type":null,"subject":"orange zeppelin with orbit ring","geometry":["organic"],"techniques":["gradient","dimensional-shading"],"type_style":null,"case":null,"mood":["playful","adventurous"],"industry":"design-creative","exemplary":false,"note":""},{"file":"zoho.svg","brand":"zoho","variant":"main","pair":null,"width":512.0,"height":177.0,"aspect":2.893,"aspect_class":"horizontal","bytes":6945,"shapes":17,"anchors":214,"colors":["#e79225","#fff16d","#ffffff","#009ada","#91c9ed","#66bf6b","#98d0a0","#760d16","#ef463e","#ffe513","#fdb924","#008cd2","#00649d","#26a146","#008a52","#d92231","#ba2234"],"n_colors":17,"color_families":["blue","green","orange","red","white","yellow"],"primary_family":"multi","gradients":4,"has_mask":false,"has_filter":false,"mark_type":"wordmark","symbol_type":null,"subject":"letters on colored 3D tiles","geometry":["square"],"techniques":["containment","color-segments","dimensional-shading","modular-repetition"],"type_style":"display-custom","case":"uppercase","mood":["playful","colorful"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"zorin-os.svg","brand":"zorin-os","variant":"main","pair":null,"width":256.0,"height":227.0,"aspect":1.128,"aspect_class":"square","bytes":595,"shapes":2,"anchors":24,"colors":["#00aaff"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"Z carved from cyan hexagon bands","geometry":["hexagon"],"techniques":["negative-space","geometric-construction"],"type_style":null,"case":null,"mood":["clean","modern"],"industry":"os-platform","exemplary":true,"note":"Z appears only through negative space between stacked bands."},{"file":"zube.svg","brand":"zube","variant":"main","pair":null,"width":256.0,"height":178.0,"aspect":1.438,"aspect_class":"wide","bytes":480,"shapes":2,"anchors":18,"colors":["#0d83dd"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"abstract","symbol_type":null,"subject":"two chevrons forming broken hexagon","geometry":["hexagon"],"techniques":["bracket-code","negative-space","mirror-symmetry"],"type_style":null,"case":null,"mood":["technical","balanced"],"industry":"productivity-collaboration","exemplary":false,"note":""},{"file":"zulip-icon.svg","brand":"zulip","variant":"icon","pair":"zulip.svg","width":256.0,"height":256.0,"aspect":1.0,"aspect_class":"square","bytes":1310,"shapes":2,"anchors":27,"colors":["#24adff","#7b71ff"],"n_colors":2,"color_families":["blue"],"primary_family":"blue","gradients":1,"has_mask":false,"has_filter":false,"mark_type":"letterform","symbol_type":null,"subject":"rounded Z in gradient circle","geometry":["circle"],"techniques":["gradient","containment"],"type_style":null,"case":null,"mood":["friendly","modern"],"industry":"social-communication","exemplary":false,"note":""},{"file":"zulip.svg","brand":"zulip","variant":"main","pair":"zulip-icon.svg","width":512.0,"height":133.0,"aspect":3.85,"aspect_class":"horizontal","bytes":1981,"shapes":2,"anchors":75,"colors":["#000000"],"n_colors":1,"color_families":["black"],"primary_family":"mono","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"rounded Z beside tracked name","geometry":[],"techniques":[],"type_style":"geometric-sans","case":"uppercase","mood":["friendly","clean"],"industry":"social-communication","exemplary":false,"note":""},{"file":"zwave.svg","brand":"zwave","variant":"main","pair":null,"width":256.0,"height":114.0,"aspect":2.246,"aspect_class":"wide","bytes":1507,"shapes":2,"anchors":75,"colors":["#00396f"],"n_colors":1,"color_families":["blue"],"primary_family":"blue","gradients":0,"has_mask":false,"has_filter":false,"mark_type":"combination","symbol_type":"letterform","subject":"Z circle with radio arcs and name","geometry":["circle"],"techniques":["motion-lines","containment"],"type_style":"display-custom","case":"uppercase","mood":["technical","connected"],"industry":"hardware-devices","exemplary":false,"note":""}] \ No newline at end of file diff --git a/.claude/skills/logo-design/assets/library/classifications.json b/.claude/skills/logo-design/assets/library/classifications.json new file mode 100644 index 0000000..bd5c517 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/classifications.json @@ -0,0 +1,31038 @@ +[ + { + "file": "100tb.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "numerals 100 with 00 as infinity loop", + "geometry": [], + "techniques": [ + "infinity-loop", + "ligature", + "letter-substitution" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "technical" + ], + "industry": "hosting-cdn", + "exemplary": true, + "note": "Double zero turned into infinity loop within the numerals" + }, + { + "file": "500px.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "thin geometric name with superscript px", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "minimal", + "modern" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "active-campaign-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "bold chevron arrow pointing right", + "geometry": [ + "freeform" + ], + "techniques": [ + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "confident" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "active-campaign.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "camel-case name with trailing chevron", + "geometry": [], + "techniques": [ + "arrow" + ], + "type_style": "grotesque-sans", + "case": "mixed", + "mood": [ + "clean", + "corporate" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "adonisjs-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "rounded letter A in rounded square", + "geometry": [ + "rounded-square", + "triangle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "adonisjs.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "rounded A tile beside lowercase name", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "adroll.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "curled hook shape beside bold name", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "playful", + "bold" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "adyen.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "custom squared lowercase green name", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "bold", + "distinctive" + ], + "industry": "payments-fintech", + "exemplary": true, + "note": "Fully custom squared letterforms make a plain name unmistakable" + }, + { + "file": "aerospike-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "sideways letter A in red square", + "geometry": [ + "square", + "triangle" + ], + "techniques": [ + "containment", + "letter-substitution" + ], + "type_style": null, + "case": null, + "mood": [ + "sharp", + "technical" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aerospike.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "spaced name in red bar with rotated A", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "sharp" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "airbnb.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "Belo loop merging pin, heart and A", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline", + "hidden-meaning", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "warm" + ], + "industry": "travel-transport", + "exemplary": true, + "note": "Single monoline loop encodes location, love and the letter A" + }, + { + "file": "airbrake.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold name with orange-yellow gradient", + "geometry": [], + "techniques": [ + "gradient" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "energetic", + "bold" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "airflow.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "multicolor pinwheel of four blades", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "colorful" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "airtable.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric box shapes in three colors", + "geometry": [ + "diamond", + "freeform" + ], + "techniques": [ + "isometric-3d", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "colorful" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "akamai.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "wave swoosh arc beside italic name", + "geometry": [ + "organic" + ], + "techniques": [ + "motion-lines", + "gradient" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "dynamic", + "corporate" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "akka.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two-tone swooping mountain-like fin shape", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "smooth" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "alfresco.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "flower-like radial petal pinwheel", + "geometry": [ + "radial", + "organic" + ], + "techniques": [ + "radial-symmetry", + "color-segments", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "colorful", + "organic" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "algolia.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "stopwatch tile beside lowercase name", + "geometry": [ + "rounded-square", + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "alpinejs-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "dark parallelogram beside light diamond", + "geometry": [ + "diamond" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "alpinejs.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "two diamond shapes beside bold name", + "geometry": [ + "diamond" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "minimal", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "altair.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "triangle inside hexagon with node dots", + "geometry": [ + "hexagon", + "triangle" + ], + "techniques": [ + "geometric-construction", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "structured" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "amazon-chime.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "radial ring of angular teal blades", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry", + "modular-repetition", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "technical" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "amazon-connect.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cloud speech bubble with nodes in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "speech-bubble", + "motion-lines", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "technical" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "amex.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "outlined name inside blue square", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "trustworthy", + "classic" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "amp-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "lightning bolt in blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "amp.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "bolt circle beside bold uppercase AMP", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "fast", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "ampersand.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "shaded magenta ampersand glyph", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "playful" + ], + "industry": "other", + "exemplary": false, + "note": "" + }, + { + "file": "amplication-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "split arch of half-circle and bar", + "geometry": [ + "circle", + "square" + ], + "techniques": [ + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "minimal" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "amplication.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "split arch beside lowercase name", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "geometric-construction" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "amplitude-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "monoline A with wave in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "confident" + ], + "industry": "marketing-analytics", + "exemplary": true, + "note": "A doubles as a sound wave: letter and meaning in one stroke" + }, + { + "file": "amplitude.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "A-wave circle beside bold name", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline", + "hidden-meaning" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "modern", + "confident" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "android-icon.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "green robot with antennae and eyes", + "geometry": [ + "circle", + "rounded-square" + ], + "techniques": [ + "modular-repetition", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "playful" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Character built from simple rounded primitives, instantly readable" + }, + { + "file": "android.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "rounded lowercase green name", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "angellist.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "peace-sign victory hand outline", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline", + "hand-drawn" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "bold" + ], + "industry": "finance-banking", + "exemplary": false, + "note": "" + }, + { + "file": "angular-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white A inside red shield", + "geometry": [ + "shield", + "triangle" + ], + "techniques": [ + "containment", + "dimensional-shading", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "strong", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "angular.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "shield A replacing first letter of name", + "geometry": [ + "shield" + ], + "techniques": [ + "containment", + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "strong", + "corporate" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "ansible.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "A in black circle above spaced name", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "simple" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "ant-design.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "diamond outline with dot and chevron", + "geometry": [ + "diamond", + "circle" + ], + "techniques": [ + "gradient", + "arrow", + "bracket-code" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "apache-camel.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "camel silhouette in orange circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "friendly" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Camel carved from circle with confident negative space" + }, + { + "file": "apache.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "gradient red-orange feather", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "classic", + "vibrant" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "apache_cloudstack.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "cartoon monkey sitting on cloud", + "geometry": [ + "organic" + ], + "techniques": [ + "hand-drawn" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "cheerful" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "apiary.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric cubes forming a Y", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "color-segments", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "fresh" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "apollostack.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "A inside orbit ring with dot", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "confident" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "apostrophe.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "outlined square circle triangle in tile", + "geometry": [ + "rounded-square", + "circle", + "triangle" + ], + "techniques": [ + "gradient", + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "creative" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "appbaseio-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "connected node graph inside circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "minimal" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "appbaseio.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "node circle beside thin lowercase name", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "minimal", + "technical" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "appcircle-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "orange rounded A with circle hole", + "geometry": [ + "triangle", + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "appcircle.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "small A icon with white lowercase name", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Wordmark is white, only visible on dark backgrounds" + }, + { + "file": "appcode.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "AC in black square over gradient shapes", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "vibrant" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "appdynamics.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "chevron A in green square", + "geometry": [ + "square", + "triangle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "confident" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "appium.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "purple circle with swirling segments", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "modern" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "apple-app-store.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "A built from pencil, brush and ruler", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "gradient", + "hidden-meaning", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "creative" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Letter A assembled from creative tools: layered hidden meaning" + }, + { + "file": "apple-pay.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "apple silhouette beside Pay", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "premium", + "minimal" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "apple.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "apple silhouette with bite", + "geometry": [ + "organic", + "circle" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "premium", + "minimal" + ], + "industry": "hardware-devices", + "exemplary": true, + "note": "Iconic single silhouette; bite adds scale cue and memorability" + }, + { + "file": "appsignal-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "monoline crown-like wave outline", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "simple" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "appsignal.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "camel-case name with crown outline", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "humanist-sans", + "case": "mixed", + "mood": [ + "friendly", + "clean" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "apptentive.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "heart outline inside speech bubble", + "geometry": [ + "circle" + ], + "techniques": [ + "speech-bubble", + "negative-space", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "friendly" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "appveyor.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "white loop shape in blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "simple" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "arangodb.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "avocado beside embossed slab name", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": "slab", + "case": "mixed", + "mood": [ + "quirky", + "dated" + ], + "industry": "database-data", + "exemplary": false, + "note": "Bevel effects and olive palette feel dated" + }, + { + "file": "archlinux.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "blue arrowhead peak with inner arch", + "geometry": [ + "triangle" + ], + "techniques": [ + "negative-space", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "sharp", + "technical" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "arduino.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "infinity loop with minus and plus", + "geometry": [ + "circle" + ], + "techniques": [ + "infinity-loop", + "hidden-meaning", + "negative-space" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "technical", + "friendly" + ], + "industry": "hardware-devices", + "exemplary": true, + "note": "Infinity loop holding minus and plus tells the story simply" + }, + { + "file": "argo-icon.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "orange octopus in astronaut helmet", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "quirky" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "argo.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "octopus astronaut beside lowercase name", + "geometry": [ + "circle" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "playful", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "armory.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "shield containing clouds and waves", + "geometry": [ + "shield" + ], + "techniques": [ + "containment", + "stacked-layers" + ], + "type_style": null, + "case": null, + "mood": [ + "strong", + "calm" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "asana.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "three coral dots above lowercase name", + "geometry": [ + "circle" + ], + "techniques": [ + "radial-symmetry" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "calm" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "asciidoctor.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "monoline A with long crossbar in tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "assembla-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "double-stroke A in dark hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "serious" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "assembla.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "hexagon A beside spaced uppercase name", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "clean" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "astro.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "A-shaped rocket with flame above name", + "geometry": [ + "triangle" + ], + "techniques": [ + "hidden-meaning", + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "modern" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Letter A becomes a rocket with one added flame" + }, + { + "file": "astronomer.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter A with orbit swoosh and stars", + "geometry": [ + "triangle", + "freeform" + ], + "techniques": [ + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "energetic" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "atlassian.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two gradient blue mountain peaks", + "geometry": [ + "triangle" + ], + "techniques": [ + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "confident", + "modern" + ], + "industry": "productivity-collaboration", + "exemplary": true, + "note": "Two gradient peaks, strong simplicity scalable to favicon" + }, + { + "file": "atom-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "monoline atom orbits in green circle", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "line-monoline", + "containment", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "atom.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "atom orbit beside thin spaced name", + "geometry": [ + "radial" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "light", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "atomic-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter A split into three rounded pieces", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "modern" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "atomic.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "split A beside bold lowercase name", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "playful" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "aurelia.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "diagonal gradient bars and fragments", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "vibrant" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "aurora.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter A assembled from small triangles", + "geometry": [ + "triangle", + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "structured", + "fresh" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "auth0-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "black shield with star cut out", + "geometry": [ + "shield", + "star" + ], + "techniques": [ + "negative-space", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "secure", + "bold" + ], + "industry": "security-identity", + "exemplary": true, + "note": "Star carved from shield via negative space, strong at any size" + }, + { + "file": "auth0.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "star shield beside lowercase name", + "geometry": [ + "shield", + "star" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "secure", + "modern" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "authy.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "white chain-link swirl in red circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "secure" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "autoit.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "stylized A in blue circle with ring", + "geometry": [ + "circle", + "triangle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "technical" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "autoprefixer.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "red serif A with dash lines", + "geometry": [ + "triangle" + ], + "techniques": [ + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "ava.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold AVA with rocket flames under As", + "geometry": [ + "triangle" + ], + "techniques": [ + "hidden-meaning" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "playful" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "awesome.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "pink sunglasses above lowercase name", + "geometry": [ + "freeform" + ], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "playful", + "cool" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "aws-amplify.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "yellow-orange striped A-like triangle", + "geometry": [ + "triangle" + ], + "techniques": [ + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "energetic" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-api-gateway.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "gateway doors framing code brackets", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "bracket-code" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-app-mesh.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "dotted isometric cube with nodes", + "geometry": [ + "square", + "hexagon" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-appflow.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two arrows inside hexagon outline", + "geometry": [ + "square", + "hexagon" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-appsync.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "circular arrows around node triangle", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-athena.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "magnifier over bucket with speed lines", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-aurora.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "database cylinder with sparkle stars", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-backup.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "node pentagon around circular arrow", + "geometry": [ + "square", + "hexagon" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-batch.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "branching tree of node circles", + "geometry": [ + "square", + "grid-modular" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-certificate-manager.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "browser window with certificate star", + "geometry": [ + "square", + "star" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "aws-cloudformation.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "document template beside cloud", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-cloudfront.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "globe with connected node path", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "aws-cloudsearch.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "magnifier over cloud", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-cloudtrail.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cloud with dashed speed trail", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "aws-cloudwatch.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cloud with magnifying glass", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "aws-codebuild.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "crane lifting code box", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "bracket-code" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "aws-codecommit.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "git branch nodes with code page", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "bracket-code", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "aws-codedeploy.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "parachute carrying a box", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "aws-codepipeline.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "slot with block feeding out", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "aws-codestar.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "code brackets ringed by node glyphs", + "geometry": [ + "square", + "radial" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "bracket-code" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "aws-cognito.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "ID card with user and checkmark", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "aws-config.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "slider controls with gear", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-documentdb.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "database cylinder with brace document", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "bracket-code" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-dynamodb.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "database cylinder with lightning bolt", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-ec2.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "processor chip over stacked squares", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "stacked-layers" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-ecs.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "hexagonal container outline", + "geometry": [ + "square", + "hexagon" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-eks.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter K inside hexagon outline", + "geometry": [ + "square", + "hexagon" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-elastic-beanstalk.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cloud with sprouting plant", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-elasticache.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "memory chip with database cylinder", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-elb.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "circle branching to three nodes", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-eventbridge.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "hexagon linked to branching nodes", + "geometry": [ + "square", + "hexagon" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-fargate.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cube on ring with small cubes", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-glacier.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "bucket with snowflake", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-glue.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "funnel with blocks and down arrow", + "geometry": [ + "square", + "triangle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-iam.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "ID card with padlock", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "aws-keyspaces.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "database cylinder with C asterisk", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-kinesis.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "converging streams of flowing lines", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-kms.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "key beside keycard", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "aws-lake-formation.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "funnel over circle of waves", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-lambda.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "outlined Greek lambda", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-lightsail.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "sail and sparkles in orange circle outline", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "light", + "technical" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "aws-mq.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "nodes and arrows around square", + "geometry": [ + "square", + "radial" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-msk.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "node triangle with K over waves", + "geometry": [ + "square", + "triangle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-neptune.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "database cylinder with node graph", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-open-search.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "bar chart with magnifier", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-opsworks.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "gear above org-chart blocks", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-quicksight.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "rising line chart in frame", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "aws-rds.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "database cylinder with expand arrows", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-redshift.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cylinder with line chart", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-route53.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "highway route shield with number 53", + "geometry": [ + "square", + "shield" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": "grotesque-sans", + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "aws-s3.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "storage bucket outline", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-secrets-manager.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "padlock within crosshair", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "aws-ses.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "envelope in circle with nodes", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "aws-shield.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "shield with plus badge", + "geometry": [ + "square", + "shield" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "aws-sns.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "funnel in circle fanning to nodes", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "aws-sqs.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "square between arrows in circle", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-step-functions.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "flowchart of blocks and nodes", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-systems-manager.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cloud with settings gear", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-timestream.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "database cylinder with trend chart", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "aws-vpc.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cloud with shield", + "geometry": [ + "square", + "shield" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "aws-waf.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "flame inside crossed-out crosshair", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "aws-xray.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cloud over circle with bar chart", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "containment", + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "corporate" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "aws.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "lowercase aws over smile arrow", + "geometry": [], + "techniques": [ + "arrow", + "hidden-meaning" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": true, + "note": "Smile arrow adds warmth and motion under a plain wordmark" + }, + { + "file": "axios.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "widely spaced uppercase name, custom I", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "light", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "babel.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "yellow brush-stroke uppercase name", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "energetic", + "raw" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "backbone-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "interlocking chevrons forming bow-tie", + "geometry": [ + "triangle", + "square" + ], + "techniques": [ + "mirror-symmetry", + "overlap-transparency", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "structured", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "backbone.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "chevron bow-tie beside thin uppercase name", + "geometry": [ + "triangle" + ], + "techniques": [ + "mirror-symmetry", + "geometric-construction" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "light", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "backerkit.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "mountain peaks with summit flag", + "geometry": [ + "triangle" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "adventurous" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "baker-street.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "ring of overlapping colored arcs", + "geometry": [ + "circle" + ], + "techniques": [ + "overlap-transparency", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "colorful", + "dynamic" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "balena.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric cube with colored faces", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "bright", + "playful" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "bamboo.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "segmented circle ending in arrow", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "arrow", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "basecamp.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "green hill inside soft smile shape", + "geometry": [ + "organic" + ], + "techniques": [ + "containment", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "calm" + ], + "industry": "productivity-collaboration", + "exemplary": true, + "note": "Hill silhouette doubles as a smile inside soft container" + }, + { + "file": "basekit.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "BK initials in black rectangle", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "ligature" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "simple" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "bash-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "hexagonal block with terminal prompt", + "geometry": [ + "hexagon" + ], + "techniques": [ + "bracket-code", + "dimensional-shading", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "solid" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "bash.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "prompt block beside bold name and tagline", + "geometry": [ + "hexagon" + ], + "techniques": [ + "bracket-code", + "dimensional-shading" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "technical", + "solid" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "batch.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "lowercase b with underline in dark tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "modern" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "beats.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "stacked color bands forming rounded B", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments", + "stacked-layers" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "behance.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold name with macron over e", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "bold", + "confident" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "bem-2.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "blocky bird-like head with underscore", + "geometry": [ + "square", + "grid-modular" + ], + "techniques": [ + "geometric-construction", + "bracket-code" + ], + "type_style": null, + "case": null, + "mood": [ + "quirky", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "bem.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "striped bars forming block shapes with underscore", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "structured" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "bigpanda.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "panda face wearing glasses", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "smart" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "bing.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "angular ribbon lowercase b", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "dynamic" + ], + "industry": "other", + "exemplary": false, + "note": "" + }, + { + "file": "bitbucket.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "blue gradient bucket with cutout", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "bitcoin.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "tilted B currency sign in orange circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "trustworthy" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "bitnami.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "lowercase b in isometric hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "negative-space", + "dimensional-shading", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "bitrise-icon.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "smiling robot face with antenna", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "bitrise.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "robot face beside bold lowercase name", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "playful", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "blender.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orbiting ring with blue eye core", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "creative" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "blitzjs-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two slanted purple bars forming bolt", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "blitzjs.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "slanted bolt beside titlecase name", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "fast", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "blocs.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "hexagon outline with three lines", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "calm" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "blogger.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "rounded B in orange tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "simple" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "blossom.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "lotus flower in dark ring", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "balanced" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "blueprint.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric cluster of colored cubes", + "geometry": [ + "hexagon", + "grid-modular" + ], + "techniques": [ + "isometric-3d", + "color-segments", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "colorful", + "structured" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "bluetooth.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "bind-rune of H and B in blue", + "geometry": [ + "organic" + ], + "techniques": [ + "hidden-meaning", + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "trustworthy" + ], + "industry": "hardware-devices", + "exemplary": true, + "note": "Runic initials merged into one glyph: history encoded simply" + }, + { + "file": "booqable-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "monoline boomerang arc", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "friendly" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "booqable.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "boomerang arc beside lowercase name", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "bootstrap.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "bold B in purple rounded square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "simple" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "bosun.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "grid of linked nodes on blue tiles", + "geometry": [ + "square", + "grid-modular" + ], + "techniques": [ + "containment", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "structured" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "botanalytics.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "speech bubble with chart-line top edge", + "geometry": [ + "freeform" + ], + "techniques": [ + "speech-bubble", + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "clever", + "technical" + ], + "industry": "marketing-analytics", + "exemplary": true, + "note": "Speech bubble edge doubles as a chart line: two ideas fused" + }, + { + "file": "bourbon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "glass of bourbon with ice", + "geometry": [ + "square" + ], + "techniques": [ + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "classic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "bower.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "colorful cartoon bird head", + "geometry": [ + "organic" + ], + "techniques": [ + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "colorful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "box.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "white lowercase box in blue tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "simple" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "brackets.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "square brackets on raised blue button", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "bracket-code", + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "solid" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "brainjs.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "faceted black brain on yellow square", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "technical" + ], + "industry": "ai-ml", + "exemplary": false, + "note": "" + }, + { + "file": "branch.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "tree branch with node dots in ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "organic", + "technical" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "brandfolder-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "B inside open frame with arrow", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "bright", + "modern" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "brandfolder.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "bracket frame hugging titlecase name", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "clean", + "modern" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "brave.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "faceted lion head in shield form", + "geometry": [ + "shield" + ], + "techniques": [ + "geometric-construction", + "gradient", + "mirror-symmetry", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "brave" + ], + "industry": "other", + "exemplary": false, + "note": "" + }, + { + "file": "braze.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "script lowercase b inside ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "elegant", + "modern" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "broccoli.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "green broccoli floret", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "playful", + "organic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "brotli.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three slanted cuts in golden circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "simple" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "browserify-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "blue wizard hat with moon and stars", + "geometry": [ + "triangle", + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "whimsical", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "browserify.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "hand-lettered gold lowercase name", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "whimsical", + "quirky" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "browserling.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "UFO outline with tractor beams", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "light" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "browserslist.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "hedgehog silhouette in yellow circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "browserstack.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "eye inside colorful concentric rings", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "color-segments", + "stacked-layers" + ], + "type_style": null, + "case": null, + "mood": [ + "colorful", + "vibrant" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "browsersync.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two slanted red tower blocks", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "brunch.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "fork knife spoon in faceted diamond", + "geometry": [ + "diamond" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "buck.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "geometric monoline deer head and antlers", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline", + "geometric-construction", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "sharp", + "technical" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Deer head built from strict geometric monoline strokes" + }, + { + "file": "buddy.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "chevron inside faceted blue hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "gradient", + "arrow", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "dynamic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "buffer.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three stacked rhombus layers", + "geometry": [ + "diamond" + ], + "techniques": [ + "stacked-layers", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "calm" + ], + "industry": "marketing-analytics", + "exemplary": true, + "note": "Three stacked layers: minimal, memorable, name-literal" + }, + { + "file": "bugherd.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "condensed name inside black circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "grotesque-sans", + "case": "mixed", + "mood": [ + "bold", + "friendly" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "bugsee.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red anteater silhouette", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "quirky" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "bugsnag-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "monoline b wrapping target dot", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "precise" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "bugsnag.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "rounded navy lowercase name", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "buildkite-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "folded green isometric ribbon kite", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "buildkite.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "folded ribbon beside bold titlecase name", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "fresh", + "confident" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "bulma.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "angular teal B-like faceted shape", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "c-plusplus.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "C with ++ inside shaded hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "dimensional-shading", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "solid" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "c-sharp.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "C with sharp sign in purple hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "dimensional-shading", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "solid" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "c.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter C in gray shaded hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "dimensional-shading", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "plain" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "cachet.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "check mark circle beside thin name", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "light", + "calm" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "caffe2.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "coffee cup with plus signs as steam", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "technical" + ], + "industry": "ai-ml", + "exemplary": false, + "note": "" + }, + { + "file": "cakephp-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "layered cake with slice removed", + "geometry": [ + "circle" + ], + "techniques": [ + "stacked-layers", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "cakephp.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "cake icon beside bold mixed-case name", + "geometry": [ + "circle" + ], + "techniques": [ + "stacked-layers" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "bold", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "campaignmonitor-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "purple envelope from angular shapes", + "geometry": [ + "triangle", + "square" + ], + "techniques": [ + "geometric-construction", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "bold" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "campaignmonitor.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "small envelope beside titlecase name", + "geometry": [ + "triangle" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "clean", + "corporate" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "canjs.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy tightly kerned lowercase name", + "geometry": [], + "techniques": [ + "ligature" + ], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "bold", + "compact" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "capacitorjs-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "X formed by overlapping blue bars", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "capacitorjs.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "blue X beside bold titlecase name", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "modern", + "confident" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "capistrano.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "C made of segmented blue ring", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "modular-repetition", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "dynamic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "carbide.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "turbine-like gear forming letter C", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "negative-space", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "cardano-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "radial pattern of graduated dots", + "geometry": [ + "radial", + "circle" + ], + "techniques": [ + "radial-symmetry", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "precise" + ], + "industry": "payments-fintech", + "exemplary": true, + "note": "Graduated dot sizes build a radial form through pure repetition" + }, + { + "file": "cardano.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "dot constellation beside uppercase name", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry", + "modular-repetition" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "trustworthy" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "cassandra.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "detailed eye above italic lowercase name", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "mystical", + "dated" + ], + "industry": "database-data", + "exemplary": false, + "note": "Detailed illustration struggles at small sizes" + }, + { + "file": "centos-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "pinwheel of colored squares with arrows", + "geometry": [ + "diamond", + "radial" + ], + "techniques": [ + "radial-symmetry", + "color-segments", + "arrow", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "colorful", + "structured" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Rotated modules and arrows create strict radial symmetry" + }, + { + "file": "centos.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "colored pinwheel beside bold mixed-case name", + "geometry": [ + "diamond", + "radial" + ], + "techniques": [ + "radial-symmetry", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "structured", + "solid" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "certbot.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "lock robot holding key beside name", + "geometry": [ + "freeform" + ], + "techniques": [], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "playful", + "secure" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "ceylon.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "gold elephant beside heavy lowercase name", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "bold", + "warm" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "chai.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "script serif c in red hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "classic", + "warm" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "chalk.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "rainbow chalk-textured uppercase letters", + "geometry": [], + "techniques": [ + "hand-drawn", + "color-segments" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "playful", + "colorful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "chargebee-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "orange C with dot and speed lines", + "geometry": [ + "circle" + ], + "techniques": [ + "motion-lines", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "friendly" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "chargebee.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "dark script titlecase name", + "geometry": [], + "techniques": [], + "type_style": "script", + "case": "titlecase", + "mood": [ + "friendly", + "personal" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "chef.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "concentric segmented C above spaced name", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "color-segments", + "modular-repetition" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "solid" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "chevereto.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "blue bold italic script lowercase name", + "geometry": [], + "techniques": [], + "type_style": "script", + "case": "lowercase", + "mood": [ + "playful", + "casual" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "chromatic-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "white interlocking knot loops on orange disc", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "overlap-transparency", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "dynamic" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "chromatic.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "interlocking knot disc beside name", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "chrome.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "tricolor ring segments around blue core", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "color-segments", + "radial-symmetry", + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "iconic" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Three color segments plus core; strong radial construction." + }, + { + "file": "cinder.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "mountain peak with rising sparks", + "geometry": [ + "triangle" + ], + "techniques": [ + "letter-substitution" + ], + "type_style": "serif", + "case": "uppercase", + "mood": [ + "crafted", + "warm" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "circleci.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "notched ring around a solid dot", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "technical" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Pure circle geometry; one notch creates motion and identity." + }, + { + "file": "cirrus-ci.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "curling horizontal lines like wind", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "calm" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "cirrus.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "two overlapping blue circles", + "geometry": [ + "circle" + ], + "techniques": [ + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "trustworthy", + "calm" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "clion.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "CL initials in black square on polygons", + "geometry": [ + "square", + "freeform" + ], + "techniques": [ + "containment", + "gradient", + "overlap-transparency" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "bold", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "cljs.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "cljs set inside two-tone ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "technical" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "clojure.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "lambda in two-tone circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "color-segments", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "clever", + "balanced" + ], + "industry": "programming-language", + "exemplary": true, + "note": "Lambda emerges from negative space between two colored halves." + }, + { + "file": "close.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "interlocking colored ellipses like orbits", + "geometry": [ + "radial", + "circle" + ], + "techniques": [ + "overlap-transparency", + "radial-symmetry", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "playful" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "cloud9.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "cloud with numeral 9", + "geometry": [ + "organic" + ], + "techniques": [ + "letter-substitution" + ], + "type_style": "slab", + "case": "titlecase", + "mood": [ + "playful", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "cloudacademy-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "flower outline with network nodes", + "geometry": [ + "organic", + "radial" + ], + "techniques": [ + "line-monoline", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "friendly" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "cloudacademy.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "network flower icon beside name", + "geometry": [ + "organic", + "radial" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "approachable" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "cloudcraft.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric square frame in blue and yellow", + "geometry": [ + "square" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "structured" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "cloudflare.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "orange cloud with lighter trailing lobe", + "geometry": [ + "organic" + ], + "techniques": [ + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "reliable" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "cloudinary.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cloud outline over three upload arrows", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline", + "arrow", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "clear" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "cloudlinux.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "swirling vortex of blue blades", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "technical" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "cobalt.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter C with radiating ticks and eye", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "vigilant" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "cockpit.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "white interlocking strokes in black disc", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "cocoapods.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "C with chevron in red square", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "bracket-code", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "codacy.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "ring of heavy dashed segments", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "modular-repetition", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "codebase.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with code-diamond replacing o", + "geometry": [], + "techniques": [ + "letter-substitution", + "bracket-code" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "technical", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "codebeat.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "heartbeat pulse line in blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "energetic" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "codecademy.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "code boxed beside cademy", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "monospace", + "case": "lowercase", + "mood": [ + "technical", + "educational" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "codeception.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "concentric C arcs with checkmark", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "confident", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "codeclimate.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "double chevron mountain peaks", + "geometry": [ + "triangle" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "solid", + "professional" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "codecov.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "umbrella outline in magenta", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "clever", + "friendly" + ], + "industry": "testing-monitoring", + "exemplary": true, + "note": "Umbrella as coverage metaphor: one simple, memorable idea." + }, + { + "file": "codefactor-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "F built from dots and bars", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "playful" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "codefactor.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "dot-and-bar F icon beside name", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": "monospace", + "case": "mixed", + "mood": [ + "technical", + "modern" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "codeigniter.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "stylized flame", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": "humanist-sans", + "case": "mixed", + "mood": [ + "energetic", + "warm" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "codepen-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "wireframe isometric cube", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "line-monoline", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "minimal" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Cube drawn with pure monoline geometry; works at any size." + }, + { + "file": "codepen.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "tracked name with cube as O", + "geometry": [], + "techniques": [ + "letter-substitution", + "isometric-3d" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "minimal", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "codepush.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "toy ray gun firing lines", + "geometry": [ + "freeform" + ], + "techniques": [ + "motion-lines", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "energetic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "codersrank.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "code chevron with stylized R", + "geometry": [ + "freeform" + ], + "techniques": [ + "bracket-code", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "coderwall.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "six dots stepped into triangle", + "geometry": [ + "grid-modular", + "triangle" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "orderly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "codesandbox.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric cube with cut-out faces", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "technical" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Cube built purely from negative-space cuts; bold single-color geometry." + }, + { + "file": "codeship.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "ship bow inside ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "sturdy", + "dependable" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "codio.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "isometric letter C in blues", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "structured" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "codrops.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "water drop in blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "simple" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "coffeescript.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "coffee cup with steam swirl", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "warm", + "friendly" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "commitizen.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter C ringed by scattered dots", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "compass.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "compass star in red teardrop", + "geometry": [ + "organic", + "star" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "adventurous" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "componentkit.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "stacked translucent L shapes on tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "stacked-layers", + "overlap-transparency", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "layered" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "compose.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "row of three isometric cubes", + "geometry": [ + "square" + ], + "techniques": [ + "isometric-3d", + "modular-repetition", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "structured", + "technical" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "composer.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "conductor raising baton above name", + "geometry": [ + "freeform" + ], + "techniques": [ + "hand-drawn" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "whimsical", + "quirky" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Overly detailed illustration; fails at small sizes." + }, + { + "file": "conan-io.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "isometric package box with C", + "geometry": [ + "square" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "concourse.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "swirling propeller blades around hub", + "geometry": [ + "radial", + "circle" + ], + "techniques": [ + "radial-symmetry", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "light" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "concrete5.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "white hand in black rounded tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "approachable" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "confluence.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two opposing blue gradient swooshes", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "fluid", + "collaborative" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "consul.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "open C ring with dot grid", + "geometry": [ + "circle" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "connected" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "contentful.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "segmented C with colored dot ends", + "geometry": [ + "circle" + ], + "techniques": [ + "color-segments", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "vibrant" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "convox.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange dot in blue ringed disc", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "simple" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "copyleft-pirate.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "copyleft sign over crossed cutlasses", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "rebellious", + "playful" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "copyleft.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "reversed C in heavy ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "principled" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "corda.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with dot replacing o", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "confident" + ], + "industry": "finance-banking", + "exemplary": false, + "note": "" + }, + { + "file": "cordova.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "robot-like head with two eyes", + "geometry": [ + "freeform" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "sturdy", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "coreos-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "coral rounded shape inside blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "warm" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "coreos.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "coral shape in blue disc", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "modern", + "clean" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "couchbase.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "couch silhouette in red circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "simple" + ], + "industry": "database-data", + "exemplary": true, + "note": "Couch reduced to one rounded negative shape; direct name reference." + }, + { + "file": "couchdb-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red couch built from stacked bars", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "relaxed", + "friendly" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "couchdb.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "red couch beside name and tagline", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": "humanist-sans", + "case": "mixed", + "mood": [ + "relaxed", + "friendly" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "coursera.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "custom lowercase blue name", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "trustworthy" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "coveralls.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy italic condensed name", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "bold", + "energetic" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "cpanel.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "custom connected italic name", + "geometry": [], + "techniques": [ + "ligature" + ], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "dynamic", + "bold" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "craftcms.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "lowercase c in red square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "crafted", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "crashlytics.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "cog-like shape with C and dot", + "geometry": [ + "radial", + "freeform" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "crateio.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "asymmetric light blue plus shape", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "clean" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "create-react-app.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "atom inside stacked outline squares", + "geometry": [ + "square", + "radial" + ], + "techniques": [ + "containment", + "stacked-layers", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "createjs.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "dark cube with code chevrons", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "negative-space", + "bracket-code" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "cross-browser-testing.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "rotating dark segments inside cyan square", + "geometry": [ + "square", + "radial" + ], + "techniques": [ + "radial-symmetry", + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "crucible.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "blue gradient vessel with V notch", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "smooth" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "crystal.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "faceted black polygon with white triangle", + "geometry": [ + "hexagon", + "freeform" + ], + "techniques": [ + "negative-space", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "sharp", + "precise" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "css-3.svg", + "mark_type": "combination", + "symbol_type": "emblem", + "subject": "numeral 3 inside blue shield", + "geometry": [ + "shield" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "solid", + "technical" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "css-3_official.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "numeral 3 formed as shield", + "geometry": [ + "shield" + ], + "techniques": [ + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "minimal" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "cssnext.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "curly brace with speed lines", + "geometry": [ + "freeform" + ], + "techniques": [ + "bracket-code", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "cucumber.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cucumber slice as speech bubble", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "speech-bubble", + "radial-symmetry", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "friendly" + ], + "industry": "testing-monitoring", + "exemplary": true, + "note": "Cucumber cross-section doubles as speech bubble for plain-language specs." + }, + { + "file": "curl.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name followed by URL slashes", + "geometry": [], + "techniques": [ + "bracket-code" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "technical", + "quirky" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "customerio-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "yellow dot above gradient arc", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "gradient", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "vibrant" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "customerio.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "yellow dot over gradient arc", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "gradient", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "cyclejs.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "open gradient hexagon ring", + "geometry": [ + "hexagon" + ], + "techniques": [ + "gradient", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "cypress.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "cy letters in grey circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "solid", + "friendly" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "d3.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "joined D and 3 gradient shapes", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "ligature" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "warm" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "dart.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "faceted teal dart-like shape", + "geometry": [ + "diamond", + "freeform" + ], + "techniques": [ + "overlap-transparency", + "dimensional-shading", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "sharp", + "modern" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "dashlane-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter D built from skewed bars", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "secure", + "structured" + ], + "industry": "security-identity", + "exemplary": true, + "note": "Letter D emerges from repeated bars; strong modular construction." + }, + { + "file": "dashlane.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "bar-built D beside name", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "secure", + "solid" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "database-labs.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "connected hexagons with circuit lines", + "geometry": [ + "hexagon", + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "connected" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "datadog.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "dog holding chart above name", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "friendly", + "playful" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "datocms-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "orange D with circular counter", + "geometry": [ + "circle", + "square" + ], + "techniques": [ + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "simple" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "datocms.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "orange D beside stacked name", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "dbt-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange X with diamond center cut", + "geometry": [ + "freeform" + ], + "techniques": [ + "negative-space", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "energetic" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "dbt.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "orange X beside name", + "geometry": [ + "freeform" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "modern" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "dcos-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "gradient outline of crossing lines in square", + "geometry": [ + "square" + ], + "techniques": [ + "line-monoline", + "gradient", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "technical" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "dcos.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "gradient crossed-line square", + "geometry": [ + "square" + ], + "techniques": [ + "line-monoline", + "gradient" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "modern" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "debian.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "red brushed spiral swirl", + "geometry": [ + "organic" + ], + "techniques": [ + "hand-drawn" + ], + "type_style": null, + "case": null, + "mood": [ + "organic", + "iconic" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "delighted-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "script D in grey circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "hand-drawn" + ], + "type_style": null, + "case": null, + "mood": [ + "elegant", + "friendly" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "delighted.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "flowing script name", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "script", + "case": "titlecase", + "mood": [ + "elegant", + "cheerful" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "deno.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "dinosaur silhouette in rainy circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "bold" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "deployhq.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold deploy with light hq", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "confident", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "derby.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red horse head profile", + "geometry": [ + "freeform" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "spirited", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "designernews.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "DN in circle with long shadow", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "flat", + "modern" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "deviantart.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "angular green glyph beside stacked name", + "geometry": [ + "freeform" + ], + "techniques": [], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "edgy", + "creative" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "dgraph-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "lightning bolt linking two nodes in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "fast" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "dgraph.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "bolt-and-node circle beside name", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient" + ], + "type_style": "monospace", + "case": "titlecase", + "mood": [ + "technical", + "energetic" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "dialogflow.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric cube with speech tail", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "speech-bubble", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "conversational" + ], + "industry": "ai-ml", + "exemplary": false, + "note": "" + }, + { + "file": "digital-ocean.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "open ring with pixel squares", + "geometry": [ + "circle" + ], + "techniques": [ + "pixel", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "friendly", + "reliable" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "dimer.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "two-tone overlapping D", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "color-segments" + ], + "type_style": "serif", + "case": "titlecase", + "mood": [ + "editorial", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "dinersclub.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "circle split by twin half-discs", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "mirror-symmetry" + ], + "type_style": "serif", + "case": "titlecase", + "mood": [ + "classic", + "trustworthy" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "discord-icon.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "controller-shaped face with two eyes", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "social-communication", + "exemplary": true, + "note": "Controller shape doubles as friendly face; minimal features, maximum personality." + }, + { + "file": "discord.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "controller face beside name", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": "display-custom", + "case": "titlecase", + "mood": [ + "playful", + "bold" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "discover.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with solid ball as O", + "geometry": [ + "circle" + ], + "techniques": [ + "letter-substitution" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "clean", + "confident" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "disqus.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter D inside speech bubble", + "geometry": [ + "circle" + ], + "techniques": [ + "speech-bubble", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "conversational" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "django-icon.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "dj in dark green tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "solid", + "dependable" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "django.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy custom lowercase name", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "solid", + "confident" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "dockbit.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "small hexagon inside gradient hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "calm" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "docker-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "whale carrying stacked containers", + "geometry": [ + "organic", + "grid-modular" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "memorable" + ], + "industry": "cloud-infrastructure", + "exemplary": true, + "note": "Whale carrying containers: literal product metaphor, instantly memorable." + }, + { + "file": "docker.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "container-carrying whale beside name", + "geometry": [ + "organic", + "grid-modular" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "approachable" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "doctrine.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange teardrop with arrow cutout", + "geometry": [ + "organic" + ], + "techniques": [ + "arrow", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "warm" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Arrow carved from teardrop via negative space; single bold idea." + }, + { + "file": "docusaurus.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "green dinosaur holding a document", + "geometry": [ + "freeform" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "dojo-icon.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "colorful ribbon dragon", + "geometry": [ + "freeform" + ], + "techniques": [ + "infinity-loop", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "ornate", + "energetic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "Detailed multicolor dragon; loses clarity at small sizes." + }, + { + "file": "dojo-toolkit.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "lowercase name with macrons over o", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "calm", + "minimal" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "dojo.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "ribbon dragon beside thin name", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "infinity-loop" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "ornate", + "light" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "dotnet.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "blue gradient ribbon wave", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": "humanist-sans", + "case": "mixed", + "mood": [ + "corporate", + "dynamic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "dreamhost.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "dark crescent moon around blue disc", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "dreamy" + ], + "industry": "hosting-cdn", + "exemplary": true, + "note": "Two circles make a crescent moon; minimal geometry, clear name link." + }, + { + "file": "dribbble-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "pink basketball", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "vibrant" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "dribbble.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bouncy script name", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "script", + "case": "lowercase", + "mood": [ + "playful", + "creative" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "drift.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with lightning bolt as I", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "bold", + "energetic" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "drip.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "smiling droplet face", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "cheerful" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "drizzle-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "chocolate truffle with pink zigzag drizzle", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "sweet", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "drizzle.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "drizzled truffle above name with zigzag z", + "geometry": [ + "organic" + ], + "techniques": [ + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "sweet", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "drone-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "ring split by diagonal cut in disc", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "drone.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "split-ring disc beside tracked name", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "clean", + "confident" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "dropbox.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "open box built from blue rhombi", + "geometry": [ + "diamond", + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "trustworthy" + ], + "industry": "productivity-collaboration", + "exemplary": true, + "note": "Five rhombi form an open box; modular and instantly legible." + }, + { + "file": "dropmark.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "teal drop with down-arrow cutout", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "simple" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "dropzone.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "concentric rounded D in blue square", + "geometry": [ + "square" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "drupal-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "water drop with inner loop in disc", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "drupal.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "drop symbol beside name", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "friendly", + "confident" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "duckduckgo.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "duck head with bowtie in ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "quirky" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "dynatrace-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "multicolor isometric square frame", + "geometry": [ + "square" + ], + "techniques": [ + "isometric-3d", + "color-segments", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "dynatrace.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "multicolor square frame beside name", + "geometry": [ + "square" + ], + "techniques": [ + "isometric-3d", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "dyndns.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "crescent ring from black to yellow", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "glossy" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "ebanx.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold name with chevron-cut E", + "geometry": [], + "techniques": [ + "negative-space" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "solid", + "corporate" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "eclipse-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "striped dark disc eclipsing orange sun", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "eclipse.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "striped eclipse disc beside name", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "solid", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "editorconfig.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "sketched mouse wearing glasses", + "geometry": [ + "freeform" + ], + "techniques": [ + "hand-drawn", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "quirky", + "nerdy" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Loose sketch lines; weak reproduction at small sizes." + }, + { + "file": "egghead.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "egg wearing thick glasses", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "nerdy", + "playful" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "elasticsearch.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "E built from colored stacked bands", + "geometry": [ + "circle" + ], + "techniques": [ + "color-segments", + "stacked-layers" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "modern" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "electron.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "atom orbits with nodes", + "geometry": [ + "radial" + ], + "techniques": [ + "line-monoline", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "light" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "element.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter e inside blue hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "elemental-ui.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "E hexagon over faint atom orbits", + "geometry": [ + "hexagon", + "radial" + ], + "techniques": [ + "containment", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "light", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "elementary.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "monoline script e inside circle", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "elegant", + "minimal" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "ello.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "white smile curve in black disc", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "friendly" + ], + "industry": "social-communication", + "exemplary": true, + "note": "A single smile arc in a circle; radical reduction of a face." + }, + { + "file": "elm.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "tangram pieces forming a square", + "geometry": [ + "square", + "triangle", + "grid-modular" + ], + "techniques": [ + "geometric-construction", + "color-segments", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "structured" + ], + "industry": "programming-language", + "exemplary": true, + "note": "Tangram pieces tile a perfect square; exemplary geometric construction." + }, + { + "file": "elo.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "elo name in black disc, tricolor o", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "color-segments", + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "modern" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "emacs.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "calligraphic name entwined with gnu horns", + "geometry": [ + "freeform" + ], + "techniques": [ + "hand-drawn", + "dimensional-shading" + ], + "type_style": "script", + "case": "titlecase", + "mood": [ + "ornate", + "quirky" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Ornate 3D calligraphy; poor scalability and legibility." + }, + { + "file": "embedly.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter e in rounded blue diamond", + "geometry": [ + "diamond" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "ember-tomster.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "hamster with glasses above script name", + "geometry": [ + "freeform" + ], + "techniques": [], + "type_style": "script", + "case": "lowercase", + "mood": [ + "playful", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "ember.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "flowing brush script name", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "script", + "case": "lowercase", + "mood": [ + "warm", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "emmet.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "green angular chevron shape in black disc", + "geometry": [ + "circle", + "triangle" + ], + "techniques": [ + "arrow", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "sharp", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "engine-yard-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "thick gradient ring with offset notch", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "dynamic" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "engine-yard.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "gradient ring beside name", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "modern", + "corporate" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "envato.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "green leaf beside name", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "fresh", + "friendly" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "envoy-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "overlapping outlined magenta hexagons", + "geometry": [ + "hexagon" + ], + "techniques": [ + "overlap-transparency", + "line-monoline", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "vibrant" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "envoy.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "overlapping hexagon outlines beside name", + "geometry": [ + "hexagon" + ], + "techniques": [ + "overlap-transparency", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "technical" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "envoyer.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "rocket framed by circular arcs", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "warm" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "enyo.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "stacked chevrons shield above name", + "geometry": [ + "shield", + "hexagon" + ], + "techniques": [ + "stacked-layers", + "dimensional-shading", + "gradient" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "solid", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "erlang.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "red e framed by brackets above name", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "bracket-code" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "classic" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "es6.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "ES6 in corner of orange square", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "direct" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "esbuild.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "black double chevron in yellow disc", + "geometry": [ + "circle" + ], + "techniques": [ + "arrow", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "esdoc.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "owl face cut into red disc", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "wise", + "friendly" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Owl face formed entirely by negative space in a disc." + }, + { + "file": "eslint-old.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "offset faceted purple hexagons", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "dimensional-shading", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "solid" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "eslint.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "nested purple hexagons", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "structured" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "eta-lang.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "white sea dragon in teal hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "mystical", + "playful" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "etcd.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "cog-shaped creature with two eyes", + "geometry": [ + "radial" + ], + "techniques": [ + "mirror-symmetry", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "technical" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "ethereum-color.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "pastel outlined octahedron", + "geometry": [ + "diamond", + "triangle" + ], + "techniques": [ + "line-monoline", + "color-segments", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "light", + "futuristic" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "ethereum.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "faceted grey octahedron", + "geometry": [ + "diamond" + ], + "techniques": [ + "dimensional-shading", + "mirror-symmetry", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "iconic" + ], + "industry": "payments-fintech", + "exemplary": true, + "note": "Faceted octahedron from flat tones; iconic, symmetrical, scalable." + }, + { + "file": "ethers.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "brushy cloud outline with swoosh", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline", + "hand-drawn" + ], + "type_style": null, + "case": null, + "mood": [ + "light", + "airy" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "ethnio.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "target-like concentric rings in dark disc", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "focused" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "eventbrite-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white e in orange disc", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "friendly" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "eventbrite.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold orange lowercase name", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "energetic" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "eventsentry.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange hexagon sliced by curved stripes", + "geometry": [ + "hexagon" + ], + "techniques": [ + "negative-space", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "warm" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "evergreen-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "white conifer tree in green disc", + "geometry": [ + "circle", + "triangle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "natural" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "evergreen.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "tree disc beside tracked name", + "geometry": [ + "circle", + "triangle" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "calm", + "clean" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "expo-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "rounded black caret chevron", + "geometry": [ + "triangle" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "confident" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "expo.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "caret chevron beside bold name", + "geometry": [ + "triangle" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "bold", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "express.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "ultra-thin titlecase name", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "minimal", + "light" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "fabric.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "interwoven yellow and blue strands", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "modular-repetition", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "woven", + "energetic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "facebook.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white f in blue rounded square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "familiar", + "trustworthy" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "falcor.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "faceted multicolor hexagon ring", + "geometry": [ + "hexagon" + ], + "techniques": [ + "color-segments", + "gradient", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "fastify-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "panther head with speed stripes", + "geometry": [ + "freeform" + ], + "techniques": [ + "motion-lines", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "fierce", + "fast" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "fastify.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "speed-striped panther head", + "geometry": [ + "freeform" + ], + "techniques": [ + "motion-lines" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "fast", + "aggressive" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "fastlane.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "pentagon of colored connected nodes", + "geometry": [ + "radial", + "circle" + ], + "techniques": [ + "color-segments", + "line-monoline", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "connected" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "fastly.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with stopwatch replacing a", + "geometry": [], + "techniques": [ + "letter-substitution", + "hidden-meaning" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "fast", + "bold" + ], + "industry": "hosting-cdn", + "exemplary": true, + "note": "Stopwatch folded into a letter conveys speed without extra symbol." + }, + { + "file": "feathersjs.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "feather inside circle outline", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "light", + "elegant" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "fedora.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "infinity f in speech-bubble disc", + "geometry": [ + "circle" + ], + "techniques": [ + "infinity-loop", + "speech-bubble", + "negative-space", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "open" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Letter f, infinity loop and speech bubble fused in one mark." + }, + { + "file": "fetch.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "dog bone inside green ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "simple" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "figma.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "five colored circles and half-rounds", + "geometry": [ + "grid-modular", + "circle" + ], + "techniques": [ + "color-segments", + "modular-repetition", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "creative" + ], + "industry": "design-creative", + "exemplary": true, + "note": "Modular circle and half-round units; each color a separate building block." + }, + { + "file": "firebase.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "flame from overlapping triangular shards", + "geometry": [ + "triangle" + ], + "techniques": [ + "overlap-transparency", + "dimensional-shading", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "energetic" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "firefox.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "fiery fox wrapped around globe", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "energetic" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "flannel.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter f from woven blue tiles", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "structured", + "technical" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "flarum.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "folded orange flag", + "geometry": [ + "square" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "bold", + "loud" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "flask.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "engraved horn above blackletter name", + "geometry": [ + "freeform" + ], + "techniques": [ + "hand-drawn" + ], + "type_style": "serif", + "case": "titlecase", + "mood": [ + "vintage", + "crafted" + ], + "industry": "framework-library", + "exemplary": false, + "note": "Fine engraving detail breaks down at small sizes." + }, + { + "file": "flat-ui.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "faceted blue gem with sparkle", + "geometry": [ + "diamond" + ], + "techniques": [ + "dimensional-shading", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "polished", + "bright" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "flattr-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two interlocking arrowed brackets forming loop", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "arrow", + "negative-space", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "cyclical" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "flattr.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "gradient interlocking arrowed halves", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "gradient", + "arrow", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "cyclical" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "fleep.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "F inside blue speech bubble", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "speech-bubble", + "containment" + ], + "type_style": "slab", + "case": "titlecase", + "mood": [ + "friendly", + "bold" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "flickr.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy black lowercase name", + "geometry": [], + "techniques": [], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "bold", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "flight.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "blue wing forming letter F", + "geometry": [ + "organic" + ], + "techniques": [ + "hidden-meaning", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "light", + "fast" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "floodio.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "wave line inside blue ring", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "flow.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "translucent triangles forming F", + "geometry": [ + "triangle", + "freeform" + ], + "techniques": [ + "overlap-transparency", + "geometric-construction", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "layered" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "flowxo.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "overlapping X and ring O", + "geometry": [ + "circle" + ], + "techniques": [ + "overlap-transparency", + "color-segments" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "fresh", + "connected" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "floydhub.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "monoline double-stroke F in ring", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "technical" + ], + "industry": "ai-ml", + "exemplary": false, + "note": "" + }, + { + "file": "flutter.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "layered blue bars forming chevron", + "geometry": [ + "triangle", + "freeform" + ], + "techniques": [ + "overlap-transparency", + "dimensional-shading", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "modern" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Few angled bars suggest F and motion; clean layered geometry." + }, + { + "file": "flux.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "green open infinity loop crossing", + "geometry": [ + "organic" + ], + "techniques": [ + "infinity-loop", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "fluid", + "light" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "fluxxor.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "flux capacitor in framed panel with name", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "hidden-meaning", + "line-monoline" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "retro", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "fly.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "gradient hot-air balloon with drop", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "light", + "uplifting" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "fomo.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "peach script name", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "script", + "case": "titlecase", + "mood": [ + "friendly", + "casual" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "font-awesome.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "white flag in blue rounded square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "simple" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "forestadmin-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "italic F on four-tone red square", + "geometry": [ + "square", + "grid-modular" + ], + "techniques": [ + "color-segments", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "structured" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "forestadmin.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "italic F on red quadrants", + "geometry": [ + "square" + ], + "techniques": [ + "color-segments", + "containment" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "professional", + "clean" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "forever.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "heavy black infinity symbol", + "geometry": [ + "organic" + ], + "techniques": [ + "infinity-loop" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "simple" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "formkeep.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "castle tower in dark hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "secure", + "solid" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "fortran.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "serif F in purple square", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "classic", + "academic" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "foundation.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "fluffy yeti wearing glasses", + "geometry": [ + "freeform" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "quirky" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "framer.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "F-like shape from triangles and squares", + "geometry": [ + "square", + "triangle", + "grid-modular" + ], + "techniques": [ + "geometric-construction", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "minimal" + ], + "industry": "design-creative", + "exemplary": true, + "note": "Squares and triangles tessellate into an F; rigorous modular geometry." + }, + { + "file": "framework7-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "numeral 7 cut into red disc", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "dynamic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "framework7.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "name overlapping red 7 disc", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "bold", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "freebsd.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red orb with devil horns", + "geometry": [ + "circle" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "mischievous", + "bold" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "freedcamp-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "tree built from modular rounded nodes", + "geometry": [ + "grid-modular", + "organic" + ], + "techniques": [ + "modular-repetition", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "organic", + "connected" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "freedcamp.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "modular node tree beside name", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": "script", + "case": "lowercase", + "mood": [ + "friendly", + "organic" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "freedomdefined.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "concentric rainbow rings target", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "color-segments", + "gradient", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "open" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "frontapp.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "navy F with pink gradient dot", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "overlap-transparency", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "bold" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "fsharp.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "split diamond chevrons in blues", + "geometry": [ + "diamond" + ], + "techniques": [ + "bracket-code", + "negative-space", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "sharp", + "technical" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "fuchsia.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "pink monoline ring with loop tail", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "fluid" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "galliumos.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "square of blue triangles with white dot", + "geometry": [ + "square", + "triangle" + ], + "techniques": [ + "color-segments", + "radial-symmetry", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "structured" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "game-analytics-icon.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "GA with barless A in black disc", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "modern" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "game-analytics.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "reversed white name with color squares", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "clean", + "modern" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "White-only artwork; unusable on light backgrounds." + }, + { + "file": "ganache-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "caramel cube dripping over chocolate", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "sweet", + "warm" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "ganache.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "dripping caramel cube above script name", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d" + ], + "type_style": "script", + "case": "titlecase", + "mood": [ + "sweet", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "gatsby.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "G with diagonal cut in purple disc", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "confident" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Letter G built from circle and diagonal negative-space cut." + }, + { + "file": "geekbot.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "robot head with glasses smiling", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "playful" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "getyourguide.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "stacked name with notched custom letters", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "energetic" + ], + "industry": "travel-transport", + "exemplary": false, + "note": "" + }, + { + "file": "ghost.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "stacked dashed horizontal lines", + "geometry": [], + "techniques": [ + "modular-repetition" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "minimal", + "calm" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "giantswarm.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "ant head with terminal-prompt eyes", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient", + "hidden-meaning", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "technical" + ], + "industry": "cloud-infrastructure", + "exemplary": true, + "note": "Terminal glyphs as eyes merge character with developer meaning." + }, + { + "file": "git-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "branch graph nodes in rotated square", + "geometry": [ + "diamond", + "rounded-square" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Single memorable idea: version branch diagram in simple diamond." + }, + { + "file": "git.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "branch graph in rotated square", + "geometry": [ + "diamond" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "technical", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "gitboard.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "monoline G in circle with orange quadrant", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "geometric-construction", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "modern" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "github-actions.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "workflow diagram of connected play and check circles", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "clean" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "github-copilot.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "face with goggles and headphones", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "playful" + ], + "industry": "ai-ml", + "exemplary": false, + "note": "" + }, + { + "file": "github-icon.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "octocat silhouette in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "iconic", + "bold" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Strong silhouette carved by negative space inside a circle." + }, + { + "file": "github-octocat.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "octopus-cat character on puddle", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "github.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold camel-case name", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "mixed", + "mood": [ + "bold", + "confident" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "gitkraken.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "kraken squid inside circular arcs", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "mirror-symmetry", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "gitlab.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "geometric tanuki head from triangles", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "geometric-construction", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "warm" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Animal head built purely from faceted triangles." + }, + { + "file": "gitter.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "vertical bars in magenta square", + "geometry": [ + "square" + ], + "techniques": [ + "gradient", + "containment", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "bold" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "gitup.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "faint concentric circles on tilted tiles", + "geometry": [ + "circle", + "rounded-square" + ], + "techniques": [ + "radial-symmetry", + "stacked-layers" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "soft" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Very low contrast; weak at small sizes." + }, + { + "file": "glamorous.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "script g beside lipstick", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency" + ], + "type_style": "serif", + "case": "lowercase", + "mood": [ + "glamorous", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "gleam.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "multicolor triangular pinwheel star", + "geometry": [ + "radial", + "triangle" + ], + "techniques": [ + "color-segments", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "playful" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "glimmerjs.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "diagonal rounded dashes in orange circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "warm" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "glint.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with bracket-shaped T", + "geometry": [], + "techniques": [ + "gradient", + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "modern", + "fresh" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "glitch-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "two stacked gradient fish", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "vibrant" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "glitch.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "two stacked gradient fish", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient", + "modular-repetition" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "playful", + "vibrant" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "gnome-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "footprint whose sole forms a G", + "geometry": [ + "organic" + ], + "techniques": [ + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "bold" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Footprint doubles as letter G; clever dual reading." + }, + { + "file": "gnome.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "footprint forming letter G", + "geometry": [ + "organic" + ], + "techniques": [ + "hidden-meaning" + ], + "type_style": "humanist-sans", + "case": "uppercase", + "mood": [ + "friendly", + "bold" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "gnu-net.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "gnu horns drawn as network graph", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline", + "hidden-meaning" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "technical", + "light" + ], + "industry": "open-source-community", + "exemplary": true, + "note": "Network graph drawn as gnu horns merges subject and name." + }, + { + "file": "gnu.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "illustrated gnu head", + "geometry": [ + "organic" + ], + "techniques": [ + "hand-drawn" + ], + "type_style": null, + "case": null, + "mood": [ + "quirky", + "classic" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "go.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "italic GO with speed lines", + "geometry": [], + "techniques": [ + "motion-lines" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "fast", + "bold" + ], + "industry": "programming-language", + "exemplary": true, + "note": "Italic custom letters plus speed lines express speed with minimal means." + }, + { + "file": "gocd.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "play arrow chevron", + "geometry": [ + "triangle" + ], + "techniques": [ + "arrow" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "gohorse.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "sketched horse head in circle with text", + "geometry": [ + "circle" + ], + "techniques": [ + "hand-drawn", + "containment" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "humorous", + "rough" + ], + "industry": "other", + "exemplary": false, + "note": "Hand-drawn sketch; poor reproduction, joke branding." + }, + { + "file": "google-360suite.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two overlapping gradient rings", + "geometry": [ + "circle" + ], + "techniques": [ + "overlap-transparency", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "vibrant" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "google-admob.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "lowercase a from arc and dot", + "geometry": [ + "circle" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "vibrant" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "google-ads.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter A from rounded bars and dot", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "vibrant" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "google-adsense.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two slanted rounded bars with dot", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "vibrant" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "google-analytics.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "rising rounded bar chart with dot", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "color-segments", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "clear", + "warm" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "google-calendar.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "calendar page showing 31", + "geometry": [ + "square" + ], + "techniques": [ + "color-segments", + "containment" + ], + "type_style": "geometric-sans", + "case": null, + "mood": [ + "friendly", + "clear" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "google-cloud-functions.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "code brackets with dots in hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "bracket-code", + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "clean" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "google-cloud-run.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "forward chevrons in hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "arrow", + "motion-lines", + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "fast" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "google-cloud.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "multicolor cloud outline", + "geometry": [ + "organic" + ], + "techniques": [ + "color-segments", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "vibrant" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "google-currents.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "interlocking zigzag M shape", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "modern" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "google-data-studio.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three toggle-like bars with dots", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "technical" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "google-developers.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "angle brackets from colored bars", + "geometry": [ + "freeform" + ], + "techniques": [ + "bracket-code", + "color-segments", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "google-drive.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "triangle of three colored bands", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "vibrant" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "google-fit.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "heart from interlocking colored strokes", + "geometry": [ + "organic" + ], + "techniques": [ + "color-segments", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "healthy", + "vibrant" + ], + "industry": "health", + "exemplary": false, + "note": "" + }, + { + "file": "google-gmail.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "M shaped as envelope", + "geometry": [ + "square" + ], + "techniques": [ + "color-segments", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "vibrant" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "google-gsuite.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "product name in sans", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "neutral", + "clean" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "google-home.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "multicolor house outline", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "warm" + ], + "industry": "hardware-devices", + "exemplary": false, + "note": "" + }, + { + "file": "google-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "four-color G", + "geometry": [ + "circle" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "iconic", + "friendly" + ], + "industry": "other", + "exemplary": true, + "note": "Geometric G with clean color segmentation; scales well." + }, + { + "file": "google-keep.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "lightbulb on folded page", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "bright" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "google-maps.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "map pin in color segments", + "geometry": [ + "organic" + ], + "techniques": [ + "color-segments", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "vibrant" + ], + "industry": "travel-transport", + "exemplary": false, + "note": "" + }, + { + "file": "google-marketing-platform.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "ring of colored segments", + "geometry": [ + "circle" + ], + "techniques": [ + "color-segments", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "vibrant" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "google-meet.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "video camera from colored blocks", + "geometry": [ + "square" + ], + "techniques": [ + "color-segments", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "clean" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "google-one.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "numeral 1 from colored strokes", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "friendly" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "google-optimize.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "purple bent bar segments", + "geometry": [ + "freeform" + ], + "techniques": [ + "stacked-layers" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "playful" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "google-pay-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "interlocking colored rounded bars", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "vibrant" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "google-pay.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "interlocking colored rounded bars", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "friendly", + "clean" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "google-photos.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "pinwheel of four half-circles", + "geometry": [ + "radial", + "circle" + ], + "techniques": [ + "radial-symmetry", + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "vibrant" + ], + "industry": "media-entertainment", + "exemplary": true, + "note": "Pinwheel from four identical half-circles; pure geometric construction." + }, + { + "file": "google-play-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "play triangle in color segments", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "dynamic" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "google-play.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "play triangle in color segments", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "arrow" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "vibrant", + "friendly" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "google-tag-manager.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "diamond tag outline", + "geometry": [ + "diamond" + ], + "techniques": [ + "negative-space", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "clean" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "google.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "multicolor name in geometric sans", + "geometry": [], + "techniques": [ + "color-segments" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "friendly", + "playful" + ], + "industry": "other", + "exemplary": false, + "note": "" + }, + { + "file": "gopher.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "cartoon gopher with big eyes", + "geometry": [ + "organic" + ], + "techniques": [ + "hand-drawn" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "gradle.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "elephant silhouette", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "calm" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "grafana.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "spiral inside flame-like cog", + "geometry": [ + "radial", + "organic" + ], + "techniques": [ + "gradient", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "warm" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "grails.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "grail chalice in circle with name", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "warm", + "classic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "graphene.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "extruded isometric letter G", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "graphql.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "node hexagon with inscribed triangle", + "geometry": [ + "hexagon", + "triangle" + ], + "techniques": [ + "line-monoline", + "radial-symmetry", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "precise" + ], + "industry": "programming-language", + "exemplary": true, + "note": "Graph nodes and edges as perfect geometric construction." + }, + { + "file": "grav.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "floating astronaut in black circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "adventurous" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "gravatar.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "G like power-button symbol", + "geometry": [ + "circle" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "graylog-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "waveform inside red ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "alert" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "graylog.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "two-tone name with waveform accent", + "geometry": [], + "techniques": [ + "color-segments", + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "technical", + "modern" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "gridsome-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "open G ring with dot", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "gridsome.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "open G ring with dot", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "fresh", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "grommet.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "purple ring", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "simple" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "groovehq.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with smile-shaped g descender", + "geometry": [], + "techniques": [ + "hidden-meaning" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "grove.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "green peaks in speech bubble", + "geometry": [ + "circle" + ], + "techniques": [ + "speech-bubble", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "natural", + "calm" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "grpc.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "light name with arrow accent on g", + "geometry": [], + "techniques": [ + "arrow" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "technical", + "light" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "grunt.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "angry boar face", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "aggressive", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "gulp.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "red cup with straw and script name", + "geometry": [ + "freeform" + ], + "techniques": [ + "containment" + ], + "type_style": "script", + "case": "titlecase", + "mood": [ + "playful", + "retro" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "gunicorn.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "green unicorn silhouette", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "playful", + "simple" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "gusto.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "G with arrow in sketchy circles", + "geometry": [ + "circle" + ], + "techniques": [ + "hand-drawn", + "arrow", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "energetic" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "gwt.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "red code bracket shapes", + "geometry": [ + "freeform" + ], + "techniques": [ + "bracket-code", + "geometric-construction" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "bold", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "hack.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "slanted gray and orange parallelograms", + "geometry": [ + "triangle" + ], + "techniques": [ + "geometric-construction", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "sharp" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "hacker-one.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "split h whose shoulder forms 1", + "geometry": [ + "freeform" + ], + "techniques": [ + "hidden-meaning", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "minimal" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "haiku-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "folded gradient letter H", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "creative" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "haml.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "wooden slingshot", + "geometry": [ + "organic" + ], + "techniques": [ + "hand-drawn" + ], + "type_style": null, + "case": null, + "mood": [ + "quirky", + "rustic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "hanami.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "layered pentagons with gem in circle", + "geometry": [ + "freeform", + "circle" + ], + "techniques": [ + "stacked-layers", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "handlebars.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "handlebar mustache", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "witty", + "simple" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Direct visual pun on the name; single memorable shape." + }, + { + "file": "hapi.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "curved node link over wordmark", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "friendly", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "hardhat-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "yellow hard hat with ether diamond", + "geometry": [ + "organic" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "sturdy", + "bright" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "hardhat.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "yellow hard hat with ether diamond", + "geometry": [ + "organic" + ], + "techniques": [ + "containment" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "sturdy", + "bright" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "hashnode-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "rounded diamond with circular hole", + "geometry": [ + "diamond", + "circle" + ], + "techniques": [ + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "modern" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "hashnode.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "rounded diamond with circular hole", + "geometry": [ + "diamond" + ], + "techniques": [ + "negative-space" + ], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "modern", + "clean" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "haskell-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "chevron, lambda and equals operator", + "geometry": [ + "triangle" + ], + "techniques": [ + "hidden-meaning", + "geometric-construction", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "precise" + ], + "industry": "programming-language", + "exemplary": true, + "note": "Encodes the bind operator and lambda in one geometric mark." + }, + { + "file": "haskell.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "chevron, lambda and equals operator", + "geometry": [ + "triangle" + ], + "techniques": [ + "hidden-meaning", + "geometric-construction" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "technical", + "bold" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "hasura.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "horned circle with lambda", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "playful" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "haxe.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "faceted square of orange triangles", + "geometry": [ + "square", + "triangle" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "warm" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "haxl.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "X merged with lambda from slanted bars", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "hbase.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "orca whale", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "strong", + "dynamic" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "headlessui-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "tilted panel inside rounded square frame", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "fresh" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "headlessui.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "tilted panel inside rounded square frame", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "gradient", + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "clean" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "heap.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "hexagon outline with notched segment", + "geometry": [ + "hexagon" + ], + "techniques": [ + "gradient", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "vibrant" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "helm.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "ship wheel around name", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "nautical" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "helpscout-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two pairs of slanted rounded bars", + "geometry": [ + "freeform" + ], + "techniques": [ + "modular-repetition", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "dynamic" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "helpscout.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "two pairs of slanted rounded bars", + "geometry": [ + "freeform" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "friendly", + "clean" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "hermes.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "winged letter H", + "geometry": [ + "freeform" + ], + "techniques": [ + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "heroku-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "stylized h in rounded square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "calm" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "heroku-redis.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "R with solid keyhole half", + "geometry": [ + "freeform" + ], + "techniques": [ + "negative-space", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "heroku.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "stylized h in rounded square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "calm" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "hexo.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "letter H in hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "solid" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "hhvm.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "slanted gray and orange parallelograms", + "geometry": [ + "triangle" + ], + "techniques": [ + "geometric-construction", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "sharp" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "hibernate.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "hexagonal ring of shaded parallelograms", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "negative-space", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "highcharts.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "overlapping translucent triangles", + "geometry": [ + "triangle" + ], + "techniques": [ + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "light" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "hipercard.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "italic name in red slanted box", + "geometry": [ + "freeform" + ], + "techniques": [ + "containment" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "dynamic", + "bold" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "hoa.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "HOA from modular bracket blocks", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "color-segments" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "technical", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "homebrew.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "beer mug with apple-stem foam", + "geometry": [ + "organic" + ], + "techniques": [ + "hand-drawn", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "warm" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "hoodie.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "overlapping outlined letters", + "geometry": [], + "techniques": [ + "line-monoline", + "overlap-transparency" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "playful", + "light" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "hosted-graphite.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "H cut from orange hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "hostgator-icon.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "grinning blue alligator", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "hostgator.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "grinning blue alligator", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "grotesque-sans", + "case": "mixed", + "mood": [ + "playful", + "bold" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "hotjar.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold name with flame accent", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "bold", + "warm" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "houndci.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "dog head profile cut into square", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "clever", + "calm" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Dog profile formed purely by negative space in square." + }, + { + "file": "html-5.svg", + "mark_type": "combination", + "symbol_type": "emblem", + "subject": "shield with numeral 5 under name", + "geometry": [ + "shield" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "bold", + "official" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "html5-boilerplate.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "extruded orange star in dark square", + "geometry": [ + "star", + "square" + ], + "techniques": [ + "dimensional-shading", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "retro" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "httpie-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "black organic blob pair", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "bold", + "quirky" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "httpie.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "black organic blob pair", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "bold", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "hubspot.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with sprocket replacing o", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "humanist-sans", + "case": "mixed", + "mood": [ + "friendly", + "approachable" + ], + "industry": "marketing-analytics", + "exemplary": true, + "note": "Textbook letter substitution: sprocket node graph as the o." + }, + { + "file": "huggy.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "dashed pink speed lines", + "geometry": [], + "techniques": [ + "motion-lines" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "energetic", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "hugo.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "letters in colored hexagon badges", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "modular-repetition", + "color-segments" + ], + "type_style": "rounded-sans", + "case": "uppercase", + "mood": [ + "playful", + "vibrant" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "humongous.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "offset heavy letter H", + "geometry": [ + "freeform" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "bold", + "quirky" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "hyper.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "terminal window with bolt prompt", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "gradient", + "containment", + "bracket-code" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "vibrant" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "hyperapp.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "plus and backslash glyphs", + "geometry": [], + "techniques": [ + "bracket-code" + ], + "type_style": "monospace", + "case": "lowercase", + "mood": [ + "technical", + "minimal" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "ibm.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "striped IBM letters", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "motion-lines" + ], + "type_style": "slab", + "case": "uppercase", + "mood": [ + "corporate", + "iconic" + ], + "industry": "hardware-devices", + "exemplary": true, + "note": "Horizontal stripes unify heavy slab letters; timeless lettermark." + }, + { + "file": "ieee.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "diamond with kite arrow emblem", + "geometry": [ + "diamond" + ], + "techniques": [ + "containment", + "arrow" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "official", + "serious" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "ifttt.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy stencil-like name", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "bold", + "utilitarian" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "imagemin.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "landscape photo with compress arrows in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "imba-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "swooping cyan wing arrow", + "geometry": [ + "organic" + ], + "techniques": [ + "arrow", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "fresh" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "imba.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "swooping cyan wing arrow", + "geometry": [ + "organic" + ], + "techniques": [ + "arrow" + ], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "fast", + "bold" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "immer-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "infinity loop with dots", + "geometry": [ + "organic" + ], + "techniques": [ + "infinity-loop", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "simple" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "immer.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "infinity loop with dots", + "geometry": [ + "organic" + ], + "techniques": [ + "infinity-loop", + "mirror-symmetry" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "fresh", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "immutable.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with offset inline shadow", + "geometry": [], + "techniques": [ + "stacked-layers" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "retro", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "impala.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "pair of curved antelope horns", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "elegant", + "dynamic" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "importio.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name in bold display letters", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "technical", + "playful" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "infer.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "logic turnstile in purple circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "inferno.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "flame inside dark ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "fiery", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "influxdb.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "polyhedron outline in rounded hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "line-monoline", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "solid" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "ink.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "overlapping multicolor faceted cubes", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "creative" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "insomnia.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "eclipse-like circle in purple ring", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "nocturnal" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "instagram-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "camera outline glyph", + "geometry": [ + "rounded-square", + "circle" + ], + "techniques": [ + "line-monoline", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "friendly" + ], + "industry": "social-communication", + "exemplary": true, + "note": "Camera reduced to three primitives; strong monoline glyph." + }, + { + "file": "instagram.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "handwritten script name", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "script", + "case": "titlecase", + "mood": [ + "casual", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "intellij-idea.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "IJ in black square over gradient shards", + "geometry": [ + "square" + ], + "techniques": [ + "gradient", + "overlap-transparency", + "containment" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "technical", + "vibrant" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "intercom-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "vertical bars forming smiling face", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "hidden-meaning", + "containment", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "simple" + ], + "industry": "social-communication", + "exemplary": true, + "note": "Plain bars read as a smiling face; simple dual meaning." + }, + { + "file": "intercom.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "vertical bars forming smiling face", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "hidden-meaning", + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "friendly", + "clean" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "internetexplorer.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "lowercase e with orbit swoosh", + "geometry": [ + "circle" + ], + "techniques": [ + "overlap-transparency", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "familiar" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "invision-icon.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "script in lettering in pink square", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "bold", + "creative" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "invision.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "boxed in plus uppercase vision", + "geometry": [], + "techniques": [ + "containment" + ], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "bold", + "creative" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "ionic-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "dot in ring with satellite dot", + "geometry": [ + "circle" + ], + "techniques": [ + "geometric-construction", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "ionic.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "dot in ring with satellite dot", + "geometry": [ + "circle" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "clean", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "ios.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "camel-case OS name", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "mixed", + "mood": [ + "clean", + "neutral" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "iron-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "I-beam letter in hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "industrial" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "iron.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "I-beam letter in hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "solid", + "industrial" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "itsalive-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "speech bubble with lightning bolt", + "geometry": [ + "circle" + ], + "techniques": [ + "speech-bubble", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "itsalive.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "speech bubble with lightning bolt", + "geometry": [ + "circle" + ], + "techniques": [ + "speech-bubble" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "energetic", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "jade.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "rabbit in rough stamp with name", + "geometry": [ + "square" + ], + "techniques": [ + "hand-drawn", + "negative-space", + "containment" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "rustic", + "traditional" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "jamstack-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "drop-shaped circle with quadrant grid", + "geometry": [ + "circle", + "grid-modular" + ], + "techniques": [ + "geometric-construction", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "jamstack.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "drop-shaped circle with quadrant grid", + "geometry": [ + "circle" + ], + "techniques": [ + "geometric-construction", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "clean" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "White wordmark invisible on light backgrounds." + }, + { + "file": "jasmine.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "radial burst in purple ring", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "java.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "steaming coffee cup", + "geometry": [ + "organic" + ], + "techniques": [ + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "classic" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "javascript.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "JS in yellow square", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "simple" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "jcb.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "JCB on three colored panels", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "color-segments", + "gradient", + "containment" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "corporate", + "bold" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "jekyll.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "script name with test tube l", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "script", + "case": "lowercase", + "mood": [ + "elegant", + "quirky" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "jelastic-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric folded shape with diamond hole", + "geometry": [ + "diamond" + ], + "techniques": [ + "isometric-3d", + "negative-space", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "modern" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "jelastic.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "isometric folded shape with diamond hole", + "geometry": [ + "diamond" + ], + "techniques": [ + "isometric-3d", + "gradient" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "technical", + "modern" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "jenkins.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "butler with bow tie in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "classic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "jest.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "jester boot with bells", + "geometry": [ + "triangle" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "quirky" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "jetbrains.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "name in black square on gradient", + "geometry": [ + "square" + ], + "techniques": [ + "gradient", + "containment", + "overlap-transparency" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "technical", + "vibrant" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "jfrog.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "splash forming frog above name", + "geometry": [ + "organic" + ], + "techniques": [ + "hidden-meaning" + ], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "lively", + "fresh" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "jhipster-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "blue bow tie", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "stylish", + "simple" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "jhipster.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "blue bow tie", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": "script", + "case": "mixed", + "mood": [ + "stylish", + "quirky" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "jira.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "stacked gradient chevron corners", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "stacked-layers", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "modern" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "joomla.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "four interlocking colored hooks", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry", + "color-segments", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "connected" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "jquery-mobile.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "overlapping translucent slanted panels", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "light" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "jquery.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "nested swirl arcs", + "geometry": [ + "organic" + ], + "techniques": [ + "motion-lines" + ], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "dynamic", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "jruby.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red cardinal bird", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "lively", + "bold" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "jsbin.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "robot trash can with eyes", + "geometry": [ + "freeform" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "quirky" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "jsdelivr.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "shield with network globe", + "geometry": [ + "shield" + ], + "techniques": [ + "dimensional-shading", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "jsdom.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "branching tree in yellow hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "jsfiddle.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cloud with infinity loop", + "geometry": [ + "organic" + ], + "techniques": [ + "infinity-loop", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "calm" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "json.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "shaded interlocking rings in black square", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "gradient", + "overlap-transparency", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "mysterious" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "jspm.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "isometric gray and yellow cube", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "jss.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "JSS over yellow square", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "overlap-transparency" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "bold", + "simple" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "juju.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "looping line with nodes in orange circle", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "warm" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "julia.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with three colored dots", + "geometry": [], + "techniques": [ + "letter-substitution", + "color-segments" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "friendly", + "academic" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "jupyter.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "name between orange orbit arcs with moons", + "geometry": [ + "circle" + ], + "techniques": [ + "hidden-meaning", + "containment" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "academic", + "warm" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Orbit arcs and moons evoke Jupiter while framing the name." + }, + { + "file": "jwt-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "radial burst of colored shards", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "technical" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "jwt.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "radial burst of colored shards", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry", + "color-segments" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "technical", + "light" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "kafka-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "linked circle nodes", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "kafka.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "linked circle nodes", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "technical", + "clean" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "kaios.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with custom split K", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "friendly", + "modern" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "kallithea.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "branching lines ending in circles", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "organic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "karma.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "K with lightning zigzag", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "fresh" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "kde.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "K with gear in blue square", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "containment", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "friendly" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "keen.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "overlapping outlined triangles", + "geometry": [ + "triangle" + ], + "techniques": [ + "line-monoline", + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "light", + "modern" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "kemal.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red two-tone fez hat", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "cultural" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "keycdn-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "keyhole in ring with network nodes", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "secure" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "keycdn.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "keyhole in ring with network nodes", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "technical", + "fast" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "keystonejs.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white K in gradient rounded square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "clean" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "khan_academy-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "sprout doubling as person in hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "negative-space", + "hidden-meaning", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "hopeful", + "friendly" + ], + "industry": "education", + "exemplary": true, + "note": "Leaf sprout reads as a person; negative space dual image." + }, + { + "file": "khan_academy.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "sprout doubling as person in hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "negative-space", + "hidden-meaning" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "friendly", + "trustworthy" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "kibana.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "K from colored triangle and arc", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "vibrant" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "kickstarter-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "rounded blobby letter K", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "bold" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "kickstarter.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy rounded uppercase name", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "playful" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "kinto-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "gradient cloud with speed trail", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "fast" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "kinto.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "gradient cloud with speed trail", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient", + "motion-lines" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "warm", + "friendly" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "kirby-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "abstract K in hexagon outline", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "line-monoline", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "solid" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "kirby.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "abstract K in hexagon outline", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "minimal", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "kissmetrics.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "heart containing bar chart", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space", + "hidden-meaning", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "clear" + ], + "industry": "marketing-analytics", + "exemplary": true, + "note": "Merges heart and bar chart into one simple silhouette." + }, + { + "file": "kitematic.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "blocky K in blue rounded square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "kloudless.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "multicolor sunburst with center ring", + "geometry": [ + "radial", + "star" + ], + "techniques": [ + "radial-symmetry", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "energetic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "knex.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange snowflake-like gear burst", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "knockout.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "red script name with underline", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "script", + "case": "titlecase", + "mood": [ + "retro", + "energetic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "koa.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "thin high-contrast serif name", + "geometry": [], + "techniques": [], + "type_style": "serif", + "case": "lowercase", + "mood": [ + "elegant", + "minimal" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "kong-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "geometric gorilla from angular shapes", + "geometry": [ + "triangle", + "freeform" + ], + "techniques": [ + "geometric-construction", + "color-segments", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "strong", + "modern" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "kong.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "geometric gorilla from angular shapes", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "strong", + "modern" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "kops.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "ship wheel with circular arrow", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "arrow" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "technical", + "nautical" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "koreio.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "hexagon of translucent colored cubes", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "overlap-transparency", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "colorful" + ], + "industry": "other", + "exemplary": false, + "note": "" + }, + { + "file": "kotlin-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "gradient square with triangular notch K", + "geometry": [ + "square", + "triangle" + ], + "techniques": [ + "gradient", + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "bold" + ], + "industry": "programming-language", + "exemplary": true, + "note": "K implied by one triangular cut; extreme geometric economy." + }, + { + "file": "kotlin.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "gradient square with triangular notch K", + "geometry": [ + "square", + "triangle" + ], + "techniques": [ + "gradient", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "modern", + "clean" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "kraken.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "hexagon of multicolor triangular facets", + "geometry": [ + "hexagon", + "triangle" + ], + "techniques": [ + "color-segments", + "geometric-construction", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "krakenjs.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "white kraken in blue hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "negative-space", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "kubernetes.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "ship wheel in blue heptagon", + "geometry": [ + "radial", + "freeform" + ], + "techniques": [ + "radial-symmetry", + "containment", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "iconic" + ], + "industry": "cloud-infrastructure", + "exemplary": true, + "note": "Helm metaphor for orchestration; clean radial construction." + }, + { + "file": "kustomer.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with chat face replacing O", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "laravel.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "isometric outlined cubes forming L", + "geometry": [ + "square" + ], + "techniques": [ + "isometric-3d", + "line-monoline", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Monoline isometric construction builds letter L from cubes." + }, + { + "file": "lastfm.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "custom name with rounded a", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "bold", + "friendly" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "lateral.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "faceted crystal on blue grid square", + "geometry": [ + "square", + "triangle" + ], + "techniques": [ + "dimensional-shading", + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "cool" + ], + "industry": "ai-ml", + "exemplary": false, + "note": "" + }, + { + "file": "launchrock.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "rock-on hand gesture", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "rebellious" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "leaflet.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "green leaf", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "script", + "case": "titlecase", + "mood": [ + "natural", + "light" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "leankit-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "play triangle cut from gray hexagon", + "geometry": [ + "hexagon", + "triangle" + ], + "techniques": [ + "negative-space", + "arrow", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "technical" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "leankit.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "play triangle cut from gray hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "negative-space", + "arrow" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "calm", + "corporate" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "lerna.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "engraved three-headed hydra", + "geometry": [ + "organic" + ], + "techniques": [ + "hand-drawn" + ], + "type_style": "serif", + "case": "titlecase", + "mood": [ + "classic", + "mythic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Detailed engraving fails at small sizes." + }, + { + "file": "less.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "name in curly braces on dark block", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "bracket-code", + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "technical" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "lets-cloud.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "cloud formed of horizontal speed lines", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline", + "motion-lines" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "light", + "techy" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "letsencrypt.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "padlock with rising sun rays", + "geometry": [ + "square" + ], + "techniques": [ + "hidden-meaning" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "trustworthy", + "friendly", + "optimistic" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "leveldb.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "stacked translucent green isometric layers", + "geometry": [ + "diamond" + ], + "techniques": [ + "isometric-3d", + "stacked-layers", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "layered", + "natural" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "liftweb.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "folded ribbon forming upward arrow", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "arrow", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "uplifting" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "lighthouse.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "lighthouse with clouds in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "playful" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "lightstep-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "wireframe polyhedron lens with green dot", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "precise" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "lightstep.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "wireframe polyhedron lens with green dot", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline", + "isometric-3d" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "technical", + "modern" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "lighttpd.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "paper plane", + "geometry": [ + "triangle" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "light", + "fast" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "linkedin-icon.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "lowercase in inside blue rounded square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "professional", + "trustworthy" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "linkedin.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "Linked with boxed in", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "professional", + "confident" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "linkerd.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric striped block with hidden L forms", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "isometric-3d", + "gradient", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "fresh" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "linode.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "stacked green isometric cubes", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "isometric-3d", + "modular-repetition", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "linux-mint.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "lm letters inside tabbed rounded frame", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "line-monoline", + "gradient" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "fresh", + "friendly" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "linux-tux.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "sitting penguin Tux", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "playful" + ], + "industry": "os-platform", + "exemplary": false, + "note": "Iconic mascot but too detailed and shaded for small sizes." + }, + { + "file": "lit-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "angular flame from stacked parallelograms", + "geometry": [ + "triangle" + ], + "techniques": [ + "overlap-transparency", + "color-segments", + "geometric-construction", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "modern" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Flame built from overlapping geometric facets; clever 'lit' pun." + }, + { + "file": "lit.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "angular faceted flame", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "color-segments", + "geometric-construction" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "modern", + "energetic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "litmus.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "ring of color segments like color wheel", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "analytical" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "loader.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "kettlebell with L cut into it", + "geometry": [ + "triangle" + ], + "techniques": [ + "negative-space", + "hidden-meaning", + "letter-substitution" + ], + "type_style": null, + "case": null, + "mood": [ + "strong", + "clever" + ], + "industry": "testing-monitoring", + "exemplary": true, + "note": "Kettlebell weight equals load testing; L carved in negative space." + }, + { + "file": "lodash.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "Lo letters over blue underline bar", + "geometry": [], + "techniques": [ + "geometric-construction" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "minimal", + "clean" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "logentries.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "L from connected nodes with gear", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "logstash.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "geometric L from half-round and square", + "geometry": [ + "square" + ], + "techniques": [ + "geometric-construction", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "database-data", + "exemplary": true, + "note": "Letter L composed from simple colored geometric primitives." + }, + { + "file": "lookback.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "red looping ribbon with central arrow", + "geometry": [ + "organic" + ], + "techniques": [ + "infinity-loop", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "bold" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "looker-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "chain of connected circles in Google colors", + "geometry": [ + "circle" + ], + "techniques": [ + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "connected" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "looker.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "chain of connected colorful circles", + "geometry": [ + "circle" + ], + "techniques": [ + "color-segments" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "friendly", + "modern" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "loom.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "radiating asterisk burst", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "energetic", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "loopback-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "interlocking isometric loops in hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "containment", + "impossible-figure" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "structured" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "loopback.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "interlocking isometric loops", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "technical", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "losant.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two interlinked outline diamonds", + "geometry": [ + "diamond" + ], + "techniques": [ + "overlap-transparency", + "line-monoline", + "infinity-loop" + ], + "type_style": null, + "case": null, + "mood": [ + "connected", + "technical" + ], + "industry": "hardware-devices", + "exemplary": false, + "note": "" + }, + { + "file": "lua.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "moon orbiting planet with Lua text", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "hidden-meaning", + "containment" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "calm", + "clever" + ], + "industry": "programming-language", + "exemplary": true, + "note": "Lua means moon; orbit and crescent cut conveyed simply." + }, + { + "file": "lucene.net.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "swirling blue ribbon loop", + "geometry": [ + "organic" + ], + "techniques": [ + "infinity-loop", + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "fluid", + "dynamic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "lucene.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "italic custom lettering with speed wing", + "geometry": [], + "techniques": [ + "motion-lines" + ], + "type_style": "display-custom", + "case": "titlecase", + "mood": [ + "retro", + "quirky" + ], + "industry": "framework-library", + "exemplary": false, + "note": "Dated retro lettering; hard to read at small sizes." + }, + { + "file": "lumen.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "diagonal red stripes forming a lamp", + "geometry": [ + "freeform" + ], + "techniques": [ + "modular-repetition", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "macOS.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "macOS set in system sans", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "mixed", + "mood": [ + "clean", + "premium" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "madge.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "M from overlapping translucent triangles", + "geometry": [ + "triangle" + ], + "techniques": [ + "overlap-transparency", + "geometric-construction" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "mystical", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "maestro.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "two overlapping red and blue circles", + "geometry": [ + "circle" + ], + "techniques": [ + "overlap-transparency", + "mirror-symmetry" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "trustworthy", + "simple" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "mageia.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "cauldron with rising bubbles", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "light", + "magical" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "magento.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "isometric folded M in orange circle", + "geometry": [ + "hexagon", + "circle" + ], + "techniques": [ + "isometric-3d", + "containment", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "mailchimp-freddie.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "winking chimp in mail carrier hat", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading", + "hand-drawn" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly", + "cheeky" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "mailchimp.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "MailChimp in brush script", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "script", + "case": "mixed", + "mood": [ + "playful", + "casual" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "maildeveloper.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "blocky MD letters with shadow", + "geometry": [ + "square" + ], + "techniques": [ + "geometric-construction", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "mailgun-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "at sign shaped like bullseye target", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "direct" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "@ sign merged with bullseye target; email plus precision." + }, + { + "file": "mailgun.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "at sign shaped like bullseye target", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "hidden-meaning" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "mailjet.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "paper plane with speed trail", + "geometry": [ + "triangle" + ], + "techniques": [ + "motion-lines" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "fast", + "friendly" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "malinajs.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "raspberry made of red circles", + "geometry": [ + "circle" + ], + "techniques": [ + "modular-repetition", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "fresh" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "manjaro.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "green blocks forming abstract m", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "solid" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Pure rectangles and gaps build an m; extreme reduction." + }, + { + "file": "manuscript.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "nested M shapes in blue-violet", + "geometry": [ + "square" + ], + "techniques": [ + "gradient", + "stacked-layers", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "mapbox-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "map pin blob with compass star", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "navigational" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "mapbox.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "map pin blob with compass star", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "maps-me.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "suitcase with map pattern in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "adventurous" + ], + "industry": "travel-transport", + "exemplary": false, + "note": "" + }, + { + "file": "mapzen-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "compass rose with angular frame lines", + "geometry": [ + "star", + "radial" + ], + "techniques": [ + "radial-symmetry", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "navigational" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "mapzen.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "compass rose with angular frame", + "geometry": [ + "star", + "radial" + ], + "techniques": [ + "radial-symmetry", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "technical", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "mariadb-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "sea lion silhouette", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "natural" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "mariadb.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "sea lion silhouette", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "humanist-sans", + "case": "mixed", + "mood": [ + "friendly", + "approachable" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "marionette.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "M puppet hanging from control bar", + "geometry": [ + "freeform" + ], + "techniques": [ + "hidden-meaning", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "clever" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "markdown.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "M and down arrow in rounded frame", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "arrow", + "letter-substitution" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "functional", + "minimal" + ], + "industry": "programming-language", + "exemplary": true, + "note": "M plus down-arrow spells 'markdown' with pure simplicity." + }, + { + "file": "marko.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "M from colorful chevron brackets", + "geometry": [ + "triangle" + ], + "techniques": [ + "bracket-code", + "color-segments", + "gradient" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "vibrant", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "marvel.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "marvel in brush script with swash", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "script", + "case": "lowercase", + "mood": [ + "creative", + "energetic" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "mastercard.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "overlapping red and yellow circles", + "geometry": [ + "circle" + ], + "techniques": [ + "overlap-transparency", + "mirror-symmetry" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "trustworthy", + "warm" + ], + "industry": "payments-fintech", + "exemplary": true, + "note": "Two overlapping circles: iconic, reducible, color-driven identity." + }, + { + "file": "mastodon-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "m inside rounded speech bubble", + "geometry": [ + "organic" + ], + "techniques": [ + "speech-bubble", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "social" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "mastodon.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "m inside rounded speech bubble", + "geometry": [ + "organic" + ], + "techniques": [ + "speech-bubble", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "open" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "material-ui.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "isometric blue blocks forming MU", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "isometric-3d", + "geometric-construction", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "structured", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "materializecss.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "M from folding pink ribbon", + "geometry": [ + "organic" + ], + "techniques": [ + "overlap-transparency", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "soft", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "matplotlib-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "polar bar chart inside circle", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "color-segments", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "scientific", + "analytical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "matplotlib.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "polar chart replaces o in name", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "scientific", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "mattermost-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "open ring with droplet needle inside", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "trustworthy" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "mattermost.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "open ring with droplet needle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "professional", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "maven.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "Maven with feather replacing v", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "bold", + "solid" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "maxcdn.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "maxcdn lettering in orange slanted box", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "motion-lines" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "fast", + "energetic" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "mdn.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "dinosaur head on folded map", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "informative" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "mdx.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "M arrow X in rounded frame", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "letter-substitution", + "arrow", + "containment" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "functional", + "playful" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "medium-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "circle and two ellipses in sequence", + "geometry": [ + "circle" + ], + "techniques": [ + "geometric-construction", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "editorial" + ], + "industry": "media-entertainment", + "exemplary": true, + "note": "Three pure ellipses; radical geometric reduction with rhythm." + }, + { + "file": "medium.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "circle and two ellipses", + "geometry": [ + "circle" + ], + "techniques": [ + "geometric-construction", + "modular-repetition" + ], + "type_style": "serif", + "case": "titlecase", + "mood": [ + "editorial", + "refined" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "memcached.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "teal M with red eyes in rounded tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "quirky", + "technical" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "memsql-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "purple gradient ribbon arcs", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "modern" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "memsql.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "purple gradient ribbon arcs", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "modern", + "techy" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "mention.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "white star in blue circle", + "geometry": [ + "circle", + "star" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "serif", + "case": "lowercase", + "mood": [ + "friendly", + "approachable" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "mercurial.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "glossy liquid mercury droplets", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading", + "gradient" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "fluid", + "dated" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Glossy chrome rendering; poor reduction and dated look." + }, + { + "file": "mesos.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "M assembled from cyan triangles", + "geometry": [ + "triangle", + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "geometric-construction", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "structured", + "modern" + ], + "industry": "cloud-infrastructure", + "exemplary": true, + "note": "M assembled from repeated triangles; modular construction lesson." + }, + { + "file": "metabase.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "dot grid with darker dots forming M", + "geometry": [ + "grid-modular", + "circle" + ], + "techniques": [ + "modular-repetition", + "pixel", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "analytical", + "friendly" + ], + "industry": "marketing-analytics", + "exemplary": true, + "note": "Letter M emerges from a uniform dot grid via tone only." + }, + { + "file": "metamask-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "low-poly fox head", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction", + "color-segments", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "crafty" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "metamask.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "low-poly fox head", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "techy", + "confident" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "meteor-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "diagonal meteor streaks", + "geometry": [ + "freeform" + ], + "techniques": [ + "motion-lines", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "dynamic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "meteor.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "METEOR with streaks replacing O", + "geometry": [], + "techniques": [ + "letter-substitution", + "motion-lines" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "dynamic", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "microcosm.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "blue planet with coral ring", + "geometry": [ + "circle" + ], + "techniques": [ + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "cosmic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "microsoft-azure.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "A from overlapping blue gradient shapes", + "geometry": [ + "triangle" + ], + "techniques": [ + "gradient", + "overlap-transparency", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "trustworthy" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "microsoft-edge.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "swirling wave forming e", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "fluid", + "modern" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "microsoft-onedrive.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cloud from overlapping blue lobes", + "geometry": [ + "organic" + ], + "techniques": [ + "overlap-transparency", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "soft", + "reliable" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "microsoft-power-bi.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "three rising yellow bars", + "geometry": [ + "square" + ], + "techniques": [ + "gradient", + "stacked-layers" + ], + "type_style": null, + "case": null, + "mood": [ + "analytical", + "warm" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "microsoft-teams.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "T tile with people silhouettes", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "overlap-transparency", + "dimensional-shading", + "containment" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "collaborative", + "professional" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "microsoft-windows.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "four-pane window in perspective", + "geometry": [ + "square", + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "iconic" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "microsoft.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "four colored squares in grid", + "geometry": [ + "square", + "grid-modular" + ], + "techniques": [ + "color-segments", + "modular-repetition" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "trustworthy", + "balanced" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Four colored squares; maximal simplicity with a clear system." + }, + { + "file": "middleman.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "3D boxy MM in yellow tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "dimensional-shading", + "isometric-3d" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "solid", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "milligram.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "outlined purple water drop", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "light", + "minimal" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "mint-lang.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "stylized green mint leaf", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "fresh", + "clean" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "mio.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "purple speech bubble with dots", + "geometry": [ + "square" + ], + "techniques": [ + "speech-bubble", + "dimensional-shading" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "friendly", + "conversational" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "mist.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "swirling dark wave strips in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "stacked-layers", + "motion-lines", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "mysterious", + "fluid" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "mithril.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three overlapping outlined rings", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "overlap-transparency", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "balanced" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "mixmax.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "M from pink bars and navy slants", + "geometry": [ + "square" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "mixpanel.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "thin lowercase name with three dots", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "light", + "analytical" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "mlab.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "glowing vacuum tube", + "geometry": [ + "freeform" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "technical", + "friendly" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "mobx.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "brackets and v forming M in orange tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "bracket-code", + "letter-substitution", + "containment" + ], + "type_style": "display-custom", + "case": null, + "mood": [ + "technical", + "clever" + ], + "industry": "framework-library", + "exemplary": true, + "note": "]v[ reads as M; code brackets double as letter strokes." + }, + { + "file": "mocha.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "hexagon badge with coffee cup and MOCHA", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "warm", + "crafted" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "mockflow-icon.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "MF from colored triangles", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "overlap-transparency", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "modern" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "mockflow.svg", + "mark_type": "combination", + "symbol_type": "lettermark", + "subject": "MF from colored triangles", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "modern", + "friendly" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "modernizr.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "stepped blocks beside half circle", + "geometry": [ + "square", + "circle" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "modx-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "angular colored shards forming X pinwheel", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "radial-symmetry", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "vibrant" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "modx.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "angular colored shards forming X", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "dynamic", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "moltin-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange wavy heart shape in hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "friendly" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "moltin.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "orange wavy shape in hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "gradient", + "containment" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "warm", + "friendly" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "momentjs.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "simple clock face", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "simple" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "monday-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two slanted pills and a dot", + "geometry": [], + "techniques": [ + "color-segments", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "energetic" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "monday.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "two slanted pills and a dot", + "geometry": [], + "techniques": [ + "color-segments" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "playful", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "monero.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "M cut into orange and gray circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "color-segments", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "secure" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "mongodb.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "green leaf", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient" + ], + "type_style": "serif", + "case": "mixed", + "mood": [ + "natural", + "approachable" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "mono.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "stylized monkey head in black square", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "quirky" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "moon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "gradient crescent moon", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "dreamy" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "mootools.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "lettering with wrench replacing l", + "geometry": [], + "techniques": [ + "letter-substitution", + "dimensional-shading" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "playful", + "dated" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "morpheus-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "M as pulse line splitting circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "color-segments", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "technical" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "morpheus.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "M as pulse line splitting circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "modern" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "mozilla.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "moz://a in black box", + "geometry": [ + "square" + ], + "techniques": [ + "letter-substitution", + "containment", + "hidden-meaning" + ], + "type_style": "slab", + "case": "lowercase", + "mood": [ + "bold", + "witty" + ], + "industry": "open-source-community", + "exemplary": true, + "note": "URL syntax :// substitutes letters; clever, ownable type idea." + }, + { + "file": "mparticle-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "checkered pattern of slanted black blocks", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "dynamic" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "mparticle.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "checkered slanted black blocks", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "modern" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "multipass.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "M from connected nodes in orange circle", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "friendly" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "mysql-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "outlined leaping dolphin", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "fluid", + "friendly" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "mysql.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "outlined leaping dolphin", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "humanist-sans", + "case": "mixed", + "mood": [ + "friendly", + "approachable" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "naiveui.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "N from folded green ribbon", + "geometry": [ + "freeform" + ], + "techniques": [ + "dimensional-shading", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "namecheap.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "N from orange gradient ribbon", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "friendly" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "nanonets.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "connected nodes zigzagging into N", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "connected" + ], + "industry": "ai-ml", + "exemplary": false, + "note": "" + }, + { + "file": "nativescript.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "N flanked by curly braces in tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "bracket-code", + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "nats-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "N on colored quadrants with speech tail", + "geometry": [ + "square" + ], + "techniques": [ + "color-segments", + "speech-bubble", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "communicative" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "nats.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "NATS letters in colored boxes", + "geometry": [ + "square" + ], + "techniques": [ + "color-segments", + "speech-bubble", + "containment" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "modular" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "neat.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "blue triangles forming folded shape", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "crisp" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "neo4j.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "neo4j with graph node connector", + "geometry": [], + "techniques": [ + "hidden-meaning" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "connected" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "neovim.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "N from green-blue gradient facets", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "technical", + "fresh" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "nestjs.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red cat head silhouette", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "fierce", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "netbeans.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "hand-drawn wireframe cube", + "geometry": [ + "diamond" + ], + "techniques": [ + "isometric-3d", + "line-monoline", + "hand-drawn" + ], + "type_style": null, + "case": null, + "mood": [ + "sketchy", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "netflix-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "red folded ribbon N on black", + "geometry": [ + "square" + ], + "techniques": [ + "dimensional-shading", + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "cinematic", + "bold" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "netflix.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "NETFLIX condensed with curved baseline", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "cinematic" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "netlify.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "teal diamond with network cut lines", + "geometry": [ + "diamond" + ], + "techniques": [ + "negative-space", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "connected" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "new-relic.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "New Relic text in teal oval", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "stacked-layers" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "dated", + "friendly" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "nextjs-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "N with fading extended diagonal in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "sharp" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "nextjs.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "thin NEXT with extended X stroke", + "geometry": [], + "techniques": [ + "ligature", + "geometric-construction" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "minimal", + "sharp" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Hairline custom letters with an extended X stroke; distinctive type customisation." + }, + { + "file": "nginx.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white N in green hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "reliable" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "nightwatch.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "wide-eyed owl character", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "watchful" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "nim-lang.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "yellow crown", + "geometry": [ + "freeform" + ], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "regal", + "playful" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "nocodb.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "bug-like face with circuit legs in tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "technical" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "nodal.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "isometric folded cyan N", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "node-sass.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "Sass script in green hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment" + ], + "type_style": "script", + "case": "titlecase", + "mood": [ + "stylish", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "nodebots.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "small robot face in yellow square", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "cute" + ], + "industry": "hardware-devices", + "exemplary": false, + "note": "" + }, + { + "file": "nodejs-icon.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "JS inside outlined green hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "technical", + "solid" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "nodejs.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "node with hexagon o and JS badge", + "geometry": [ + "hexagon" + ], + "techniques": [ + "letter-substitution", + "containment" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "technical", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "nodemon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "horned demon n in green hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "hidden-meaning", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "mischievous" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Two horns turn an n into a demon; one witty idea." + }, + { + "file": "nodeos.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "stacked n diamond and OS letters", + "geometry": [ + "diamond" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "bold", + "technical" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "nodewebkit.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "compass needle in dark hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "navigational" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "nomad.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "N on isometric green hexagon cube", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "noysi.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "N cut by diagonal in teal tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "npm-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white n in red square", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "containment", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "utilitarian" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "n carved from a solid square; pure negative-space simplicity." + }, + { + "file": "npm.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "blocky red npm lettering", + "geometry": [], + "techniques": [ + "geometric-construction" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "bold", + "utilitarian" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "nuclide.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "purple slabs with orbiting ellipse", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "cosmic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "numpy.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "isometric cubes forming N and P", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "isometric-3d", + "modular-repetition", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "scientific", + "structured" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "nuxt-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two green overlapping triangles", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "simple" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "nuxt.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "two green triangles like mountains", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "fresh", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "nx.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "N with curling wave x", + "geometry": [], + "techniques": [ + "ligature" + ], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "bold", + "dynamic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "oauth.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "A in circle ringed by OAUTH text", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "radial-symmetry" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "secure", + "official" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "ocaml.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "white camel in orange box", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "warm", + "quirky" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "octodns.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "octagonal network of linked rings", + "geometry": [ + "radial", + "circle" + ], + "techniques": [ + "radial-symmetry", + "line-monoline", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "connected", + "technical" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "octopus-deploy.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "blue octopus silhouette", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "olark.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "Olark script with speech tail underline", + "geometry": [], + "techniques": [ + "hand-drawn", + "speech-bubble" + ], + "type_style": "script", + "case": "titlecase", + "mood": [ + "friendly", + "conversational" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "onesignal.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "broadcast signal rings in red circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "alert" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "open-graph.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "globe grid in hexagon with nodes", + "geometry": [ + "hexagon" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "connected" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "open-zeppelin-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "Z from blue parallelograms", + "geometry": [ + "square" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "secure", + "modern" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "open-zeppelin.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "Z from blue parallelograms", + "geometry": [ + "square" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "modern", + "trustworthy" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "openai-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "hexagonal knot of interlocking strokes", + "geometry": [ + "hexagon", + "radial" + ], + "techniques": [ + "radial-symmetry", + "modular-repetition", + "line-monoline", + "impossible-figure" + ], + "type_style": null, + "case": null, + "mood": [ + "intelligent", + "balanced" + ], + "industry": "ai-ml", + "exemplary": true, + "note": "One rounded module rotated six times forms an interlaced knot." + }, + { + "file": "openai.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "hexagonal knot of interlocking strokes", + "geometry": [ + "hexagon", + "radial" + ], + "techniques": [ + "radial-symmetry", + "modular-repetition" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "intelligent", + "clean" + ], + "industry": "ai-ml", + "exemplary": false, + "note": "" + }, + { + "file": "opencart.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "shopping cart from line and dots", + "geometry": [], + "techniques": [ + "line-monoline" + ], + "type_style": "rounded-sans", + "case": "lowercase", + "mood": [ + "friendly", + "casual" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "opencollective.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "open ring C with lighter segment", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "open", + "friendly" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "opencv.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "three RGB open rings in triangle", + "geometry": [ + "circle", + "triangle" + ], + "techniques": [ + "color-segments", + "radial-symmetry", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "technical", + "vivid" + ], + "industry": "ai-ml", + "exemplary": false, + "note": "" + }, + { + "file": "openframeworks.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "solid circle and blocky F", + "geometry": [ + "circle", + "square" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "graphic" + ], + "industry": "framework-library", + "exemplary": true, + "note": "O and F from primitive circle and blocks; bold geometric reduction." + }, + { + "file": "opengl.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "OpenGL text with orbiting swoosh", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "motion-lines" + ], + "type_style": "humanist-sans", + "case": "mixed", + "mood": [ + "dated", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "openjs-foundation-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "gradient hexagon with all diagonals connected", + "geometry": [ + "hexagon" + ], + "techniques": [ + "line-monoline", + "gradient", + "geometric-construction", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "connected", + "inclusive" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "openjs-foundation.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "gradient hexagon with connected diagonals", + "geometry": [ + "hexagon" + ], + "techniques": [ + "line-monoline", + "gradient", + "geometric-construction" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "inclusive", + "calm" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "openlayers.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "stacked rounded diamond layers", + "geometry": [ + "diamond" + ], + "techniques": [ + "stacked-layers", + "isometric-3d", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "layered", + "fresh" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "openshift.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "red ring with offset slanted segments", + "geometry": [ + "circle" + ], + "techniques": [ + "color-segments", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "dynamic" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "opensource.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "green ring with keyhole opening", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "open", + "trustworthy" + ], + "industry": "open-source-community", + "exemplary": true, + "note": "Keyhole notch opens the ring; open-source idea in one gesture." + }, + { + "file": "openstack-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "red tile split by white rectangle", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "negative-space", + "containment", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "structured" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "openstack.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "red tile split by white rectangle", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "solid", + "approachable" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "opentelemetry-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "geometric telescope", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "curious", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "opentelemetry.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "geometric telescope", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "technical", + "friendly" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "opera.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "red shaded O ring", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "opsgenie.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "person figure with V-shaped body", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "alert" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "optimizely.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "overlapping blue rings with stripes", + "geometry": [ + "circle" + ], + "techniques": [ + "overlap-transparency", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "bold" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "oracle.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "ORACLE in wide rounded capitals", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "corporate", + "solid" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "oreilly.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "O'REILLY in bold capitals", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "authoritative", + "plain" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "origami.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "folded paper facets in blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "dimensional-shading", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "crafted", + "light" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "origin.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange ring with flaring swirl tail", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "warm" + ], + "industry": "gaming", + "exemplary": false, + "note": "" + }, + { + "file": "oshw.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "gear with keyhole notch", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "negative-space", + "hidden-meaning", + "radial-symmetry" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "open", + "technical" + ], + "industry": "hardware-devices", + "exemplary": true, + "note": "Gear with keyhole notch fuses hardware and openness." + }, + { + "file": "osquery.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "black and purple chevrons in pinwheel", + "geometry": [ + "diamond", + "radial" + ], + "techniques": [ + "radial-symmetry", + "color-segments", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "sharp", + "technical" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "packer.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "slanted blue blocks forming P", + "geometry": [ + "freeform" + ], + "techniques": [ + "dimensional-shading", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "pagekit.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "square frame with notch forming P", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "line-monoline", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "bold" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "A single square outline with one notch reads as P." + }, + { + "file": "pagekite.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "red and gray chevrons like a kite", + "geometry": [ + "freeform" + ], + "techniques": [ + "arrow", + "color-segments", + "stacked-layers" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "dated" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "pagerduty-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "green D bowl above small square", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "urgent" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "pagerduty.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "PagerDuty in green custom sans", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "friendly", + "urgent" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "panda.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "cute panda face", + "geometry": [ + "circle" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "cute", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "parcel-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "open cardboard box", + "geometry": [ + "freeform" + ], + "techniques": [ + "dimensional-shading", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "realistic", + "warm" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Illustrative box rendering; too detailed for a scalable mark." + }, + { + "file": "parcel.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "PARCEL in condensed inline capitals", + "geometry": [], + "techniques": [ + "line-monoline" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "retro", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "parse.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "looping p stroke in blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "fluid" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "parsehub.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "dark p with teal circle bowl", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "partytown-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "party popper with confetti", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "festive", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "partytown.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "party popper with confetti", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "festive", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "passbolt-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "key cut into red diamond", + "geometry": [ + "diamond" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "secure", + "bold" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "passbolt.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "key cut into red diamond", + "geometry": [ + "diamond" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "secure", + "confident" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "passport.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "ring of colored segments forming P", + "geometry": [ + "circle" + ], + "techniques": [ + "color-segments", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "friendly" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "patreon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "circle beside vertical bar forming P", + "geometry": [ + "circle" + ], + "techniques": [ + "geometric-construction", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "minimal" + ], + "industry": "payments-fintech", + "exemplary": true, + "note": "P reduced to a bar and a circle; simplest possible construction." + }, + { + "file": "paypal.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "two overlapping italic P letters", + "geometry": [], + "techniques": [ + "overlap-transparency", + "color-segments" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "trustworthy", + "dynamic" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "peer5.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "P on orange shield like HTML5 badge", + "geometry": [ + "shield" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "derivative" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "pepperoni.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "pizza slice as rocket", + "geometry": [ + "triangle" + ], + "techniques": [ + "hidden-meaning", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "fun" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "percona.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "P with yellow bowl in gradient circle", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "bold" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "percy-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "purple hedgehog silhouette", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "playful", + "spiky" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "percy.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "purple hedgehog silhouette", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "playful", + "friendly" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "perf-rocks.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "PERF ROCKS with lightning bolt divider", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "energetic", + "bold" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "perl.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "onion in dark circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "classic", + "technical" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "phalcon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "low-poly green falcon", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "sharp" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "phoenix.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "flaming phoenix bird", + "geometry": [ + "organic" + ], + "techniques": [ + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "fiery", + "dynamic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "phonegap-bot.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "isometric gray robot", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "mechanical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "phonegap.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "stacked phone outlines like brackets", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "stacked-layers", + "negative-space", + "bracket-code" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "php-alt.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "php in heavy italic lettering", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "bold", + "classic" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "php.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "php lettering in blue oval", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "classic", + "friendly" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "phpstorm.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "PS in black square on gradient shape", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "vibrant", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "pinterest.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "P shaped like a pin in red circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "friendly" + ], + "industry": "social-communication", + "exemplary": true, + "note": "P letter doubles as a map pin; subtle hidden meaning." + }, + { + "file": "pipedrive.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "pipedrive in bold lowercase", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "solid", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "pipefy.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "pipefy with custom p and y", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "pivotal_tracker.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange pinwheel segments in blue ring", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "color-segments", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "organized" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "pixijs.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "PixiJS in heavy magenta lettering", + "geometry": [], + "techniques": [ + "ligature" + ], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "bold", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "pkg.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "black pyramid with center line", + "geometry": [ + "triangle" + ], + "techniques": [ + "mirror-symmetry", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "minimal" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "planless-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "P from colored rounded shapes", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "planless.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "P from colored rounded shapes", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "plastic-scm.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "P with cube in isometric orange hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "platformio.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "alien ant head in orange ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "quirky" + ], + "industry": "hardware-devices", + "exemplary": false, + "note": "" + }, + { + "file": "play.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "green chevron play arrow", + "geometry": [ + "triangle" + ], + "techniques": [ + "arrow", + "dimensional-shading" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "friendly", + "energetic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "playwright.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red and green theater masks", + "geometry": [ + "organic" + ], + "techniques": [ + "overlap-transparency", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "dramatic", + "playful" + ], + "industry": "testing-monitoring", + "exemplary": true, + "note": "Theater masks literalize the name; memorable dual-mask idea." + }, + { + "file": "pm2.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "PM2 name with equals-sign speed lines", + "geometry": [], + "techniques": [ + "motion-lines", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "fast", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "pnpm.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "square block grid beside name", + "geometry": [ + "grid-modular", + "square" + ], + "techniques": [ + "modular-repetition", + "color-segments" + ], + "type_style": "rounded-sans", + "case": "lowercase", + "mood": [ + "orderly", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Grid of blocks hints at package structure" + }, + { + "file": "poeditor.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "stylized parrot head, speech-bubble body", + "geometry": [ + "rounded-square", + "organic" + ], + "techniques": [ + "negative-space", + "speech-bubble", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "polymer.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "zigzag chain of faceted triangles", + "geometry": [ + "triangle", + "hexagon" + ], + "techniques": [ + "modular-repetition", + "color-segments", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "postcss.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "alchemical circle, triangle and square", + "geometry": [ + "circle", + "triangle", + "square" + ], + "techniques": [ + "containment", + "hand-drawn", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "mystical", + "raw" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "postgraphile.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "low-poly blue elephant head", + "geometry": [ + "freeform" + ], + "techniques": [ + "dimensional-shading", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "strong" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "postgresql.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "outlined elephant head Slonik", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "sturdy", + "friendly" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "postman-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "rocket-man figure in orange circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "postman.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "rocket-man circle beside spaced wordmark", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "energetic", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "pouchdb.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "low-poly green animal head", + "geometry": [ + "freeform", + "triangle" + ], + "techniques": [ + "color-segments", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "modern" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "preact.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "atom orbits inside purple hexagon", + "geometry": [ + "hexagon", + "radial" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "compact" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "precursor.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "P built from open arc and bar", + "geometry": [ + "circle" + ], + "techniques": [ + "geometric-construction", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "bold" + ], + "industry": "design-creative", + "exemplary": true, + "note": "P constructed from open arc and bar, pure geometry" + }, + { + "file": "prerender-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "interlocking color blocks forming r and d", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "color-segments", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "prerender.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "block icon beside PRERENDER.IO name", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "color-segments" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "modern", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "prestashop.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "puffin bird inside blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "playful" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "Detailed illustration, weak at small sizes" + }, + { + "file": "presto.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "dot grid fading in speed pattern", + "geometry": [ + "rounded-square", + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "motion-lines", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "technical" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "prettier.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "rows of colored lines like formatted code", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "color-segments", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "orderly", + "clean" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Directly visualises tidy formatted code lines" + }, + { + "file": "prisma.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "prism triangle with inner facet", + "geometry": [ + "triangle" + ], + "techniques": [ + "negative-space", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "sharp", + "minimal" + ], + "industry": "database-data", + "exemplary": true, + "note": "Single-stroke prism, strong simple silhouette" + }, + { + "file": "prismic-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "overlapping rounded square outlines", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "overlap-transparency", + "gradient", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "colorful", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "prismic.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "interlocking squares icon plus name", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "clean" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "processwire.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "P drawn as continuous spiral stroke", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "fluid" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "P drawn in one continuous stroke, very economical" + }, + { + "file": "productboard-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three color triangles forming chevron", + "geometry": [ + "triangle", + "diamond" + ], + "techniques": [ + "color-segments", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "bright" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "productboard.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "color chevron icon plus name", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "arrow" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "dynamic" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "producthunt.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white P in orange circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "bold" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "progress.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric green arrow of stacked planes", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "arrow", + "stacked-layers" + ], + "type_style": null, + "case": null, + "mood": [ + "forward", + "energetic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "prometheus.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "torch flame in red circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "warm" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "promises.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "word then in yellow square", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "hidden-meaning" + ], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "simple", + "witty" + ], + "industry": "framework-library", + "exemplary": false, + "note": "Uses the API keyword then as identity" + }, + { + "file": "proofy.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "envelope check inside green shield", + "geometry": [ + "shield" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "trustworthy", + "clean" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "prospect.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "white carrot in purple rounded square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "bold" + ], + "industry": "other", + "exemplary": false, + "note": "" + }, + { + "file": "protactor.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "protractor half-dial in red circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "protoio.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "proto.io name in rounded geometric type", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "clean", + "friendly" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "protonet.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "orange hexagon beside PROTONET name", + "geometry": [ + "hexagon" + ], + "techniques": [], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "solid", + "technical" + ], + "industry": "hardware-devices", + "exemplary": false, + "note": "" + }, + { + "file": "prott.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "custom prott type with joined tt", + "geometry": [], + "techniques": [ + "ligature" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "friendly", + "bold" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "pug.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "pug dog face in grey circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "cute" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "pumpkindb.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "orange pumpkin with single eye", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "quirky" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "puppet-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange squares linked by angled strings", + "geometry": [ + "square" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "structured" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "puppet.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "node-and-string icon plus bold name", + "geometry": [ + "square" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "puppeteer.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "marionette control over browser window with name", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "hidden-meaning", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "playful", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Literal puppet-controls-browser metaphor" + }, + { + "file": "puppy-linux.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "outlined cartoon puppy face", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline", + "hand-drawn" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "purescript-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "equals lines between angle brackets", + "geometry": [], + "techniques": [ + "bracket-code", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "minimal" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "purescript.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "bracket symbol plus spaced uppercase name", + "geometry": [], + "techniques": [ + "bracket-code" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "clean" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "pushbullet.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "bar and half-disc bullet in green circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "dimensional-shading", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "simple" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "pusher-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric stacked stripes forming a P", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "modular-repetition", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "dynamic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "pusher.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "striped isometric icon plus PUSHER name", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "pwa.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "PWA letters with purple W", + "geometry": [], + "techniques": [ + "color-segments", + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "pycharm.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "PC in black square over gradient shapes", + "geometry": [ + "square", + "freeform" + ], + "techniques": [ + "containment", + "gradient", + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "vibrant", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "python.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "two interlocking snakes, blue and yellow", + "geometry": [ + "organic" + ], + "techniques": [ + "radial-symmetry", + "color-segments", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "balanced" + ], + "industry": "programming-language", + "exemplary": true, + "note": "Rotational symmetry of two snakes, memorable and simple" + }, + { + "file": "pytorch.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "open flame-like ring with dot", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "minimal" + ], + "industry": "ai-ml", + "exemplary": false, + "note": "" + }, + { + "file": "pyup.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "isometric blocks forming letter p", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "q.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "then chain-link inside yellow hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "technical", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "qlik.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "Qlik name with green Q symbol", + "geometry": [ + "circle" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "modern", + "bold" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "qt.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "Qt letters in cut-corner green shape", + "geometry": [ + "freeform" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "bold", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "quarkus-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "cube pinwheel inside blue frame", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "isometric-3d", + "color-segments", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "busy" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "quarkus.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "frame icon plus spaced QUARKUS name", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "clean" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "quay.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "interlocking blue chevron brackets", + "geometry": [ + "diamond" + ], + "techniques": [ + "bracket-code", + "overlap-transparency", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "dynamic" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "quobyte.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "Q as thick circular ring with tail", + "geometry": [ + "circle" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "simple" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "quora.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "Quora in red bold serif", + "geometry": [], + "techniques": [], + "type_style": "serif", + "case": "titlecase", + "mood": [ + "intellectual", + "classic" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "r-lang.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "blue R over grey ellipse ring", + "geometry": [ + "circle" + ], + "techniques": [ + "overlap-transparency", + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "academic", + "solid" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "rabbitmq-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "blocky rabbit-ear silhouette with square hole", + "geometry": [ + "square", + "grid-modular" + ], + "techniques": [ + "negative-space", + "hidden-meaning", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "simple" + ], + "industry": "cloud-infrastructure", + "exemplary": true, + "note": "Rabbit reduced to rectangles, strong geometric abstraction" + }, + { + "file": "rabbitmq.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "blocky rabbit icon plus condensed name", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space" + ], + "type_style": "grotesque-sans", + "case": "mixed", + "mood": [ + "technical", + "bold" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "rackspace.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "rackspace in bold italic lowercase", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "energetic", + "confident" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "rails.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "rail track arc over bold RAILS", + "geometry": [ + "circle" + ], + "techniques": [ + "motion-lines" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "energetic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "ramda.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "lambda shaped into ram head with horn", + "geometry": [ + "organic" + ], + "techniques": [ + "hidden-meaning", + "letter-substitution", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "clever", + "bold" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Lambda doubles as ram: name pun made visual" + }, + { + "file": "raml.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "RAML in thin light-blue strokes", + "geometry": [], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "light", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "rancher-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "blocky blue bull silhouette", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "sturdy", + "bold" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "rancher.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "bull silhouette plus RANCHER name", + "geometry": [ + "freeform" + ], + "techniques": [], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "sturdy", + "bold" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "raphael.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange curves and blue dot in rounded diamond", + "geometry": [ + "diamond", + "rounded-square" + ], + "techniques": [ + "containment", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "artistic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "raspberry-pi.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "outlined raspberry with green leaves", + "geometry": [ + "organic" + ], + "techniques": [ + "modular-repetition", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "playful" + ], + "industry": "hardware-devices", + "exemplary": false, + "note": "" + }, + { + "file": "rax.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "R from chevron stroke and arc", + "geometry": [ + "freeform" + ], + "techniques": [ + "geometric-construction", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "react-query-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red atom orbits around yellow hexagon", + "geometry": [ + "radial", + "hexagon" + ], + "techniques": [ + "radial-symmetry", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "react-query.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "atom-flower icon plus React Query name", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "vibrant", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "react-router.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "dots joined by red route path", + "geometry": [ + "circle" + ], + "techniques": [ + "hidden-meaning", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "minimal" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "react-spring.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "scribbled coil over red circle", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "hand-drawn", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "loose", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "react-styleguidist.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "blue cartoon octopus", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "react.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "atom with three elliptical orbits", + "geometry": [ + "radial", + "circle" + ], + "techniques": [ + "radial-symmetry", + "line-monoline", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "iconic" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Iconic radial construction, works as single-color line mark" + }, + { + "file": "reactivex.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "curling electric eel in pink gradient", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "vivid" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "realm.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "sunset wave layers inside circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "stacked-layers", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "warm" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "reapp.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two offset bracket shapes blue and green", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "color-segments", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "reasonml-icon.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "RE set in red square corner", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "solid" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "reasonml.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "REASON with RE boxed in red", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "solid" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "reddit-icon.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "Snoo alien head in orange circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "reddit.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "Snoo circle plus reddit lowercase name", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "rounded-sans", + "case": "lowercase", + "mood": [ + "playful", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "redhat-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red fedora with black band", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "confident", + "iconic" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Single object, flat, instantly recognisable silhouette" + }, + { + "file": "redhat.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "fedora icon plus Red Hat name", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "confident", + "modern" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "redis.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "stacked red isometric layers with shapes", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "stacked-layers", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "redsmin.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "isometric hexagonal R in red shades", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "redux-observable.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "purple fish creatures forming a ring", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "gradient", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "vivid" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "redux-saga.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "interlocking grey and green loops with nodes", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "light" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "redux.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three purple looping strokes with dots", + "geometry": [ + "radial" + ], + "techniques": [ + "line-monoline", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "fluid", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "redwoodjs.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "diamond tiles forming redwood cone", + "geometry": [ + "diamond", + "hexagon" + ], + "techniques": [ + "modular-repetition", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "natural", + "structured" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "reindex.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "stacked chevron lines with node dots", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline", + "stacked-layers", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "light" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "relay.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange S-shaped route with end nodes", + "geometry": [], + "techniques": [ + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "release.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "outlined cube with play triangle", + "geometry": [ + "hexagon", + "square" + ], + "techniques": [ + "isometric-3d", + "line-monoline", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "minimal" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "remix-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "heavy R with detached stem pieces", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "remix.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy custom Remix type, split R", + "geometry": [], + "techniques": [ + "negative-space" + ], + "type_style": "display-custom", + "case": "titlecase", + "mood": [ + "bold", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "Custom cut in R gives an ownable detail" + }, + { + "file": "require.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "archery target with arrow and arched name", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "arrow" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "playful", + "precise" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "rescript-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "r from bar and dot in red square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "bold" + ], + "industry": "programming-language", + "exemplary": true, + "note": "Letter r reduced to a bar and a dot" + }, + { + "file": "rescript.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "r square icon plus rescript name", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "simple", + "modern" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "rest-li.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "black winged horse head", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "powerful", + "dramatic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "rethinkdb.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "RethinkDB in dark teal slab serif", + "geometry": [], + "techniques": [], + "type_style": "slab", + "case": "mixed", + "mood": [ + "solid", + "academic" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "retool-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three offset stacked rounded bars", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "stacked-layers", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "minimal" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "retool.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "stacked bars icon plus bold Retool", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "stacked-layers" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "solid", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "riak.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "curved lines fanning to surrounding dots", + "geometry": [ + "radial" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "connected" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "riot.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "blocky red R with notch cutouts", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "energetic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "rocket-chat-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red speech bubble with three dots", + "geometry": [ + "organic" + ], + "techniques": [ + "speech-bubble" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "chatty" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "rocket-chat.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "speech bubble plus rocket.chat name", + "geometry": [ + "organic" + ], + "techniques": [ + "speech-bubble" + ], + "type_style": "rounded-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "rocksdb.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cheetah leaping up steps in black tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "energetic" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "rocky-linux-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "green circle cut by mountain chevron", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "confident" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Mountain peak carved from circle with one cut" + }, + { + "file": "rocky-linux.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "mountain circle plus Rocky Linux name", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "clean", + "confident" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "rollbar-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "blue outlined sheared quarter-cylinder", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "light" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "rollbar.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "outlined 3D icon plus bold Rollbar", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "technical", + "solid" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "rollupjs.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "red R with rolling paper curl", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "overlap-transparency", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "warm" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "rome-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "Roman arches, yellow inner arch", + "geometry": [ + "freeform" + ], + "techniques": [ + "mirror-symmetry", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "classic", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "rome.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "arch icon plus Rome serif name", + "geometry": [ + "freeform" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": "serif", + "case": "titlecase", + "mood": [ + "classic", + "solid" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "rsa.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "RSA white type in red box", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "secure", + "bold" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "rsmq.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "red vertical bars in folded perspective", + "geometry": [ + "square" + ], + "techniques": [ + "modular-repetition", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "rubocop.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "robot cop helmet with red visor", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "strict", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "ruby.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "faceted red gemstone", + "geometry": [ + "diamond" + ], + "techniques": [ + "dimensional-shading", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "precious", + "warm" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "rubygems.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "gem inside red hexagon outline", + "geometry": [ + "hexagon", + "diamond" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "simple" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "rubymine.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "RM in black square over gradient shapes", + "geometry": [ + "square", + "freeform" + ], + "techniques": [ + "containment", + "gradient", + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "vibrant", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "rum.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "RUM in thin type wrapped in brackets", + "geometry": [], + "techniques": [ + "bracket-code", + "line-monoline" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "light", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "runscope.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "partial gear ring around blue dot", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "solid" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "rust.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "R inside black gear cog", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "containment", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "industrial", + "solid" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "rxdb.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "pixelated gradient stacked bars plus RxDB", + "geometry": [ + "square" + ], + "techniques": [ + "pixel", + "stacked-layers", + "gradient" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "vivid", + "technical" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "safari.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "blue compass dial with needle", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "precise", + "polished" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "sagui.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "purple sitting monkey", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "playful", + "cute" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "sails.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "two teal sails side by side", + "geometry": [ + "triangle", + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "simple" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "salesforce.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "salesforce name inside blue cloud", + "geometry": [ + "organic" + ], + "techniques": [ + "containment" + ], + "type_style": "humanist-sans", + "case": "lowercase", + "mood": [ + "friendly", + "approachable" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "sameroom.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "grey square face with eyes and smile", + "geometry": [ + "rounded-square" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "playful" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "samsung.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "SAMSUNG wide type, A without crossbar", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "corporate", + "modern" + ], + "industry": "hardware-devices", + "exemplary": false, + "note": "" + }, + { + "file": "sanity.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "SANITY in coral red bold caps", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "sass-doc.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "sass DOC under code comment marks", + "geometry": [], + "techniques": [ + "bracket-code" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "technical", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "sass.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "Sass in flowing pink script", + "geometry": [], + "techniques": [], + "type_style": "script", + "case": "titlecase", + "mood": [ + "elegant", + "playful" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "saucelabs.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "lightning bolt cut into red circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "fast" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "scala.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "red spiral staircase of stacked bands", + "geometry": [ + "freeform" + ], + "techniques": [ + "stacked-layers", + "dimensional-shading", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "dynamic" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "scaledrone.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "purple disc with gradient crescent", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "smooth", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "scribd-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "teal S made of two hooks", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "fluid" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "scribd.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "hook S icon plus spaced SCRIBD", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "clean", + "literate" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "section-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "nested green outlined building frames", + "geometry": [ + "square" + ], + "techniques": [ + "line-monoline", + "stacked-layers", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "structured", + "technical" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "section.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "frame icon plus Section name", + "geometry": [ + "square" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "structured", + "clean" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "segment-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "arcs, bars and dots forming S", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "hidden-meaning", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "technical" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "segment.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "arc-S icon plus segment name", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "clean", + "friendly" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "selenium.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "Se with check mark in green square", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "reliable", + "bold" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "semantic-release.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "shutter pinwheel inside hexagon", + "geometry": [ + "hexagon", + "radial" + ], + "techniques": [ + "radial-symmetry", + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "precise" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "semantic-ui.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white S in teal square", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "clean" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "semantic-web.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "tri-color isometric cube plus two-line name", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "academic", + "colorful" + ], + "industry": "other", + "exemplary": false, + "note": "" + }, + { + "file": "semaphoreci.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange and green chevrons forming wave", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "sencha.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "green leaf-like S curve", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "fluid" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "sendgrid-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "blue squares in staggered pixel grid", + "geometry": [ + "grid-modular", + "square" + ], + "techniques": [ + "modular-repetition", + "pixel", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "orderly" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "sendgrid.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "pixel grid icon plus SendGrid name", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "pixel", + "color-segments" + ], + "type_style": "grotesque-sans", + "case": "mixed", + "mood": [ + "technical", + "solid" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "seneca.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "black ionic column capital and shaft", + "geometry": [ + "freeform" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "classic", + "solid" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "sensu-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "nested arcs inside green diamond outline", + "geometry": [ + "diamond" + ], + "techniques": [ + "containment", + "negative-space", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "fresh" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "sensu.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "diamond arcs icon plus Sensu name", + "geometry": [ + "diamond" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "technical", + "friendly" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "sentry-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "triangle glyph with concentric inner arcs", + "geometry": [ + "triangle" + ], + "techniques": [ + "line-monoline", + "negative-space", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "watchful", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "sentry.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "arc triangle icon plus SENTRY", + "geometry": [ + "triangle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "solid" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "sequelize.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "stacked cubes inside blue isometric hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "containment", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "structured", + "technical" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "serverless.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "coral bars split by slanted gaps", + "geometry": [ + "square" + ], + "techniques": [ + "modular-repetition", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "dynamic" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "sherlock-icon.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "line-drawn detective with cap and pipe", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "quirky", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "sherlock.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "detective icon plus bold SHERLOCK", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "quirky", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "shields.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "Shields IO split badge", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "color-segments" + ], + "type_style": "humanist-sans", + "case": "mixed", + "mood": [ + "technical", + "simple" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "shipit.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "orange sailboat plus SHIPIT name", + "geometry": [ + "triangle" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "confident", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "shippable.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy tight shippable lowercase", + "geometry": [], + "techniques": [], + "type_style": "grotesque-sans", + "case": "lowercase", + "mood": [ + "bold", + "confident" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "shogun.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "shogun in purple with macron o", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "friendly" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "shopify.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "green shopping bag with S", + "geometry": [ + "freeform" + ], + "techniques": [ + "dimensional-shading", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "approachable" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "sidekick.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange ring with notch cut", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "warm" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "sidekiq-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red karate high-kick silhouette", + "geometry": [ + "organic" + ], + "techniques": [ + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "strong" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "sidekiq.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "kicking figure plus Sidekiq name", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "energetic", + "light" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "signal.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "blue speech bubble with dashed outer ring", + "geometry": [ + "circle" + ], + "techniques": [ + "speech-bubble", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "trustworthy", + "calm" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "sinatra.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "realistic white fedora hat", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "classic", + "suave" + ], + "industry": "framework-library", + "exemplary": false, + "note": "Photoreal rendering, weak as a scalable mark" + }, + { + "file": "sitepoint.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange and blue chevrons forming S", + "geometry": [ + "freeform" + ], + "techniques": [ + "bracket-code", + "color-segments", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "technical" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "skaffolder.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "Skaffolder with bracket-arrow ending", + "geometry": [], + "techniques": [ + "bracket-code" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "technical", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "sketch.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "faceted yellow-orange diamond gem", + "geometry": [ + "diamond" + ], + "techniques": [ + "dimensional-shading", + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "precious", + "bright" + ], + "industry": "design-creative", + "exemplary": true, + "note": "Clean faceted construction, shading by flat color only" + }, + { + "file": "skylight.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "color pinwheel star in grey hexagon", + "geometry": [ + "hexagon", + "radial" + ], + "techniques": [ + "color-segments", + "radial-symmetry", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "colorful", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "skype.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white S in blue cloud-circle", + "geometry": [ + "organic", + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "soft" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "slack-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "four-color rounded bars forming hash pinwheel", + "geometry": [ + "radial", + "rounded-square" + ], + "techniques": [ + "modular-repetition", + "radial-symmetry", + "color-segments", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "colorful" + ], + "industry": "productivity-collaboration", + "exemplary": true, + "note": "Modular pieces form hashtag and pinwheel" + }, + { + "file": "slack.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "hash pinwheel plus bold slack name", + "geometry": [ + "radial" + ], + "techniques": [ + "modular-repetition", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "confident" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "slides.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "S on stack of offset slide squares", + "geometry": [ + "square" + ], + "techniques": [ + "stacked-layers", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "warm" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "slim.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white S curve splitting green circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "simple" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "smartling.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "concentric broken red rings", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "line-monoline", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "technical" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "smashingmagazine.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "S on skewed orange tile", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "bold" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "snap-svg.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "isometric hexagon ring with trailing tail", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "color-segments", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "structured" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "snowflake-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "snowflake of six arrowed arms", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry", + "modular-repetition", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "crisp", + "cool" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "snowflake.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "snowflake icon plus light lowercase name", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "crisp", + "clean" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "snowpack.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "black mountain with snow-cap cutout", + "geometry": [ + "triangle" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "minimal" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Mountain and snow cap from one triangle and one cut" + }, + { + "file": "snupps.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "orange S shaped as speech bubble", + "geometry": [ + "freeform" + ], + "techniques": [ + "speech-bubble", + "letter-substitution" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "snyk.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "stern doberman dog head", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "alert", + "protective" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "socket.io.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "lightning bolt inside black ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "minimal" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Bolt in ring: simple, scalable, single-color" + }, + { + "file": "solarwinds.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "lowercase name with orange wind swoosh", + "geometry": [ + "freeform" + ], + "techniques": [ + "motion-lines" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "light", + "corporate" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "solid.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white S in purple hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "modern" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "solidity.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "split grey octahedron of triangles", + "geometry": [ + "triangle", + "diamond" + ], + "techniques": [ + "color-segments", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "geometric" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "solidjs-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "blue 3D slabs forming an S", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "gradient", + "stacked-layers" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "solidjs.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "slab S icon plus spaced SOLID", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "clean", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "solr.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "thin Solr name with red sunburst", + "geometry": [ + "radial" + ], + "techniques": [ + "radial-symmetry" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "light", + "warm" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "sonarqube.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "bold lowercase name with sonar arcs", + "geometry": [ + "circle" + ], + "techniques": [ + "motion-lines", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "technical", + "confident" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "soundcloud.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "waveform-bar cloud above SOUNDCLOUD", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient", + "modular-repetition", + "hidden-meaning" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "warm", + "energetic" + ], + "industry": "media-entertainment", + "exemplary": true, + "note": "Cloud built from sound bars fuses both halves of name" + }, + { + "file": "sourcegraph.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three crossing colored rounded bars", + "geometry": [ + "radial" + ], + "techniques": [ + "color-segments", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "dynamic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "sourcetrail.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "blue anteater silhouette", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "curious" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "sourcetree.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "blue pin shape with round hole", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "spark.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "orange comet with fading trails", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "motion-lines", + "gradient", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "energetic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "sparkcentral.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "rounded bars forming asterisk figure", + "geometry": [ + "radial" + ], + "techniques": [ + "color-segments", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "balanced" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "sparkpost.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "SPARKPOST with flame replacing O", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "energetic", + "technical" + ], + "industry": "marketing-analytics", + "exemplary": true, + "note": "Flame-for-O substitution adds one memorable accent" + }, + { + "file": "speakerdeck.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "rounded teal S and bracket forming SD", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "geometric-construction", + "negative-space" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "modern" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "speedcurve.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "double paperclip-like blue loops", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "fluid", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "spidermonkey-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "black monkey silhouette forming an S", + "geometry": [ + "organic" + ], + "techniques": [ + "hidden-meaning", + "letter-substitution" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "clever" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Monkey silhouette doubles as the letter S" + }, + { + "file": "spidermonkey.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "SpiderMonkey serif with monkey S", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "serif", + "case": "mixed", + "mood": [ + "classic", + "quirky" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "spinnaker.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "gradient blue sail above name", + "geometry": [ + "triangle", + "organic" + ], + "techniques": [ + "gradient", + "overlap-transparency" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "dynamic", + "fresh" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "splunk.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "splunk followed by prompt chevron", + "geometry": [], + "techniques": [ + "bracket-code" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "technical", + "bold" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "spotify-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three sound-wave arcs in green circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "friendly" + ], + "industry": "media-entertainment", + "exemplary": true, + "note": "Three arcs in a circle: minimal and instantly readable" + }, + { + "file": "spotify.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "wave circle plus bold Spotify name", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "motion-lines" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "bold", + "friendly" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "spree.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "smiling cart with arrow plus spree", + "geometry": [ + "freeform" + ], + "techniques": [ + "arrow", + "hidden-meaning" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "playful" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "spring-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "leaf cut from green circle with dot", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "natural" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "spring.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "leaf circle plus green spring name", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "fresh", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "sqlite.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "feather quill on blue square plus SQLite serif", + "geometry": [ + "square" + ], + "techniques": [ + "gradient", + "overlap-transparency" + ], + "type_style": "serif", + "case": "mixed", + "mood": [ + "classic", + "dated" + ], + "industry": "database-data", + "exemplary": false, + "note": "Gradient square plus serif feels dated" + }, + { + "file": "square.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "small square inside rounded dark square", + "geometry": [ + "rounded-square", + "square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "trustworthy" + ], + "industry": "payments-fintech", + "exemplary": true, + "note": "Name made literal with two nested squares" + }, + { + "file": "squarespace.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two interlocking black link loops", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline", + "overlap-transparency", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "elegant", + "bold" + ], + "industry": "design-creative", + "exemplary": true, + "note": "Interlocking modular strokes, strong single-color mark" + }, + { + "file": "stackbit-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "outlined isometric stacked layer squares", + "geometry": [ + "diamond" + ], + "techniques": [ + "isometric-3d", + "stacked-layers", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "light" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "stackbit.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "layer icon plus white STACKBIT wordmark", + "geometry": [ + "diamond" + ], + "techniques": [ + "isometric-3d", + "stacked-layers" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "clean" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "White wordmark invisible on light backgrounds" + }, + { + "file": "stackoverflow-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "orange bars fanning out of grey tray", + "geometry": [ + "freeform" + ], + "techniques": [ + "stacked-layers", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "energetic" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Literally depicts a stack overflowing its tray" + }, + { + "file": "stackoverflow.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "overflowing tray plus stackoverflow name", + "geometry": [ + "freeform" + ], + "techniques": [ + "stacked-layers", + "hidden-meaning" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "stackshare.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "branching node graph in blue rounded square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "clean" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "statuspage.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "blue arc floating over circle", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "modern" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "stdlib-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "intertwined blue and orange S strands", + "geometry": [ + "organic" + ], + "techniques": [ + "overlap-transparency", + "gradient", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "stdlib.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "twisted strands icon plus stdlib name", + "geometry": [ + "organic" + ], + "techniques": [ + "color-segments" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "technical", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "steam.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "piston linkage inside black circle", + "geometry": [ + "circle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "mechanical", + "bold" + ], + "industry": "gaming", + "exemplary": true, + "note": "Steam-engine linkage in negative space, strong silhouette" + }, + { + "file": "stenciljs-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three slanted black parallelogram bars", + "geometry": [ + "freeform" + ], + "techniques": [ + "modular-repetition", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "stenciljs.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "slanted bars icon plus bold stencil", + "geometry": [ + "freeform" + ], + "techniques": [ + "motion-lines" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "bold", + "fast" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "stetho.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "stethoscope with gear in green circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "stickermule.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "brown mule standing on stickermule name", + "geometry": [ + "organic" + ], + "techniques": [ + "color-segments" + ], + "type_style": "rounded-sans", + "case": "lowercase", + "mood": [ + "playful", + "friendly" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "stimulus.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "white stream waves inside black square", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "containment", + "arrow" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "dynamic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "stitch.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "dashed seam line in yellow square", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "negative-space", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "bright" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "stoplight.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "line-drawn robot in blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "storybook-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white S on pink bookmarked book", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "storybook.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "book S icon plus Storybook name", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "friendly", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "strapi-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "folded purple ribbon shape", + "geometry": [ + "square", + "triangle" + ], + "techniques": [ + "overlap-transparency", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "light" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "strapi.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "folded ribbon icon plus strapi name", + "geometry": [ + "square" + ], + "techniques": [ + "overlap-transparency" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "strider.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "white radiating lines splitting blue circle", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "color-segments", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "cool" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "stripe.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy purple stripe lowercase", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "confident", + "modern" + ], + "industry": "payments-fintech", + "exemplary": true, + "note": "Tight custom lowercase, wordmark carries the brand alone" + }, + { + "file": "struts.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "isometric blue S block", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "styleci.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "white CI in red square", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "simple" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "stylefmt.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "magic wand between code brackets with sparkles", + "geometry": [], + "techniques": [ + "bracket-code", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "stylelint.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "tuxedo shirt front with bow tie", + "geometry": [ + "triangle" + ], + "techniques": [ + "negative-space", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "elegant", + "witty" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Tuxedo metaphor for 'style'; shirt formed by negative space." + }, + { + "file": "stylis.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "italic bold name with extended y", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "dynamic", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "stylus.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "brush script name", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "script", + "case": "lowercase", + "mood": [ + "expressive", + "fluid" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "sublimetext-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "S built from slanted folded ribbons", + "geometry": [ + "freeform" + ], + "techniques": [ + "stacked-layers", + "dimensional-shading", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "energetic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "sublimetext.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "folded ribbon S beside name", + "geometry": [ + "freeform" + ], + "techniques": [ + "dimensional-shading", + "gradient" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "bold", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Wordmark filled white; disappears on light backgrounds." + }, + { + "file": "subversion.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "sweeping S curves cut through blue rectangle", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "fluid" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "sugarss.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "smiling sugar cube character", + "geometry": [ + "circle", + "square" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "cute" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "supabase-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "split lightning bolt", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "modern" + ], + "industry": "database-data", + "exemplary": true, + "note": "Bolt split into two offset halves; minimal, memorable." + }, + { + "file": "supabase.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "split lightning bolt with name", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "clean" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "surge.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "walrus face with tusks", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "quirky" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "survicate.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "angular face with check-mark smile", + "geometry": [ + "triangle" + ], + "techniques": [ + "mirror-symmetry", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "smart" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "suse.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "green chameleon above bold name", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "friendly", + "confident" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "susy.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "serif S between angle brackets", + "geometry": [], + "techniques": [ + "bracket-code" + ], + "type_style": "serif", + "case": "uppercase", + "mood": [ + "playful", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "svelte-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "S from interlocking rounded links", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "energetic" + ], + "industry": "framework-library", + "exemplary": true, + "note": "S drawn as two interlocking rounded links; strong negative space." + }, + { + "file": "svelte.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "interlocking S beside tracked name", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "modern", + "clean" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "svg.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "eight-armed asterisk with node dots", + "geometry": [ + "radial", + "circle" + ], + "techniques": [ + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "playful" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "swagger.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "curly braces with dots in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "bracket-code", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "swift.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "swift bird in rounded square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "negative-space", + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "sleek" + ], + "industry": "programming-language", + "exemplary": true, + "note": "Name-literal bird in negative space; simple swoosh construction." + }, + { + "file": "swiftype.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "lightning bolt in rounded blob", + "geometry": [ + "rounded-square", + "organic" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "energetic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "symfony.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "calligraphic sf ligature in black circle", + "geometry": [ + "circle" + ], + "techniques": [ + "ligature", + "containment", + "negative-space" + ], + "type_style": "script", + "case": "lowercase", + "mood": [ + "elegant", + "classic" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "sysdig-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "shovel drawn in parallel strokes", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "clever" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "t3.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "T3 in circle ringed by dots", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "containment", + "radial-symmetry" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "modern", + "playful" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "tableau-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "cluster of colored plus signs", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "analytical", + "vibrant" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "tableau.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "plus-sign cluster with +ableau name", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "letter-substitution", + "modular-repetition", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "analytical", + "clean" + ], + "industry": "marketing-analytics", + "exemplary": true, + "note": "t replaced by plus sign, echoing symbol; coherent system." + }, + { + "file": "taiga.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "rotated translucent squares forming flower", + "geometry": [ + "square", + "radial" + ], + "techniques": [ + "overlap-transparency", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "organic", + "calm" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "tailwindcss-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two stacked wind waves", + "geometry": [ + "organic" + ], + "techniques": [ + "modular-repetition", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "fluid", + "fresh" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Two repeated wave strokes; minimal, memorable, name-literal." + }, + { + "file": "tailwindcss.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "double wave beside name", + "geometry": [ + "organic" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "fresh", + "clean" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "tapcart-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "concentric arcs like tap ripple", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "dynamic" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "tapcart.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "concentric arcs beside name", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "friendly" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "targetprocess.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "colored rounded bars in radial cluster", + "geometry": [ + "radial", + "hexagon" + ], + "techniques": [ + "modular-repetition", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "organized" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "taskade-icon.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "fluffy sheep face", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "cute", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "taskade.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "sheep face beside name", + "geometry": [ + "circle" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "clean" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "tastejs.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "red monster licking a popsicle", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "wacky" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "Detailed illustration; poor scalability at small sizes." + }, + { + "file": "tauri.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two interlocking arcs with dots", + "geometry": [ + "circle" + ], + "techniques": [ + "radial-symmetry", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "modern" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "tealium.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "diagonal rows of growing dots", + "geometry": [ + "circle", + "grid-modular" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "flowing" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "teamgrid.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "row of vertical hexagonal bars", + "geometry": [ + "grid-modular" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "rhythmic", + "orderly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "teamwork-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "lowercase t with pink dot", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "teamwork.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold name with pink period", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "confident" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "telegram.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "paper plane in blue circle", + "geometry": [ + "circle", + "triangle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "tensorflow.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "isometric blocks reading as T and F", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "ai-ml", + "exemplary": true, + "note": "One isometric form reads as T and F from different sides." + }, + { + "file": "terminal.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "terminal window with prompt cursor", + "geometry": [ + "square" + ], + "techniques": [ + "bracket-code", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "minimal" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "terraform-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "isometric parallelograms forming a T", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "modular-repetition", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "solid" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "terraform.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "isometric T blocks beside name", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "technical", + "confident" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "terser-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "overlapping colored bars forming asterisk", + "geometry": [ + "radial" + ], + "techniques": [ + "overlap-transparency", + "color-segments", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "energetic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "terser.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name in overlapping multicolor letters", + "geometry": [], + "techniques": [ + "overlap-transparency", + "color-segments" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "vibrant", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "testing-library.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "red cartoon octopus", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "friendly" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "testlodge.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "faceted low-poly letter T", + "geometry": [ + "triangle" + ], + "techniques": [ + "geometric-construction", + "color-segments", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "crisp", + "modern" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "threejs.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "triangle subdivided into wireframe mesh", + "geometry": [ + "triangle", + "grid-modular" + ], + "techniques": [ + "line-monoline", + "geometric-construction", + "isometric-3d" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "precise" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Subdivided triangle mesh signals 3D in pure line geometry." + }, + { + "file": "tidal-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "four diamonds in tight cluster", + "geometry": [ + "diamond", + "grid-modular" + ], + "techniques": [ + "modular-repetition", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "bold" + ], + "industry": "media-entertainment", + "exemplary": true, + "note": "Four identical diamonds; extreme simplicity, scales perfectly." + }, + { + "file": "tidal.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "diamond cluster with tracked name", + "geometry": [ + "diamond" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "minimal", + "premium" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "tiktok-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "music note with cyan-red glitch offset", + "geometry": [ + "freeform" + ], + "techniques": [ + "stacked-layers", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "youthful" + ], + "industry": "social-communication", + "exemplary": true, + "note": "Chromatic offset layers evoke motion; note doubles as d." + }, + { + "file": "tiktok.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "glitch music note beside name", + "geometry": [ + "freeform" + ], + "techniques": [ + "stacked-layers" + ], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "energetic", + "bold" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "tnw.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "custom heavy connected TNW letters", + "geometry": [], + "techniques": [ + "ligature" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "loud" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "todoist-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "stacked check strokes in red square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "stacked-layers", + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "organized", + "energetic" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "todoist.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "stacked checks beside name", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "stacked-layers", + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "organized" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "todomvc.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "check mark in dashed box", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "functional" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "tomcat.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "leaping cartoon tomcat", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "playful", + "retro" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "toml.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "bold T inside square brackets", + "geometry": [ + "square" + ], + "techniques": [ + "bracket-code", + "containment" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "technical", + "sturdy" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "tor.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with onion replacing o", + "geometry": [], + "techniques": [ + "letter-substitution", + "hidden-meaning" + ], + "type_style": "display-custom", + "case": "titlecase", + "mood": [ + "trustworthy", + "bold" + ], + "industry": "security-identity", + "exemplary": true, + "note": "Onion substitutes the o, explaining onion routing at a glance." + }, + { + "file": "torus.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "gradient 3D ring", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "vibrant" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "traackr.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "dot-grid T shape beside name", + "geometry": [ + "grid-modular", + "circle" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "confident" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "trac.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "red animal paw print", + "geometry": [ + "organic" + ], + "techniques": [ + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "simple" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "travis-ci-monochrome.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "mustached builder with T hard hat", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "quirky" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "travis-ci.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "mustached builder with T hard hat", + "geometry": [ + "organic" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "quirky" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "treasuredata-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "faceted gradient gemstone", + "geometry": [ + "diamond" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "premium", + "modern" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "treasuredata.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "small gem beside tracked name", + "geometry": [ + "diamond" + ], + "techniques": [ + "gradient" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "premium", + "clean" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "treehouse.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "white tree branch in green hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "growing" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "trello.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "kanban board with two cards", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "negative-space", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "organized", + "simple" + ], + "industry": "productivity-collaboration", + "exemplary": true, + "note": "Product's own board UI reduced to two bars; instantly explanatory." + }, + { + "file": "truffle-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "chocolate truffle with swirl top", + "geometry": [ + "circle" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "sweet", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "truffle.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "chocolate truffle above tracked name", + "geometry": [ + "circle" + ], + "techniques": [], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "sweet", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "tsnode.svg", + "mark_type": "combination", + "symbol_type": "lettermark", + "subject": "TS hexagon with node, hexagon o", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "letter-substitution" + ], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "technical", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "tsu.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy chunky name with macron", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "bold", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "tsuru.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "origami crane of flat triangles", + "geometry": [ + "triangle" + ], + "techniques": [ + "geometric-construction", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "light", + "elegant" + ], + "industry": "cloud-infrastructure", + "exemplary": true, + "note": "Name-literal origami crane from flat triangles; clean construction." + }, + { + "file": "tumblr-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "heavy lowercase t", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "bold", + "casual" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "tumblr.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy name with trailing period", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "bold", + "casual" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "tunein.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "TUNE and IN in offset boxes", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "overlap-transparency" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "fresh" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "tuple.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "paired offset parallelograms beside name", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "isometric-3d" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "solid" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "turborepo-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "black ring inside segmented gradient arc", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "gradient", + "color-segments", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "turborepo.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold name with ring replacing O", + "geometry": [], + "techniques": [ + "letter-substitution", + "gradient" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "fast", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "turret.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "chess rook castle tower", + "geometry": [ + "freeform" + ], + "techniques": [ + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "strong" + ], + "industry": "other", + "exemplary": false, + "note": "" + }, + { + "file": "twilio-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "four dots in red ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "modular-repetition", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "bold" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "twilio.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "four-dot ring beside name", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "bold", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "twitch.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "glitch speech bubble with eyes", + "geometry": [ + "freeform" + ], + "techniques": [ + "speech-bubble", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "bold" + ], + "industry": "media-entertainment", + "exemplary": true, + "note": "Speech bubble with two eyes: chat and character in one shape." + }, + { + "file": "twitter.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "blue bird in flight", + "geometry": [ + "organic", + "circle" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "light" + ], + "industry": "social-communication", + "exemplary": true, + "note": "Bird constructed entirely from overlapping circle arcs." + }, + { + "file": "typeform-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "T inside hand-drawn circle", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "hand-drawn", + "line-monoline", + "containment" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "human", + "minimal" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "typeform.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "hand-drawn circle overlapping name", + "geometry": [ + "circle", + "organic" + ], + "techniques": [ + "hand-drawn", + "line-monoline" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "human", + "minimal" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "typescript-icon.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "TS in blue square", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "solid" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "typescript.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "light camel-case name", + "geometry": [], + "techniques": [], + "type_style": "humanist-sans", + "case": "mixed", + "mood": [ + "technical", + "clean" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "typo3-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "bent orange cone with notch", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": null, + "case": null, + "mood": [ + "bold", + "warm" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "typo3.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "orange cone beside condensed name", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "technical", + "plain" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "ubuntu.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "circle of three friends in orange disc", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "radial-symmetry", + "negative-space", + "containment", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "communal" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Three abstract figures form a ring; radial symmetry carries 'community'." + }, + { + "file": "udacity-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "folded ribbon U outline", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "dynamic" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "udacity.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "ribbon U beside tracked name", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "modern", + "clean" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "udemy-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "U under purple chevron cap", + "geometry": [ + "freeform" + ], + "techniques": [ + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "udemy.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold name with chevron over u", + "geometry": [], + "techniques": [ + "hidden-meaning" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "confident" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "uikit.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "broken isometric hexagon outline", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "clean" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "umu.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "giraffe silhouette in yellow square", + "geometry": [ + "square" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "warm" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "unbounce-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "slashed circle in dark disc", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "modern" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "unbounce.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "slashed circle beside name", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "confident" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "undertow.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "grey U riding a wave swoosh", + "geometry": [ + "organic" + ], + "techniques": [ + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "fluid", + "calm" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "unionpay.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "name over three colored parallelograms", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments", + "containment", + "stacked-layers" + ], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "established", + "trustworthy" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "unitjs.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "check mark hexagon with arrow", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "arrow", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "reliable", + "technical" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "unito-icon.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "monoline un ligature in teal circle", + "geometry": [ + "circle" + ], + "techniques": [ + "ligature", + "line-monoline", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "connected", + "calm" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "unito.svg", + "mark_type": "combination", + "symbol_type": "lettermark", + "subject": "un ligature circle beside name", + "geometry": [ + "circle" + ], + "techniques": [ + "ligature", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "clean" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "unity.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "cube implied by three arrow shapes", + "geometry": [ + "triangle" + ], + "techniques": [ + "negative-space", + "isometric-3d", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "gaming", + "exemplary": true, + "note": "Cube emerges from negative space between three angular pieces." + }, + { + "file": "unocss.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three primitive shapes in grid", + "geometry": [ + "grid-modular", + "circle", + "square" + ], + "techniques": [ + "geometric-construction", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "modular" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "unrealengine-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "calligraphic U in circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "powerful", + "classic" + ], + "industry": "gaming", + "exemplary": false, + "note": "" + }, + { + "file": "unrealengine.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "U circle above extended name", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "powerful", + "bold" + ], + "industry": "gaming", + "exemplary": false, + "note": "" + }, + { + "file": "upcase.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with caret replacing A", + "geometry": [], + "techniques": [ + "letter-substitution", + "arrow" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "clean", + "upward" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "upwork.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with custom green up ligature", + "geometry": [], + "techniques": [ + "ligature" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "friendly", + "confident" + ], + "industry": "other", + "exemplary": false, + "note": "" + }, + { + "file": "user-testing-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "U in blue speech bubble", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "speech-bubble", + "containment", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "friendly", + "clear" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "user-testing.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "User in speech bubble, then Testing", + "geometry": [], + "techniques": [ + "speech-bubble", + "containment" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "friendly", + "clear" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "uservoice-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "orange U with dotted left stroke", + "geometry": [ + "freeform" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "friendly" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "uservoice.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "dotted U beside name", + "geometry": [ + "freeform" + ], + "techniques": [ + "modular-repetition" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "friendly", + "solid" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "uwsgi.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "condensed name with green u", + "geometry": [], + "techniques": [ + "color-segments" + ], + "type_style": "grotesque-sans", + "case": "mixed", + "mood": [ + "technical", + "plain" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "v8-ignition.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "lightning bolt in circle with funnel", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "energetic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "v8-turbofan.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "fan in blue circle on V frame", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "fast" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "v8.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "blue 8 over grey V", + "geometry": [], + "techniques": [ + "stacked-layers" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "technical", + "bold" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "vaadin.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "name with bracket-arrow glyph", + "geometry": [], + "techniques": [ + "bracket-code" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "friendly", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "vaddy.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "green ring around dot like eye", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "watchful", + "fresh" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "vagrant-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "isometric 3D letter V", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "vagrant.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "3D V beside name", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "solid", + "confident" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "vault-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "inverted triangle with keypad dot grid", + "geometry": [ + "triangle", + "grid-modular" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "secure", + "stark" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "vault.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "keypad triangle beside name", + "geometry": [ + "triangle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "secure", + "bold" + ], + "industry": "security-identity", + "exemplary": false, + "note": "" + }, + { + "file": "vector-timber.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "V from two slanted cyan strokes", + "geometry": [ + "freeform" + ], + "techniques": [ + "modular-repetition", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "sharp" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "vercel-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "solid black equilateral triangle", + "geometry": [ + "triangle" + ], + "techniques": [ + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "confident" + ], + "industry": "hosting-cdn", + "exemplary": true, + "note": "A single equilateral triangle; reduction to the absolute minimum." + }, + { + "file": "vercel.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "triangle beside name", + "geometry": [ + "triangle" + ], + "techniques": [], + "type_style": "geometric-sans", + "case": "titlecase", + "mood": [ + "minimal", + "confident" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "verdaccio-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "dark green V with speed lines", + "geometry": [ + "freeform" + ], + "techniques": [ + "motion-lines", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "sturdy" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "verdaccio.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "speed-line V beside italic name", + "geometry": [ + "freeform" + ], + "techniques": [ + "motion-lines" + ], + "type_style": "humanist-sans", + "case": "titlecase", + "mood": [ + "light", + "fast" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "vernemq.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "V of two hinged rounded bars", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "connected" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "vim.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "beveled V and im on green diamond", + "geometry": [ + "diamond" + ], + "techniques": [ + "dimensional-shading", + "containment" + ], + "type_style": "display-custom", + "case": "titlecase", + "mood": [ + "retro", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Dated bevel and chrome effects; busy at small sizes." + }, + { + "file": "vimeo-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "flowing script lowercase v", + "geometry": [ + "organic" + ], + "techniques": [], + "type_style": "script", + "case": "lowercase", + "mood": [ + "friendly", + "creative" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "vimeo.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "flowing brush-script name", + "geometry": [], + "techniques": [ + "hand-drawn" + ], + "type_style": "script", + "case": "lowercase", + "mood": [ + "friendly", + "creative" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "visa.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy italic custom name", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "trustworthy", + "dynamic" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "visaelectron.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "italic VISA over Electron", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "trustworthy", + "dynamic" + ], + "industry": "payments-fintech", + "exemplary": false, + "note": "" + }, + { + "file": "visual-studio-code.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "folded ribbon forming angle bracket", + "geometry": [ + "freeform" + ], + "techniques": [ + "gradient", + "dimensional-shading", + "bracket-code" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "modern" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "visual-studio.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "folded purple ribbon infinity loop", + "geometry": [ + "freeform" + ], + "techniques": [ + "infinity-loop", + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "polished" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "vitejs.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "gradient V with lightning bolt", + "geometry": [ + "triangle" + ], + "techniques": [ + "gradient", + "overlap-transparency", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "vibrant" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "vitest.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "check-mark V with lightning bolt", + "geometry": [ + "freeform" + ], + "techniques": [ + "hidden-meaning", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "fast", + "reliable" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "vivaldi-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "V in white circle on red square", + "geometry": [ + "rounded-square", + "circle" + ], + "techniques": [ + "containment", + "dimensional-shading", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "friendly" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "vivaldi.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "V badge beside tracked name", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "bold", + "confident" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "vlang.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "V from two slanted blue planks", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "simple", + "technical" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "void.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "italic VOID across broken green ring", + "geometry": [ + "circle" + ], + "techniques": [ + "overlap-transparency" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "bold", + "technical" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "vue.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "nested green and navy chevrons", + "geometry": [ + "triangle" + ], + "techniques": [ + "stacked-layers", + "mirror-symmetry", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "friendly" + ], + "industry": "framework-library", + "exemplary": true, + "note": "Two nested chevrons make a V; flat geometry, instantly recognisable." + }, + { + "file": "vuetifyjs.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "V from light blue parallelograms", + "geometry": [ + "triangle" + ], + "techniques": [ + "color-segments", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "light" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "vueuse.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "U from nested green and navy bars", + "geometry": [ + "freeform" + ], + "techniques": [ + "stacked-layers", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "friendly" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "vulkan.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "red name under swoosh arc", + "geometry": [], + "techniques": [ + "motion-lines" + ], + "type_style": "display-custom", + "case": "titlecase", + "mood": [ + "powerful", + "dynamic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "vultr.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "thin tracked name with accent flag", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "clean", + "technical" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "vwo.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "monoline gradient VWO letters", + "geometry": [], + "techniques": [ + "line-monoline", + "gradient" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "modern", + "vibrant" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "w3c.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "custom W3C letterforms", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "institutional", + "classic" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "waffle-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "isometric waffle with melting chocolate", + "geometry": [ + "diamond", + "grid-modular" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "sweet" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "waffle.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "waffle grid diamond dripping syrup", + "geometry": [ + "diamond", + "grid-modular" + ], + "techniques": [ + "negative-space", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "sweet" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "wagtail.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "wagtail bird silhouette", + "geometry": [ + "organic" + ], + "techniques": [ + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "elegant", + "simple" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "wakatime.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "monoline w check inside clock ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "minimal", + "precise" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "watchman.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "eye with hexagon iris in circle", + "geometry": [ + "circle", + "hexagon" + ], + "techniques": [ + "containment", + "negative-space", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "watchful", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "wearos.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "colored slanted bars and dots forming W", + "geometry": [ + "freeform" + ], + "techniques": [ + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "modern" + ], + "industry": "os-platform", + "exemplary": false, + "note": "" + }, + { + "file": "weave.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "W woven from colored stripes", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "color-segments", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "vibrant" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "web-fundamentals.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "outlined six-arm asterisk", + "geometry": [ + "radial", + "star" + ], + "techniques": [ + "radial-symmetry", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "technical" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "web.dev-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "prompt chevron with gradient underscore", + "geometry": [ + "freeform" + ], + "techniques": [ + "bracket-code", + "gradient" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "modern" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "web.dev.svg", + "mark_type": "combination", + "symbol_type": "abstract", + "subject": "prompt chevron beside name", + "geometry": [ + "freeform" + ], + "techniques": [ + "bracket-code" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "clean", + "technical" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "web3js.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "isometric 3D W3JS letters", + "geometry": [ + "freeform" + ], + "techniques": [ + "isometric-3d", + "dimensional-shading" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "technical", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "webassembly.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "WA in notched purple square", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "solid" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "webcomponents.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "faceted hexagonal C of polygons", + "geometry": [ + "hexagon" + ], + "techniques": [ + "dimensional-shading", + "gradient", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "modular" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "webdriverio.svg", + "mark_type": "combination", + "symbol_type": "mascot", + "subject": "orange robot above thin name", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "playful" + ], + "industry": "testing-monitoring", + "exemplary": false, + "note": "" + }, + { + "file": "webflow.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold italic custom name", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "dynamic", + "confident" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "webhint-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "narwhal in purple ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "webhint.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "narwhal ring above name", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "clean" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "webhooks.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "three hooked nodes in triangular loop", + "geometry": [ + "triangle", + "circle" + ], + "techniques": [ + "radial-symmetry", + "line-monoline", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "connected", + "technical" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "webix-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "faceted purple W", + "geometry": [ + "triangle" + ], + "techniques": [ + "dimensional-shading", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "bold" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "webix.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "faceted W beside name", + "geometry": [ + "triangle" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "friendly", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "webmin.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "light blue three-lobed propeller shape", + "geometry": [ + "organic" + ], + "techniques": [ + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "soft", + "friendly" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "webpack.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "cube inside isometric hexagon shell", + "geometry": [ + "hexagon" + ], + "techniques": [ + "isometric-3d", + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "solid" + ], + "industry": "developer-tools", + "exemplary": true, + "note": "Cube in cube reads as 'package'; clean isometric construction." + }, + { + "file": "webplatform.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "W of overlapping jointed color bars", + "geometry": [ + "freeform" + ], + "techniques": [ + "overlap-transparency", + "color-segments", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "open" + ], + "industry": "education", + "exemplary": false, + "note": "" + }, + { + "file": "webrtc.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "speech bubble on colored circle flower", + "geometry": [ + "circle", + "radial" + ], + "techniques": [ + "speech-bubble", + "color-segments", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "vibrant", + "friendly" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "websocket.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "interlocking angular black strokes", + "geometry": [ + "freeform" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "stark" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "webstorm.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "WS in black square on gradient shard", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "vibrant" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "webtask.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "offset nested colored squares", + "geometry": [ + "square" + ], + "techniques": [ + "stacked-layers", + "color-segments" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "modular" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "webtorrent.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "heart in dark hexagon with shadow", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "warm", + "friendly" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "weebly.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "rounded outlined blue W", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "simple" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "whalar.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "whale tail in teal circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "fresh" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "whatsapp.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "phone handset inside speech bubble", + "geometry": [ + "circle" + ], + "techniques": [ + "speech-bubble", + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "approachable" + ], + "industry": "social-communication", + "exemplary": true, + "note": "Phone plus speech bubble fuses call and chat in one silhouette." + }, + { + "file": "whatwg.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "question mark in green ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": null, + "case": null, + "mood": [ + "curious", + "simple" + ], + "industry": "open-source-community", + "exemplary": false, + "note": "" + }, + { + "file": "wicket-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "W shaped as crown in orange circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "regal", + "warm" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "wicket.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "crown W between condensed words", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "bold", + "sturdy" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "wifi.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "Wi Fi in yin-yang style oval", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "bold", + "universal" + ], + "industry": "hardware-devices", + "exemplary": false, + "note": "" + }, + { + "file": "wildfly.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "sketched dragonfly after name", + "geometry": [ + "organic" + ], + "techniques": [ + "line-monoline" + ], + "type_style": "humanist-sans", + "case": "mixed", + "mood": [ + "light", + "technical" + ], + "industry": "cloud-infrastructure", + "exemplary": false, + "note": "" + }, + { + "file": "wire.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "thin continuous monoline name", + "geometry": [], + "techniques": [ + "line-monoline" + ], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "minimal", + "elegant" + ], + "industry": "social-communication", + "exemplary": true, + "note": "Single-weight wire-like strokes literally embody the name." + }, + { + "file": "wix.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "heavy custom name with small i", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "bold", + "playful" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "wmr.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "astronaut working on laptop", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "detailed" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "Detailed illustration; does not reduce to a small mark." + }, + { + "file": "woocommerce-icon.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "Woo inside purple speech bubble", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "speech-bubble", + "containment" + ], + "type_style": "display-custom", + "case": "titlecase", + "mood": [ + "friendly", + "playful" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "woocommerce.svg", + "mark_type": "combination", + "symbol_type": "emblem", + "subject": "Woo bubble beside COMMERCE", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "speech-bubble", + "containment" + ], + "type_style": "display-custom", + "case": "mixed", + "mood": [ + "friendly", + "bold" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "woopra.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with oo as infinity loop", + "geometry": [], + "techniques": [ + "infinity-loop", + "ligature" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "modern", + "clever" + ], + "industry": "marketing-analytics", + "exemplary": false, + "note": "" + }, + { + "file": "wordpress-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "serif W in ringed circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "serif", + "case": "uppercase", + "mood": [ + "established", + "classic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "wordpress.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "W circle beside small-caps serif name", + "geometry": [ + "circle" + ], + "techniques": [ + "containment" + ], + "type_style": "serif", + "case": "mixed", + "mood": [ + "established", + "classic" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "workboard.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "B built from chevrons in blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "arrow", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "modern", + "directional" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "workplace.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with w enclosed in ring", + "geometry": [], + "techniques": [ + "containment", + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "modern" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "wpengine.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "grid of teal tiles around diamond gap", + "geometry": [ + "grid-modular", + "square" + ], + "techniques": [ + "negative-space", + "modular-repetition" + ], + "type_style": null, + "case": null, + "mood": [ + "solid", + "technical" + ], + "industry": "hosting-cdn", + "exemplary": false, + "note": "" + }, + { + "file": "wufoo.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "slanted white W in red circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "xamarin.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "X in blue hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "clean" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "xampp.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "white looped knot in orange square", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "xcart.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "cart icon in orange square with name", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment" + ], + "type_style": "grotesque-sans", + "case": "uppercase", + "mood": [ + "bold", + "commercial" + ], + "industry": "ecommerce-retail", + "exemplary": false, + "note": "" + }, + { + "file": "xero.svg", + "mark_type": "emblem", + "symbol_type": null, + "subject": "thin name inside blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "line-monoline" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "clean" + ], + "industry": "finance-banking", + "exemplary": false, + "note": "" + }, + { + "file": "xplenty.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "mountain peaks in ring", + "geometry": [ + "circle" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "calm", + "solid" + ], + "industry": "database-data", + "exemplary": false, + "note": "" + }, + { + "file": "xstate.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold X followed by tracked STATE", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "clean" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "xtend.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "X with leading chevron arrows", + "geometry": [ + "freeform" + ], + "techniques": [ + "arrow", + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "dynamic", + "bold" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "xwiki-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "grey X with four colored ticks", + "geometry": [ + "radial" + ], + "techniques": [ + "color-segments", + "radial-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "collaborative", + "bright" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "xwiki.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "ticked X beside thin WIKI", + "geometry": [ + "radial" + ], + "techniques": [ + "color-segments" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "light", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "yahoo.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold purple name with exclamation", + "geometry": [], + "techniques": [], + "type_style": "display-custom", + "case": "lowercase", + "mood": [ + "playful", + "loud" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "yaml.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "geometric stencil YAML letters", + "geometry": [], + "techniques": [ + "geometric-construction", + "negative-space" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "technical", + "stark" + ], + "industry": "programming-language", + "exemplary": false, + "note": "" + }, + { + "file": "yammer.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "blue y with radiating lines", + "geometry": [ + "freeform" + ], + "techniques": [ + "motion-lines" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "social" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "yandex-ru.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "Cyrillic name with red first letter", + "geometry": [], + "techniques": [ + "color-segments" + ], + "type_style": "grotesque-sans", + "case": "titlecase", + "mood": [ + "bold", + "local" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "yarn.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "outlined cat in blue circle", + "geometry": [ + "circle" + ], + "techniques": [ + "line-monoline", + "containment", + "hidden-meaning" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "playful" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "ycombinator.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white Y in orange square", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "simple", + "confident" + ], + "industry": "finance-banking", + "exemplary": false, + "note": "" + }, + { + "file": "yeoman.svg", + "mark_type": "mascot", + "symbol_type": null, + "subject": "mustached beefeater guard saluting", + "geometry": [ + "organic" + ], + "techniques": [ + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "quirky", + "friendly" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "yii.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "Y from three gradient petals", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient", + "overlap-transparency" + ], + "type_style": null, + "case": null, + "mood": [ + "fresh", + "vibrant" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "youtrack.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "YT in black square on gradient X", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "gradient", + "color-segments" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "technical", + "vibrant" + ], + "industry": "developer-tools", + "exemplary": false, + "note": "" + }, + { + "file": "youtube-icon.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "play triangle in red rounded screen", + "geometry": [ + "rounded-square", + "triangle" + ], + "techniques": [ + "negative-space", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "bold", + "iconic" + ], + "industry": "media-entertainment", + "exemplary": true, + "note": "Universal play symbol in a TV-shaped container; radical simplicity." + }, + { + "file": "youtube.svg", + "mark_type": "combination", + "symbol_type": "pictorial", + "subject": "play button beside condensed name", + "geometry": [ + "rounded-square" + ], + "techniques": [ + "containment", + "negative-space" + ], + "type_style": "grotesque-sans", + "case": "mixed", + "mood": [ + "bold", + "familiar" + ], + "industry": "media-entertainment", + "exemplary": false, + "note": "" + }, + { + "file": "zapier-icon.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "orange asterisk with square center", + "geometry": [ + "radial", + "star" + ], + "techniques": [ + "radial-symmetry", + "negative-space" + ], + "type_style": null, + "case": null, + "mood": [ + "energetic", + "bold" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "zapier.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "name with asterisk dotting the i", + "geometry": [], + "techniques": [ + "letter-substitution" + ], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "friendly", + "energetic" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "zend-framework.svg", + "mark_type": "lettermark", + "symbol_type": null, + "subject": "green Z and speed-striped F", + "geometry": [], + "techniques": [ + "motion-lines", + "ligature" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "fast", + "technical" + ], + "industry": "framework-library", + "exemplary": false, + "note": "" + }, + { + "file": "zendesk-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "Z from two triangles and semicircles", + "geometry": [ + "triangle", + "circle" + ], + "techniques": [ + "geometric-construction", + "negative-space", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "balanced", + "calm" + ], + "industry": "productivity-collaboration", + "exemplary": true, + "note": "Z built from two triangles and two semicircles; pure geometric construction." + }, + { + "file": "zendesk.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "lowercase name in dark green", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "lowercase", + "mood": [ + "calm", + "friendly" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "zenhub-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "white Z in purple square", + "geometry": [ + "square" + ], + "techniques": [ + "containment" + ], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "simple", + "solid" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "zenhub.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "bold camel-case name", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "mixed", + "mood": [ + "confident", + "technical" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "zeplin.svg", + "mark_type": "pictorial", + "symbol_type": null, + "subject": "orange zeppelin with orbit ring", + "geometry": [ + "organic" + ], + "techniques": [ + "gradient", + "dimensional-shading" + ], + "type_style": null, + "case": null, + "mood": [ + "playful", + "adventurous" + ], + "industry": "design-creative", + "exemplary": false, + "note": "" + }, + { + "file": "zoho.svg", + "mark_type": "wordmark", + "symbol_type": null, + "subject": "letters on colored 3D tiles", + "geometry": [ + "square" + ], + "techniques": [ + "containment", + "color-segments", + "dimensional-shading", + "modular-repetition" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "playful", + "colorful" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "zorin-os.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "Z carved from cyan hexagon bands", + "geometry": [ + "hexagon" + ], + "techniques": [ + "negative-space", + "geometric-construction" + ], + "type_style": null, + "case": null, + "mood": [ + "clean", + "modern" + ], + "industry": "os-platform", + "exemplary": true, + "note": "Z appears only through negative space between stacked bands." + }, + { + "file": "zube.svg", + "mark_type": "abstract", + "symbol_type": null, + "subject": "two chevrons forming broken hexagon", + "geometry": [ + "hexagon" + ], + "techniques": [ + "bracket-code", + "negative-space", + "mirror-symmetry" + ], + "type_style": null, + "case": null, + "mood": [ + "technical", + "balanced" + ], + "industry": "productivity-collaboration", + "exemplary": false, + "note": "" + }, + { + "file": "zulip-icon.svg", + "mark_type": "letterform", + "symbol_type": null, + "subject": "rounded Z in gradient circle", + "geometry": [ + "circle" + ], + "techniques": [ + "gradient", + "containment" + ], + "type_style": null, + "case": null, + "mood": [ + "friendly", + "modern" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "zulip.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "rounded Z beside tracked name", + "geometry": [], + "techniques": [], + "type_style": "geometric-sans", + "case": "uppercase", + "mood": [ + "friendly", + "clean" + ], + "industry": "social-communication", + "exemplary": false, + "note": "" + }, + { + "file": "zwave.svg", + "mark_type": "combination", + "symbol_type": "letterform", + "subject": "Z circle with radio arcs and name", + "geometry": [ + "circle" + ], + "techniques": [ + "motion-lines", + "containment" + ], + "type_style": "display-custom", + "case": "uppercase", + "mood": [ + "technical", + "connected" + ], + "industry": "hardware-devices", + "exemplary": false, + "note": "" + } +] \ No newline at end of file diff --git a/.claude/skills/logo-design/assets/library/gallery.html b/.claude/skills/logo-design/assets/library/gallery.html new file mode 100644 index 0000000..dbbd642 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/gallery.html @@ -0,0 +1,48 @@ + + +Logo Reference Library + +

Logo Reference Library — for studying patterns; all marks are trademarks of their owners. Never copy.

+
+ + + + + + + + +
+
+ diff --git a/.claude/skills/logo-design/assets/library/stats.json b/.claude/skills/logo-design/assets/library/stats.json new file mode 100644 index 0000000..385ae86 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/stats.json @@ -0,0 +1,392 @@ +{ + "count": 1432, + "anchors_all": { + "p10": 23.0, + "p25": 37.0, + "median": 75.0, + "p75": 155.0, + "p90": 257.8, + "p95": 379.45 + }, + "anchors_square": { + "p10": 21.0, + "p25": 31.0, + "median": 53.0, + "p75": 95.5, + "p90": 194.0, + "p95": 274.0 + }, + "shapes_all": { + "p10": 2.0, + "p25": 2.0, + "median": 3.0, + "p75": 6.0, + "p90": 12.0, + "p95": 19.0 + }, + "n_colors_all": { + "p10": 1.0, + "p25": 1.0, + "median": 2.0, + "p75": 4.0, + "p90": 7.0, + "p95": 10.0 + }, + "n_colors_square": { + "p10": 1.0, + "p25": 1.0, + "median": 2.0, + "p75": 4.0, + "p90": 7.0, + "p95": 10.0 + }, + "gradient_share": 0.19, + "mark_types": [ + [ + "abstract", + 337 + ], + [ + "combination", + 295 + ], + [ + "pictorial", + 289 + ], + [ + "letterform", + 218 + ], + [ + "wordmark", + 142 + ], + [ + "emblem", + 54 + ], + [ + "mascot", + 54 + ], + [ + "lettermark", + 43 + ] + ], + "primary_family": [ + [ + "multi", + 397 + ], + [ + "blue", + 319 + ], + [ + "mono", + 185 + ], + [ + "red", + 180 + ], + [ + "green", + 93 + ], + [ + "orange", + 92 + ], + [ + "cyan", + 66 + ], + [ + "purple", + 60 + ], + [ + "yellow", + 28 + ], + [ + "pink", + 12 + ] + ], + "aspect_class": [ + [ + "square", + 791 + ], + [ + "horizontal", + 223 + ], + [ + "wide", + 187 + ], + [ + "extra-wide", + 133 + ], + [ + "tall", + 98 + ] + ], + "techniques": [ + [ + "containment", + 453 + ], + [ + "negative-space", + 284 + ], + [ + "line-monoline", + 249 + ], + [ + "gradient", + 218 + ], + [ + "color-segments", + 204 + ], + [ + "dimensional-shading", + 147 + ], + [ + "geometric-construction", + 127 + ], + [ + "modular-repetition", + 107 + ], + [ + "overlap-transparency", + 104 + ], + [ + "hidden-meaning", + 103 + ], + [ + "isometric-3d", + 90 + ], + [ + "radial-symmetry", + 87 + ], + [ + "motion-lines", + 65 + ], + [ + "mirror-symmetry", + 64 + ], + [ + "arrow", + 57 + ], + [ + "letter-substitution", + 49 + ], + [ + "stacked-layers", + 49 + ], + [ + "bracket-code", + 46 + ], + [ + "hand-drawn", + 38 + ], + [ + "speech-bubble", + 29 + ], + [ + "ligature", + 16 + ], + [ + "infinity-loop", + 15 + ], + [ + "pixel", + 5 + ], + [ + "impossible-figure", + 2 + ] + ], + "geometry": [ + [ + "circle", + 367 + ], + [ + "organic", + 197 + ], + [ + "square", + 196 + ], + [ + "freeform", + 179 + ], + [ + "triangle", + 116 + ], + [ + "hexagon", + 114 + ], + [ + "rounded-square", + 99 + ], + [ + "radial", + 92 + ], + [ + "grid-modular", + 56 + ], + [ + "diamond", + 51 + ], + [ + "shield", + 16 + ], + [ + "star", + 11 + ] + ], + "industries": [ + [ + "developer-tools", + 295 + ], + [ + "framework-library", + 247 + ], + [ + "cloud-infrastructure", + 97 + ], + [ + "database-data", + 90 + ], + [ + "testing-monitoring", + 89 + ], + [ + "productivity-collaboration", + 81 + ], + [ + "marketing-analytics", + 78 + ], + [ + "programming-language", + 70 + ], + [ + "social-communication", + 61 + ], + [ + "os-platform", + 46 + ], + [ + "payments-fintech", + 37 + ], + [ + "design-creative", + 35 + ], + [ + "security-identity", + 34 + ], + [ + "hosting-cdn", + 32 + ], + [ + "media-entertainment", + 30 + ], + [ + "education", + 23 + ], + [ + "ecommerce-retail", + 20 + ], + [ + "open-source-community", + 16 + ], + [ + "hardware-devices", + 14 + ], + [ + "ai-ml", + 12 + ], + [ + "other", + 11 + ], + [ + "gaming", + 5 + ], + [ + "travel-transport", + 4 + ], + [ + "finance-banking", + 4 + ], + [ + "health", + 1 + ] + ] +} \ No newline at end of file diff --git a/.claude/skills/logo-design/assets/library/svg/100tb.svg b/.claude/skills/logo-design/assets/library/svg/100tb.svg new file mode 100644 index 0000000..1185fe5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/100tb.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/500px.svg b/.claude/skills/logo-design/assets/library/svg/500px.svg new file mode 100644 index 0000000..7d3b360 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/500px.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/active-campaign-icon.svg b/.claude/skills/logo-design/assets/library/svg/active-campaign-icon.svg new file mode 100644 index 0000000..9794529 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/active-campaign-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/active-campaign.svg b/.claude/skills/logo-design/assets/library/svg/active-campaign.svg new file mode 100644 index 0000000..2e3062b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/active-campaign.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/adonisjs-icon.svg b/.claude/skills/logo-design/assets/library/svg/adonisjs-icon.svg new file mode 100644 index 0000000..e42f9bf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/adonisjs-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/adonisjs.svg b/.claude/skills/logo-design/assets/library/svg/adonisjs.svg new file mode 100644 index 0000000..4735e04 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/adonisjs.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/adroll.svg b/.claude/skills/logo-design/assets/library/svg/adroll.svg new file mode 100644 index 0000000..333e49e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/adroll.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/adyen.svg b/.claude/skills/logo-design/assets/library/svg/adyen.svg new file mode 100644 index 0000000..f6c68d5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/adyen.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aerospike-icon.svg b/.claude/skills/logo-design/assets/library/svg/aerospike-icon.svg new file mode 100644 index 0000000..351a351 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aerospike-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aerospike.svg b/.claude/skills/logo-design/assets/library/svg/aerospike.svg new file mode 100644 index 0000000..e7bbcb5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aerospike.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/airbnb.svg b/.claude/skills/logo-design/assets/library/svg/airbnb.svg new file mode 100644 index 0000000..08f9ee8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/airbnb.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/airbrake.svg b/.claude/skills/logo-design/assets/library/svg/airbrake.svg new file mode 100644 index 0000000..5fcc679 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/airbrake.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/airflow.svg b/.claude/skills/logo-design/assets/library/svg/airflow.svg new file mode 100644 index 0000000..aeb3662 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/airflow.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/airtable.svg b/.claude/skills/logo-design/assets/library/svg/airtable.svg new file mode 100644 index 0000000..ce297b9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/airtable.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/akamai.svg b/.claude/skills/logo-design/assets/library/svg/akamai.svg new file mode 100644 index 0000000..5078b5f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/akamai.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/akka.svg b/.claude/skills/logo-design/assets/library/svg/akka.svg new file mode 100644 index 0000000..9905561 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/akka.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/alfresco.svg b/.claude/skills/logo-design/assets/library/svg/alfresco.svg new file mode 100644 index 0000000..627fa1d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/alfresco.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/algolia.svg b/.claude/skills/logo-design/assets/library/svg/algolia.svg new file mode 100644 index 0000000..c5f1db4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/algolia.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/alpinejs-icon.svg b/.claude/skills/logo-design/assets/library/svg/alpinejs-icon.svg new file mode 100644 index 0000000..4a96b6a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/alpinejs-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/alpinejs.svg b/.claude/skills/logo-design/assets/library/svg/alpinejs.svg new file mode 100644 index 0000000..bfeb142 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/alpinejs.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/altair.svg b/.claude/skills/logo-design/assets/library/svg/altair.svg new file mode 100644 index 0000000..8c9514f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/altair.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/amazon-chime.svg b/.claude/skills/logo-design/assets/library/svg/amazon-chime.svg new file mode 100644 index 0000000..d877b4b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/amazon-chime.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/amazon-connect.svg b/.claude/skills/logo-design/assets/library/svg/amazon-connect.svg new file mode 100644 index 0000000..e44cfc8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/amazon-connect.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/amex.svg b/.claude/skills/logo-design/assets/library/svg/amex.svg new file mode 100644 index 0000000..6aa4f4e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/amex.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/amp-icon.svg b/.claude/skills/logo-design/assets/library/svg/amp-icon.svg new file mode 100644 index 0000000..ff1c1bb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/amp-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/amp.svg b/.claude/skills/logo-design/assets/library/svg/amp.svg new file mode 100644 index 0000000..027adec --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/amp.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ampersand.svg b/.claude/skills/logo-design/assets/library/svg/ampersand.svg new file mode 100644 index 0000000..d207f01 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ampersand.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/amplication-icon.svg b/.claude/skills/logo-design/assets/library/svg/amplication-icon.svg new file mode 100644 index 0000000..d34493d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/amplication-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/amplication.svg b/.claude/skills/logo-design/assets/library/svg/amplication.svg new file mode 100644 index 0000000..b81ff70 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/amplication.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/amplitude-icon.svg b/.claude/skills/logo-design/assets/library/svg/amplitude-icon.svg new file mode 100644 index 0000000..7b98e42 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/amplitude-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/amplitude.svg b/.claude/skills/logo-design/assets/library/svg/amplitude.svg new file mode 100644 index 0000000..801d30a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/amplitude.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/android-icon.svg b/.claude/skills/logo-design/assets/library/svg/android-icon.svg new file mode 100644 index 0000000..1954e37 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/android-icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/android.svg b/.claude/skills/logo-design/assets/library/svg/android.svg new file mode 100644 index 0000000..e390835 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/android.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/angellist.svg b/.claude/skills/logo-design/assets/library/svg/angellist.svg new file mode 100644 index 0000000..b9d9e55 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/angellist.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/angular-icon.svg b/.claude/skills/logo-design/assets/library/svg/angular-icon.svg new file mode 100644 index 0000000..5dfcee3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/angular-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/angular.svg b/.claude/skills/logo-design/assets/library/svg/angular.svg new file mode 100644 index 0000000..dc024a9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/angular.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ansible.svg b/.claude/skills/logo-design/assets/library/svg/ansible.svg new file mode 100644 index 0000000..7e2616a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ansible.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ant-design.svg b/.claude/skills/logo-design/assets/library/svg/ant-design.svg new file mode 100644 index 0000000..45b04fd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ant-design.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/apache-camel.svg b/.claude/skills/logo-design/assets/library/svg/apache-camel.svg new file mode 100644 index 0000000..7020caf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/apache-camel.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/apache.svg b/.claude/skills/logo-design/assets/library/svg/apache.svg new file mode 100644 index 0000000..93e9413 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/apache.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/apache_cloudstack.svg b/.claude/skills/logo-design/assets/library/svg/apache_cloudstack.svg new file mode 100644 index 0000000..0e0d8b1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/apache_cloudstack.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/apiary.svg b/.claude/skills/logo-design/assets/library/svg/apiary.svg new file mode 100644 index 0000000..155984a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/apiary.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/apollostack.svg b/.claude/skills/logo-design/assets/library/svg/apollostack.svg new file mode 100644 index 0000000..15eed98 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/apollostack.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/apostrophe.svg b/.claude/skills/logo-design/assets/library/svg/apostrophe.svg new file mode 100644 index 0000000..5eeb009 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/apostrophe.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/appbaseio-icon.svg b/.claude/skills/logo-design/assets/library/svg/appbaseio-icon.svg new file mode 100644 index 0000000..4266e02 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/appbaseio-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/appbaseio.svg b/.claude/skills/logo-design/assets/library/svg/appbaseio.svg new file mode 100644 index 0000000..4f604cb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/appbaseio.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/appcircle-icon.svg b/.claude/skills/logo-design/assets/library/svg/appcircle-icon.svg new file mode 100644 index 0000000..cee02d2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/appcircle-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/appcircle.svg b/.claude/skills/logo-design/assets/library/svg/appcircle.svg new file mode 100644 index 0000000..57150be --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/appcircle.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/appcode.svg b/.claude/skills/logo-design/assets/library/svg/appcode.svg new file mode 100644 index 0000000..a2588c7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/appcode.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/appdynamics.svg b/.claude/skills/logo-design/assets/library/svg/appdynamics.svg new file mode 100644 index 0000000..4d076a3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/appdynamics.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/appium.svg b/.claude/skills/logo-design/assets/library/svg/appium.svg new file mode 100644 index 0000000..04656bc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/appium.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/apple-app-store.svg b/.claude/skills/logo-design/assets/library/svg/apple-app-store.svg new file mode 100644 index 0000000..fd3013c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/apple-app-store.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/apple-pay.svg b/.claude/skills/logo-design/assets/library/svg/apple-pay.svg new file mode 100644 index 0000000..398449d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/apple-pay.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/apple.svg b/.claude/skills/logo-design/assets/library/svg/apple.svg new file mode 100644 index 0000000..7df4759 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/apple.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/appsignal-icon.svg b/.claude/skills/logo-design/assets/library/svg/appsignal-icon.svg new file mode 100644 index 0000000..3677db9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/appsignal-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/appsignal.svg b/.claude/skills/logo-design/assets/library/svg/appsignal.svg new file mode 100644 index 0000000..50728df --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/appsignal.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/apptentive.svg b/.claude/skills/logo-design/assets/library/svg/apptentive.svg new file mode 100644 index 0000000..8ce72c9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/apptentive.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/appveyor.svg b/.claude/skills/logo-design/assets/library/svg/appveyor.svg new file mode 100644 index 0000000..a56fea7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/appveyor.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/arangodb.svg b/.claude/skills/logo-design/assets/library/svg/arangodb.svg new file mode 100644 index 0000000..2bdc560 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/arangodb.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/archlinux.svg b/.claude/skills/logo-design/assets/library/svg/archlinux.svg new file mode 100644 index 0000000..0918af8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/archlinux.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/arduino.svg b/.claude/skills/logo-design/assets/library/svg/arduino.svg new file mode 100644 index 0000000..6e3ae9f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/arduino.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/argo-icon.svg b/.claude/skills/logo-design/assets/library/svg/argo-icon.svg new file mode 100644 index 0000000..68c93c5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/argo-icon.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/argo.svg b/.claude/skills/logo-design/assets/library/svg/argo.svg new file mode 100644 index 0000000..4c88f7d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/argo.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/armory.svg b/.claude/skills/logo-design/assets/library/svg/armory.svg new file mode 100644 index 0000000..0277c9b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/armory.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/asana.svg b/.claude/skills/logo-design/assets/library/svg/asana.svg new file mode 100644 index 0000000..0d25e24 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/asana.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/asciidoctor.svg b/.claude/skills/logo-design/assets/library/svg/asciidoctor.svg new file mode 100644 index 0000000..bec60ae --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/asciidoctor.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/assembla-icon.svg b/.claude/skills/logo-design/assets/library/svg/assembla-icon.svg new file mode 100644 index 0000000..f14f087 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/assembla-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/assembla.svg b/.claude/skills/logo-design/assets/library/svg/assembla.svg new file mode 100644 index 0000000..ca90d7a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/assembla.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/astro.svg b/.claude/skills/logo-design/assets/library/svg/astro.svg new file mode 100644 index 0000000..46df279 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/astro.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/astronomer.svg b/.claude/skills/logo-design/assets/library/svg/astronomer.svg new file mode 100644 index 0000000..26afb9c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/astronomer.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/atlassian.svg b/.claude/skills/logo-design/assets/library/svg/atlassian.svg new file mode 100644 index 0000000..9342b52 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/atlassian.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/atom-icon.svg b/.claude/skills/logo-design/assets/library/svg/atom-icon.svg new file mode 100644 index 0000000..1c7b923 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/atom-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/atom.svg b/.claude/skills/logo-design/assets/library/svg/atom.svg new file mode 100644 index 0000000..76ef302 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/atom.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/atomic-icon.svg b/.claude/skills/logo-design/assets/library/svg/atomic-icon.svg new file mode 100644 index 0000000..5144e69 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/atomic-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/atomic.svg b/.claude/skills/logo-design/assets/library/svg/atomic.svg new file mode 100644 index 0000000..e93226b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/atomic.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aurelia.svg b/.claude/skills/logo-design/assets/library/svg/aurelia.svg new file mode 100644 index 0000000..4b8c27e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aurelia.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aurora.svg b/.claude/skills/logo-design/assets/library/svg/aurora.svg new file mode 100644 index 0000000..3ae76ca --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aurora.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/auth0-icon.svg b/.claude/skills/logo-design/assets/library/svg/auth0-icon.svg new file mode 100644 index 0000000..39fc597 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/auth0-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/auth0.svg b/.claude/skills/logo-design/assets/library/svg/auth0.svg new file mode 100644 index 0000000..24a9c78 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/auth0.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/authy.svg b/.claude/skills/logo-design/assets/library/svg/authy.svg new file mode 100644 index 0000000..2501d63 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/authy.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/autoit.svg b/.claude/skills/logo-design/assets/library/svg/autoit.svg new file mode 100644 index 0000000..b5f4d26 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/autoit.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/autoprefixer.svg b/.claude/skills/logo-design/assets/library/svg/autoprefixer.svg new file mode 100644 index 0000000..c8bbcc1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/autoprefixer.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ava.svg b/.claude/skills/logo-design/assets/library/svg/ava.svg new file mode 100644 index 0000000..f6a3df1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ava.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/awesome.svg b/.claude/skills/logo-design/assets/library/svg/awesome.svg new file mode 100644 index 0000000..34c89ca --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/awesome.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-amplify.svg b/.claude/skills/logo-design/assets/library/svg/aws-amplify.svg new file mode 100644 index 0000000..94f4181 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-amplify.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-api-gateway.svg b/.claude/skills/logo-design/assets/library/svg/aws-api-gateway.svg new file mode 100644 index 0000000..c92875e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-api-gateway.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-app-mesh.svg b/.claude/skills/logo-design/assets/library/svg/aws-app-mesh.svg new file mode 100644 index 0000000..9a15d3e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-app-mesh.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-appflow.svg b/.claude/skills/logo-design/assets/library/svg/aws-appflow.svg new file mode 100644 index 0000000..3d00fe8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-appflow.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-appsync.svg b/.claude/skills/logo-design/assets/library/svg/aws-appsync.svg new file mode 100644 index 0000000..2c07eae --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-appsync.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-athena.svg b/.claude/skills/logo-design/assets/library/svg/aws-athena.svg new file mode 100644 index 0000000..32a0e25 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-athena.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-aurora.svg b/.claude/skills/logo-design/assets/library/svg/aws-aurora.svg new file mode 100644 index 0000000..29fab41 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-aurora.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-backup.svg b/.claude/skills/logo-design/assets/library/svg/aws-backup.svg new file mode 100644 index 0000000..54ee04f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-backup.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-batch.svg b/.claude/skills/logo-design/assets/library/svg/aws-batch.svg new file mode 100644 index 0000000..e2dc790 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-batch.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-certificate-manager.svg b/.claude/skills/logo-design/assets/library/svg/aws-certificate-manager.svg new file mode 100644 index 0000000..ae2f384 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-certificate-manager.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cloudformation.svg b/.claude/skills/logo-design/assets/library/svg/aws-cloudformation.svg new file mode 100644 index 0000000..589ef2e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-cloudformation.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cloudfront.svg b/.claude/skills/logo-design/assets/library/svg/aws-cloudfront.svg new file mode 100644 index 0000000..2ec3290 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-cloudfront.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cloudsearch.svg b/.claude/skills/logo-design/assets/library/svg/aws-cloudsearch.svg new file mode 100644 index 0000000..611a209 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-cloudsearch.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cloudtrail.svg b/.claude/skills/logo-design/assets/library/svg/aws-cloudtrail.svg new file mode 100644 index 0000000..83ca66d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-cloudtrail.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cloudwatch.svg b/.claude/skills/logo-design/assets/library/svg/aws-cloudwatch.svg new file mode 100644 index 0000000..d9c362e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-cloudwatch.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-codebuild.svg b/.claude/skills/logo-design/assets/library/svg/aws-codebuild.svg new file mode 100644 index 0000000..b4f7b3c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-codebuild.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-codecommit.svg b/.claude/skills/logo-design/assets/library/svg/aws-codecommit.svg new file mode 100644 index 0000000..d0ae4d6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-codecommit.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-codedeploy.svg b/.claude/skills/logo-design/assets/library/svg/aws-codedeploy.svg new file mode 100644 index 0000000..d8b1c92 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-codedeploy.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-codepipeline.svg b/.claude/skills/logo-design/assets/library/svg/aws-codepipeline.svg new file mode 100644 index 0000000..3cdce33 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-codepipeline.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-codestar.svg b/.claude/skills/logo-design/assets/library/svg/aws-codestar.svg new file mode 100644 index 0000000..2539bcb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-codestar.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cognito.svg b/.claude/skills/logo-design/assets/library/svg/aws-cognito.svg new file mode 100644 index 0000000..d477834 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-cognito.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-config.svg b/.claude/skills/logo-design/assets/library/svg/aws-config.svg new file mode 100644 index 0000000..47c6464 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-config.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-documentdb.svg b/.claude/skills/logo-design/assets/library/svg/aws-documentdb.svg new file mode 100644 index 0000000..0edb67b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-documentdb.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-dynamodb.svg b/.claude/skills/logo-design/assets/library/svg/aws-dynamodb.svg new file mode 100644 index 0000000..b0cdfbe --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-dynamodb.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-ec2.svg b/.claude/skills/logo-design/assets/library/svg/aws-ec2.svg new file mode 100644 index 0000000..7fb0c8d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-ec2.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-ecs.svg b/.claude/skills/logo-design/assets/library/svg/aws-ecs.svg new file mode 100644 index 0000000..feddc5b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-ecs.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-eks.svg b/.claude/skills/logo-design/assets/library/svg/aws-eks.svg new file mode 100644 index 0000000..c12d201 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-eks.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-elastic-beanstalk.svg b/.claude/skills/logo-design/assets/library/svg/aws-elastic-beanstalk.svg new file mode 100644 index 0000000..f105019 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-elastic-beanstalk.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-elasticache.svg b/.claude/skills/logo-design/assets/library/svg/aws-elasticache.svg new file mode 100644 index 0000000..11b9e0d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-elasticache.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-elb.svg b/.claude/skills/logo-design/assets/library/svg/aws-elb.svg new file mode 100644 index 0000000..d4fa7f6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-elb.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-eventbridge.svg b/.claude/skills/logo-design/assets/library/svg/aws-eventbridge.svg new file mode 100644 index 0000000..8edd382 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-eventbridge.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-fargate.svg b/.claude/skills/logo-design/assets/library/svg/aws-fargate.svg new file mode 100644 index 0000000..03fe19c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-fargate.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-glacier.svg b/.claude/skills/logo-design/assets/library/svg/aws-glacier.svg new file mode 100644 index 0000000..ef5e82d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-glacier.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-glue.svg b/.claude/skills/logo-design/assets/library/svg/aws-glue.svg new file mode 100644 index 0000000..328862b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-glue.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-iam.svg b/.claude/skills/logo-design/assets/library/svg/aws-iam.svg new file mode 100644 index 0000000..251ddb2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-iam.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-keyspaces.svg b/.claude/skills/logo-design/assets/library/svg/aws-keyspaces.svg new file mode 100644 index 0000000..6777cde --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-keyspaces.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-kinesis.svg b/.claude/skills/logo-design/assets/library/svg/aws-kinesis.svg new file mode 100644 index 0000000..378fe79 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-kinesis.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-kms.svg b/.claude/skills/logo-design/assets/library/svg/aws-kms.svg new file mode 100644 index 0000000..b8228fd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-kms.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-lake-formation.svg b/.claude/skills/logo-design/assets/library/svg/aws-lake-formation.svg new file mode 100644 index 0000000..a7a6e0d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-lake-formation.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-lambda.svg b/.claude/skills/logo-design/assets/library/svg/aws-lambda.svg new file mode 100644 index 0000000..6c166d4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-lambda.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-lightsail.svg b/.claude/skills/logo-design/assets/library/svg/aws-lightsail.svg new file mode 100644 index 0000000..c4f62b5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-lightsail.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-mq.svg b/.claude/skills/logo-design/assets/library/svg/aws-mq.svg new file mode 100644 index 0000000..96dfd0a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-mq.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-msk.svg b/.claude/skills/logo-design/assets/library/svg/aws-msk.svg new file mode 100644 index 0000000..0c83d0f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-msk.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-neptune.svg b/.claude/skills/logo-design/assets/library/svg/aws-neptune.svg new file mode 100644 index 0000000..4a9c1a3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-neptune.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-open-search.svg b/.claude/skills/logo-design/assets/library/svg/aws-open-search.svg new file mode 100644 index 0000000..4cff6b4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-open-search.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-opsworks.svg b/.claude/skills/logo-design/assets/library/svg/aws-opsworks.svg new file mode 100644 index 0000000..fc08827 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-opsworks.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-quicksight.svg b/.claude/skills/logo-design/assets/library/svg/aws-quicksight.svg new file mode 100644 index 0000000..2624e2c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-quicksight.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-rds.svg b/.claude/skills/logo-design/assets/library/svg/aws-rds.svg new file mode 100644 index 0000000..cfd258b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-rds.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-redshift.svg b/.claude/skills/logo-design/assets/library/svg/aws-redshift.svg new file mode 100644 index 0000000..1ad29b9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-redshift.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-route53.svg b/.claude/skills/logo-design/assets/library/svg/aws-route53.svg new file mode 100644 index 0000000..e51e4fa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-route53.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-s3.svg b/.claude/skills/logo-design/assets/library/svg/aws-s3.svg new file mode 100644 index 0000000..d7fd723 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-s3.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-secrets-manager.svg b/.claude/skills/logo-design/assets/library/svg/aws-secrets-manager.svg new file mode 100644 index 0000000..38cb97a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-secrets-manager.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-ses.svg b/.claude/skills/logo-design/assets/library/svg/aws-ses.svg new file mode 100644 index 0000000..968dad3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-ses.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-shield.svg b/.claude/skills/logo-design/assets/library/svg/aws-shield.svg new file mode 100644 index 0000000..0d4e63f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-shield.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-sns.svg b/.claude/skills/logo-design/assets/library/svg/aws-sns.svg new file mode 100644 index 0000000..77ffedb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-sns.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-sqs.svg b/.claude/skills/logo-design/assets/library/svg/aws-sqs.svg new file mode 100644 index 0000000..a1fb7b5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-sqs.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-step-functions.svg b/.claude/skills/logo-design/assets/library/svg/aws-step-functions.svg new file mode 100644 index 0000000..4ba08e8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-step-functions.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-systems-manager.svg b/.claude/skills/logo-design/assets/library/svg/aws-systems-manager.svg new file mode 100644 index 0000000..a1c575f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-systems-manager.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-timestream.svg b/.claude/skills/logo-design/assets/library/svg/aws-timestream.svg new file mode 100644 index 0000000..4da73ca --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-timestream.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-vpc.svg b/.claude/skills/logo-design/assets/library/svg/aws-vpc.svg new file mode 100644 index 0000000..9182bed --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-vpc.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-waf.svg b/.claude/skills/logo-design/assets/library/svg/aws-waf.svg new file mode 100644 index 0000000..4e20810 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-waf.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws-xray.svg b/.claude/skills/logo-design/assets/library/svg/aws-xray.svg new file mode 100644 index 0000000..5ffc0ac --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws-xray.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/aws.svg b/.claude/skills/logo-design/assets/library/svg/aws.svg new file mode 100644 index 0000000..5d367be --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/aws.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/axios.svg b/.claude/skills/logo-design/assets/library/svg/axios.svg new file mode 100644 index 0000000..07e8d28 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/axios.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/babel.svg b/.claude/skills/logo-design/assets/library/svg/babel.svg new file mode 100644 index 0000000..9a3fd35 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/babel.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/backbone-icon.svg b/.claude/skills/logo-design/assets/library/svg/backbone-icon.svg new file mode 100644 index 0000000..94cd948 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/backbone-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/backbone.svg b/.claude/skills/logo-design/assets/library/svg/backbone.svg new file mode 100644 index 0000000..a5bd0a7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/backbone.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/backerkit.svg b/.claude/skills/logo-design/assets/library/svg/backerkit.svg new file mode 100644 index 0000000..0807d55 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/backerkit.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/baker-street.svg b/.claude/skills/logo-design/assets/library/svg/baker-street.svg new file mode 100644 index 0000000..a7bd632 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/baker-street.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/balena.svg b/.claude/skills/logo-design/assets/library/svg/balena.svg new file mode 100644 index 0000000..7e52088 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/balena.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bamboo.svg b/.claude/skills/logo-design/assets/library/svg/bamboo.svg new file mode 100644 index 0000000..272298b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bamboo.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/basecamp.svg b/.claude/skills/logo-design/assets/library/svg/basecamp.svg new file mode 100644 index 0000000..cc7c508 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/basecamp.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/basekit.svg b/.claude/skills/logo-design/assets/library/svg/basekit.svg new file mode 100644 index 0000000..23f6884 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/basekit.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bash-icon.svg b/.claude/skills/logo-design/assets/library/svg/bash-icon.svg new file mode 100644 index 0000000..6278eac --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bash-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bash.svg b/.claude/skills/logo-design/assets/library/svg/bash.svg new file mode 100644 index 0000000..1c79b18 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bash.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/batch.svg b/.claude/skills/logo-design/assets/library/svg/batch.svg new file mode 100644 index 0000000..d590c7e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/batch.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/beats.svg b/.claude/skills/logo-design/assets/library/svg/beats.svg new file mode 100644 index 0000000..710f0f4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/beats.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/behance.svg b/.claude/skills/logo-design/assets/library/svg/behance.svg new file mode 100644 index 0000000..bf4f5c8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/behance.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bem-2.svg b/.claude/skills/logo-design/assets/library/svg/bem-2.svg new file mode 100644 index 0000000..d4cdb78 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bem-2.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bem.svg b/.claude/skills/logo-design/assets/library/svg/bem.svg new file mode 100644 index 0000000..4e3499b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bem.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bigpanda.svg b/.claude/skills/logo-design/assets/library/svg/bigpanda.svg new file mode 100644 index 0000000..98a7d12 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bigpanda.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bing.svg b/.claude/skills/logo-design/assets/library/svg/bing.svg new file mode 100644 index 0000000..750f1f2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bing.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bitbucket.svg b/.claude/skills/logo-design/assets/library/svg/bitbucket.svg new file mode 100644 index 0000000..54d8681 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bitbucket.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bitcoin.svg b/.claude/skills/logo-design/assets/library/svg/bitcoin.svg new file mode 100644 index 0000000..a140fe3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bitcoin.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bitnami.svg b/.claude/skills/logo-design/assets/library/svg/bitnami.svg new file mode 100644 index 0000000..5727987 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bitnami.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bitrise-icon.svg b/.claude/skills/logo-design/assets/library/svg/bitrise-icon.svg new file mode 100644 index 0000000..140928d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bitrise-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bitrise.svg b/.claude/skills/logo-design/assets/library/svg/bitrise.svg new file mode 100644 index 0000000..4047ddd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bitrise.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/blender.svg b/.claude/skills/logo-design/assets/library/svg/blender.svg new file mode 100644 index 0000000..c062924 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/blender.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/blitzjs-icon.svg b/.claude/skills/logo-design/assets/library/svg/blitzjs-icon.svg new file mode 100644 index 0000000..24a5c4f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/blitzjs-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/blitzjs.svg b/.claude/skills/logo-design/assets/library/svg/blitzjs.svg new file mode 100644 index 0000000..b62e846 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/blitzjs.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/blocs.svg b/.claude/skills/logo-design/assets/library/svg/blocs.svg new file mode 100644 index 0000000..001c5ed --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/blocs.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/blogger.svg b/.claude/skills/logo-design/assets/library/svg/blogger.svg new file mode 100644 index 0000000..5de87ff --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/blogger.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/blossom.svg b/.claude/skills/logo-design/assets/library/svg/blossom.svg new file mode 100644 index 0000000..f2d2819 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/blossom.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/blueprint.svg b/.claude/skills/logo-design/assets/library/svg/blueprint.svg new file mode 100644 index 0000000..7edc06f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/blueprint.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bluetooth.svg b/.claude/skills/logo-design/assets/library/svg/bluetooth.svg new file mode 100644 index 0000000..05e51f5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bluetooth.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/booqable-icon.svg b/.claude/skills/logo-design/assets/library/svg/booqable-icon.svg new file mode 100644 index 0000000..5b0334c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/booqable-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/booqable.svg b/.claude/skills/logo-design/assets/library/svg/booqable.svg new file mode 100644 index 0000000..7debde9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/booqable.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bootstrap.svg b/.claude/skills/logo-design/assets/library/svg/bootstrap.svg new file mode 100644 index 0000000..f91cfe6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bootstrap.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bosun.svg b/.claude/skills/logo-design/assets/library/svg/bosun.svg new file mode 100644 index 0000000..49d911a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bosun.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/botanalytics.svg b/.claude/skills/logo-design/assets/library/svg/botanalytics.svg new file mode 100644 index 0000000..9e6c161 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/botanalytics.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bourbon.svg b/.claude/skills/logo-design/assets/library/svg/bourbon.svg new file mode 100644 index 0000000..422822a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bourbon.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bower.svg b/.claude/skills/logo-design/assets/library/svg/bower.svg new file mode 100644 index 0000000..c88f3e5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bower.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/box.svg b/.claude/skills/logo-design/assets/library/svg/box.svg new file mode 100644 index 0000000..8e6d7d8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/box.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/brackets.svg b/.claude/skills/logo-design/assets/library/svg/brackets.svg new file mode 100644 index 0000000..419544c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/brackets.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/brainjs.svg b/.claude/skills/logo-design/assets/library/svg/brainjs.svg new file mode 100644 index 0000000..bb46892 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/brainjs.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/branch.svg b/.claude/skills/logo-design/assets/library/svg/branch.svg new file mode 100644 index 0000000..52103e0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/branch.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/brandfolder-icon.svg b/.claude/skills/logo-design/assets/library/svg/brandfolder-icon.svg new file mode 100644 index 0000000..5cc4e7f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/brandfolder-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/brandfolder.svg b/.claude/skills/logo-design/assets/library/svg/brandfolder.svg new file mode 100644 index 0000000..feda0c0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/brandfolder.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/brave.svg b/.claude/skills/logo-design/assets/library/svg/brave.svg new file mode 100644 index 0000000..606628c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/brave.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/braze.svg b/.claude/skills/logo-design/assets/library/svg/braze.svg new file mode 100644 index 0000000..a3a0286 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/braze.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/broccoli.svg b/.claude/skills/logo-design/assets/library/svg/broccoli.svg new file mode 100644 index 0000000..bafb03c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/broccoli.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/brotli.svg b/.claude/skills/logo-design/assets/library/svg/brotli.svg new file mode 100644 index 0000000..f49a226 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/brotli.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/browserify-icon.svg b/.claude/skills/logo-design/assets/library/svg/browserify-icon.svg new file mode 100644 index 0000000..4554828 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/browserify-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/browserify.svg b/.claude/skills/logo-design/assets/library/svg/browserify.svg new file mode 100644 index 0000000..235f4e2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/browserify.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/browserling.svg b/.claude/skills/logo-design/assets/library/svg/browserling.svg new file mode 100644 index 0000000..ce96585 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/browserling.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/browserslist.svg b/.claude/skills/logo-design/assets/library/svg/browserslist.svg new file mode 100644 index 0000000..ac0efac --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/browserslist.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/browserstack.svg b/.claude/skills/logo-design/assets/library/svg/browserstack.svg new file mode 100644 index 0000000..bc5c164 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/browserstack.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/browsersync.svg b/.claude/skills/logo-design/assets/library/svg/browsersync.svg new file mode 100644 index 0000000..08315f6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/browsersync.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/brunch.svg b/.claude/skills/logo-design/assets/library/svg/brunch.svg new file mode 100644 index 0000000..5562f78 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/brunch.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/buck.svg b/.claude/skills/logo-design/assets/library/svg/buck.svg new file mode 100644 index 0000000..90e8790 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/buck.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/buddy.svg b/.claude/skills/logo-design/assets/library/svg/buddy.svg new file mode 100644 index 0000000..1764223 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/buddy.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/buffer.svg b/.claude/skills/logo-design/assets/library/svg/buffer.svg new file mode 100644 index 0000000..13b682b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/buffer.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bugherd.svg b/.claude/skills/logo-design/assets/library/svg/bugherd.svg new file mode 100644 index 0000000..2ff15ff --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bugherd.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bugsee.svg b/.claude/skills/logo-design/assets/library/svg/bugsee.svg new file mode 100644 index 0000000..eaf8bcf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bugsee.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bugsnag-icon.svg b/.claude/skills/logo-design/assets/library/svg/bugsnag-icon.svg new file mode 100644 index 0000000..087d9e2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bugsnag-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bugsnag.svg b/.claude/skills/logo-design/assets/library/svg/bugsnag.svg new file mode 100644 index 0000000..2068d3f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bugsnag.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/buildkite-icon.svg b/.claude/skills/logo-design/assets/library/svg/buildkite-icon.svg new file mode 100644 index 0000000..07c4e16 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/buildkite-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/buildkite.svg b/.claude/skills/logo-design/assets/library/svg/buildkite.svg new file mode 100644 index 0000000..d9e3401 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/buildkite.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/bulma.svg b/.claude/skills/logo-design/assets/library/svg/bulma.svg new file mode 100644 index 0000000..8a7ca38 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/bulma.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/c-plusplus.svg b/.claude/skills/logo-design/assets/library/svg/c-plusplus.svg new file mode 100644 index 0000000..91c25d3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/c-plusplus.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/c-sharp.svg b/.claude/skills/logo-design/assets/library/svg/c-sharp.svg new file mode 100644 index 0000000..ba9cad6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/c-sharp.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/c.svg b/.claude/skills/logo-design/assets/library/svg/c.svg new file mode 100644 index 0000000..f5812f4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/c.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cachet.svg b/.claude/skills/logo-design/assets/library/svg/cachet.svg new file mode 100644 index 0000000..1f41727 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cachet.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/caffe2.svg b/.claude/skills/logo-design/assets/library/svg/caffe2.svg new file mode 100644 index 0000000..e8bb3f4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/caffe2.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cakephp-icon.svg b/.claude/skills/logo-design/assets/library/svg/cakephp-icon.svg new file mode 100644 index 0000000..f4933c7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cakephp-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cakephp.svg b/.claude/skills/logo-design/assets/library/svg/cakephp.svg new file mode 100644 index 0000000..88ee12d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cakephp.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/campaignmonitor-icon.svg b/.claude/skills/logo-design/assets/library/svg/campaignmonitor-icon.svg new file mode 100644 index 0000000..59e4046 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/campaignmonitor-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/campaignmonitor.svg b/.claude/skills/logo-design/assets/library/svg/campaignmonitor.svg new file mode 100644 index 0000000..e2534cd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/campaignmonitor.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/canjs.svg b/.claude/skills/logo-design/assets/library/svg/canjs.svg new file mode 100644 index 0000000..54f02a3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/canjs.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/capacitorjs-icon.svg b/.claude/skills/logo-design/assets/library/svg/capacitorjs-icon.svg new file mode 100644 index 0000000..641803c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/capacitorjs-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/capacitorjs.svg b/.claude/skills/logo-design/assets/library/svg/capacitorjs.svg new file mode 100644 index 0000000..6245076 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/capacitorjs.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/capistrano.svg b/.claude/skills/logo-design/assets/library/svg/capistrano.svg new file mode 100644 index 0000000..47b7ed9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/capistrano.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/carbide.svg b/.claude/skills/logo-design/assets/library/svg/carbide.svg new file mode 100644 index 0000000..42fb54a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/carbide.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cardano-icon.svg b/.claude/skills/logo-design/assets/library/svg/cardano-icon.svg new file mode 100644 index 0000000..323e020 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cardano-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cardano.svg b/.claude/skills/logo-design/assets/library/svg/cardano.svg new file mode 100644 index 0000000..e53cfdb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cardano.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cassandra.svg b/.claude/skills/logo-design/assets/library/svg/cassandra.svg new file mode 100644 index 0000000..9ff5291 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cassandra.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/centos-icon.svg b/.claude/skills/logo-design/assets/library/svg/centos-icon.svg new file mode 100644 index 0000000..f02f9ec --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/centos-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/centos.svg b/.claude/skills/logo-design/assets/library/svg/centos.svg new file mode 100644 index 0000000..a9ad316 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/centos.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/certbot.svg b/.claude/skills/logo-design/assets/library/svg/certbot.svg new file mode 100644 index 0000000..ddf2a6b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/certbot.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ceylon.svg b/.claude/skills/logo-design/assets/library/svg/ceylon.svg new file mode 100644 index 0000000..a2c2186 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ceylon.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/chai.svg b/.claude/skills/logo-design/assets/library/svg/chai.svg new file mode 100644 index 0000000..41d346b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/chai.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/chalk.svg b/.claude/skills/logo-design/assets/library/svg/chalk.svg new file mode 100644 index 0000000..ee527ae --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/chalk.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/chargebee-icon.svg b/.claude/skills/logo-design/assets/library/svg/chargebee-icon.svg new file mode 100644 index 0000000..6fbe07b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/chargebee-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/chargebee.svg b/.claude/skills/logo-design/assets/library/svg/chargebee.svg new file mode 100644 index 0000000..73858e7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/chargebee.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/chef.svg b/.claude/skills/logo-design/assets/library/svg/chef.svg new file mode 100644 index 0000000..bf1004a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/chef.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/chevereto.svg b/.claude/skills/logo-design/assets/library/svg/chevereto.svg new file mode 100644 index 0000000..9aa6263 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/chevereto.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/chromatic-icon.svg b/.claude/skills/logo-design/assets/library/svg/chromatic-icon.svg new file mode 100644 index 0000000..50b7ccb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/chromatic-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/chromatic.svg b/.claude/skills/logo-design/assets/library/svg/chromatic.svg new file mode 100644 index 0000000..58b179d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/chromatic.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/chrome.svg b/.claude/skills/logo-design/assets/library/svg/chrome.svg new file mode 100644 index 0000000..1ba8fd3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/chrome.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cinder.svg b/.claude/skills/logo-design/assets/library/svg/cinder.svg new file mode 100644 index 0000000..33f3c00 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cinder.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/circleci.svg b/.claude/skills/logo-design/assets/library/svg/circleci.svg new file mode 100644 index 0000000..ca1c013 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/circleci.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cirrus-ci.svg b/.claude/skills/logo-design/assets/library/svg/cirrus-ci.svg new file mode 100644 index 0000000..57cec4a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cirrus-ci.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cirrus.svg b/.claude/skills/logo-design/assets/library/svg/cirrus.svg new file mode 100644 index 0000000..fa8f122 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cirrus.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/clion.svg b/.claude/skills/logo-design/assets/library/svg/clion.svg new file mode 100644 index 0000000..3417019 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/clion.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cljs.svg b/.claude/skills/logo-design/assets/library/svg/cljs.svg new file mode 100644 index 0000000..517648b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cljs.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/clojure.svg b/.claude/skills/logo-design/assets/library/svg/clojure.svg new file mode 100644 index 0000000..4ae06d5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/clojure.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/close.svg b/.claude/skills/logo-design/assets/library/svg/close.svg new file mode 100644 index 0000000..59afaa8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/close.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cloud9.svg b/.claude/skills/logo-design/assets/library/svg/cloud9.svg new file mode 100644 index 0000000..cf74819 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cloud9.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cloudacademy-icon.svg b/.claude/skills/logo-design/assets/library/svg/cloudacademy-icon.svg new file mode 100644 index 0000000..d8fcf68 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cloudacademy-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cloudacademy.svg b/.claude/skills/logo-design/assets/library/svg/cloudacademy.svg new file mode 100644 index 0000000..b697f72 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cloudacademy.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cloudcraft.svg b/.claude/skills/logo-design/assets/library/svg/cloudcraft.svg new file mode 100644 index 0000000..33fae1b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cloudcraft.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cloudflare.svg b/.claude/skills/logo-design/assets/library/svg/cloudflare.svg new file mode 100644 index 0000000..f7cff0b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cloudflare.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cloudinary.svg b/.claude/skills/logo-design/assets/library/svg/cloudinary.svg new file mode 100644 index 0000000..3be3f04 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cloudinary.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cloudlinux.svg b/.claude/skills/logo-design/assets/library/svg/cloudlinux.svg new file mode 100644 index 0000000..f30c816 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cloudlinux.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cobalt.svg b/.claude/skills/logo-design/assets/library/svg/cobalt.svg new file mode 100644 index 0000000..1a949ca --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cobalt.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cockpit.svg b/.claude/skills/logo-design/assets/library/svg/cockpit.svg new file mode 100644 index 0000000..5e21ddc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cockpit.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cocoapods.svg b/.claude/skills/logo-design/assets/library/svg/cocoapods.svg new file mode 100644 index 0000000..71aace0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cocoapods.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codacy.svg b/.claude/skills/logo-design/assets/library/svg/codacy.svg new file mode 100644 index 0000000..2201c1a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codacy.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codebase.svg b/.claude/skills/logo-design/assets/library/svg/codebase.svg new file mode 100644 index 0000000..e66dd1d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codebase.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codebeat.svg b/.claude/skills/logo-design/assets/library/svg/codebeat.svg new file mode 100644 index 0000000..f4a6f12 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codebeat.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codecademy.svg b/.claude/skills/logo-design/assets/library/svg/codecademy.svg new file mode 100644 index 0000000..4012db6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codecademy.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codeception.svg b/.claude/skills/logo-design/assets/library/svg/codeception.svg new file mode 100644 index 0000000..121fe5e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codeception.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codeclimate.svg b/.claude/skills/logo-design/assets/library/svg/codeclimate.svg new file mode 100644 index 0000000..8ec5aea --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codeclimate.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codecov.svg b/.claude/skills/logo-design/assets/library/svg/codecov.svg new file mode 100644 index 0000000..947b8aa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codecov.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codefactor-icon.svg b/.claude/skills/logo-design/assets/library/svg/codefactor-icon.svg new file mode 100644 index 0000000..6bb0f60 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codefactor-icon.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codefactor.svg b/.claude/skills/logo-design/assets/library/svg/codefactor.svg new file mode 100644 index 0000000..5114198 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codefactor.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codeigniter.svg b/.claude/skills/logo-design/assets/library/svg/codeigniter.svg new file mode 100644 index 0000000..e1cbc9e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codeigniter.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codepen-icon.svg b/.claude/skills/logo-design/assets/library/svg/codepen-icon.svg new file mode 100644 index 0000000..b0cf125 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codepen-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codepen.svg b/.claude/skills/logo-design/assets/library/svg/codepen.svg new file mode 100644 index 0000000..571595c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codepen.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codepush.svg b/.claude/skills/logo-design/assets/library/svg/codepush.svg new file mode 100644 index 0000000..8c8dd71 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codepush.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codersrank.svg b/.claude/skills/logo-design/assets/library/svg/codersrank.svg new file mode 100644 index 0000000..d646450 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codersrank.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/coderwall.svg b/.claude/skills/logo-design/assets/library/svg/coderwall.svg new file mode 100644 index 0000000..7713930 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/coderwall.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codesandbox.svg b/.claude/skills/logo-design/assets/library/svg/codesandbox.svg new file mode 100644 index 0000000..6a4ed45 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codesandbox.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codeship.svg b/.claude/skills/logo-design/assets/library/svg/codeship.svg new file mode 100644 index 0000000..0fa6edd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codeship.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codio.svg b/.claude/skills/logo-design/assets/library/svg/codio.svg new file mode 100644 index 0000000..af46d1a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codio.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/codrops.svg b/.claude/skills/logo-design/assets/library/svg/codrops.svg new file mode 100644 index 0000000..4c6277f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/codrops.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/coffeescript.svg b/.claude/skills/logo-design/assets/library/svg/coffeescript.svg new file mode 100644 index 0000000..6f46e94 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/coffeescript.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/commitizen.svg b/.claude/skills/logo-design/assets/library/svg/commitizen.svg new file mode 100644 index 0000000..a74f825 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/commitizen.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/compass.svg b/.claude/skills/logo-design/assets/library/svg/compass.svg new file mode 100644 index 0000000..89b8c3e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/compass.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/componentkit.svg b/.claude/skills/logo-design/assets/library/svg/componentkit.svg new file mode 100644 index 0000000..12d75c7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/componentkit.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/compose.svg b/.claude/skills/logo-design/assets/library/svg/compose.svg new file mode 100644 index 0000000..bbbc9cb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/compose.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/composer.svg b/.claude/skills/logo-design/assets/library/svg/composer.svg new file mode 100644 index 0000000..110fab2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/composer.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/conan-io.svg b/.claude/skills/logo-design/assets/library/svg/conan-io.svg new file mode 100644 index 0000000..a9f6d93 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/conan-io.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/concourse.svg b/.claude/skills/logo-design/assets/library/svg/concourse.svg new file mode 100644 index 0000000..498d204 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/concourse.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/concrete5.svg b/.claude/skills/logo-design/assets/library/svg/concrete5.svg new file mode 100644 index 0000000..6d2392c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/concrete5.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/confluence.svg b/.claude/skills/logo-design/assets/library/svg/confluence.svg new file mode 100644 index 0000000..7e405d1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/confluence.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/consul.svg b/.claude/skills/logo-design/assets/library/svg/consul.svg new file mode 100644 index 0000000..be5b64d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/consul.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/contentful.svg b/.claude/skills/logo-design/assets/library/svg/contentful.svg new file mode 100644 index 0000000..e532abb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/contentful.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/convox.svg b/.claude/skills/logo-design/assets/library/svg/convox.svg new file mode 100644 index 0000000..9354ff4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/convox.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/copyleft-pirate.svg b/.claude/skills/logo-design/assets/library/svg/copyleft-pirate.svg new file mode 100644 index 0000000..4cf91a6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/copyleft-pirate.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/copyleft.svg b/.claude/skills/logo-design/assets/library/svg/copyleft.svg new file mode 100644 index 0000000..1446861 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/copyleft.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/corda.svg b/.claude/skills/logo-design/assets/library/svg/corda.svg new file mode 100644 index 0000000..59ecd72 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/corda.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cordova.svg b/.claude/skills/logo-design/assets/library/svg/cordova.svg new file mode 100644 index 0000000..820bff5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cordova.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/coreos-icon.svg b/.claude/skills/logo-design/assets/library/svg/coreos-icon.svg new file mode 100644 index 0000000..11d6ed0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/coreos-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/coreos.svg b/.claude/skills/logo-design/assets/library/svg/coreos.svg new file mode 100644 index 0000000..95c1c24 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/coreos.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/couchbase.svg b/.claude/skills/logo-design/assets/library/svg/couchbase.svg new file mode 100644 index 0000000..7def85b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/couchbase.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/couchdb-icon.svg b/.claude/skills/logo-design/assets/library/svg/couchdb-icon.svg new file mode 100644 index 0000000..f4e706e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/couchdb-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/couchdb.svg b/.claude/skills/logo-design/assets/library/svg/couchdb.svg new file mode 100644 index 0000000..51581e3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/couchdb.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/coursera.svg b/.claude/skills/logo-design/assets/library/svg/coursera.svg new file mode 100644 index 0000000..b120c44 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/coursera.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/coveralls.svg b/.claude/skills/logo-design/assets/library/svg/coveralls.svg new file mode 100644 index 0000000..282636d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/coveralls.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cpanel.svg b/.claude/skills/logo-design/assets/library/svg/cpanel.svg new file mode 100644 index 0000000..e6683e5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cpanel.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/craftcms.svg b/.claude/skills/logo-design/assets/library/svg/craftcms.svg new file mode 100644 index 0000000..40e7e3c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/craftcms.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/crashlytics.svg b/.claude/skills/logo-design/assets/library/svg/crashlytics.svg new file mode 100644 index 0000000..b9fc905 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/crashlytics.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/crateio.svg b/.claude/skills/logo-design/assets/library/svg/crateio.svg new file mode 100644 index 0000000..24613bd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/crateio.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/create-react-app.svg b/.claude/skills/logo-design/assets/library/svg/create-react-app.svg new file mode 100644 index 0000000..92da438 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/create-react-app.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/createjs.svg b/.claude/skills/logo-design/assets/library/svg/createjs.svg new file mode 100644 index 0000000..5f08ce8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/createjs.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cross-browser-testing.svg b/.claude/skills/logo-design/assets/library/svg/cross-browser-testing.svg new file mode 100644 index 0000000..9275789 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cross-browser-testing.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/crucible.svg b/.claude/skills/logo-design/assets/library/svg/crucible.svg new file mode 100644 index 0000000..527ae73 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/crucible.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/crystal.svg b/.claude/skills/logo-design/assets/library/svg/crystal.svg new file mode 100644 index 0000000..ebd969e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/crystal.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/css-3.svg b/.claude/skills/logo-design/assets/library/svg/css-3.svg new file mode 100644 index 0000000..1526f3b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/css-3.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/css-3_official.svg b/.claude/skills/logo-design/assets/library/svg/css-3_official.svg new file mode 100644 index 0000000..f1c9939 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/css-3_official.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cssnext.svg b/.claude/skills/logo-design/assets/library/svg/cssnext.svg new file mode 100644 index 0000000..fc432d4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cssnext.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cucumber.svg b/.claude/skills/logo-design/assets/library/svg/cucumber.svg new file mode 100644 index 0000000..937acc8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cucumber.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/curl.svg b/.claude/skills/logo-design/assets/library/svg/curl.svg new file mode 100644 index 0000000..104ba3c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/curl.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/customerio-icon.svg b/.claude/skills/logo-design/assets/library/svg/customerio-icon.svg new file mode 100644 index 0000000..88229c3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/customerio-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/customerio.svg b/.claude/skills/logo-design/assets/library/svg/customerio.svg new file mode 100644 index 0000000..b3c7271 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/customerio.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cyclejs.svg b/.claude/skills/logo-design/assets/library/svg/cyclejs.svg new file mode 100644 index 0000000..ef4bc9d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cyclejs.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/cypress.svg b/.claude/skills/logo-design/assets/library/svg/cypress.svg new file mode 100644 index 0000000..17230b4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/cypress.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/d3.svg b/.claude/skills/logo-design/assets/library/svg/d3.svg new file mode 100644 index 0000000..24e21be --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/d3.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dart.svg b/.claude/skills/logo-design/assets/library/svg/dart.svg new file mode 100644 index 0000000..9cbc429 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dart.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dashlane-icon.svg b/.claude/skills/logo-design/assets/library/svg/dashlane-icon.svg new file mode 100644 index 0000000..457ec11 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dashlane-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dashlane.svg b/.claude/skills/logo-design/assets/library/svg/dashlane.svg new file mode 100644 index 0000000..2641b30 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dashlane.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/database-labs.svg b/.claude/skills/logo-design/assets/library/svg/database-labs.svg new file mode 100644 index 0000000..34e7b56 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/database-labs.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/datadog.svg b/.claude/skills/logo-design/assets/library/svg/datadog.svg new file mode 100644 index 0000000..8000a38 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/datadog.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/datocms-icon.svg b/.claude/skills/logo-design/assets/library/svg/datocms-icon.svg new file mode 100644 index 0000000..eeeb417 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/datocms-icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/datocms.svg b/.claude/skills/logo-design/assets/library/svg/datocms.svg new file mode 100644 index 0000000..fdb0554 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/datocms.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dbt-icon.svg b/.claude/skills/logo-design/assets/library/svg/dbt-icon.svg new file mode 100644 index 0000000..fa33326 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dbt-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dbt.svg b/.claude/skills/logo-design/assets/library/svg/dbt.svg new file mode 100644 index 0000000..c72cabe --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dbt.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dcos-icon.svg b/.claude/skills/logo-design/assets/library/svg/dcos-icon.svg new file mode 100644 index 0000000..13399a2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dcos-icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dcos.svg b/.claude/skills/logo-design/assets/library/svg/dcos.svg new file mode 100644 index 0000000..001f44b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dcos.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/debian.svg b/.claude/skills/logo-design/assets/library/svg/debian.svg new file mode 100644 index 0000000..fe8c457 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/debian.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/delighted-icon.svg b/.claude/skills/logo-design/assets/library/svg/delighted-icon.svg new file mode 100644 index 0000000..b36dece --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/delighted-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/delighted.svg b/.claude/skills/logo-design/assets/library/svg/delighted.svg new file mode 100644 index 0000000..c1ffe25 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/delighted.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/deno.svg b/.claude/skills/logo-design/assets/library/svg/deno.svg new file mode 100644 index 0000000..7687e66 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/deno.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/deployhq.svg b/.claude/skills/logo-design/assets/library/svg/deployhq.svg new file mode 100644 index 0000000..8dd8f85 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/deployhq.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/derby.svg b/.claude/skills/logo-design/assets/library/svg/derby.svg new file mode 100644 index 0000000..b9380c7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/derby.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/designernews.svg b/.claude/skills/logo-design/assets/library/svg/designernews.svg new file mode 100644 index 0000000..34590e3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/designernews.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/deviantart.svg b/.claude/skills/logo-design/assets/library/svg/deviantart.svg new file mode 100644 index 0000000..fb96b7a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/deviantart.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dgraph-icon.svg b/.claude/skills/logo-design/assets/library/svg/dgraph-icon.svg new file mode 100644 index 0000000..b2182da --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dgraph-icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dgraph.svg b/.claude/skills/logo-design/assets/library/svg/dgraph.svg new file mode 100644 index 0000000..32679d1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dgraph.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dialogflow.svg b/.claude/skills/logo-design/assets/library/svg/dialogflow.svg new file mode 100644 index 0000000..faad495 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dialogflow.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/digital-ocean.svg b/.claude/skills/logo-design/assets/library/svg/digital-ocean.svg new file mode 100644 index 0000000..5132fac --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/digital-ocean.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dimer.svg b/.claude/skills/logo-design/assets/library/svg/dimer.svg new file mode 100644 index 0000000..5db2147 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dimer.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dinersclub.svg b/.claude/skills/logo-design/assets/library/svg/dinersclub.svg new file mode 100644 index 0000000..776932b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dinersclub.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/discord-icon.svg b/.claude/skills/logo-design/assets/library/svg/discord-icon.svg new file mode 100644 index 0000000..ff33841 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/discord-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/discord.svg b/.claude/skills/logo-design/assets/library/svg/discord.svg new file mode 100644 index 0000000..f1c6b71 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/discord.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/discover.svg b/.claude/skills/logo-design/assets/library/svg/discover.svg new file mode 100644 index 0000000..c9f2e7a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/discover.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/disqus.svg b/.claude/skills/logo-design/assets/library/svg/disqus.svg new file mode 100644 index 0000000..b19e165 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/disqus.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/django-icon.svg b/.claude/skills/logo-design/assets/library/svg/django-icon.svg new file mode 100644 index 0000000..b5cf35f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/django-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/django.svg b/.claude/skills/logo-design/assets/library/svg/django.svg new file mode 100644 index 0000000..a41b5ff --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/django.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dockbit.svg b/.claude/skills/logo-design/assets/library/svg/dockbit.svg new file mode 100644 index 0000000..40b470d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dockbit.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/docker-icon.svg b/.claude/skills/logo-design/assets/library/svg/docker-icon.svg new file mode 100644 index 0000000..0bddc6d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/docker-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/docker.svg b/.claude/skills/logo-design/assets/library/svg/docker.svg new file mode 100644 index 0000000..a9c64d1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/docker.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/doctrine.svg b/.claude/skills/logo-design/assets/library/svg/doctrine.svg new file mode 100644 index 0000000..6368c28 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/doctrine.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/docusaurus.svg b/.claude/skills/logo-design/assets/library/svg/docusaurus.svg new file mode 100644 index 0000000..0f87958 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/docusaurus.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dojo-icon.svg b/.claude/skills/logo-design/assets/library/svg/dojo-icon.svg new file mode 100644 index 0000000..d397cca --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dojo-icon.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dojo-toolkit.svg b/.claude/skills/logo-design/assets/library/svg/dojo-toolkit.svg new file mode 100644 index 0000000..3df4a1e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dojo-toolkit.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dojo.svg b/.claude/skills/logo-design/assets/library/svg/dojo.svg new file mode 100644 index 0000000..3fdbbd5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dojo.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dotnet.svg b/.claude/skills/logo-design/assets/library/svg/dotnet.svg new file mode 100644 index 0000000..99f8c40 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dotnet.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dreamhost.svg b/.claude/skills/logo-design/assets/library/svg/dreamhost.svg new file mode 100644 index 0000000..6d4d5ad --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dreamhost.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dribbble-icon.svg b/.claude/skills/logo-design/assets/library/svg/dribbble-icon.svg new file mode 100644 index 0000000..05b5dc7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dribbble-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dribbble.svg b/.claude/skills/logo-design/assets/library/svg/dribbble.svg new file mode 100644 index 0000000..00b1de5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dribbble.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/drift.svg b/.claude/skills/logo-design/assets/library/svg/drift.svg new file mode 100644 index 0000000..2ecd366 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/drift.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/drip.svg b/.claude/skills/logo-design/assets/library/svg/drip.svg new file mode 100644 index 0000000..028411a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/drip.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/drizzle-icon.svg b/.claude/skills/logo-design/assets/library/svg/drizzle-icon.svg new file mode 100644 index 0000000..31646b6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/drizzle-icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/drizzle.svg b/.claude/skills/logo-design/assets/library/svg/drizzle.svg new file mode 100644 index 0000000..d46e121 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/drizzle.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/drone-icon.svg b/.claude/skills/logo-design/assets/library/svg/drone-icon.svg new file mode 100644 index 0000000..a767866 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/drone-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/drone.svg b/.claude/skills/logo-design/assets/library/svg/drone.svg new file mode 100644 index 0000000..b18d097 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/drone.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dropbox.svg b/.claude/skills/logo-design/assets/library/svg/dropbox.svg new file mode 100644 index 0000000..630fb89 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dropbox.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dropmark.svg b/.claude/skills/logo-design/assets/library/svg/dropmark.svg new file mode 100644 index 0000000..48b77a5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dropmark.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dropzone.svg b/.claude/skills/logo-design/assets/library/svg/dropzone.svg new file mode 100644 index 0000000..a15f8a5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dropzone.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/drupal-icon.svg b/.claude/skills/logo-design/assets/library/svg/drupal-icon.svg new file mode 100644 index 0000000..07a1afa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/drupal-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/drupal.svg b/.claude/skills/logo-design/assets/library/svg/drupal.svg new file mode 100644 index 0000000..2039693 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/drupal.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/duckduckgo.svg b/.claude/skills/logo-design/assets/library/svg/duckduckgo.svg new file mode 100644 index 0000000..194e4a1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/duckduckgo.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dynatrace-icon.svg b/.claude/skills/logo-design/assets/library/svg/dynatrace-icon.svg new file mode 100644 index 0000000..d483e8d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dynatrace-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dynatrace.svg b/.claude/skills/logo-design/assets/library/svg/dynatrace.svg new file mode 100644 index 0000000..63983ad --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dynatrace.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/dyndns.svg b/.claude/skills/logo-design/assets/library/svg/dyndns.svg new file mode 100644 index 0000000..85c1a54 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/dyndns.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ebanx.svg b/.claude/skills/logo-design/assets/library/svg/ebanx.svg new file mode 100644 index 0000000..93dfaeb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ebanx.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/eclipse-icon.svg b/.claude/skills/logo-design/assets/library/svg/eclipse-icon.svg new file mode 100644 index 0000000..48a77e4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/eclipse-icon.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/eclipse.svg b/.claude/skills/logo-design/assets/library/svg/eclipse.svg new file mode 100644 index 0000000..fdddda0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/eclipse.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/editorconfig.svg b/.claude/skills/logo-design/assets/library/svg/editorconfig.svg new file mode 100644 index 0000000..79a3074 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/editorconfig.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/egghead.svg b/.claude/skills/logo-design/assets/library/svg/egghead.svg new file mode 100644 index 0000000..ded1975 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/egghead.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/elasticsearch.svg b/.claude/skills/logo-design/assets/library/svg/elasticsearch.svg new file mode 100644 index 0000000..819bfe2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/elasticsearch.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/electron.svg b/.claude/skills/logo-design/assets/library/svg/electron.svg new file mode 100644 index 0000000..419190d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/electron.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/element.svg b/.claude/skills/logo-design/assets/library/svg/element.svg new file mode 100644 index 0000000..63d8aeb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/element.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/elemental-ui.svg b/.claude/skills/logo-design/assets/library/svg/elemental-ui.svg new file mode 100644 index 0000000..e22e066 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/elemental-ui.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/elementary.svg b/.claude/skills/logo-design/assets/library/svg/elementary.svg new file mode 100644 index 0000000..ebc3e06 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/elementary.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ello.svg b/.claude/skills/logo-design/assets/library/svg/ello.svg new file mode 100644 index 0000000..6319338 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ello.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/elm.svg b/.claude/skills/logo-design/assets/library/svg/elm.svg new file mode 100644 index 0000000..fa2072e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/elm.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/elo.svg b/.claude/skills/logo-design/assets/library/svg/elo.svg new file mode 100644 index 0000000..0625e7f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/elo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/emacs.svg b/.claude/skills/logo-design/assets/library/svg/emacs.svg new file mode 100644 index 0000000..efd4af4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/emacs.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/embedly.svg b/.claude/skills/logo-design/assets/library/svg/embedly.svg new file mode 100644 index 0000000..6abc463 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/embedly.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ember-tomster.svg b/.claude/skills/logo-design/assets/library/svg/ember-tomster.svg new file mode 100644 index 0000000..99c057c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ember-tomster.svg @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ember.svg b/.claude/skills/logo-design/assets/library/svg/ember.svg new file mode 100644 index 0000000..50eb492 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ember.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/emmet.svg b/.claude/skills/logo-design/assets/library/svg/emmet.svg new file mode 100644 index 0000000..b396080 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/emmet.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/engine-yard-icon.svg b/.claude/skills/logo-design/assets/library/svg/engine-yard-icon.svg new file mode 100644 index 0000000..76461f7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/engine-yard-icon.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/engine-yard.svg b/.claude/skills/logo-design/assets/library/svg/engine-yard.svg new file mode 100644 index 0000000..ee5da2a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/engine-yard.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/envato.svg b/.claude/skills/logo-design/assets/library/svg/envato.svg new file mode 100644 index 0000000..7354dc1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/envato.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/envoy-icon.svg b/.claude/skills/logo-design/assets/library/svg/envoy-icon.svg new file mode 100644 index 0000000..6316043 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/envoy-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/envoy.svg b/.claude/skills/logo-design/assets/library/svg/envoy.svg new file mode 100644 index 0000000..689a7d2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/envoy.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/envoyer.svg b/.claude/skills/logo-design/assets/library/svg/envoyer.svg new file mode 100644 index 0000000..81848c6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/envoyer.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/enyo.svg b/.claude/skills/logo-design/assets/library/svg/enyo.svg new file mode 100644 index 0000000..0bdf154 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/enyo.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/erlang.svg b/.claude/skills/logo-design/assets/library/svg/erlang.svg new file mode 100644 index 0000000..bcee379 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/erlang.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/es6.svg b/.claude/skills/logo-design/assets/library/svg/es6.svg new file mode 100644 index 0000000..a101dee --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/es6.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/esbuild.svg b/.claude/skills/logo-design/assets/library/svg/esbuild.svg new file mode 100644 index 0000000..eabdcbe --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/esbuild.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/esdoc.svg b/.claude/skills/logo-design/assets/library/svg/esdoc.svg new file mode 100644 index 0000000..afd1090 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/esdoc.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/eslint-old.svg b/.claude/skills/logo-design/assets/library/svg/eslint-old.svg new file mode 100644 index 0000000..efa6ee1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/eslint-old.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/eslint.svg b/.claude/skills/logo-design/assets/library/svg/eslint.svg new file mode 100644 index 0000000..3b1b2af --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/eslint.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/eta-lang.svg b/.claude/skills/logo-design/assets/library/svg/eta-lang.svg new file mode 100644 index 0000000..6994e28 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/eta-lang.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/etcd.svg b/.claude/skills/logo-design/assets/library/svg/etcd.svg new file mode 100644 index 0000000..d719d36 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/etcd.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ethereum-color.svg b/.claude/skills/logo-design/assets/library/svg/ethereum-color.svg new file mode 100644 index 0000000..e0de4f5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ethereum-color.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ethereum.svg b/.claude/skills/logo-design/assets/library/svg/ethereum.svg new file mode 100644 index 0000000..5b15d72 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ethereum.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ethers.svg b/.claude/skills/logo-design/assets/library/svg/ethers.svg new file mode 100644 index 0000000..303ae58 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ethers.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ethnio.svg b/.claude/skills/logo-design/assets/library/svg/ethnio.svg new file mode 100644 index 0000000..62b71db --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ethnio.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/eventbrite-icon.svg b/.claude/skills/logo-design/assets/library/svg/eventbrite-icon.svg new file mode 100644 index 0000000..78713a0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/eventbrite-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/eventbrite.svg b/.claude/skills/logo-design/assets/library/svg/eventbrite.svg new file mode 100644 index 0000000..3116c7a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/eventbrite.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/eventsentry.svg b/.claude/skills/logo-design/assets/library/svg/eventsentry.svg new file mode 100644 index 0000000..e7e147d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/eventsentry.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/evergreen-icon.svg b/.claude/skills/logo-design/assets/library/svg/evergreen-icon.svg new file mode 100644 index 0000000..e104f7b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/evergreen-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/evergreen.svg b/.claude/skills/logo-design/assets/library/svg/evergreen.svg new file mode 100644 index 0000000..d3d4197 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/evergreen.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/expo-icon.svg b/.claude/skills/logo-design/assets/library/svg/expo-icon.svg new file mode 100644 index 0000000..f1ece3f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/expo-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/expo.svg b/.claude/skills/logo-design/assets/library/svg/expo.svg new file mode 100644 index 0000000..5f9b07c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/expo.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/express.svg b/.claude/skills/logo-design/assets/library/svg/express.svg new file mode 100644 index 0000000..d8572a9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/express.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fabric.svg b/.claude/skills/logo-design/assets/library/svg/fabric.svg new file mode 100644 index 0000000..e612338 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fabric.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/facebook.svg b/.claude/skills/logo-design/assets/library/svg/facebook.svg new file mode 100644 index 0000000..9a51a1a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/facebook.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/falcor.svg b/.claude/skills/logo-design/assets/library/svg/falcor.svg new file mode 100644 index 0000000..4586f8a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/falcor.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fastify-icon.svg b/.claude/skills/logo-design/assets/library/svg/fastify-icon.svg new file mode 100644 index 0000000..7d939fd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fastify-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fastify.svg b/.claude/skills/logo-design/assets/library/svg/fastify.svg new file mode 100644 index 0000000..26b053d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fastify.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fastlane.svg b/.claude/skills/logo-design/assets/library/svg/fastlane.svg new file mode 100644 index 0000000..a8037af --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fastlane.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fastly.svg b/.claude/skills/logo-design/assets/library/svg/fastly.svg new file mode 100644 index 0000000..0853c72 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fastly.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/feathersjs.svg b/.claude/skills/logo-design/assets/library/svg/feathersjs.svg new file mode 100644 index 0000000..937739e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/feathersjs.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fedora.svg b/.claude/skills/logo-design/assets/library/svg/fedora.svg new file mode 100644 index 0000000..5cad205 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fedora.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fetch.svg b/.claude/skills/logo-design/assets/library/svg/fetch.svg new file mode 100644 index 0000000..7ba15b2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fetch.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/figma.svg b/.claude/skills/logo-design/assets/library/svg/figma.svg new file mode 100644 index 0000000..10aa0a1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/figma.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/firebase.svg b/.claude/skills/logo-design/assets/library/svg/firebase.svg new file mode 100644 index 0000000..9e03039 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/firebase.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/firefox.svg b/.claude/skills/logo-design/assets/library/svg/firefox.svg new file mode 100644 index 0000000..94305c6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/firefox.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flannel.svg b/.claude/skills/logo-design/assets/library/svg/flannel.svg new file mode 100644 index 0000000..b8d074f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flannel.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flarum.svg b/.claude/skills/logo-design/assets/library/svg/flarum.svg new file mode 100644 index 0000000..16540c4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flarum.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flask.svg b/.claude/skills/logo-design/assets/library/svg/flask.svg new file mode 100644 index 0000000..921d1ac --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flask.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flat-ui.svg b/.claude/skills/logo-design/assets/library/svg/flat-ui.svg new file mode 100644 index 0000000..16047d3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flat-ui.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flattr-icon.svg b/.claude/skills/logo-design/assets/library/svg/flattr-icon.svg new file mode 100644 index 0000000..cbed4e9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flattr-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flattr.svg b/.claude/skills/logo-design/assets/library/svg/flattr.svg new file mode 100644 index 0000000..0caf16c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flattr.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fleep.svg b/.claude/skills/logo-design/assets/library/svg/fleep.svg new file mode 100644 index 0000000..e328ac6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fleep.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flickr.svg b/.claude/skills/logo-design/assets/library/svg/flickr.svg new file mode 100644 index 0000000..4d43d7e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flickr.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flight.svg b/.claude/skills/logo-design/assets/library/svg/flight.svg new file mode 100644 index 0000000..e2099a1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flight.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/floodio.svg b/.claude/skills/logo-design/assets/library/svg/floodio.svg new file mode 100644 index 0000000..665eb59 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/floodio.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flow.svg b/.claude/skills/logo-design/assets/library/svg/flow.svg new file mode 100644 index 0000000..c5c5972 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flow.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flowxo.svg b/.claude/skills/logo-design/assets/library/svg/flowxo.svg new file mode 100644 index 0000000..058b9ce --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flowxo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/floydhub.svg b/.claude/skills/logo-design/assets/library/svg/floydhub.svg new file mode 100644 index 0000000..906c997 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/floydhub.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flutter.svg b/.claude/skills/logo-design/assets/library/svg/flutter.svg new file mode 100644 index 0000000..cd0318d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flutter.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/flux.svg b/.claude/skills/logo-design/assets/library/svg/flux.svg new file mode 100644 index 0000000..64e3c29 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/flux.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fluxxor.svg b/.claude/skills/logo-design/assets/library/svg/fluxxor.svg new file mode 100644 index 0000000..159c103 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fluxxor.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fly.svg b/.claude/skills/logo-design/assets/library/svg/fly.svg new file mode 100644 index 0000000..2811057 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fly.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fomo.svg b/.claude/skills/logo-design/assets/library/svg/fomo.svg new file mode 100644 index 0000000..bf3a5f2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fomo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/font-awesome.svg b/.claude/skills/logo-design/assets/library/svg/font-awesome.svg new file mode 100644 index 0000000..36692ef --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/font-awesome.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/forestadmin-icon.svg b/.claude/skills/logo-design/assets/library/svg/forestadmin-icon.svg new file mode 100644 index 0000000..f71e21d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/forestadmin-icon.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/forestadmin.svg b/.claude/skills/logo-design/assets/library/svg/forestadmin.svg new file mode 100644 index 0000000..caa2808 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/forestadmin.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/forever.svg b/.claude/skills/logo-design/assets/library/svg/forever.svg new file mode 100644 index 0000000..8394d7c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/forever.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/formkeep.svg b/.claude/skills/logo-design/assets/library/svg/formkeep.svg new file mode 100644 index 0000000..ab79081 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/formkeep.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fortran.svg b/.claude/skills/logo-design/assets/library/svg/fortran.svg new file mode 100644 index 0000000..560da96 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fortran.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/foundation.svg b/.claude/skills/logo-design/assets/library/svg/foundation.svg new file mode 100644 index 0000000..281a79a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/foundation.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/framer.svg b/.claude/skills/logo-design/assets/library/svg/framer.svg new file mode 100644 index 0000000..19a3b1d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/framer.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/framework7-icon.svg b/.claude/skills/logo-design/assets/library/svg/framework7-icon.svg new file mode 100644 index 0000000..8e05692 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/framework7-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/framework7.svg b/.claude/skills/logo-design/assets/library/svg/framework7.svg new file mode 100644 index 0000000..da2c15d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/framework7.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/freebsd.svg b/.claude/skills/logo-design/assets/library/svg/freebsd.svg new file mode 100644 index 0000000..6dcb05c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/freebsd.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/freedcamp-icon.svg b/.claude/skills/logo-design/assets/library/svg/freedcamp-icon.svg new file mode 100644 index 0000000..92878be --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/freedcamp-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/freedcamp.svg b/.claude/skills/logo-design/assets/library/svg/freedcamp.svg new file mode 100644 index 0000000..1cf4a33 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/freedcamp.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/freedomdefined.svg b/.claude/skills/logo-design/assets/library/svg/freedomdefined.svg new file mode 100644 index 0000000..b7a8098 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/freedomdefined.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/frontapp.svg b/.claude/skills/logo-design/assets/library/svg/frontapp.svg new file mode 100644 index 0000000..9bf4a5b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/frontapp.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fsharp.svg b/.claude/skills/logo-design/assets/library/svg/fsharp.svg new file mode 100644 index 0000000..f171162 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fsharp.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/fuchsia.svg b/.claude/skills/logo-design/assets/library/svg/fuchsia.svg new file mode 100644 index 0000000..d526d72 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/fuchsia.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/galliumos.svg b/.claude/skills/logo-design/assets/library/svg/galliumos.svg new file mode 100644 index 0000000..43f70a2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/galliumos.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/game-analytics-icon.svg b/.claude/skills/logo-design/assets/library/svg/game-analytics-icon.svg new file mode 100644 index 0000000..c4dcd97 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/game-analytics-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/game-analytics.svg b/.claude/skills/logo-design/assets/library/svg/game-analytics.svg new file mode 100644 index 0000000..9ead890 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/game-analytics.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ganache-icon.svg b/.claude/skills/logo-design/assets/library/svg/ganache-icon.svg new file mode 100644 index 0000000..54a58b8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ganache-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ganache.svg b/.claude/skills/logo-design/assets/library/svg/ganache.svg new file mode 100644 index 0000000..d5bedce --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ganache.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gatsby.svg b/.claude/skills/logo-design/assets/library/svg/gatsby.svg new file mode 100644 index 0000000..1a68fb0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gatsby.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/geekbot.svg b/.claude/skills/logo-design/assets/library/svg/geekbot.svg new file mode 100644 index 0000000..410ce0a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/geekbot.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/getyourguide.svg b/.claude/skills/logo-design/assets/library/svg/getyourguide.svg new file mode 100644 index 0000000..da58566 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/getyourguide.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ghost.svg b/.claude/skills/logo-design/assets/library/svg/ghost.svg new file mode 100644 index 0000000..e341d88 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ghost.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/giantswarm.svg b/.claude/skills/logo-design/assets/library/svg/giantswarm.svg new file mode 100644 index 0000000..34ba436 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/giantswarm.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/git-icon.svg b/.claude/skills/logo-design/assets/library/svg/git-icon.svg new file mode 100644 index 0000000..e7bc933 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/git-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/git.svg b/.claude/skills/logo-design/assets/library/svg/git.svg new file mode 100644 index 0000000..90992c3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/git.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gitboard.svg b/.claude/skills/logo-design/assets/library/svg/gitboard.svg new file mode 100644 index 0000000..eb7b523 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gitboard.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/github-actions.svg b/.claude/skills/logo-design/assets/library/svg/github-actions.svg new file mode 100644 index 0000000..6876a3d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/github-actions.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/github-copilot.svg b/.claude/skills/logo-design/assets/library/svg/github-copilot.svg new file mode 100644 index 0000000..e3af5dc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/github-copilot.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/github-icon.svg b/.claude/skills/logo-design/assets/library/svg/github-icon.svg new file mode 100644 index 0000000..1bff607 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/github-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/github-octocat.svg b/.claude/skills/logo-design/assets/library/svg/github-octocat.svg new file mode 100644 index 0000000..f8687ac --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/github-octocat.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/github.svg b/.claude/skills/logo-design/assets/library/svg/github.svg new file mode 100644 index 0000000..a8a6b01 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/github.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gitkraken.svg b/.claude/skills/logo-design/assets/library/svg/gitkraken.svg new file mode 100644 index 0000000..eefc658 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gitkraken.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gitlab.svg b/.claude/skills/logo-design/assets/library/svg/gitlab.svg new file mode 100644 index 0000000..e85ce31 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gitlab.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gitter.svg b/.claude/skills/logo-design/assets/library/svg/gitter.svg new file mode 100644 index 0000000..68dd8cf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gitter.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gitup.svg b/.claude/skills/logo-design/assets/library/svg/gitup.svg new file mode 100644 index 0000000..69ab7eb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gitup.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/glamorous.svg b/.claude/skills/logo-design/assets/library/svg/glamorous.svg new file mode 100644 index 0000000..8a9bbb4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/glamorous.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gleam.svg b/.claude/skills/logo-design/assets/library/svg/gleam.svg new file mode 100644 index 0000000..50a7016 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gleam.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/glimmerjs.svg b/.claude/skills/logo-design/assets/library/svg/glimmerjs.svg new file mode 100644 index 0000000..3064f5c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/glimmerjs.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/glint.svg b/.claude/skills/logo-design/assets/library/svg/glint.svg new file mode 100644 index 0000000..5741c1f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/glint.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/glitch-icon.svg b/.claude/skills/logo-design/assets/library/svg/glitch-icon.svg new file mode 100644 index 0000000..3c98004 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/glitch-icon.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/glitch.svg b/.claude/skills/logo-design/assets/library/svg/glitch.svg new file mode 100644 index 0000000..9aae661 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/glitch.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gnome-icon.svg b/.claude/skills/logo-design/assets/library/svg/gnome-icon.svg new file mode 100644 index 0000000..c18e475 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gnome-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gnome.svg b/.claude/skills/logo-design/assets/library/svg/gnome.svg new file mode 100644 index 0000000..b0c82e8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gnome.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gnu-net.svg b/.claude/skills/logo-design/assets/library/svg/gnu-net.svg new file mode 100644 index 0000000..91e9cf3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gnu-net.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gnu.svg b/.claude/skills/logo-design/assets/library/svg/gnu.svg new file mode 100644 index 0000000..0f9e18e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gnu.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/go.svg b/.claude/skills/logo-design/assets/library/svg/go.svg new file mode 100644 index 0000000..6154429 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/go.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gocd.svg b/.claude/skills/logo-design/assets/library/svg/gocd.svg new file mode 100644 index 0000000..5eda9a7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gocd.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gohorse.svg b/.claude/skills/logo-design/assets/library/svg/gohorse.svg new file mode 100644 index 0000000..a904949 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gohorse.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-360suite.svg b/.claude/skills/logo-design/assets/library/svg/google-360suite.svg new file mode 100644 index 0000000..d33e26c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-360suite.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-admob.svg b/.claude/skills/logo-design/assets/library/svg/google-admob.svg new file mode 100644 index 0000000..e0a2bf0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-admob.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-ads.svg b/.claude/skills/logo-design/assets/library/svg/google-ads.svg new file mode 100644 index 0000000..22a982a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-ads.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-adsense.svg b/.claude/skills/logo-design/assets/library/svg/google-adsense.svg new file mode 100644 index 0000000..20d8a6b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-adsense.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-analytics.svg b/.claude/skills/logo-design/assets/library/svg/google-analytics.svg new file mode 100644 index 0000000..ba6e282 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-analytics.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-calendar.svg b/.claude/skills/logo-design/assets/library/svg/google-calendar.svg new file mode 100644 index 0000000..18d222f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-calendar.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-cloud-functions.svg b/.claude/skills/logo-design/assets/library/svg/google-cloud-functions.svg new file mode 100644 index 0000000..f06c5db --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-cloud-functions.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-cloud-run.svg b/.claude/skills/logo-design/assets/library/svg/google-cloud-run.svg new file mode 100644 index 0000000..a863549 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-cloud-run.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-cloud.svg b/.claude/skills/logo-design/assets/library/svg/google-cloud.svg new file mode 100644 index 0000000..4400bec --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-cloud.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-currents.svg b/.claude/skills/logo-design/assets/library/svg/google-currents.svg new file mode 100644 index 0000000..a7de376 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-currents.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-data-studio.svg b/.claude/skills/logo-design/assets/library/svg/google-data-studio.svg new file mode 100644 index 0000000..01a95ef --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-data-studio.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-developers.svg b/.claude/skills/logo-design/assets/library/svg/google-developers.svg new file mode 100644 index 0000000..c8006cc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-developers.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-drive.svg b/.claude/skills/logo-design/assets/library/svg/google-drive.svg new file mode 100644 index 0000000..52b2749 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-drive.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-fit.svg b/.claude/skills/logo-design/assets/library/svg/google-fit.svg new file mode 100644 index 0000000..d8fd735 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-fit.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-gmail.svg b/.claude/skills/logo-design/assets/library/svg/google-gmail.svg new file mode 100644 index 0000000..a84c5f6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-gmail.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-gsuite.svg b/.claude/skills/logo-design/assets/library/svg/google-gsuite.svg new file mode 100644 index 0000000..2ae6ff9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-gsuite.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-home.svg b/.claude/skills/logo-design/assets/library/svg/google-home.svg new file mode 100644 index 0000000..6cbe3e1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-home.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-icon.svg b/.claude/skills/logo-design/assets/library/svg/google-icon.svg new file mode 100644 index 0000000..a479328 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-keep.svg b/.claude/skills/logo-design/assets/library/svg/google-keep.svg new file mode 100644 index 0000000..19f67d7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-keep.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-maps.svg b/.claude/skills/logo-design/assets/library/svg/google-maps.svg new file mode 100644 index 0000000..633d4eb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-maps.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-marketing-platform.svg b/.claude/skills/logo-design/assets/library/svg/google-marketing-platform.svg new file mode 100644 index 0000000..5a355fe --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-marketing-platform.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-meet.svg b/.claude/skills/logo-design/assets/library/svg/google-meet.svg new file mode 100644 index 0000000..6896e30 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-meet.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-one.svg b/.claude/skills/logo-design/assets/library/svg/google-one.svg new file mode 100644 index 0000000..495a054 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-one.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-optimize.svg b/.claude/skills/logo-design/assets/library/svg/google-optimize.svg new file mode 100644 index 0000000..6f01e34 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-optimize.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-pay-icon.svg b/.claude/skills/logo-design/assets/library/svg/google-pay-icon.svg new file mode 100644 index 0000000..6b5739d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-pay-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-pay.svg b/.claude/skills/logo-design/assets/library/svg/google-pay.svg new file mode 100644 index 0000000..ac46f5e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-pay.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-photos.svg b/.claude/skills/logo-design/assets/library/svg/google-photos.svg new file mode 100644 index 0000000..02ff1dc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-photos.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-play-icon.svg b/.claude/skills/logo-design/assets/library/svg/google-play-icon.svg new file mode 100644 index 0000000..dc0a586 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-play-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-play.svg b/.claude/skills/logo-design/assets/library/svg/google-play.svg new file mode 100644 index 0000000..93da986 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-play.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google-tag-manager.svg b/.claude/skills/logo-design/assets/library/svg/google-tag-manager.svg new file mode 100644 index 0000000..88bebaa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google-tag-manager.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/google.svg b/.claude/skills/logo-design/assets/library/svg/google.svg new file mode 100644 index 0000000..f2626bd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/google.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gopher.svg b/.claude/skills/logo-design/assets/library/svg/gopher.svg new file mode 100644 index 0000000..bc14364 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gopher.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gradle.svg b/.claude/skills/logo-design/assets/library/svg/gradle.svg new file mode 100644 index 0000000..469ab00 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gradle.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/grafana.svg b/.claude/skills/logo-design/assets/library/svg/grafana.svg new file mode 100644 index 0000000..145bf4f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/grafana.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/grails.svg b/.claude/skills/logo-design/assets/library/svg/grails.svg new file mode 100644 index 0000000..2e1394a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/grails.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/graphene.svg b/.claude/skills/logo-design/assets/library/svg/graphene.svg new file mode 100644 index 0000000..915ce56 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/graphene.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/graphql.svg b/.claude/skills/logo-design/assets/library/svg/graphql.svg new file mode 100644 index 0000000..ae53e93 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/graphql.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/grav.svg b/.claude/skills/logo-design/assets/library/svg/grav.svg new file mode 100644 index 0000000..6caa1a2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/grav.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gravatar.svg b/.claude/skills/logo-design/assets/library/svg/gravatar.svg new file mode 100644 index 0000000..2c8c66f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gravatar.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/graylog-icon.svg b/.claude/skills/logo-design/assets/library/svg/graylog-icon.svg new file mode 100644 index 0000000..e797ecb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/graylog-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/graylog.svg b/.claude/skills/logo-design/assets/library/svg/graylog.svg new file mode 100644 index 0000000..682bf21 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/graylog.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gridsome-icon.svg b/.claude/skills/logo-design/assets/library/svg/gridsome-icon.svg new file mode 100644 index 0000000..8a65249 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gridsome-icon.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gridsome.svg b/.claude/skills/logo-design/assets/library/svg/gridsome.svg new file mode 100644 index 0000000..73253e3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gridsome.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/grommet.svg b/.claude/skills/logo-design/assets/library/svg/grommet.svg new file mode 100644 index 0000000..9aff533 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/grommet.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/groovehq.svg b/.claude/skills/logo-design/assets/library/svg/groovehq.svg new file mode 100644 index 0000000..8895085 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/groovehq.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/grove.svg b/.claude/skills/logo-design/assets/library/svg/grove.svg new file mode 100644 index 0000000..952b706 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/grove.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/grpc.svg b/.claude/skills/logo-design/assets/library/svg/grpc.svg new file mode 100644 index 0000000..c04e2b6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/grpc.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/grunt.svg b/.claude/skills/logo-design/assets/library/svg/grunt.svg new file mode 100644 index 0000000..8e5cd70 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/grunt.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gulp.svg b/.claude/skills/logo-design/assets/library/svg/gulp.svg new file mode 100644 index 0000000..214d10f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gulp.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gunicorn.svg b/.claude/skills/logo-design/assets/library/svg/gunicorn.svg new file mode 100644 index 0000000..2f78a8c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gunicorn.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gusto.svg b/.claude/skills/logo-design/assets/library/svg/gusto.svg new file mode 100644 index 0000000..5e0039c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gusto.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/gwt.svg b/.claude/skills/logo-design/assets/library/svg/gwt.svg new file mode 100644 index 0000000..7d26f73 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/gwt.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hack.svg b/.claude/skills/logo-design/assets/library/svg/hack.svg new file mode 100644 index 0000000..8685927 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hack.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hacker-one.svg b/.claude/skills/logo-design/assets/library/svg/hacker-one.svg new file mode 100644 index 0000000..7474b74 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hacker-one.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/haiku-icon.svg b/.claude/skills/logo-design/assets/library/svg/haiku-icon.svg new file mode 100644 index 0000000..8de48db --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/haiku-icon.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/haml.svg b/.claude/skills/logo-design/assets/library/svg/haml.svg new file mode 100644 index 0000000..ce0de17 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/haml.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hanami.svg b/.claude/skills/logo-design/assets/library/svg/hanami.svg new file mode 100644 index 0000000..d1a65bf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hanami.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/handlebars.svg b/.claude/skills/logo-design/assets/library/svg/handlebars.svg new file mode 100644 index 0000000..e0a18e9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/handlebars.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hapi.svg b/.claude/skills/logo-design/assets/library/svg/hapi.svg new file mode 100644 index 0000000..d05c5c5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hapi.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hardhat-icon.svg b/.claude/skills/logo-design/assets/library/svg/hardhat-icon.svg new file mode 100644 index 0000000..711de57 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hardhat-icon.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hardhat.svg b/.claude/skills/logo-design/assets/library/svg/hardhat.svg new file mode 100644 index 0000000..0c31f49 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hardhat.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hashnode-icon.svg b/.claude/skills/logo-design/assets/library/svg/hashnode-icon.svg new file mode 100644 index 0000000..90414e8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hashnode-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hashnode.svg b/.claude/skills/logo-design/assets/library/svg/hashnode.svg new file mode 100644 index 0000000..ab96cd6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hashnode.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/haskell-icon.svg b/.claude/skills/logo-design/assets/library/svg/haskell-icon.svg new file mode 100644 index 0000000..7ce8106 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/haskell-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/haskell.svg b/.claude/skills/logo-design/assets/library/svg/haskell.svg new file mode 100644 index 0000000..bd178d3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/haskell.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hasura.svg b/.claude/skills/logo-design/assets/library/svg/hasura.svg new file mode 100644 index 0000000..f80a2e1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hasura.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/haxe.svg b/.claude/skills/logo-design/assets/library/svg/haxe.svg new file mode 100644 index 0000000..6ce9dbe --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/haxe.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/haxl.svg b/.claude/skills/logo-design/assets/library/svg/haxl.svg new file mode 100644 index 0000000..b3d8c34 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/haxl.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hbase.svg b/.claude/skills/logo-design/assets/library/svg/hbase.svg new file mode 100644 index 0000000..a06f999 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hbase.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/headlessui-icon.svg b/.claude/skills/logo-design/assets/library/svg/headlessui-icon.svg new file mode 100644 index 0000000..251b750 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/headlessui-icon.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/headlessui.svg b/.claude/skills/logo-design/assets/library/svg/headlessui.svg new file mode 100644 index 0000000..262879c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/headlessui.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/heap.svg b/.claude/skills/logo-design/assets/library/svg/heap.svg new file mode 100644 index 0000000..50687a7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/heap.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/helm.svg b/.claude/skills/logo-design/assets/library/svg/helm.svg new file mode 100644 index 0000000..e192c6c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/helm.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/helpscout-icon.svg b/.claude/skills/logo-design/assets/library/svg/helpscout-icon.svg new file mode 100644 index 0000000..8d3a66c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/helpscout-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/helpscout.svg b/.claude/skills/logo-design/assets/library/svg/helpscout.svg new file mode 100644 index 0000000..3c8914c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/helpscout.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hermes.svg b/.claude/skills/logo-design/assets/library/svg/hermes.svg new file mode 100644 index 0000000..5624411 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hermes.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/heroku-icon.svg b/.claude/skills/logo-design/assets/library/svg/heroku-icon.svg new file mode 100644 index 0000000..4ade08f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/heroku-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/heroku-redis.svg b/.claude/skills/logo-design/assets/library/svg/heroku-redis.svg new file mode 100644 index 0000000..e907257 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/heroku-redis.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/heroku.svg b/.claude/skills/logo-design/assets/library/svg/heroku.svg new file mode 100644 index 0000000..30a3ed7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/heroku.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hexo.svg b/.claude/skills/logo-design/assets/library/svg/hexo.svg new file mode 100644 index 0000000..7c042af --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hexo.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hhvm.svg b/.claude/skills/logo-design/assets/library/svg/hhvm.svg new file mode 100644 index 0000000..699db00 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hhvm.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hibernate.svg b/.claude/skills/logo-design/assets/library/svg/hibernate.svg new file mode 100644 index 0000000..545ce17 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hibernate.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/highcharts.svg b/.claude/skills/logo-design/assets/library/svg/highcharts.svg new file mode 100644 index 0000000..f599a71 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/highcharts.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hipercard.svg b/.claude/skills/logo-design/assets/library/svg/hipercard.svg new file mode 100644 index 0000000..28a35c1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hipercard.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hoa.svg b/.claude/skills/logo-design/assets/library/svg/hoa.svg new file mode 100644 index 0000000..71a2b6f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hoa.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/homebrew.svg b/.claude/skills/logo-design/assets/library/svg/homebrew.svg new file mode 100644 index 0000000..200f49f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/homebrew.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hoodie.svg b/.claude/skills/logo-design/assets/library/svg/hoodie.svg new file mode 100644 index 0000000..b68f287 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hoodie.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hosted-graphite.svg b/.claude/skills/logo-design/assets/library/svg/hosted-graphite.svg new file mode 100644 index 0000000..ab7b104 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hosted-graphite.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hostgator-icon.svg b/.claude/skills/logo-design/assets/library/svg/hostgator-icon.svg new file mode 100644 index 0000000..2958e53 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hostgator-icon.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hostgator.svg b/.claude/skills/logo-design/assets/library/svg/hostgator.svg new file mode 100644 index 0000000..aeafbbf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hostgator.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hotjar.svg b/.claude/skills/logo-design/assets/library/svg/hotjar.svg new file mode 100644 index 0000000..7f9cbbf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hotjar.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/houndci.svg b/.claude/skills/logo-design/assets/library/svg/houndci.svg new file mode 100644 index 0000000..9d15237 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/houndci.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/html-5.svg b/.claude/skills/logo-design/assets/library/svg/html-5.svg new file mode 100644 index 0000000..868366e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/html-5.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/html5-boilerplate.svg b/.claude/skills/logo-design/assets/library/svg/html5-boilerplate.svg new file mode 100644 index 0000000..900f746 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/html5-boilerplate.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/httpie-icon.svg b/.claude/skills/logo-design/assets/library/svg/httpie-icon.svg new file mode 100644 index 0000000..5fc7839 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/httpie-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/httpie.svg b/.claude/skills/logo-design/assets/library/svg/httpie.svg new file mode 100644 index 0000000..d878030 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/httpie.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hubspot.svg b/.claude/skills/logo-design/assets/library/svg/hubspot.svg new file mode 100644 index 0000000..7ae4311 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hubspot.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/huggy.svg b/.claude/skills/logo-design/assets/library/svg/huggy.svg new file mode 100644 index 0000000..d3ba903 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/huggy.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hugo.svg b/.claude/skills/logo-design/assets/library/svg/hugo.svg new file mode 100644 index 0000000..fa5474d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hugo.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/humongous.svg b/.claude/skills/logo-design/assets/library/svg/humongous.svg new file mode 100644 index 0000000..541d20a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/humongous.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hyper.svg b/.claude/skills/logo-design/assets/library/svg/hyper.svg new file mode 100644 index 0000000..64d0d73 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hyper.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/hyperapp.svg b/.claude/skills/logo-design/assets/library/svg/hyperapp.svg new file mode 100644 index 0000000..564db67 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/hyperapp.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ibm.svg b/.claude/skills/logo-design/assets/library/svg/ibm.svg new file mode 100644 index 0000000..ac73276 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ibm.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ieee.svg b/.claude/skills/logo-design/assets/library/svg/ieee.svg new file mode 100644 index 0000000..a254f3c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ieee.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ifttt.svg b/.claude/skills/logo-design/assets/library/svg/ifttt.svg new file mode 100644 index 0000000..3bc6cde --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ifttt.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/imagemin.svg b/.claude/skills/logo-design/assets/library/svg/imagemin.svg new file mode 100644 index 0000000..1187b78 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/imagemin.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/imba-icon.svg b/.claude/skills/logo-design/assets/library/svg/imba-icon.svg new file mode 100644 index 0000000..5f2286d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/imba-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/imba.svg b/.claude/skills/logo-design/assets/library/svg/imba.svg new file mode 100644 index 0000000..3ccb93e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/imba.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/immer-icon.svg b/.claude/skills/logo-design/assets/library/svg/immer-icon.svg new file mode 100644 index 0000000..9a0d1fa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/immer-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/immer.svg b/.claude/skills/logo-design/assets/library/svg/immer.svg new file mode 100644 index 0000000..af3766a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/immer.svg @@ -0,0 +1,4 @@ + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/immutable.svg b/.claude/skills/logo-design/assets/library/svg/immutable.svg new file mode 100644 index 0000000..5a040c3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/immutable.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/impala.svg b/.claude/skills/logo-design/assets/library/svg/impala.svg new file mode 100644 index 0000000..062b778 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/impala.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/importio.svg b/.claude/skills/logo-design/assets/library/svg/importio.svg new file mode 100644 index 0000000..45b8a68 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/importio.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/infer.svg b/.claude/skills/logo-design/assets/library/svg/infer.svg new file mode 100644 index 0000000..9b06c76 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/infer.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/inferno.svg b/.claude/skills/logo-design/assets/library/svg/inferno.svg new file mode 100644 index 0000000..0dd5849 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/inferno.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/influxdb.svg b/.claude/skills/logo-design/assets/library/svg/influxdb.svg new file mode 100644 index 0000000..fc1a698 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/influxdb.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ink.svg b/.claude/skills/logo-design/assets/library/svg/ink.svg new file mode 100644 index 0000000..03ae637 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ink.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/insomnia.svg b/.claude/skills/logo-design/assets/library/svg/insomnia.svg new file mode 100644 index 0000000..2e7654e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/insomnia.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/instagram-icon.svg b/.claude/skills/logo-design/assets/library/svg/instagram-icon.svg new file mode 100644 index 0000000..64cd8d3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/instagram-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/instagram.svg b/.claude/skills/logo-design/assets/library/svg/instagram.svg new file mode 100644 index 0000000..0346bba --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/instagram.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/intellij-idea.svg b/.claude/skills/logo-design/assets/library/svg/intellij-idea.svg new file mode 100644 index 0000000..6e03c5a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/intellij-idea.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/intercom-icon.svg b/.claude/skills/logo-design/assets/library/svg/intercom-icon.svg new file mode 100644 index 0000000..401c098 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/intercom-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/intercom.svg b/.claude/skills/logo-design/assets/library/svg/intercom.svg new file mode 100644 index 0000000..ee11e20 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/intercom.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/internetexplorer.svg b/.claude/skills/logo-design/assets/library/svg/internetexplorer.svg new file mode 100644 index 0000000..7cf54ba --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/internetexplorer.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/invision-icon.svg b/.claude/skills/logo-design/assets/library/svg/invision-icon.svg new file mode 100644 index 0000000..97c723c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/invision-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/invision.svg b/.claude/skills/logo-design/assets/library/svg/invision.svg new file mode 100644 index 0000000..1247726 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/invision.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ionic-icon.svg b/.claude/skills/logo-design/assets/library/svg/ionic-icon.svg new file mode 100644 index 0000000..b6f661f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ionic-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ionic.svg b/.claude/skills/logo-design/assets/library/svg/ionic.svg new file mode 100644 index 0000000..eccf11a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ionic.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ios.svg b/.claude/skills/logo-design/assets/library/svg/ios.svg new file mode 100644 index 0000000..7fb0f8e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ios.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/iron-icon.svg b/.claude/skills/logo-design/assets/library/svg/iron-icon.svg new file mode 100644 index 0000000..c20cbdd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/iron-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/iron.svg b/.claude/skills/logo-design/assets/library/svg/iron.svg new file mode 100644 index 0000000..f786a49 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/iron.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/itsalive-icon.svg b/.claude/skills/logo-design/assets/library/svg/itsalive-icon.svg new file mode 100644 index 0000000..6d773ba --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/itsalive-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/itsalive.svg b/.claude/skills/logo-design/assets/library/svg/itsalive.svg new file mode 100644 index 0000000..6ca758f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/itsalive.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jade.svg b/.claude/skills/logo-design/assets/library/svg/jade.svg new file mode 100644 index 0000000..906369b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jade.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jamstack-icon.svg b/.claude/skills/logo-design/assets/library/svg/jamstack-icon.svg new file mode 100644 index 0000000..ecad994 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jamstack-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jamstack.svg b/.claude/skills/logo-design/assets/library/svg/jamstack.svg new file mode 100644 index 0000000..264a41c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jamstack.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jasmine.svg b/.claude/skills/logo-design/assets/library/svg/jasmine.svg new file mode 100644 index 0000000..c9e46e4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jasmine.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/java.svg b/.claude/skills/logo-design/assets/library/svg/java.svg new file mode 100644 index 0000000..64d8cc4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/java.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/javascript.svg b/.claude/skills/logo-design/assets/library/svg/javascript.svg new file mode 100644 index 0000000..3ed055d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/javascript.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jcb.svg b/.claude/skills/logo-design/assets/library/svg/jcb.svg new file mode 100644 index 0000000..469c22c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jcb.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jekyll.svg b/.claude/skills/logo-design/assets/library/svg/jekyll.svg new file mode 100644 index 0000000..63fcacc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jekyll.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jelastic-icon.svg b/.claude/skills/logo-design/assets/library/svg/jelastic-icon.svg new file mode 100644 index 0000000..2a3f5fb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jelastic-icon.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jelastic.svg b/.claude/skills/logo-design/assets/library/svg/jelastic.svg new file mode 100644 index 0000000..c1c416a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jelastic.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jenkins.svg b/.claude/skills/logo-design/assets/library/svg/jenkins.svg new file mode 100644 index 0000000..f576e5e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jenkins.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jest.svg b/.claude/skills/logo-design/assets/library/svg/jest.svg new file mode 100644 index 0000000..384baa8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jest.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jetbrains.svg b/.claude/skills/logo-design/assets/library/svg/jetbrains.svg new file mode 100644 index 0000000..0b20b7e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jetbrains.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jfrog.svg b/.claude/skills/logo-design/assets/library/svg/jfrog.svg new file mode 100644 index 0000000..7d0fd06 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jfrog.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jhipster-icon.svg b/.claude/skills/logo-design/assets/library/svg/jhipster-icon.svg new file mode 100644 index 0000000..658daf0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jhipster-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jhipster.svg b/.claude/skills/logo-design/assets/library/svg/jhipster.svg new file mode 100644 index 0000000..d2c3daa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jhipster.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jira.svg b/.claude/skills/logo-design/assets/library/svg/jira.svg new file mode 100644 index 0000000..5889efc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jira.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/joomla.svg b/.claude/skills/logo-design/assets/library/svg/joomla.svg new file mode 100644 index 0000000..9a8f28f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/joomla.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jquery-mobile.svg b/.claude/skills/logo-design/assets/library/svg/jquery-mobile.svg new file mode 100644 index 0000000..bfcad24 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jquery-mobile.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jquery.svg b/.claude/skills/logo-design/assets/library/svg/jquery.svg new file mode 100644 index 0000000..d684a9a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jquery.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jruby.svg b/.claude/skills/logo-design/assets/library/svg/jruby.svg new file mode 100644 index 0000000..9d697de --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jruby.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jsbin.svg b/.claude/skills/logo-design/assets/library/svg/jsbin.svg new file mode 100644 index 0000000..bf99926 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jsbin.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jsdelivr.svg b/.claude/skills/logo-design/assets/library/svg/jsdelivr.svg new file mode 100644 index 0000000..19964d8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jsdelivr.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jsdom.svg b/.claude/skills/logo-design/assets/library/svg/jsdom.svg new file mode 100644 index 0000000..0f29ac3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jsdom.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jsfiddle.svg b/.claude/skills/logo-design/assets/library/svg/jsfiddle.svg new file mode 100644 index 0000000..072b6e7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jsfiddle.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/json.svg b/.claude/skills/logo-design/assets/library/svg/json.svg new file mode 100644 index 0000000..88b3698 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/json.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jspm.svg b/.claude/skills/logo-design/assets/library/svg/jspm.svg new file mode 100644 index 0000000..4d79a6b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jspm.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jss.svg b/.claude/skills/logo-design/assets/library/svg/jss.svg new file mode 100644 index 0000000..a3f2418 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jss.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/juju.svg b/.claude/skills/logo-design/assets/library/svg/juju.svg new file mode 100644 index 0000000..c87e979 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/juju.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/julia.svg b/.claude/skills/logo-design/assets/library/svg/julia.svg new file mode 100644 index 0000000..124c07a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/julia.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jupyter.svg b/.claude/skills/logo-design/assets/library/svg/jupyter.svg new file mode 100644 index 0000000..b31d595 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jupyter.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jwt-icon.svg b/.claude/skills/logo-design/assets/library/svg/jwt-icon.svg new file mode 100644 index 0000000..2127928 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jwt-icon.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/jwt.svg b/.claude/skills/logo-design/assets/library/svg/jwt.svg new file mode 100644 index 0000000..38d577a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/jwt.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kafka-icon.svg b/.claude/skills/logo-design/assets/library/svg/kafka-icon.svg new file mode 100644 index 0000000..5558563 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kafka-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kafka.svg b/.claude/skills/logo-design/assets/library/svg/kafka.svg new file mode 100644 index 0000000..52d6ff5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kafka.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kaios.svg b/.claude/skills/logo-design/assets/library/svg/kaios.svg new file mode 100644 index 0000000..4f71d68 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kaios.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kallithea.svg b/.claude/skills/logo-design/assets/library/svg/kallithea.svg new file mode 100644 index 0000000..a593739 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kallithea.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/karma.svg b/.claude/skills/logo-design/assets/library/svg/karma.svg new file mode 100644 index 0000000..22a5873 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/karma.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kde.svg b/.claude/skills/logo-design/assets/library/svg/kde.svg new file mode 100644 index 0000000..844a701 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kde.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/keen.svg b/.claude/skills/logo-design/assets/library/svg/keen.svg new file mode 100644 index 0000000..9640e2a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/keen.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kemal.svg b/.claude/skills/logo-design/assets/library/svg/kemal.svg new file mode 100644 index 0000000..ee531c3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kemal.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/keycdn-icon.svg b/.claude/skills/logo-design/assets/library/svg/keycdn-icon.svg new file mode 100644 index 0000000..57df5d2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/keycdn-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/keycdn.svg b/.claude/skills/logo-design/assets/library/svg/keycdn.svg new file mode 100644 index 0000000..66841d2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/keycdn.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/keystonejs.svg b/.claude/skills/logo-design/assets/library/svg/keystonejs.svg new file mode 100644 index 0000000..5b10a9b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/keystonejs.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/khan_academy-icon.svg b/.claude/skills/logo-design/assets/library/svg/khan_academy-icon.svg new file mode 100644 index 0000000..c344357 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/khan_academy-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/khan_academy.svg b/.claude/skills/logo-design/assets/library/svg/khan_academy.svg new file mode 100644 index 0000000..873e793 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/khan_academy.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kibana.svg b/.claude/skills/logo-design/assets/library/svg/kibana.svg new file mode 100644 index 0000000..17de3ed --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kibana.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kickstarter-icon.svg b/.claude/skills/logo-design/assets/library/svg/kickstarter-icon.svg new file mode 100644 index 0000000..c80cbe7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kickstarter-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kickstarter.svg b/.claude/skills/logo-design/assets/library/svg/kickstarter.svg new file mode 100644 index 0000000..b7adf1d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kickstarter.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kinto-icon.svg b/.claude/skills/logo-design/assets/library/svg/kinto-icon.svg new file mode 100644 index 0000000..5f32720 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kinto-icon.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kinto.svg b/.claude/skills/logo-design/assets/library/svg/kinto.svg new file mode 100644 index 0000000..4070817 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kinto.svg @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kirby-icon.svg b/.claude/skills/logo-design/assets/library/svg/kirby-icon.svg new file mode 100644 index 0000000..e5738a0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kirby-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kirby.svg b/.claude/skills/logo-design/assets/library/svg/kirby.svg new file mode 100644 index 0000000..cbd59b3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kirby.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kissmetrics.svg b/.claude/skills/logo-design/assets/library/svg/kissmetrics.svg new file mode 100644 index 0000000..092333c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kissmetrics.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kitematic.svg b/.claude/skills/logo-design/assets/library/svg/kitematic.svg new file mode 100644 index 0000000..798fcd2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kitematic.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kloudless.svg b/.claude/skills/logo-design/assets/library/svg/kloudless.svg new file mode 100644 index 0000000..10daefb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kloudless.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/knex.svg b/.claude/skills/logo-design/assets/library/svg/knex.svg new file mode 100644 index 0000000..9b87f02 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/knex.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/knockout.svg b/.claude/skills/logo-design/assets/library/svg/knockout.svg new file mode 100644 index 0000000..51ed358 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/knockout.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/koa.svg b/.claude/skills/logo-design/assets/library/svg/koa.svg new file mode 100644 index 0000000..c90e049 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/koa.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kong-icon.svg b/.claude/skills/logo-design/assets/library/svg/kong-icon.svg new file mode 100644 index 0000000..6941065 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kong-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kong.svg b/.claude/skills/logo-design/assets/library/svg/kong.svg new file mode 100644 index 0000000..8fc47a0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kong.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kops.svg b/.claude/skills/logo-design/assets/library/svg/kops.svg new file mode 100644 index 0000000..0e6938a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kops.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/koreio.svg b/.claude/skills/logo-design/assets/library/svg/koreio.svg new file mode 100644 index 0000000..ca998b1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/koreio.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kotlin-icon.svg b/.claude/skills/logo-design/assets/library/svg/kotlin-icon.svg new file mode 100644 index 0000000..9f09ba8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kotlin-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kotlin.svg b/.claude/skills/logo-design/assets/library/svg/kotlin.svg new file mode 100644 index 0000000..3327b44 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kotlin.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kraken.svg b/.claude/skills/logo-design/assets/library/svg/kraken.svg new file mode 100644 index 0000000..e961a06 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kraken.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/krakenjs.svg b/.claude/skills/logo-design/assets/library/svg/krakenjs.svg new file mode 100644 index 0000000..efe346f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/krakenjs.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kubernetes.svg b/.claude/skills/logo-design/assets/library/svg/kubernetes.svg new file mode 100644 index 0000000..409db4c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kubernetes.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/kustomer.svg b/.claude/skills/logo-design/assets/library/svg/kustomer.svg new file mode 100644 index 0000000..4a96c11 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/kustomer.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/laravel.svg b/.claude/skills/logo-design/assets/library/svg/laravel.svg new file mode 100644 index 0000000..882b99f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/laravel.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lastfm.svg b/.claude/skills/logo-design/assets/library/svg/lastfm.svg new file mode 100644 index 0000000..8b98a87 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lastfm.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lateral.svg b/.claude/skills/logo-design/assets/library/svg/lateral.svg new file mode 100644 index 0000000..ca92db0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lateral.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/launchrock.svg b/.claude/skills/logo-design/assets/library/svg/launchrock.svg new file mode 100644 index 0000000..4b85cb0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/launchrock.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/leaflet.svg b/.claude/skills/logo-design/assets/library/svg/leaflet.svg new file mode 100644 index 0000000..db09c89 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/leaflet.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/leankit-icon.svg b/.claude/skills/logo-design/assets/library/svg/leankit-icon.svg new file mode 100644 index 0000000..0fa5072 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/leankit-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/leankit.svg b/.claude/skills/logo-design/assets/library/svg/leankit.svg new file mode 100644 index 0000000..0c26d59 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/leankit.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lerna.svg b/.claude/skills/logo-design/assets/library/svg/lerna.svg new file mode 100644 index 0000000..1f0cc76 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lerna.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/less.svg b/.claude/skills/logo-design/assets/library/svg/less.svg new file mode 100644 index 0000000..dab4d59 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/less.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lets-cloud.svg b/.claude/skills/logo-design/assets/library/svg/lets-cloud.svg new file mode 100644 index 0000000..4b8ff3f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lets-cloud.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/letsencrypt.svg b/.claude/skills/logo-design/assets/library/svg/letsencrypt.svg new file mode 100644 index 0000000..d91eefd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/letsencrypt.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/leveldb.svg b/.claude/skills/logo-design/assets/library/svg/leveldb.svg new file mode 100644 index 0000000..899c002 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/leveldb.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/liftweb.svg b/.claude/skills/logo-design/assets/library/svg/liftweb.svg new file mode 100644 index 0000000..1025912 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/liftweb.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lighthouse.svg b/.claude/skills/logo-design/assets/library/svg/lighthouse.svg new file mode 100644 index 0000000..89dd3e5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lighthouse.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lightstep-icon.svg b/.claude/skills/logo-design/assets/library/svg/lightstep-icon.svg new file mode 100644 index 0000000..64b5b77 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lightstep-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lightstep.svg b/.claude/skills/logo-design/assets/library/svg/lightstep.svg new file mode 100644 index 0000000..5be9dc9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lightstep.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lighttpd.svg b/.claude/skills/logo-design/assets/library/svg/lighttpd.svg new file mode 100644 index 0000000..38511fd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lighttpd.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/linkedin-icon.svg b/.claude/skills/logo-design/assets/library/svg/linkedin-icon.svg new file mode 100644 index 0000000..2ca0751 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/linkedin-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/linkedin.svg b/.claude/skills/logo-design/assets/library/svg/linkedin.svg new file mode 100644 index 0000000..40c40a0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/linkedin.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/linkerd.svg b/.claude/skills/logo-design/assets/library/svg/linkerd.svg new file mode 100644 index 0000000..eda1f3e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/linkerd.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/linode.svg b/.claude/skills/logo-design/assets/library/svg/linode.svg new file mode 100644 index 0000000..e2ec7d5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/linode.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/linux-mint.svg b/.claude/skills/logo-design/assets/library/svg/linux-mint.svg new file mode 100644 index 0000000..59cf86a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/linux-mint.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/linux-tux.svg b/.claude/skills/logo-design/assets/library/svg/linux-tux.svg new file mode 100644 index 0000000..1ed7b7c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/linux-tux.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lit-icon.svg b/.claude/skills/logo-design/assets/library/svg/lit-icon.svg new file mode 100644 index 0000000..1074a9d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lit-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lit.svg b/.claude/skills/logo-design/assets/library/svg/lit.svg new file mode 100644 index 0000000..6d398ec --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lit.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/litmus.svg b/.claude/skills/logo-design/assets/library/svg/litmus.svg new file mode 100644 index 0000000..302edbd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/litmus.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/loader.svg b/.claude/skills/logo-design/assets/library/svg/loader.svg new file mode 100644 index 0000000..0a8277a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/loader.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lodash.svg b/.claude/skills/logo-design/assets/library/svg/lodash.svg new file mode 100644 index 0000000..6f987fa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lodash.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/logentries.svg b/.claude/skills/logo-design/assets/library/svg/logentries.svg new file mode 100644 index 0000000..90c715e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/logentries.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/logstash.svg b/.claude/skills/logo-design/assets/library/svg/logstash.svg new file mode 100644 index 0000000..705937b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/logstash.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lookback.svg b/.claude/skills/logo-design/assets/library/svg/lookback.svg new file mode 100644 index 0000000..91e9bb8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lookback.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/looker-icon.svg b/.claude/skills/logo-design/assets/library/svg/looker-icon.svg new file mode 100644 index 0000000..987eac7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/looker-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/looker.svg b/.claude/skills/logo-design/assets/library/svg/looker.svg new file mode 100644 index 0000000..9556317 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/looker.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/loom.svg b/.claude/skills/logo-design/assets/library/svg/loom.svg new file mode 100644 index 0000000..1357c2d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/loom.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/loopback-icon.svg b/.claude/skills/logo-design/assets/library/svg/loopback-icon.svg new file mode 100644 index 0000000..c5634bb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/loopback-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/loopback.svg b/.claude/skills/logo-design/assets/library/svg/loopback.svg new file mode 100644 index 0000000..797ffe2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/loopback.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/losant.svg b/.claude/skills/logo-design/assets/library/svg/losant.svg new file mode 100644 index 0000000..faa12fe --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/losant.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lua.svg b/.claude/skills/logo-design/assets/library/svg/lua.svg new file mode 100644 index 0000000..e7ea089 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lua.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lucene.net.svg b/.claude/skills/logo-design/assets/library/svg/lucene.net.svg new file mode 100644 index 0000000..a1e5b93 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lucene.net.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lucene.svg b/.claude/skills/logo-design/assets/library/svg/lucene.svg new file mode 100644 index 0000000..bb5961b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lucene.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/lumen.svg b/.claude/skills/logo-design/assets/library/svg/lumen.svg new file mode 100644 index 0000000..139d183 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/lumen.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/macOS.svg b/.claude/skills/logo-design/assets/library/svg/macOS.svg new file mode 100644 index 0000000..5f0e7d7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/macOS.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/madge.svg b/.claude/skills/logo-design/assets/library/svg/madge.svg new file mode 100644 index 0000000..a476b17 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/madge.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/maestro.svg b/.claude/skills/logo-design/assets/library/svg/maestro.svg new file mode 100644 index 0000000..150a551 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/maestro.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mageia.svg b/.claude/skills/logo-design/assets/library/svg/mageia.svg new file mode 100644 index 0000000..95ab8b0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mageia.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/magento.svg b/.claude/skills/logo-design/assets/library/svg/magento.svg new file mode 100644 index 0000000..cbaea9f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/magento.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mailchimp-freddie.svg b/.claude/skills/logo-design/assets/library/svg/mailchimp-freddie.svg new file mode 100644 index 0000000..e53777e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mailchimp-freddie.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mailchimp.svg b/.claude/skills/logo-design/assets/library/svg/mailchimp.svg new file mode 100644 index 0000000..61313a2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mailchimp.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/maildeveloper.svg b/.claude/skills/logo-design/assets/library/svg/maildeveloper.svg new file mode 100644 index 0000000..2ab7fc6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/maildeveloper.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mailgun-icon.svg b/.claude/skills/logo-design/assets/library/svg/mailgun-icon.svg new file mode 100644 index 0000000..d80b579 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mailgun-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mailgun.svg b/.claude/skills/logo-design/assets/library/svg/mailgun.svg new file mode 100644 index 0000000..6d3353a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mailgun.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mailjet.svg b/.claude/skills/logo-design/assets/library/svg/mailjet.svg new file mode 100644 index 0000000..fc95144 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mailjet.svg @@ -0,0 +1,4 @@ + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/malinajs.svg b/.claude/skills/logo-design/assets/library/svg/malinajs.svg new file mode 100644 index 0000000..c8384ae --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/malinajs.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/manjaro.svg b/.claude/skills/logo-design/assets/library/svg/manjaro.svg new file mode 100644 index 0000000..483e9fd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/manjaro.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/manuscript.svg b/.claude/skills/logo-design/assets/library/svg/manuscript.svg new file mode 100644 index 0000000..33afbb2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/manuscript.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mapbox-icon.svg b/.claude/skills/logo-design/assets/library/svg/mapbox-icon.svg new file mode 100644 index 0000000..c395042 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mapbox-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mapbox.svg b/.claude/skills/logo-design/assets/library/svg/mapbox.svg new file mode 100644 index 0000000..1268613 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mapbox.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/maps-me.svg b/.claude/skills/logo-design/assets/library/svg/maps-me.svg new file mode 100644 index 0000000..634e5e4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/maps-me.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mapzen-icon.svg b/.claude/skills/logo-design/assets/library/svg/mapzen-icon.svg new file mode 100644 index 0000000..897a510 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mapzen-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mapzen.svg b/.claude/skills/logo-design/assets/library/svg/mapzen.svg new file mode 100644 index 0000000..b09a727 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mapzen.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mariadb-icon.svg b/.claude/skills/logo-design/assets/library/svg/mariadb-icon.svg new file mode 100644 index 0000000..a757f94 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mariadb-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mariadb.svg b/.claude/skills/logo-design/assets/library/svg/mariadb.svg new file mode 100644 index 0000000..dd02b93 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mariadb.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/marionette.svg b/.claude/skills/logo-design/assets/library/svg/marionette.svg new file mode 100644 index 0000000..b60576c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/marionette.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/markdown.svg b/.claude/skills/logo-design/assets/library/svg/markdown.svg new file mode 100644 index 0000000..870805a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/markdown.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/marko.svg b/.claude/skills/logo-design/assets/library/svg/marko.svg new file mode 100644 index 0000000..2e393df --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/marko.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/marvel.svg b/.claude/skills/logo-design/assets/library/svg/marvel.svg new file mode 100644 index 0000000..3facf3b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/marvel.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mastercard.svg b/.claude/skills/logo-design/assets/library/svg/mastercard.svg new file mode 100644 index 0000000..777ae18 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mastercard.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mastodon-icon.svg b/.claude/skills/logo-design/assets/library/svg/mastodon-icon.svg new file mode 100644 index 0000000..d8a71d0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mastodon-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mastodon.svg b/.claude/skills/logo-design/assets/library/svg/mastodon.svg new file mode 100644 index 0000000..34edf17 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mastodon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/material-ui.svg b/.claude/skills/logo-design/assets/library/svg/material-ui.svg new file mode 100644 index 0000000..6a514fa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/material-ui.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/materializecss.svg b/.claude/skills/logo-design/assets/library/svg/materializecss.svg new file mode 100644 index 0000000..1e0a132 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/materializecss.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/matplotlib-icon.svg b/.claude/skills/logo-design/assets/library/svg/matplotlib-icon.svg new file mode 100644 index 0000000..d95764b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/matplotlib-icon.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/matplotlib.svg b/.claude/skills/logo-design/assets/library/svg/matplotlib.svg new file mode 100644 index 0000000..abd80fe --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/matplotlib.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mattermost-icon.svg b/.claude/skills/logo-design/assets/library/svg/mattermost-icon.svg new file mode 100644 index 0000000..23673e0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mattermost-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mattermost.svg b/.claude/skills/logo-design/assets/library/svg/mattermost.svg new file mode 100644 index 0000000..847698f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mattermost.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/maven.svg b/.claude/skills/logo-design/assets/library/svg/maven.svg new file mode 100644 index 0000000..c8f24f8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/maven.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/maxcdn.svg b/.claude/skills/logo-design/assets/library/svg/maxcdn.svg new file mode 100644 index 0000000..4d78536 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/maxcdn.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mdn.svg b/.claude/skills/logo-design/assets/library/svg/mdn.svg new file mode 100644 index 0000000..e98a502 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mdn.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mdx.svg b/.claude/skills/logo-design/assets/library/svg/mdx.svg new file mode 100644 index 0000000..bc6b194 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mdx.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/medium-icon.svg b/.claude/skills/logo-design/assets/library/svg/medium-icon.svg new file mode 100644 index 0000000..99ec825 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/medium-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/medium.svg b/.claude/skills/logo-design/assets/library/svg/medium.svg new file mode 100644 index 0000000..2156479 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/medium.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/memcached.svg b/.claude/skills/logo-design/assets/library/svg/memcached.svg new file mode 100644 index 0000000..066bb31 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/memcached.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/memsql-icon.svg b/.claude/skills/logo-design/assets/library/svg/memsql-icon.svg new file mode 100644 index 0000000..b98b901 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/memsql-icon.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/memsql.svg b/.claude/skills/logo-design/assets/library/svg/memsql.svg new file mode 100644 index 0000000..105ce77 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/memsql.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mention.svg b/.claude/skills/logo-design/assets/library/svg/mention.svg new file mode 100644 index 0000000..7e868cd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mention.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mercurial.svg b/.claude/skills/logo-design/assets/library/svg/mercurial.svg new file mode 100644 index 0000000..8446537 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mercurial.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mesos.svg b/.claude/skills/logo-design/assets/library/svg/mesos.svg new file mode 100644 index 0000000..53c86d2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mesos.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/metabase.svg b/.claude/skills/logo-design/assets/library/svg/metabase.svg new file mode 100644 index 0000000..3312bb3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/metabase.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/metamask-icon.svg b/.claude/skills/logo-design/assets/library/svg/metamask-icon.svg new file mode 100644 index 0000000..1f42b16 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/metamask-icon.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/metamask.svg b/.claude/skills/logo-design/assets/library/svg/metamask.svg new file mode 100644 index 0000000..b9b72ab --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/metamask.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/meteor-icon.svg b/.claude/skills/logo-design/assets/library/svg/meteor-icon.svg new file mode 100644 index 0000000..4e4089e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/meteor-icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/meteor.svg b/.claude/skills/logo-design/assets/library/svg/meteor.svg new file mode 100644 index 0000000..3fbc6ef --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/meteor.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/microcosm.svg b/.claude/skills/logo-design/assets/library/svg/microcosm.svg new file mode 100644 index 0000000..1a0a64d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/microcosm.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-azure.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-azure.svg new file mode 100644 index 0000000..886ed29 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/microsoft-azure.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-edge.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-edge.svg new file mode 100644 index 0000000..c4cd320 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/microsoft-edge.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-onedrive.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-onedrive.svg new file mode 100644 index 0000000..6c78633 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/microsoft-onedrive.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-power-bi.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-power-bi.svg new file mode 100644 index 0000000..2bebf9d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/microsoft-power-bi.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-teams.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-teams.svg new file mode 100644 index 0000000..da7fee0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/microsoft-teams.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-windows.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-windows.svg new file mode 100644 index 0000000..b4a7fdc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/microsoft-windows.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft.svg b/.claude/skills/logo-design/assets/library/svg/microsoft.svg new file mode 100644 index 0000000..c6cb96f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/microsoft.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/middleman.svg b/.claude/skills/logo-design/assets/library/svg/middleman.svg new file mode 100644 index 0000000..7156f12 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/middleman.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/milligram.svg b/.claude/skills/logo-design/assets/library/svg/milligram.svg new file mode 100644 index 0000000..60fadda --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/milligram.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mint-lang.svg b/.claude/skills/logo-design/assets/library/svg/mint-lang.svg new file mode 100644 index 0000000..6a9a7d8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mint-lang.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mio.svg b/.claude/skills/logo-design/assets/library/svg/mio.svg new file mode 100644 index 0000000..1c5ca83 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mio.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mist.svg b/.claude/skills/logo-design/assets/library/svg/mist.svg new file mode 100644 index 0000000..e0abc29 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mist.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mithril.svg b/.claude/skills/logo-design/assets/library/svg/mithril.svg new file mode 100644 index 0000000..73d1a52 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mithril.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mixmax.svg b/.claude/skills/logo-design/assets/library/svg/mixmax.svg new file mode 100644 index 0000000..9e25858 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mixmax.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mixpanel.svg b/.claude/skills/logo-design/assets/library/svg/mixpanel.svg new file mode 100644 index 0000000..ef7c67f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mixpanel.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mlab.svg b/.claude/skills/logo-design/assets/library/svg/mlab.svg new file mode 100644 index 0000000..2fd5236 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mlab.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mobx.svg b/.claude/skills/logo-design/assets/library/svg/mobx.svg new file mode 100644 index 0000000..f9e7ba0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mobx.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mocha.svg b/.claude/skills/logo-design/assets/library/svg/mocha.svg new file mode 100644 index 0000000..28a3aaf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mocha.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mockflow-icon.svg b/.claude/skills/logo-design/assets/library/svg/mockflow-icon.svg new file mode 100644 index 0000000..a9b4df1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mockflow-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mockflow.svg b/.claude/skills/logo-design/assets/library/svg/mockflow.svg new file mode 100644 index 0000000..7fdfc79 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mockflow.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/modernizr.svg b/.claude/skills/logo-design/assets/library/svg/modernizr.svg new file mode 100644 index 0000000..6a16c67 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/modernizr.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/modx-icon.svg b/.claude/skills/logo-design/assets/library/svg/modx-icon.svg new file mode 100644 index 0000000..2bac2e8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/modx-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/modx.svg b/.claude/skills/logo-design/assets/library/svg/modx.svg new file mode 100644 index 0000000..4018dbb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/modx.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/moltin-icon.svg b/.claude/skills/logo-design/assets/library/svg/moltin-icon.svg new file mode 100644 index 0000000..7d911ef --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/moltin-icon.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/moltin.svg b/.claude/skills/logo-design/assets/library/svg/moltin.svg new file mode 100644 index 0000000..d2adc4a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/moltin.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/momentjs.svg b/.claude/skills/logo-design/assets/library/svg/momentjs.svg new file mode 100644 index 0000000..b4c8990 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/momentjs.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/monday-icon.svg b/.claude/skills/logo-design/assets/library/svg/monday-icon.svg new file mode 100644 index 0000000..7274668 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/monday-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/monday.svg b/.claude/skills/logo-design/assets/library/svg/monday.svg new file mode 100644 index 0000000..dd571a3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/monday.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/monero.svg b/.claude/skills/logo-design/assets/library/svg/monero.svg new file mode 100644 index 0000000..43a959a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/monero.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mongodb.svg b/.claude/skills/logo-design/assets/library/svg/mongodb.svg new file mode 100644 index 0000000..9bd8279 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mongodb.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mono.svg b/.claude/skills/logo-design/assets/library/svg/mono.svg new file mode 100644 index 0000000..2773cd3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mono.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/moon.svg b/.claude/skills/logo-design/assets/library/svg/moon.svg new file mode 100644 index 0000000..0f19391 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/moon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mootools.svg b/.claude/skills/logo-design/assets/library/svg/mootools.svg new file mode 100644 index 0000000..1702a30 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mootools.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/morpheus-icon.svg b/.claude/skills/logo-design/assets/library/svg/morpheus-icon.svg new file mode 100644 index 0000000..187c772 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/morpheus-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/morpheus.svg b/.claude/skills/logo-design/assets/library/svg/morpheus.svg new file mode 100644 index 0000000..eb744f5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/morpheus.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mozilla.svg b/.claude/skills/logo-design/assets/library/svg/mozilla.svg new file mode 100644 index 0000000..5971a41 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mozilla.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mparticle-icon.svg b/.claude/skills/logo-design/assets/library/svg/mparticle-icon.svg new file mode 100644 index 0000000..ca081ba --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mparticle-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mparticle.svg b/.claude/skills/logo-design/assets/library/svg/mparticle.svg new file mode 100644 index 0000000..9b80d21 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mparticle.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/multipass.svg b/.claude/skills/logo-design/assets/library/svg/multipass.svg new file mode 100644 index 0000000..52d35e9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/multipass.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mysql-icon.svg b/.claude/skills/logo-design/assets/library/svg/mysql-icon.svg new file mode 100644 index 0000000..6313821 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mysql-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/mysql.svg b/.claude/skills/logo-design/assets/library/svg/mysql.svg new file mode 100644 index 0000000..778d3f0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/mysql.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/naiveui.svg b/.claude/skills/logo-design/assets/library/svg/naiveui.svg new file mode 100644 index 0000000..b4dd837 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/naiveui.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/namecheap.svg b/.claude/skills/logo-design/assets/library/svg/namecheap.svg new file mode 100644 index 0000000..27d84e2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/namecheap.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nanonets.svg b/.claude/skills/logo-design/assets/library/svg/nanonets.svg new file mode 100644 index 0000000..251984b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nanonets.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nativescript.svg b/.claude/skills/logo-design/assets/library/svg/nativescript.svg new file mode 100644 index 0000000..b5baf98 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nativescript.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nats-icon.svg b/.claude/skills/logo-design/assets/library/svg/nats-icon.svg new file mode 100644 index 0000000..44b9578 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nats-icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nats.svg b/.claude/skills/logo-design/assets/library/svg/nats.svg new file mode 100644 index 0000000..1cc68ca --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nats.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/neat.svg b/.claude/skills/logo-design/assets/library/svg/neat.svg new file mode 100644 index 0000000..971ed8c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/neat.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/neo4j.svg b/.claude/skills/logo-design/assets/library/svg/neo4j.svg new file mode 100644 index 0000000..4c88c51 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/neo4j.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/neovim.svg b/.claude/skills/logo-design/assets/library/svg/neovim.svg new file mode 100644 index 0000000..58aef20 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/neovim.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nestjs.svg b/.claude/skills/logo-design/assets/library/svg/nestjs.svg new file mode 100644 index 0000000..3a60db0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nestjs.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/netbeans.svg b/.claude/skills/logo-design/assets/library/svg/netbeans.svg new file mode 100644 index 0000000..50d20e1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/netbeans.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/netflix-icon.svg b/.claude/skills/logo-design/assets/library/svg/netflix-icon.svg new file mode 100644 index 0000000..2abe549 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/netflix-icon.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/netflix.svg b/.claude/skills/logo-design/assets/library/svg/netflix.svg new file mode 100644 index 0000000..abe8054 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/netflix.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/netlify.svg b/.claude/skills/logo-design/assets/library/svg/netlify.svg new file mode 100644 index 0000000..aaec220 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/netlify.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/new-relic.svg b/.claude/skills/logo-design/assets/library/svg/new-relic.svg new file mode 100644 index 0000000..1b3791e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/new-relic.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nextjs-icon.svg b/.claude/skills/logo-design/assets/library/svg/nextjs-icon.svg new file mode 100644 index 0000000..1d7a84a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nextjs-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nextjs.svg b/.claude/skills/logo-design/assets/library/svg/nextjs.svg new file mode 100644 index 0000000..17fdf85 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nextjs.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nginx.svg b/.claude/skills/logo-design/assets/library/svg/nginx.svg new file mode 100644 index 0000000..a30e0b2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nginx.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nightwatch.svg b/.claude/skills/logo-design/assets/library/svg/nightwatch.svg new file mode 100644 index 0000000..57f860d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nightwatch.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nim-lang.svg b/.claude/skills/logo-design/assets/library/svg/nim-lang.svg new file mode 100644 index 0000000..4ebd2cb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nim-lang.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nocodb.svg b/.claude/skills/logo-design/assets/library/svg/nocodb.svg new file mode 100644 index 0000000..2f801cb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nocodb.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nodal.svg b/.claude/skills/logo-design/assets/library/svg/nodal.svg new file mode 100644 index 0000000..d8c57bd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nodal.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/node-sass.svg b/.claude/skills/logo-design/assets/library/svg/node-sass.svg new file mode 100644 index 0000000..bd0f5bc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/node-sass.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nodebots.svg b/.claude/skills/logo-design/assets/library/svg/nodebots.svg new file mode 100644 index 0000000..16c6765 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nodebots.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nodejs-icon.svg b/.claude/skills/logo-design/assets/library/svg/nodejs-icon.svg new file mode 100644 index 0000000..c048a4d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nodejs-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nodejs.svg b/.claude/skills/logo-design/assets/library/svg/nodejs.svg new file mode 100644 index 0000000..c95bfef --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nodejs.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nodemon.svg b/.claude/skills/logo-design/assets/library/svg/nodemon.svg new file mode 100644 index 0000000..fe32b29 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nodemon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nodeos.svg b/.claude/skills/logo-design/assets/library/svg/nodeos.svg new file mode 100644 index 0000000..e417311 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nodeos.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nodewebkit.svg b/.claude/skills/logo-design/assets/library/svg/nodewebkit.svg new file mode 100644 index 0000000..4ddf547 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nodewebkit.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nomad.svg b/.claude/skills/logo-design/assets/library/svg/nomad.svg new file mode 100644 index 0000000..a559f38 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nomad.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/noysi.svg b/.claude/skills/logo-design/assets/library/svg/noysi.svg new file mode 100644 index 0000000..4fb0014 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/noysi.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/npm-icon.svg b/.claude/skills/logo-design/assets/library/svg/npm-icon.svg new file mode 100644 index 0000000..3aeb1b5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/npm-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/npm.svg b/.claude/skills/logo-design/assets/library/svg/npm.svg new file mode 100644 index 0000000..458e97a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/npm.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nuclide.svg b/.claude/skills/logo-design/assets/library/svg/nuclide.svg new file mode 100644 index 0000000..789c400 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nuclide.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/numpy.svg b/.claude/skills/logo-design/assets/library/svg/numpy.svg new file mode 100644 index 0000000..df927b8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/numpy.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nuxt-icon.svg b/.claude/skills/logo-design/assets/library/svg/nuxt-icon.svg new file mode 100644 index 0000000..dba25e6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nuxt-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nuxt.svg b/.claude/skills/logo-design/assets/library/svg/nuxt.svg new file mode 100644 index 0000000..147e49a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nuxt.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/nx.svg b/.claude/skills/logo-design/assets/library/svg/nx.svg new file mode 100644 index 0000000..dc60906 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/nx.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/oauth.svg b/.claude/skills/logo-design/assets/library/svg/oauth.svg new file mode 100644 index 0000000..815505a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/oauth.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ocaml.svg b/.claude/skills/logo-design/assets/library/svg/ocaml.svg new file mode 100644 index 0000000..d4db2fa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ocaml.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/octodns.svg b/.claude/skills/logo-design/assets/library/svg/octodns.svg new file mode 100644 index 0000000..c623b2b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/octodns.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/octopus-deploy.svg b/.claude/skills/logo-design/assets/library/svg/octopus-deploy.svg new file mode 100644 index 0000000..1b076ea --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/octopus-deploy.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/olark.svg b/.claude/skills/logo-design/assets/library/svg/olark.svg new file mode 100644 index 0000000..1d835a7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/olark.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/onesignal.svg b/.claude/skills/logo-design/assets/library/svg/onesignal.svg new file mode 100644 index 0000000..d8c4200 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/onesignal.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/open-graph.svg b/.claude/skills/logo-design/assets/library/svg/open-graph.svg new file mode 100644 index 0000000..ba1e101 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/open-graph.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/open-zeppelin-icon.svg b/.claude/skills/logo-design/assets/library/svg/open-zeppelin-icon.svg new file mode 100644 index 0000000..f8f4af2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/open-zeppelin-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/open-zeppelin.svg b/.claude/skills/logo-design/assets/library/svg/open-zeppelin.svg new file mode 100644 index 0000000..d0ae452 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/open-zeppelin.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/openai-icon.svg b/.claude/skills/logo-design/assets/library/svg/openai-icon.svg new file mode 100644 index 0000000..7dbf89a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/openai-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/openai.svg b/.claude/skills/logo-design/assets/library/svg/openai.svg new file mode 100644 index 0000000..afd1974 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/openai.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/opencart.svg b/.claude/skills/logo-design/assets/library/svg/opencart.svg new file mode 100644 index 0000000..7536b33 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/opencart.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/opencollective.svg b/.claude/skills/logo-design/assets/library/svg/opencollective.svg new file mode 100644 index 0000000..5cddb4d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/opencollective.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/opencv.svg b/.claude/skills/logo-design/assets/library/svg/opencv.svg new file mode 100644 index 0000000..d5b93e1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/opencv.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/openframeworks.svg b/.claude/skills/logo-design/assets/library/svg/openframeworks.svg new file mode 100644 index 0000000..a565945 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/openframeworks.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/opengl.svg b/.claude/skills/logo-design/assets/library/svg/opengl.svg new file mode 100644 index 0000000..b2c1416 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/opengl.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/openjs-foundation-icon.svg b/.claude/skills/logo-design/assets/library/svg/openjs-foundation-icon.svg new file mode 100644 index 0000000..75285ab --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/openjs-foundation-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/openjs-foundation.svg b/.claude/skills/logo-design/assets/library/svg/openjs-foundation.svg new file mode 100644 index 0000000..f485d00 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/openjs-foundation.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/openlayers.svg b/.claude/skills/logo-design/assets/library/svg/openlayers.svg new file mode 100644 index 0000000..d04a49b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/openlayers.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/openshift.svg b/.claude/skills/logo-design/assets/library/svg/openshift.svg new file mode 100644 index 0000000..41783b6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/openshift.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/opensource.svg b/.claude/skills/logo-design/assets/library/svg/opensource.svg new file mode 100644 index 0000000..7617a92 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/opensource.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/openstack-icon.svg b/.claude/skills/logo-design/assets/library/svg/openstack-icon.svg new file mode 100644 index 0000000..cb5b329 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/openstack-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/openstack.svg b/.claude/skills/logo-design/assets/library/svg/openstack.svg new file mode 100644 index 0000000..e5d879c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/openstack.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/opentelemetry-icon.svg b/.claude/skills/logo-design/assets/library/svg/opentelemetry-icon.svg new file mode 100644 index 0000000..74c7958 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/opentelemetry-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/opentelemetry.svg b/.claude/skills/logo-design/assets/library/svg/opentelemetry.svg new file mode 100644 index 0000000..70d36e9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/opentelemetry.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/opera.svg b/.claude/skills/logo-design/assets/library/svg/opera.svg new file mode 100644 index 0000000..1cf2a0d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/opera.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/opsgenie.svg b/.claude/skills/logo-design/assets/library/svg/opsgenie.svg new file mode 100644 index 0000000..8dbf2b0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/opsgenie.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/optimizely.svg b/.claude/skills/logo-design/assets/library/svg/optimizely.svg new file mode 100644 index 0000000..5cd3f6f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/optimizely.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/oracle.svg b/.claude/skills/logo-design/assets/library/svg/oracle.svg new file mode 100644 index 0000000..043b588 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/oracle.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/oreilly.svg b/.claude/skills/logo-design/assets/library/svg/oreilly.svg new file mode 100644 index 0000000..6e62573 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/oreilly.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/origami.svg b/.claude/skills/logo-design/assets/library/svg/origami.svg new file mode 100644 index 0000000..f16205f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/origami.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/origin.svg b/.claude/skills/logo-design/assets/library/svg/origin.svg new file mode 100644 index 0000000..df6e0d8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/origin.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/oshw.svg b/.claude/skills/logo-design/assets/library/svg/oshw.svg new file mode 100644 index 0000000..98efb4d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/oshw.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/osquery.svg b/.claude/skills/logo-design/assets/library/svg/osquery.svg new file mode 100644 index 0000000..69849b2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/osquery.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/packer.svg b/.claude/skills/logo-design/assets/library/svg/packer.svg new file mode 100644 index 0000000..988997a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/packer.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pagekit.svg b/.claude/skills/logo-design/assets/library/svg/pagekit.svg new file mode 100644 index 0000000..28266a2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pagekit.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pagekite.svg b/.claude/skills/logo-design/assets/library/svg/pagekite.svg new file mode 100644 index 0000000..1de607c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pagekite.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pagerduty-icon.svg b/.claude/skills/logo-design/assets/library/svg/pagerduty-icon.svg new file mode 100644 index 0000000..36d946c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pagerduty-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pagerduty.svg b/.claude/skills/logo-design/assets/library/svg/pagerduty.svg new file mode 100644 index 0000000..05718a2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pagerduty.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/panda.svg b/.claude/skills/logo-design/assets/library/svg/panda.svg new file mode 100644 index 0000000..c030f55 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/panda.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/parcel-icon.svg b/.claude/skills/logo-design/assets/library/svg/parcel-icon.svg new file mode 100644 index 0000000..074c097 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/parcel-icon.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/parcel.svg b/.claude/skills/logo-design/assets/library/svg/parcel.svg new file mode 100644 index 0000000..6b5e5bb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/parcel.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/parse.svg b/.claude/skills/logo-design/assets/library/svg/parse.svg new file mode 100644 index 0000000..94cc2bb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/parse.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/parsehub.svg b/.claude/skills/logo-design/assets/library/svg/parsehub.svg new file mode 100644 index 0000000..2e5b39f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/parsehub.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/partytown-icon.svg b/.claude/skills/logo-design/assets/library/svg/partytown-icon.svg new file mode 100644 index 0000000..6ab2ff2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/partytown-icon.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/partytown.svg b/.claude/skills/logo-design/assets/library/svg/partytown.svg new file mode 100644 index 0000000..3505e6f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/partytown.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/passbolt-icon.svg b/.claude/skills/logo-design/assets/library/svg/passbolt-icon.svg new file mode 100644 index 0000000..98e4144 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/passbolt-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/passbolt.svg b/.claude/skills/logo-design/assets/library/svg/passbolt.svg new file mode 100644 index 0000000..47c0acf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/passbolt.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/passport.svg b/.claude/skills/logo-design/assets/library/svg/passport.svg new file mode 100644 index 0000000..14641ad --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/passport.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/patreon.svg b/.claude/skills/logo-design/assets/library/svg/patreon.svg new file mode 100644 index 0000000..63d06e5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/patreon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/paypal.svg b/.claude/skills/logo-design/assets/library/svg/paypal.svg new file mode 100644 index 0000000..538eb7d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/paypal.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/peer5.svg b/.claude/skills/logo-design/assets/library/svg/peer5.svg new file mode 100644 index 0000000..e850e92 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/peer5.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pepperoni.svg b/.claude/skills/logo-design/assets/library/svg/pepperoni.svg new file mode 100644 index 0000000..f8d764b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pepperoni.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/percona.svg b/.claude/skills/logo-design/assets/library/svg/percona.svg new file mode 100644 index 0000000..b84d072 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/percona.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/percy-icon.svg b/.claude/skills/logo-design/assets/library/svg/percy-icon.svg new file mode 100644 index 0000000..52bebe1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/percy-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/percy.svg b/.claude/skills/logo-design/assets/library/svg/percy.svg new file mode 100644 index 0000000..548ff8a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/percy.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/perf-rocks.svg b/.claude/skills/logo-design/assets/library/svg/perf-rocks.svg new file mode 100644 index 0000000..d239d9b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/perf-rocks.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/perl.svg b/.claude/skills/logo-design/assets/library/svg/perl.svg new file mode 100644 index 0000000..6e7cbae --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/perl.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/phalcon.svg b/.claude/skills/logo-design/assets/library/svg/phalcon.svg new file mode 100644 index 0000000..bc9559b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/phalcon.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/phoenix.svg b/.claude/skills/logo-design/assets/library/svg/phoenix.svg new file mode 100644 index 0000000..2c39a1b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/phoenix.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/phonegap-bot.svg b/.claude/skills/logo-design/assets/library/svg/phonegap-bot.svg new file mode 100644 index 0000000..9f93785 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/phonegap-bot.svg @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/phonegap.svg b/.claude/skills/logo-design/assets/library/svg/phonegap.svg new file mode 100644 index 0000000..661d718 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/phonegap.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/php-alt.svg b/.claude/skills/logo-design/assets/library/svg/php-alt.svg new file mode 100644 index 0000000..acb913d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/php-alt.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/php.svg b/.claude/skills/logo-design/assets/library/svg/php.svg new file mode 100644 index 0000000..7b63025 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/php.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/phpstorm.svg b/.claude/skills/logo-design/assets/library/svg/phpstorm.svg new file mode 100644 index 0000000..d1559b3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/phpstorm.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pinterest.svg b/.claude/skills/logo-design/assets/library/svg/pinterest.svg new file mode 100644 index 0000000..16b9cc7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pinterest.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pipedrive.svg b/.claude/skills/logo-design/assets/library/svg/pipedrive.svg new file mode 100644 index 0000000..9ec6c05 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pipedrive.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pipefy.svg b/.claude/skills/logo-design/assets/library/svg/pipefy.svg new file mode 100644 index 0000000..7690521 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pipefy.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pivotal_tracker.svg b/.claude/skills/logo-design/assets/library/svg/pivotal_tracker.svg new file mode 100644 index 0000000..c2e51e4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pivotal_tracker.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pixijs.svg b/.claude/skills/logo-design/assets/library/svg/pixijs.svg new file mode 100644 index 0000000..b027bc4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pixijs.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pkg.svg b/.claude/skills/logo-design/assets/library/svg/pkg.svg new file mode 100644 index 0000000..5b1d2d6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pkg.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/planless-icon.svg b/.claude/skills/logo-design/assets/library/svg/planless-icon.svg new file mode 100644 index 0000000..098f5f1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/planless-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/planless.svg b/.claude/skills/logo-design/assets/library/svg/planless.svg new file mode 100644 index 0000000..ea88662 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/planless.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/plastic-scm.svg b/.claude/skills/logo-design/assets/library/svg/plastic-scm.svg new file mode 100644 index 0000000..36d467c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/plastic-scm.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/platformio.svg b/.claude/skills/logo-design/assets/library/svg/platformio.svg new file mode 100644 index 0000000..c4406e7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/platformio.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/play.svg b/.claude/skills/logo-design/assets/library/svg/play.svg new file mode 100644 index 0000000..182125c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/play.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/playwright.svg b/.claude/skills/logo-design/assets/library/svg/playwright.svg new file mode 100644 index 0000000..f3a60e6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/playwright.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pm2.svg b/.claude/skills/logo-design/assets/library/svg/pm2.svg new file mode 100644 index 0000000..647b5be --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pm2.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pnpm.svg b/.claude/skills/logo-design/assets/library/svg/pnpm.svg new file mode 100644 index 0000000..e3860d6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pnpm.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/poeditor.svg b/.claude/skills/logo-design/assets/library/svg/poeditor.svg new file mode 100644 index 0000000..958ddb5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/poeditor.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/polymer.svg b/.claude/skills/logo-design/assets/library/svg/polymer.svg new file mode 100644 index 0000000..9a5ffe0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/polymer.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/postcss.svg b/.claude/skills/logo-design/assets/library/svg/postcss.svg new file mode 100644 index 0000000..5272b75 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/postcss.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/postgraphile.svg b/.claude/skills/logo-design/assets/library/svg/postgraphile.svg new file mode 100644 index 0000000..9af80d0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/postgraphile.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/postgresql.svg b/.claude/skills/logo-design/assets/library/svg/postgresql.svg new file mode 100644 index 0000000..4ee76c8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/postgresql.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/postman-icon.svg b/.claude/skills/logo-design/assets/library/svg/postman-icon.svg new file mode 100644 index 0000000..fa49fbb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/postman-icon.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/postman.svg b/.claude/skills/logo-design/assets/library/svg/postman.svg new file mode 100644 index 0000000..f6dc155 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/postman.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pouchdb.svg b/.claude/skills/logo-design/assets/library/svg/pouchdb.svg new file mode 100644 index 0000000..e7aebcd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pouchdb.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/preact.svg b/.claude/skills/logo-design/assets/library/svg/preact.svg new file mode 100644 index 0000000..a8d395e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/preact.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/precursor.svg b/.claude/skills/logo-design/assets/library/svg/precursor.svg new file mode 100644 index 0000000..a1358f0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/precursor.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/prerender-icon.svg b/.claude/skills/logo-design/assets/library/svg/prerender-icon.svg new file mode 100644 index 0000000..31a5a55 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/prerender-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/prerender.svg b/.claude/skills/logo-design/assets/library/svg/prerender.svg new file mode 100644 index 0000000..166819c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/prerender.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/prestashop.svg b/.claude/skills/logo-design/assets/library/svg/prestashop.svg new file mode 100644 index 0000000..27a2deb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/prestashop.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/presto.svg b/.claude/skills/logo-design/assets/library/svg/presto.svg new file mode 100644 index 0000000..455e440 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/presto.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/prettier.svg b/.claude/skills/logo-design/assets/library/svg/prettier.svg new file mode 100644 index 0000000..c0404eb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/prettier.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/prisma.svg b/.claude/skills/logo-design/assets/library/svg/prisma.svg new file mode 100644 index 0000000..1c84bb6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/prisma.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/prismic-icon.svg b/.claude/skills/logo-design/assets/library/svg/prismic-icon.svg new file mode 100644 index 0000000..d1a1a16 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/prismic-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/prismic.svg b/.claude/skills/logo-design/assets/library/svg/prismic.svg new file mode 100644 index 0000000..ac0b298 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/prismic.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/processwire.svg b/.claude/skills/logo-design/assets/library/svg/processwire.svg new file mode 100644 index 0000000..bf94f7e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/processwire.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/productboard-icon.svg b/.claude/skills/logo-design/assets/library/svg/productboard-icon.svg new file mode 100644 index 0000000..8df3791 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/productboard-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/productboard.svg b/.claude/skills/logo-design/assets/library/svg/productboard.svg new file mode 100644 index 0000000..9a42e57 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/productboard.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/producthunt.svg b/.claude/skills/logo-design/assets/library/svg/producthunt.svg new file mode 100644 index 0000000..582f56f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/producthunt.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/progress.svg b/.claude/skills/logo-design/assets/library/svg/progress.svg new file mode 100644 index 0000000..6cde8ab --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/progress.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/prometheus.svg b/.claude/skills/logo-design/assets/library/svg/prometheus.svg new file mode 100644 index 0000000..e4d54bf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/prometheus.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/promises.svg b/.claude/skills/logo-design/assets/library/svg/promises.svg new file mode 100644 index 0000000..d60afcc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/promises.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/proofy.svg b/.claude/skills/logo-design/assets/library/svg/proofy.svg new file mode 100644 index 0000000..3ad1bdf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/proofy.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/prospect.svg b/.claude/skills/logo-design/assets/library/svg/prospect.svg new file mode 100644 index 0000000..02d0bf5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/prospect.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/protactor.svg b/.claude/skills/logo-design/assets/library/svg/protactor.svg new file mode 100644 index 0000000..37dad25 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/protactor.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/protoio.svg b/.claude/skills/logo-design/assets/library/svg/protoio.svg new file mode 100644 index 0000000..c4ab360 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/protoio.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/protonet.svg b/.claude/skills/logo-design/assets/library/svg/protonet.svg new file mode 100644 index 0000000..49cd5e8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/protonet.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/prott.svg b/.claude/skills/logo-design/assets/library/svg/prott.svg new file mode 100644 index 0000000..a657b56 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/prott.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pug.svg b/.claude/skills/logo-design/assets/library/svg/pug.svg new file mode 100644 index 0000000..6a778f2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pug.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pumpkindb.svg b/.claude/skills/logo-design/assets/library/svg/pumpkindb.svg new file mode 100644 index 0000000..2a7db9b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pumpkindb.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/puppet-icon.svg b/.claude/skills/logo-design/assets/library/svg/puppet-icon.svg new file mode 100644 index 0000000..3706558 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/puppet-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/puppet.svg b/.claude/skills/logo-design/assets/library/svg/puppet.svg new file mode 100644 index 0000000..81d512c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/puppet.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/puppeteer.svg b/.claude/skills/logo-design/assets/library/svg/puppeteer.svg new file mode 100644 index 0000000..6f5c0fc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/puppeteer.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/puppy-linux.svg b/.claude/skills/logo-design/assets/library/svg/puppy-linux.svg new file mode 100644 index 0000000..5817ebb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/puppy-linux.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/purescript-icon.svg b/.claude/skills/logo-design/assets/library/svg/purescript-icon.svg new file mode 100644 index 0000000..479400e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/purescript-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/purescript.svg b/.claude/skills/logo-design/assets/library/svg/purescript.svg new file mode 100644 index 0000000..7b24e59 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/purescript.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pushbullet.svg b/.claude/skills/logo-design/assets/library/svg/pushbullet.svg new file mode 100644 index 0000000..390368c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pushbullet.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pusher-icon.svg b/.claude/skills/logo-design/assets/library/svg/pusher-icon.svg new file mode 100644 index 0000000..d8c23b0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pusher-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pusher.svg b/.claude/skills/logo-design/assets/library/svg/pusher.svg new file mode 100644 index 0000000..69c0ce3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pusher.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pwa.svg b/.claude/skills/logo-design/assets/library/svg/pwa.svg new file mode 100644 index 0000000..a3f8361 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pwa.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pycharm.svg b/.claude/skills/logo-design/assets/library/svg/pycharm.svg new file mode 100644 index 0000000..a479393 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pycharm.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/python.svg b/.claude/skills/logo-design/assets/library/svg/python.svg new file mode 100644 index 0000000..1655e14 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/python.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pytorch.svg b/.claude/skills/logo-design/assets/library/svg/pytorch.svg new file mode 100644 index 0000000..efad5a4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pytorch.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/pyup.svg b/.claude/skills/logo-design/assets/library/svg/pyup.svg new file mode 100644 index 0000000..022d3fa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/pyup.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/q.svg b/.claude/skills/logo-design/assets/library/svg/q.svg new file mode 100644 index 0000000..f3bfc36 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/q.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/qlik.svg b/.claude/skills/logo-design/assets/library/svg/qlik.svg new file mode 100644 index 0000000..a17fdb5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/qlik.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/qt.svg b/.claude/skills/logo-design/assets/library/svg/qt.svg new file mode 100644 index 0000000..1d4b443 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/qt.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/quarkus-icon.svg b/.claude/skills/logo-design/assets/library/svg/quarkus-icon.svg new file mode 100644 index 0000000..eda1040 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/quarkus-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/quarkus.svg b/.claude/skills/logo-design/assets/library/svg/quarkus.svg new file mode 100644 index 0000000..f4db20a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/quarkus.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/quay.svg b/.claude/skills/logo-design/assets/library/svg/quay.svg new file mode 100644 index 0000000..d872865 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/quay.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/quobyte.svg b/.claude/skills/logo-design/assets/library/svg/quobyte.svg new file mode 100644 index 0000000..4b778f7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/quobyte.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/quora.svg b/.claude/skills/logo-design/assets/library/svg/quora.svg new file mode 100644 index 0000000..ad86868 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/quora.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/r-lang.svg b/.claude/skills/logo-design/assets/library/svg/r-lang.svg new file mode 100644 index 0000000..b7d8f17 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/r-lang.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rabbitmq-icon.svg b/.claude/skills/logo-design/assets/library/svg/rabbitmq-icon.svg new file mode 100644 index 0000000..a09ea52 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rabbitmq-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rabbitmq.svg b/.claude/skills/logo-design/assets/library/svg/rabbitmq.svg new file mode 100644 index 0000000..7c4e1c5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rabbitmq.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rackspace.svg b/.claude/skills/logo-design/assets/library/svg/rackspace.svg new file mode 100644 index 0000000..4ec036a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rackspace.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rails.svg b/.claude/skills/logo-design/assets/library/svg/rails.svg new file mode 100644 index 0000000..90db830 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rails.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ramda.svg b/.claude/skills/logo-design/assets/library/svg/ramda.svg new file mode 100644 index 0000000..7e2fd04 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ramda.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/raml.svg b/.claude/skills/logo-design/assets/library/svg/raml.svg new file mode 100644 index 0000000..3a3001c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/raml.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rancher-icon.svg b/.claude/skills/logo-design/assets/library/svg/rancher-icon.svg new file mode 100644 index 0000000..9da56e9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rancher-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rancher.svg b/.claude/skills/logo-design/assets/library/svg/rancher.svg new file mode 100644 index 0000000..8e19cd5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rancher.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/raphael.svg b/.claude/skills/logo-design/assets/library/svg/raphael.svg new file mode 100644 index 0000000..698f5d4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/raphael.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/raspberry-pi.svg b/.claude/skills/logo-design/assets/library/svg/raspberry-pi.svg new file mode 100644 index 0000000..ba87700 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/raspberry-pi.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rax.svg b/.claude/skills/logo-design/assets/library/svg/rax.svg new file mode 100644 index 0000000..b2ab20e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rax.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/react-query-icon.svg b/.claude/skills/logo-design/assets/library/svg/react-query-icon.svg new file mode 100644 index 0000000..8b3570c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/react-query-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/react-query.svg b/.claude/skills/logo-design/assets/library/svg/react-query.svg new file mode 100644 index 0000000..e8a8ef3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/react-query.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/react-router.svg b/.claude/skills/logo-design/assets/library/svg/react-router.svg new file mode 100644 index 0000000..a41865b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/react-router.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/react-spring.svg b/.claude/skills/logo-design/assets/library/svg/react-spring.svg new file mode 100644 index 0000000..75b96de --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/react-spring.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/react-styleguidist.svg b/.claude/skills/logo-design/assets/library/svg/react-styleguidist.svg new file mode 100644 index 0000000..5a82464 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/react-styleguidist.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/react.svg b/.claude/skills/logo-design/assets/library/svg/react.svg new file mode 100644 index 0000000..4c514e9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/react.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/reactivex.svg b/.claude/skills/logo-design/assets/library/svg/reactivex.svg new file mode 100644 index 0000000..87a44a7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/reactivex.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/realm.svg b/.claude/skills/logo-design/assets/library/svg/realm.svg new file mode 100644 index 0000000..39e417a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/realm.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/reapp.svg b/.claude/skills/logo-design/assets/library/svg/reapp.svg new file mode 100644 index 0000000..3db6ac9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/reapp.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/reasonml-icon.svg b/.claude/skills/logo-design/assets/library/svg/reasonml-icon.svg new file mode 100644 index 0000000..ed23467 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/reasonml-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/reasonml.svg b/.claude/skills/logo-design/assets/library/svg/reasonml.svg new file mode 100644 index 0000000..509a4fb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/reasonml.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/reddit-icon.svg b/.claude/skills/logo-design/assets/library/svg/reddit-icon.svg new file mode 100644 index 0000000..e5d92b7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/reddit-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/reddit.svg b/.claude/skills/logo-design/assets/library/svg/reddit.svg new file mode 100644 index 0000000..14b8c8d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/reddit.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/redhat-icon.svg b/.claude/skills/logo-design/assets/library/svg/redhat-icon.svg new file mode 100644 index 0000000..7483024 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/redhat-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/redhat.svg b/.claude/skills/logo-design/assets/library/svg/redhat.svg new file mode 100644 index 0000000..697c9f1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/redhat.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/redis.svg b/.claude/skills/logo-design/assets/library/svg/redis.svg new file mode 100644 index 0000000..7a56580 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/redis.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/redsmin.svg b/.claude/skills/logo-design/assets/library/svg/redsmin.svg new file mode 100644 index 0000000..6dcfea2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/redsmin.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/redux-observable.svg b/.claude/skills/logo-design/assets/library/svg/redux-observable.svg new file mode 100644 index 0000000..06abfd8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/redux-observable.svg @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/redux-saga.svg b/.claude/skills/logo-design/assets/library/svg/redux-saga.svg new file mode 100644 index 0000000..aa59d95 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/redux-saga.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/redux.svg b/.claude/skills/logo-design/assets/library/svg/redux.svg new file mode 100644 index 0000000..35c9de5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/redux.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/redwoodjs.svg b/.claude/skills/logo-design/assets/library/svg/redwoodjs.svg new file mode 100644 index 0000000..d5d8eb5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/redwoodjs.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/reindex.svg b/.claude/skills/logo-design/assets/library/svg/reindex.svg new file mode 100644 index 0000000..f676e5d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/reindex.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/relay.svg b/.claude/skills/logo-design/assets/library/svg/relay.svg new file mode 100644 index 0000000..ba756b5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/relay.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/release.svg b/.claude/skills/logo-design/assets/library/svg/release.svg new file mode 100644 index 0000000..a4c41fe --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/release.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/remix-icon.svg b/.claude/skills/logo-design/assets/library/svg/remix-icon.svg new file mode 100644 index 0000000..e41dd15 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/remix-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/remix.svg b/.claude/skills/logo-design/assets/library/svg/remix.svg new file mode 100644 index 0000000..31cf082 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/remix.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/require.svg b/.claude/skills/logo-design/assets/library/svg/require.svg new file mode 100644 index 0000000..6f2bde9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/require.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rescript-icon.svg b/.claude/skills/logo-design/assets/library/svg/rescript-icon.svg new file mode 100644 index 0000000..bce2370 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rescript-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rescript.svg b/.claude/skills/logo-design/assets/library/svg/rescript.svg new file mode 100644 index 0000000..fd3d357 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rescript.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rest-li.svg b/.claude/skills/logo-design/assets/library/svg/rest-li.svg new file mode 100644 index 0000000..e5453fe --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rest-li.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rethinkdb.svg b/.claude/skills/logo-design/assets/library/svg/rethinkdb.svg new file mode 100644 index 0000000..6f0d331 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rethinkdb.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/retool-icon.svg b/.claude/skills/logo-design/assets/library/svg/retool-icon.svg new file mode 100644 index 0000000..6d9dfdb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/retool-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/retool.svg b/.claude/skills/logo-design/assets/library/svg/retool.svg new file mode 100644 index 0000000..a1b7c03 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/retool.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/riak.svg b/.claude/skills/logo-design/assets/library/svg/riak.svg new file mode 100644 index 0000000..ffc3011 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/riak.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/riot.svg b/.claude/skills/logo-design/assets/library/svg/riot.svg new file mode 100644 index 0000000..b8a4f89 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/riot.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rocket-chat-icon.svg b/.claude/skills/logo-design/assets/library/svg/rocket-chat-icon.svg new file mode 100644 index 0000000..e9da2e3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rocket-chat-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rocket-chat.svg b/.claude/skills/logo-design/assets/library/svg/rocket-chat.svg new file mode 100644 index 0000000..e7262d8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rocket-chat.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rocksdb.svg b/.claude/skills/logo-design/assets/library/svg/rocksdb.svg new file mode 100644 index 0000000..60928b6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rocksdb.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rocky-linux-icon.svg b/.claude/skills/logo-design/assets/library/svg/rocky-linux-icon.svg new file mode 100644 index 0000000..cade175 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rocky-linux-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rocky-linux.svg b/.claude/skills/logo-design/assets/library/svg/rocky-linux.svg new file mode 100644 index 0000000..b192d88 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rocky-linux.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rollbar-icon.svg b/.claude/skills/logo-design/assets/library/svg/rollbar-icon.svg new file mode 100644 index 0000000..f930a5f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rollbar-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rollbar.svg b/.claude/skills/logo-design/assets/library/svg/rollbar.svg new file mode 100644 index 0000000..32af20b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rollbar.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rollupjs.svg b/.claude/skills/logo-design/assets/library/svg/rollupjs.svg new file mode 100644 index 0000000..c894d15 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rollupjs.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rome-icon.svg b/.claude/skills/logo-design/assets/library/svg/rome-icon.svg new file mode 100644 index 0000000..4e2d8b4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rome-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rome.svg b/.claude/skills/logo-design/assets/library/svg/rome.svg new file mode 100644 index 0000000..3fe8df0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rome.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rsa.svg b/.claude/skills/logo-design/assets/library/svg/rsa.svg new file mode 100644 index 0000000..854c108 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rsa.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rsmq.svg b/.claude/skills/logo-design/assets/library/svg/rsmq.svg new file mode 100644 index 0000000..3ebab4a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rsmq.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rubocop.svg b/.claude/skills/logo-design/assets/library/svg/rubocop.svg new file mode 100644 index 0000000..2f32e7f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rubocop.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ruby.svg b/.claude/skills/logo-design/assets/library/svg/ruby.svg new file mode 100644 index 0000000..5232aaa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ruby.svg @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rubygems.svg b/.claude/skills/logo-design/assets/library/svg/rubygems.svg new file mode 100644 index 0000000..c76d3e6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rubygems.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rubymine.svg b/.claude/skills/logo-design/assets/library/svg/rubymine.svg new file mode 100644 index 0000000..29d69c2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rubymine.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rum.svg b/.claude/skills/logo-design/assets/library/svg/rum.svg new file mode 100644 index 0000000..ce9bb72 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rum.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/runscope.svg b/.claude/skills/logo-design/assets/library/svg/runscope.svg new file mode 100644 index 0000000..785d97b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/runscope.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rust.svg b/.claude/skills/logo-design/assets/library/svg/rust.svg new file mode 100644 index 0000000..0b1411d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rust.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/rxdb.svg b/.claude/skills/logo-design/assets/library/svg/rxdb.svg new file mode 100644 index 0000000..d71fa39 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/rxdb.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/safari.svg b/.claude/skills/logo-design/assets/library/svg/safari.svg new file mode 100644 index 0000000..1901de3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/safari.svg @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sagui.svg b/.claude/skills/logo-design/assets/library/svg/sagui.svg new file mode 100644 index 0000000..8814b6b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sagui.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sails.svg b/.claude/skills/logo-design/assets/library/svg/sails.svg new file mode 100644 index 0000000..f4c183d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sails.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/salesforce.svg b/.claude/skills/logo-design/assets/library/svg/salesforce.svg new file mode 100644 index 0000000..540007d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/salesforce.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sameroom.svg b/.claude/skills/logo-design/assets/library/svg/sameroom.svg new file mode 100644 index 0000000..1c0c636 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sameroom.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/samsung.svg b/.claude/skills/logo-design/assets/library/svg/samsung.svg new file mode 100644 index 0000000..6547945 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/samsung.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sanity.svg b/.claude/skills/logo-design/assets/library/svg/sanity.svg new file mode 100644 index 0000000..f09336f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sanity.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sass-doc.svg b/.claude/skills/logo-design/assets/library/svg/sass-doc.svg new file mode 100644 index 0000000..bca8e42 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sass-doc.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sass.svg b/.claude/skills/logo-design/assets/library/svg/sass.svg new file mode 100644 index 0000000..97dc972 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sass.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/saucelabs.svg b/.claude/skills/logo-design/assets/library/svg/saucelabs.svg new file mode 100644 index 0000000..8fb4b6b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/saucelabs.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/scala.svg b/.claude/skills/logo-design/assets/library/svg/scala.svg new file mode 100644 index 0000000..aab8f40 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/scala.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/scaledrone.svg b/.claude/skills/logo-design/assets/library/svg/scaledrone.svg new file mode 100644 index 0000000..2cba9d2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/scaledrone.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/scribd-icon.svg b/.claude/skills/logo-design/assets/library/svg/scribd-icon.svg new file mode 100644 index 0000000..c37f592 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/scribd-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/scribd.svg b/.claude/skills/logo-design/assets/library/svg/scribd.svg new file mode 100644 index 0000000..dae48ba --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/scribd.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/section-icon.svg b/.claude/skills/logo-design/assets/library/svg/section-icon.svg new file mode 100644 index 0000000..96e68ba --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/section-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/section.svg b/.claude/skills/logo-design/assets/library/svg/section.svg new file mode 100644 index 0000000..4ba4269 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/section.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/segment-icon.svg b/.claude/skills/logo-design/assets/library/svg/segment-icon.svg new file mode 100644 index 0000000..3e64fb3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/segment-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/segment.svg b/.claude/skills/logo-design/assets/library/svg/segment.svg new file mode 100644 index 0000000..d0cfcf1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/segment.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/selenium.svg b/.claude/skills/logo-design/assets/library/svg/selenium.svg new file mode 100644 index 0000000..74d1207 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/selenium.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/semantic-release.svg b/.claude/skills/logo-design/assets/library/svg/semantic-release.svg new file mode 100644 index 0000000..23c9d13 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/semantic-release.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/semantic-ui.svg b/.claude/skills/logo-design/assets/library/svg/semantic-ui.svg new file mode 100644 index 0000000..c8bae87 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/semantic-ui.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/semantic-web.svg b/.claude/skills/logo-design/assets/library/svg/semantic-web.svg new file mode 100644 index 0000000..1224c03 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/semantic-web.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/semaphoreci.svg b/.claude/skills/logo-design/assets/library/svg/semaphoreci.svg new file mode 100644 index 0000000..c39faac --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/semaphoreci.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sencha.svg b/.claude/skills/logo-design/assets/library/svg/sencha.svg new file mode 100644 index 0000000..292d233 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sencha.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sendgrid-icon.svg b/.claude/skills/logo-design/assets/library/svg/sendgrid-icon.svg new file mode 100644 index 0000000..ef31bc2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sendgrid-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sendgrid.svg b/.claude/skills/logo-design/assets/library/svg/sendgrid.svg new file mode 100644 index 0000000..8e5bb17 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sendgrid.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/seneca.svg b/.claude/skills/logo-design/assets/library/svg/seneca.svg new file mode 100644 index 0000000..30be6db --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/seneca.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sensu-icon.svg b/.claude/skills/logo-design/assets/library/svg/sensu-icon.svg new file mode 100644 index 0000000..425adb6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sensu-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sensu.svg b/.claude/skills/logo-design/assets/library/svg/sensu.svg new file mode 100644 index 0000000..8a9c104 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sensu.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sentry-icon.svg b/.claude/skills/logo-design/assets/library/svg/sentry-icon.svg new file mode 100644 index 0000000..4c2cc5d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sentry-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sentry.svg b/.claude/skills/logo-design/assets/library/svg/sentry.svg new file mode 100644 index 0000000..7c4028b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sentry.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sequelize.svg b/.claude/skills/logo-design/assets/library/svg/sequelize.svg new file mode 100644 index 0000000..3fd2a44 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sequelize.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/serverless.svg b/.claude/skills/logo-design/assets/library/svg/serverless.svg new file mode 100644 index 0000000..96845a5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/serverless.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sherlock-icon.svg b/.claude/skills/logo-design/assets/library/svg/sherlock-icon.svg new file mode 100644 index 0000000..e0a8c3a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sherlock-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sherlock.svg b/.claude/skills/logo-design/assets/library/svg/sherlock.svg new file mode 100644 index 0000000..8b6297c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sherlock.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/shields.svg b/.claude/skills/logo-design/assets/library/svg/shields.svg new file mode 100644 index 0000000..df46345 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/shields.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/shipit.svg b/.claude/skills/logo-design/assets/library/svg/shipit.svg new file mode 100644 index 0000000..961a244 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/shipit.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/shippable.svg b/.claude/skills/logo-design/assets/library/svg/shippable.svg new file mode 100644 index 0000000..f5642a7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/shippable.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/shogun.svg b/.claude/skills/logo-design/assets/library/svg/shogun.svg new file mode 100644 index 0000000..db50aa0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/shogun.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/shopify.svg b/.claude/skills/logo-design/assets/library/svg/shopify.svg new file mode 100644 index 0000000..b431a49 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/shopify.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sidekick.svg b/.claude/skills/logo-design/assets/library/svg/sidekick.svg new file mode 100644 index 0000000..c176680 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sidekick.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sidekiq-icon.svg b/.claude/skills/logo-design/assets/library/svg/sidekiq-icon.svg new file mode 100644 index 0000000..7c33d4b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sidekiq-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sidekiq.svg b/.claude/skills/logo-design/assets/library/svg/sidekiq.svg new file mode 100644 index 0000000..5252532 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sidekiq.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/signal.svg b/.claude/skills/logo-design/assets/library/svg/signal.svg new file mode 100644 index 0000000..1c3379b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/signal.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sinatra.svg b/.claude/skills/logo-design/assets/library/svg/sinatra.svg new file mode 100644 index 0000000..07c58e8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sinatra.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sitepoint.svg b/.claude/skills/logo-design/assets/library/svg/sitepoint.svg new file mode 100644 index 0000000..c3c1657 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sitepoint.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/skaffolder.svg b/.claude/skills/logo-design/assets/library/svg/skaffolder.svg new file mode 100644 index 0000000..dc33b58 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/skaffolder.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sketch.svg b/.claude/skills/logo-design/assets/library/svg/sketch.svg new file mode 100644 index 0000000..d244fe0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sketch.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/skylight.svg b/.claude/skills/logo-design/assets/library/svg/skylight.svg new file mode 100644 index 0000000..ddb7b82 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/skylight.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/skype.svg b/.claude/skills/logo-design/assets/library/svg/skype.svg new file mode 100644 index 0000000..292e20a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/skype.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/slack-icon.svg b/.claude/skills/logo-design/assets/library/svg/slack-icon.svg new file mode 100644 index 0000000..049ca59 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/slack-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/slack.svg b/.claude/skills/logo-design/assets/library/svg/slack.svg new file mode 100644 index 0000000..61776bc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/slack.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/slides.svg b/.claude/skills/logo-design/assets/library/svg/slides.svg new file mode 100644 index 0000000..d6a988d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/slides.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/slim.svg b/.claude/skills/logo-design/assets/library/svg/slim.svg new file mode 100644 index 0000000..1312704 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/slim.svg @@ -0,0 +1,4 @@ + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/smartling.svg b/.claude/skills/logo-design/assets/library/svg/smartling.svg new file mode 100644 index 0000000..7950ab1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/smartling.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/smashingmagazine.svg b/.claude/skills/logo-design/assets/library/svg/smashingmagazine.svg new file mode 100644 index 0000000..57f31b2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/smashingmagazine.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/snap-svg.svg b/.claude/skills/logo-design/assets/library/svg/snap-svg.svg new file mode 100644 index 0000000..4deb1a6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/snap-svg.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/snowflake-icon.svg b/.claude/skills/logo-design/assets/library/svg/snowflake-icon.svg new file mode 100644 index 0000000..695aad5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/snowflake-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/snowflake.svg b/.claude/skills/logo-design/assets/library/svg/snowflake.svg new file mode 100644 index 0000000..83d980d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/snowflake.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/snowpack.svg b/.claude/skills/logo-design/assets/library/svg/snowpack.svg new file mode 100644 index 0000000..cbb81d1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/snowpack.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/snupps.svg b/.claude/skills/logo-design/assets/library/svg/snupps.svg new file mode 100644 index 0000000..5d91789 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/snupps.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/snyk.svg b/.claude/skills/logo-design/assets/library/svg/snyk.svg new file mode 100644 index 0000000..cf04cdb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/snyk.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/socket.io.svg b/.claude/skills/logo-design/assets/library/svg/socket.io.svg new file mode 100644 index 0000000..c7bbb6c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/socket.io.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/solarwinds.svg b/.claude/skills/logo-design/assets/library/svg/solarwinds.svg new file mode 100644 index 0000000..833f0e2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/solarwinds.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/solid.svg b/.claude/skills/logo-design/assets/library/svg/solid.svg new file mode 100644 index 0000000..4f18e1e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/solid.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/solidity.svg b/.claude/skills/logo-design/assets/library/svg/solidity.svg new file mode 100644 index 0000000..b6331f8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/solidity.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/solidjs-icon.svg b/.claude/skills/logo-design/assets/library/svg/solidjs-icon.svg new file mode 100644 index 0000000..4d471f0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/solidjs-icon.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/solidjs.svg b/.claude/skills/logo-design/assets/library/svg/solidjs.svg new file mode 100644 index 0000000..25eb34e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/solidjs.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/solr.svg b/.claude/skills/logo-design/assets/library/svg/solr.svg new file mode 100644 index 0000000..3a300e1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/solr.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sonarqube.svg b/.claude/skills/logo-design/assets/library/svg/sonarqube.svg new file mode 100644 index 0000000..acafc45 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sonarqube.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/soundcloud.svg b/.claude/skills/logo-design/assets/library/svg/soundcloud.svg new file mode 100644 index 0000000..66744f5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/soundcloud.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sourcegraph.svg b/.claude/skills/logo-design/assets/library/svg/sourcegraph.svg new file mode 100644 index 0000000..815a2ab --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sourcegraph.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sourcetrail.svg b/.claude/skills/logo-design/assets/library/svg/sourcetrail.svg new file mode 100644 index 0000000..d1d52ee --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sourcetrail.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sourcetree.svg b/.claude/skills/logo-design/assets/library/svg/sourcetree.svg new file mode 100644 index 0000000..098c521 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sourcetree.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/spark.svg b/.claude/skills/logo-design/assets/library/svg/spark.svg new file mode 100644 index 0000000..0fcfceb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/spark.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sparkcentral.svg b/.claude/skills/logo-design/assets/library/svg/sparkcentral.svg new file mode 100644 index 0000000..c724013 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sparkcentral.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sparkpost.svg b/.claude/skills/logo-design/assets/library/svg/sparkpost.svg new file mode 100644 index 0000000..6e2ba3c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sparkpost.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/speakerdeck.svg b/.claude/skills/logo-design/assets/library/svg/speakerdeck.svg new file mode 100644 index 0000000..fcb7e14 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/speakerdeck.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/speedcurve.svg b/.claude/skills/logo-design/assets/library/svg/speedcurve.svg new file mode 100644 index 0000000..a4acdd0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/speedcurve.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/spidermonkey-icon.svg b/.claude/skills/logo-design/assets/library/svg/spidermonkey-icon.svg new file mode 100644 index 0000000..99f1868 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/spidermonkey-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/spidermonkey.svg b/.claude/skills/logo-design/assets/library/svg/spidermonkey.svg new file mode 100644 index 0000000..3d94602 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/spidermonkey.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/spinnaker.svg b/.claude/skills/logo-design/assets/library/svg/spinnaker.svg new file mode 100644 index 0000000..4f49b80 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/spinnaker.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/splunk.svg b/.claude/skills/logo-design/assets/library/svg/splunk.svg new file mode 100644 index 0000000..52a42ff --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/splunk.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/spotify-icon.svg b/.claude/skills/logo-design/assets/library/svg/spotify-icon.svg new file mode 100644 index 0000000..964645a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/spotify-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/spotify.svg b/.claude/skills/logo-design/assets/library/svg/spotify.svg new file mode 100644 index 0000000..7de9834 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/spotify.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/spree.svg b/.claude/skills/logo-design/assets/library/svg/spree.svg new file mode 100644 index 0000000..a9928df --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/spree.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/spring-icon.svg b/.claude/skills/logo-design/assets/library/svg/spring-icon.svg new file mode 100644 index 0000000..61cfbbf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/spring-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/spring.svg b/.claude/skills/logo-design/assets/library/svg/spring.svg new file mode 100644 index 0000000..d90c9d8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/spring.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sqlite.svg b/.claude/skills/logo-design/assets/library/svg/sqlite.svg new file mode 100644 index 0000000..618e225 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sqlite.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/square.svg b/.claude/skills/logo-design/assets/library/svg/square.svg new file mode 100644 index 0000000..af672b6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/square.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/squarespace.svg b/.claude/skills/logo-design/assets/library/svg/squarespace.svg new file mode 100644 index 0000000..7ccaa15 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/squarespace.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stackbit-icon.svg b/.claude/skills/logo-design/assets/library/svg/stackbit-icon.svg new file mode 100644 index 0000000..043a4a9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stackbit-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stackbit.svg b/.claude/skills/logo-design/assets/library/svg/stackbit.svg new file mode 100644 index 0000000..5a5b74c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stackbit.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stackoverflow-icon.svg b/.claude/skills/logo-design/assets/library/svg/stackoverflow-icon.svg new file mode 100644 index 0000000..b829388 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stackoverflow-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stackoverflow.svg b/.claude/skills/logo-design/assets/library/svg/stackoverflow.svg new file mode 100644 index 0000000..b968e7c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stackoverflow.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stackshare.svg b/.claude/skills/logo-design/assets/library/svg/stackshare.svg new file mode 100644 index 0000000..16c9034 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stackshare.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/statuspage.svg b/.claude/skills/logo-design/assets/library/svg/statuspage.svg new file mode 100644 index 0000000..7bbb39f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/statuspage.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stdlib-icon.svg b/.claude/skills/logo-design/assets/library/svg/stdlib-icon.svg new file mode 100644 index 0000000..d8d2817 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stdlib-icon.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stdlib.svg b/.claude/skills/logo-design/assets/library/svg/stdlib.svg new file mode 100644 index 0000000..c801bac --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stdlib.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/steam.svg b/.claude/skills/logo-design/assets/library/svg/steam.svg new file mode 100644 index 0000000..03587f5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/steam.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stenciljs-icon.svg b/.claude/skills/logo-design/assets/library/svg/stenciljs-icon.svg new file mode 100644 index 0000000..eb0b90d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stenciljs-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stenciljs.svg b/.claude/skills/logo-design/assets/library/svg/stenciljs.svg new file mode 100644 index 0000000..fd28474 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stenciljs.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stetho.svg b/.claude/skills/logo-design/assets/library/svg/stetho.svg new file mode 100644 index 0000000..1efa8e7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stetho.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stickermule.svg b/.claude/skills/logo-design/assets/library/svg/stickermule.svg new file mode 100644 index 0000000..53b2c38 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stickermule.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stimulus.svg b/.claude/skills/logo-design/assets/library/svg/stimulus.svg new file mode 100644 index 0000000..e4c3a2f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stimulus.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stitch.svg b/.claude/skills/logo-design/assets/library/svg/stitch.svg new file mode 100644 index 0000000..8cf2f4d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stitch.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stoplight.svg b/.claude/skills/logo-design/assets/library/svg/stoplight.svg new file mode 100644 index 0000000..bb599de --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stoplight.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/storybook-icon.svg b/.claude/skills/logo-design/assets/library/svg/storybook-icon.svg new file mode 100644 index 0000000..6271795 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/storybook-icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/storybook.svg b/.claude/skills/logo-design/assets/library/svg/storybook.svg new file mode 100644 index 0000000..7d502a1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/storybook.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/strapi-icon.svg b/.claude/skills/logo-design/assets/library/svg/strapi-icon.svg new file mode 100644 index 0000000..41c5fca --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/strapi-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/strapi.svg b/.claude/skills/logo-design/assets/library/svg/strapi.svg new file mode 100644 index 0000000..5f46d0e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/strapi.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/strider.svg b/.claude/skills/logo-design/assets/library/svg/strider.svg new file mode 100644 index 0000000..fd5e733 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/strider.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stripe.svg b/.claude/skills/logo-design/assets/library/svg/stripe.svg new file mode 100644 index 0000000..9b3cc9f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stripe.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/struts.svg b/.claude/skills/logo-design/assets/library/svg/struts.svg new file mode 100644 index 0000000..869a3ee --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/struts.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/styleci.svg b/.claude/skills/logo-design/assets/library/svg/styleci.svg new file mode 100644 index 0000000..d33ce2c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/styleci.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stylefmt.svg b/.claude/skills/logo-design/assets/library/svg/stylefmt.svg new file mode 100644 index 0000000..9306a23 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stylefmt.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stylelint.svg b/.claude/skills/logo-design/assets/library/svg/stylelint.svg new file mode 100644 index 0000000..464e749 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stylelint.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stylis.svg b/.claude/skills/logo-design/assets/library/svg/stylis.svg new file mode 100644 index 0000000..5b29d95 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stylis.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/stylus.svg b/.claude/skills/logo-design/assets/library/svg/stylus.svg new file mode 100644 index 0000000..13727d4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/stylus.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sublimetext-icon.svg b/.claude/skills/logo-design/assets/library/svg/sublimetext-icon.svg new file mode 100644 index 0000000..ce6db52 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sublimetext-icon.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sublimetext.svg b/.claude/skills/logo-design/assets/library/svg/sublimetext.svg new file mode 100644 index 0000000..85ab615 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sublimetext.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/subversion.svg b/.claude/skills/logo-design/assets/library/svg/subversion.svg new file mode 100644 index 0000000..2d521f7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/subversion.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sugarss.svg b/.claude/skills/logo-design/assets/library/svg/sugarss.svg new file mode 100644 index 0000000..d09cff3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sugarss.svg @@ -0,0 +1,571 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/supabase-icon.svg b/.claude/skills/logo-design/assets/library/svg/supabase-icon.svg new file mode 100644 index 0000000..a3003f7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/supabase-icon.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/supabase.svg b/.claude/skills/logo-design/assets/library/svg/supabase.svg new file mode 100644 index 0000000..157e5d9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/supabase.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/surge.svg b/.claude/skills/logo-design/assets/library/svg/surge.svg new file mode 100644 index 0000000..dcb7438 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/surge.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/survicate.svg b/.claude/skills/logo-design/assets/library/svg/survicate.svg new file mode 100644 index 0000000..11b5f56 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/survicate.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/suse.svg b/.claude/skills/logo-design/assets/library/svg/suse.svg new file mode 100644 index 0000000..b17f82c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/suse.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/susy.svg b/.claude/skills/logo-design/assets/library/svg/susy.svg new file mode 100644 index 0000000..4acec37 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/susy.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/svelte-icon.svg b/.claude/skills/logo-design/assets/library/svg/svelte-icon.svg new file mode 100644 index 0000000..b4c5a00 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/svelte-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/svelte.svg b/.claude/skills/logo-design/assets/library/svg/svelte.svg new file mode 100644 index 0000000..cd4f06c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/svelte.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/svg.svg b/.claude/skills/logo-design/assets/library/svg/svg.svg new file mode 100644 index 0000000..3244650 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/svg.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/swagger.svg b/.claude/skills/logo-design/assets/library/svg/swagger.svg new file mode 100644 index 0000000..b009ac3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/swagger.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/swift.svg b/.claude/skills/logo-design/assets/library/svg/swift.svg new file mode 100644 index 0000000..5dbaed7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/swift.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/swiftype.svg b/.claude/skills/logo-design/assets/library/svg/swiftype.svg new file mode 100644 index 0000000..d780bea --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/swiftype.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/symfony.svg b/.claude/skills/logo-design/assets/library/svg/symfony.svg new file mode 100644 index 0000000..08ae93a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/symfony.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/sysdig-icon.svg b/.claude/skills/logo-design/assets/library/svg/sysdig-icon.svg new file mode 100644 index 0000000..3ea3dd5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/sysdig-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/t3.svg b/.claude/skills/logo-design/assets/library/svg/t3.svg new file mode 100644 index 0000000..c2216fd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/t3.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tableau-icon.svg b/.claude/skills/logo-design/assets/library/svg/tableau-icon.svg new file mode 100644 index 0000000..a305906 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tableau-icon.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tableau.svg b/.claude/skills/logo-design/assets/library/svg/tableau.svg new file mode 100644 index 0000000..795b0f1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tableau.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/taiga.svg b/.claude/skills/logo-design/assets/library/svg/taiga.svg new file mode 100644 index 0000000..859cf16 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/taiga.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tailwindcss-icon.svg b/.claude/skills/logo-design/assets/library/svg/tailwindcss-icon.svg new file mode 100644 index 0000000..ddcc2fc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tailwindcss-icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tailwindcss.svg b/.claude/skills/logo-design/assets/library/svg/tailwindcss.svg new file mode 100644 index 0000000..eff31b2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tailwindcss.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tapcart-icon.svg b/.claude/skills/logo-design/assets/library/svg/tapcart-icon.svg new file mode 100644 index 0000000..164965b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tapcart-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tapcart.svg b/.claude/skills/logo-design/assets/library/svg/tapcart.svg new file mode 100644 index 0000000..22ca29d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tapcart.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/targetprocess.svg b/.claude/skills/logo-design/assets/library/svg/targetprocess.svg new file mode 100644 index 0000000..c2b7854 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/targetprocess.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/taskade-icon.svg b/.claude/skills/logo-design/assets/library/svg/taskade-icon.svg new file mode 100644 index 0000000..92463ac --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/taskade-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/taskade.svg b/.claude/skills/logo-design/assets/library/svg/taskade.svg new file mode 100644 index 0000000..507cad8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/taskade.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tastejs.svg b/.claude/skills/logo-design/assets/library/svg/tastejs.svg new file mode 100644 index 0000000..69d3a6b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tastejs.svg @@ -0,0 +1,615 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tauri.svg b/.claude/skills/logo-design/assets/library/svg/tauri.svg new file mode 100644 index 0000000..f21af36 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tauri.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tealium.svg b/.claude/skills/logo-design/assets/library/svg/tealium.svg new file mode 100644 index 0000000..ceeda47 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tealium.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/teamgrid.svg b/.claude/skills/logo-design/assets/library/svg/teamgrid.svg new file mode 100644 index 0000000..5d3ffa9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/teamgrid.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/teamwork-icon.svg b/.claude/skills/logo-design/assets/library/svg/teamwork-icon.svg new file mode 100644 index 0000000..e885ab4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/teamwork-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/teamwork.svg b/.claude/skills/logo-design/assets/library/svg/teamwork.svg new file mode 100644 index 0000000..be538ee --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/teamwork.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/telegram.svg b/.claude/skills/logo-design/assets/library/svg/telegram.svg new file mode 100644 index 0000000..2965c00 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/telegram.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tensorflow.svg b/.claude/skills/logo-design/assets/library/svg/tensorflow.svg new file mode 100644 index 0000000..5475958 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tensorflow.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/terminal.svg b/.claude/skills/logo-design/assets/library/svg/terminal.svg new file mode 100644 index 0000000..4d01b7e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/terminal.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/terraform-icon.svg b/.claude/skills/logo-design/assets/library/svg/terraform-icon.svg new file mode 100644 index 0000000..5e067bd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/terraform-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/terraform.svg b/.claude/skills/logo-design/assets/library/svg/terraform.svg new file mode 100644 index 0000000..3ca53ff --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/terraform.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/terser-icon.svg b/.claude/skills/logo-design/assets/library/svg/terser-icon.svg new file mode 100644 index 0000000..ea9e6d9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/terser-icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/terser.svg b/.claude/skills/logo-design/assets/library/svg/terser.svg new file mode 100644 index 0000000..a991a1d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/terser.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/testing-library.svg b/.claude/skills/logo-design/assets/library/svg/testing-library.svg new file mode 100644 index 0000000..d6f2edc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/testing-library.svg @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/testlodge.svg b/.claude/skills/logo-design/assets/library/svg/testlodge.svg new file mode 100644 index 0000000..5d0fbf1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/testlodge.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/threejs.svg b/.claude/skills/logo-design/assets/library/svg/threejs.svg new file mode 100644 index 0000000..a5d80ad --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/threejs.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tidal-icon.svg b/.claude/skills/logo-design/assets/library/svg/tidal-icon.svg new file mode 100644 index 0000000..32fc4db --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tidal-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tidal.svg b/.claude/skills/logo-design/assets/library/svg/tidal.svg new file mode 100644 index 0000000..f3398bb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tidal.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tiktok-icon.svg b/.claude/skills/logo-design/assets/library/svg/tiktok-icon.svg new file mode 100644 index 0000000..4defc5e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tiktok-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tiktok.svg b/.claude/skills/logo-design/assets/library/svg/tiktok.svg new file mode 100644 index 0000000..d3b1500 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tiktok.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tnw.svg b/.claude/skills/logo-design/assets/library/svg/tnw.svg new file mode 100644 index 0000000..3b4cf6c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tnw.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/todoist-icon.svg b/.claude/skills/logo-design/assets/library/svg/todoist-icon.svg new file mode 100644 index 0000000..ec39d40 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/todoist-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/todoist.svg b/.claude/skills/logo-design/assets/library/svg/todoist.svg new file mode 100644 index 0000000..9cb69ad --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/todoist.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/todomvc.svg b/.claude/skills/logo-design/assets/library/svg/todomvc.svg new file mode 100644 index 0000000..b51e534 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/todomvc.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tomcat.svg b/.claude/skills/logo-design/assets/library/svg/tomcat.svg new file mode 100644 index 0000000..c97d03e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tomcat.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/toml.svg b/.claude/skills/logo-design/assets/library/svg/toml.svg new file mode 100644 index 0000000..6322705 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/toml.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tor.svg b/.claude/skills/logo-design/assets/library/svg/tor.svg new file mode 100644 index 0000000..07d7ccc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tor.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/torus.svg b/.claude/skills/logo-design/assets/library/svg/torus.svg new file mode 100644 index 0000000..4586314 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/torus.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/traackr.svg b/.claude/skills/logo-design/assets/library/svg/traackr.svg new file mode 100644 index 0000000..cdd84ad --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/traackr.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/trac.svg b/.claude/skills/logo-design/assets/library/svg/trac.svg new file mode 100644 index 0000000..a4118d7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/trac.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/travis-ci-monochrome.svg b/.claude/skills/logo-design/assets/library/svg/travis-ci-monochrome.svg new file mode 100644 index 0000000..f83d582 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/travis-ci-monochrome.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/travis-ci.svg b/.claude/skills/logo-design/assets/library/svg/travis-ci.svg new file mode 100644 index 0000000..cb2518e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/travis-ci.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/treasuredata-icon.svg b/.claude/skills/logo-design/assets/library/svg/treasuredata-icon.svg new file mode 100644 index 0000000..8df7972 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/treasuredata-icon.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/treasuredata.svg b/.claude/skills/logo-design/assets/library/svg/treasuredata.svg new file mode 100644 index 0000000..746d669 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/treasuredata.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/treehouse.svg b/.claude/skills/logo-design/assets/library/svg/treehouse.svg new file mode 100644 index 0000000..e5e55d4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/treehouse.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/trello.svg b/.claude/skills/logo-design/assets/library/svg/trello.svg new file mode 100644 index 0000000..d8ae484 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/trello.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/truffle-icon.svg b/.claude/skills/logo-design/assets/library/svg/truffle-icon.svg new file mode 100644 index 0000000..39cfca3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/truffle-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/truffle.svg b/.claude/skills/logo-design/assets/library/svg/truffle.svg new file mode 100644 index 0000000..2469847 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/truffle.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tsnode.svg b/.claude/skills/logo-design/assets/library/svg/tsnode.svg new file mode 100644 index 0000000..003fd86 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tsnode.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tsu.svg b/.claude/skills/logo-design/assets/library/svg/tsu.svg new file mode 100644 index 0000000..92c846c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tsu.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tsuru.svg b/.claude/skills/logo-design/assets/library/svg/tsuru.svg new file mode 100644 index 0000000..91c76ca --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tsuru.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tumblr-icon.svg b/.claude/skills/logo-design/assets/library/svg/tumblr-icon.svg new file mode 100644 index 0000000..1d686e4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tumblr-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tumblr.svg b/.claude/skills/logo-design/assets/library/svg/tumblr.svg new file mode 100644 index 0000000..2c3eda1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tumblr.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tunein.svg b/.claude/skills/logo-design/assets/library/svg/tunein.svg new file mode 100644 index 0000000..8814929 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tunein.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/tuple.svg b/.claude/skills/logo-design/assets/library/svg/tuple.svg new file mode 100644 index 0000000..50ac227 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/tuple.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/turborepo-icon.svg b/.claude/skills/logo-design/assets/library/svg/turborepo-icon.svg new file mode 100644 index 0000000..745b259 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/turborepo-icon.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/turborepo.svg b/.claude/skills/logo-design/assets/library/svg/turborepo.svg new file mode 100644 index 0000000..7e9bdb9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/turborepo.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/turret.svg b/.claude/skills/logo-design/assets/library/svg/turret.svg new file mode 100644 index 0000000..c4a400c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/turret.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/twilio-icon.svg b/.claude/skills/logo-design/assets/library/svg/twilio-icon.svg new file mode 100644 index 0000000..844d2dc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/twilio-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/twilio.svg b/.claude/skills/logo-design/assets/library/svg/twilio.svg new file mode 100644 index 0000000..cc96627 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/twilio.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/twitch.svg b/.claude/skills/logo-design/assets/library/svg/twitch.svg new file mode 100644 index 0000000..56ea968 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/twitch.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/twitter.svg b/.claude/skills/logo-design/assets/library/svg/twitter.svg new file mode 100644 index 0000000..5d45938 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/twitter.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/typeform-icon.svg b/.claude/skills/logo-design/assets/library/svg/typeform-icon.svg new file mode 100644 index 0000000..5000ae9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/typeform-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/typeform.svg b/.claude/skills/logo-design/assets/library/svg/typeform.svg new file mode 100644 index 0000000..7602aed --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/typeform.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/typescript-icon.svg b/.claude/skills/logo-design/assets/library/svg/typescript-icon.svg new file mode 100644 index 0000000..887e81e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/typescript-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/typescript.svg b/.claude/skills/logo-design/assets/library/svg/typescript.svg new file mode 100644 index 0000000..81a1bb7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/typescript.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/typo3-icon.svg b/.claude/skills/logo-design/assets/library/svg/typo3-icon.svg new file mode 100644 index 0000000..536b763 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/typo3-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/typo3.svg b/.claude/skills/logo-design/assets/library/svg/typo3.svg new file mode 100644 index 0000000..9f4a9a0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/typo3.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ubuntu.svg b/.claude/skills/logo-design/assets/library/svg/ubuntu.svg new file mode 100644 index 0000000..a4a9fda --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ubuntu.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/udacity-icon.svg b/.claude/skills/logo-design/assets/library/svg/udacity-icon.svg new file mode 100644 index 0000000..4c29c43 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/udacity-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/udacity.svg b/.claude/skills/logo-design/assets/library/svg/udacity.svg new file mode 100644 index 0000000..18da276 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/udacity.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/udemy-icon.svg b/.claude/skills/logo-design/assets/library/svg/udemy-icon.svg new file mode 100644 index 0000000..ad6a86e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/udemy-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/udemy.svg b/.claude/skills/logo-design/assets/library/svg/udemy.svg new file mode 100644 index 0000000..9cb1c31 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/udemy.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/uikit.svg b/.claude/skills/logo-design/assets/library/svg/uikit.svg new file mode 100644 index 0000000..92e2ba8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/uikit.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/umu.svg b/.claude/skills/logo-design/assets/library/svg/umu.svg new file mode 100644 index 0000000..e55d1aa --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/umu.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/unbounce-icon.svg b/.claude/skills/logo-design/assets/library/svg/unbounce-icon.svg new file mode 100644 index 0000000..60e5cd3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/unbounce-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/unbounce.svg b/.claude/skills/logo-design/assets/library/svg/unbounce.svg new file mode 100644 index 0000000..4cfdaef --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/unbounce.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/undertow.svg b/.claude/skills/logo-design/assets/library/svg/undertow.svg new file mode 100644 index 0000000..dab9829 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/undertow.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/unionpay.svg b/.claude/skills/logo-design/assets/library/svg/unionpay.svg new file mode 100644 index 0000000..e3d437a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/unionpay.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/unitjs.svg b/.claude/skills/logo-design/assets/library/svg/unitjs.svg new file mode 100644 index 0000000..d96b18f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/unitjs.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/unito-icon.svg b/.claude/skills/logo-design/assets/library/svg/unito-icon.svg new file mode 100644 index 0000000..a7abab8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/unito-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/unito.svg b/.claude/skills/logo-design/assets/library/svg/unito.svg new file mode 100644 index 0000000..ace907e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/unito.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/unity.svg b/.claude/skills/logo-design/assets/library/svg/unity.svg new file mode 100644 index 0000000..042b8d7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/unity.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/unocss.svg b/.claude/skills/logo-design/assets/library/svg/unocss.svg new file mode 100644 index 0000000..bff436b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/unocss.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/unrealengine-icon.svg b/.claude/skills/logo-design/assets/library/svg/unrealengine-icon.svg new file mode 100644 index 0000000..5a6e077 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/unrealengine-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/unrealengine.svg b/.claude/skills/logo-design/assets/library/svg/unrealengine.svg new file mode 100644 index 0000000..8f85ce4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/unrealengine.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/upcase.svg b/.claude/skills/logo-design/assets/library/svg/upcase.svg new file mode 100644 index 0000000..626e68f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/upcase.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/upwork.svg b/.claude/skills/logo-design/assets/library/svg/upwork.svg new file mode 100644 index 0000000..f5cae7d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/upwork.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/user-testing-icon.svg b/.claude/skills/logo-design/assets/library/svg/user-testing-icon.svg new file mode 100644 index 0000000..70e2f06 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/user-testing-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/user-testing.svg b/.claude/skills/logo-design/assets/library/svg/user-testing.svg new file mode 100644 index 0000000..f0901d7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/user-testing.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/uservoice-icon.svg b/.claude/skills/logo-design/assets/library/svg/uservoice-icon.svg new file mode 100644 index 0000000..cf6061e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/uservoice-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/uservoice.svg b/.claude/skills/logo-design/assets/library/svg/uservoice.svg new file mode 100644 index 0000000..257373d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/uservoice.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/uwsgi.svg b/.claude/skills/logo-design/assets/library/svg/uwsgi.svg new file mode 100644 index 0000000..0290552 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/uwsgi.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/v8-ignition.svg b/.claude/skills/logo-design/assets/library/svg/v8-ignition.svg new file mode 100644 index 0000000..4f0ed51 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/v8-ignition.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/v8-turbofan.svg b/.claude/skills/logo-design/assets/library/svg/v8-turbofan.svg new file mode 100644 index 0000000..90b074d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/v8-turbofan.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/v8.svg b/.claude/skills/logo-design/assets/library/svg/v8.svg new file mode 100644 index 0000000..9f8addf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/v8.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vaadin.svg b/.claude/skills/logo-design/assets/library/svg/vaadin.svg new file mode 100644 index 0000000..9457875 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vaadin.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vaddy.svg b/.claude/skills/logo-design/assets/library/svg/vaddy.svg new file mode 100644 index 0000000..90e1585 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vaddy.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vagrant-icon.svg b/.claude/skills/logo-design/assets/library/svg/vagrant-icon.svg new file mode 100644 index 0000000..2220a6c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vagrant-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vagrant.svg b/.claude/skills/logo-design/assets/library/svg/vagrant.svg new file mode 100644 index 0000000..37974dc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vagrant.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vault-icon.svg b/.claude/skills/logo-design/assets/library/svg/vault-icon.svg new file mode 100644 index 0000000..bfa40e0 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vault-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vault.svg b/.claude/skills/logo-design/assets/library/svg/vault.svg new file mode 100644 index 0000000..23e6e42 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vault.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vector-timber.svg b/.claude/skills/logo-design/assets/library/svg/vector-timber.svg new file mode 100644 index 0000000..0458487 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vector-timber.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vercel-icon.svg b/.claude/skills/logo-design/assets/library/svg/vercel-icon.svg new file mode 100644 index 0000000..a4a38d1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vercel-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vercel.svg b/.claude/skills/logo-design/assets/library/svg/vercel.svg new file mode 100644 index 0000000..7eb306e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vercel.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/verdaccio-icon.svg b/.claude/skills/logo-design/assets/library/svg/verdaccio-icon.svg new file mode 100644 index 0000000..ea9faa4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/verdaccio-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/verdaccio.svg b/.claude/skills/logo-design/assets/library/svg/verdaccio.svg new file mode 100644 index 0000000..03c096e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/verdaccio.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vernemq.svg b/.claude/skills/logo-design/assets/library/svg/vernemq.svg new file mode 100644 index 0000000..fba113f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vernemq.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vim.svg b/.claude/skills/logo-design/assets/library/svg/vim.svg new file mode 100644 index 0000000..38fc6cb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vim.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vimeo-icon.svg b/.claude/skills/logo-design/assets/library/svg/vimeo-icon.svg new file mode 100644 index 0000000..8b27d74 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vimeo-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vimeo.svg b/.claude/skills/logo-design/assets/library/svg/vimeo.svg new file mode 100644 index 0000000..fe9f017 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vimeo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/visa.svg b/.claude/skills/logo-design/assets/library/svg/visa.svg new file mode 100644 index 0000000..d031bed --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/visa.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/visaelectron.svg b/.claude/skills/logo-design/assets/library/svg/visaelectron.svg new file mode 100644 index 0000000..a5e23a4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/visaelectron.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/visual-studio-code.svg b/.claude/skills/logo-design/assets/library/svg/visual-studio-code.svg new file mode 100644 index 0000000..f28370f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/visual-studio-code.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/visual-studio.svg b/.claude/skills/logo-design/assets/library/svg/visual-studio.svg new file mode 100644 index 0000000..7236a32 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/visual-studio.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vitejs.svg b/.claude/skills/logo-design/assets/library/svg/vitejs.svg new file mode 100644 index 0000000..2dddea3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vitejs.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vitest.svg b/.claude/skills/logo-design/assets/library/svg/vitest.svg new file mode 100644 index 0000000..6097bba --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vitest.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vivaldi-icon.svg b/.claude/skills/logo-design/assets/library/svg/vivaldi-icon.svg new file mode 100644 index 0000000..47d6080 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vivaldi-icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vivaldi.svg b/.claude/skills/logo-design/assets/library/svg/vivaldi.svg new file mode 100644 index 0000000..f74563a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vivaldi.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vlang.svg b/.claude/skills/logo-design/assets/library/svg/vlang.svg new file mode 100644 index 0000000..3e358e4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vlang.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/void.svg b/.claude/skills/logo-design/assets/library/svg/void.svg new file mode 100644 index 0000000..e17f99e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/void.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vue.svg b/.claude/skills/logo-design/assets/library/svg/vue.svg new file mode 100644 index 0000000..4cd8088 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vue.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vuetifyjs.svg b/.claude/skills/logo-design/assets/library/svg/vuetifyjs.svg new file mode 100644 index 0000000..0445b79 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vuetifyjs.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vueuse.svg b/.claude/skills/logo-design/assets/library/svg/vueuse.svg new file mode 100644 index 0000000..25f373e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vueuse.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vulkan.svg b/.claude/skills/logo-design/assets/library/svg/vulkan.svg new file mode 100644 index 0000000..8fbbea8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vulkan.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vultr.svg b/.claude/skills/logo-design/assets/library/svg/vultr.svg new file mode 100644 index 0000000..08a27b7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vultr.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/vwo.svg b/.claude/skills/logo-design/assets/library/svg/vwo.svg new file mode 100644 index 0000000..24d2abd --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/vwo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/w3c.svg b/.claude/skills/logo-design/assets/library/svg/w3c.svg new file mode 100644 index 0000000..896dc74 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/w3c.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/waffle-icon.svg b/.claude/skills/logo-design/assets/library/svg/waffle-icon.svg new file mode 100644 index 0000000..88c2a1d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/waffle-icon.svg @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/waffle.svg b/.claude/skills/logo-design/assets/library/svg/waffle.svg new file mode 100644 index 0000000..e95a2d1 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/waffle.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wagtail.svg b/.claude/skills/logo-design/assets/library/svg/wagtail.svg new file mode 100644 index 0000000..c0b1d60 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wagtail.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wakatime.svg b/.claude/skills/logo-design/assets/library/svg/wakatime.svg new file mode 100644 index 0000000..a223d48 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wakatime.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/watchman.svg b/.claude/skills/logo-design/assets/library/svg/watchman.svg new file mode 100644 index 0000000..4ede2af --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/watchman.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wearos.svg b/.claude/skills/logo-design/assets/library/svg/wearos.svg new file mode 100644 index 0000000..75892b4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wearos.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/weave.svg b/.claude/skills/logo-design/assets/library/svg/weave.svg new file mode 100644 index 0000000..0771dc2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/weave.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/web-fundamentals.svg b/.claude/skills/logo-design/assets/library/svg/web-fundamentals.svg new file mode 100644 index 0000000..0b1b15c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/web-fundamentals.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/web.dev-icon.svg b/.claude/skills/logo-design/assets/library/svg/web.dev-icon.svg new file mode 100644 index 0000000..bf649ca --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/web.dev-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/web.dev.svg b/.claude/skills/logo-design/assets/library/svg/web.dev.svg new file mode 100644 index 0000000..3cdeec6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/web.dev.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/web3js.svg b/.claude/skills/logo-design/assets/library/svg/web3js.svg new file mode 100644 index 0000000..254ce38 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/web3js.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webassembly.svg b/.claude/skills/logo-design/assets/library/svg/webassembly.svg new file mode 100644 index 0000000..e359c06 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webassembly.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webcomponents.svg b/.claude/skills/logo-design/assets/library/svg/webcomponents.svg new file mode 100644 index 0000000..f9bac2b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webcomponents.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webdriverio.svg b/.claude/skills/logo-design/assets/library/svg/webdriverio.svg new file mode 100644 index 0000000..d6d4429 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webdriverio.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webflow.svg b/.claude/skills/logo-design/assets/library/svg/webflow.svg new file mode 100644 index 0000000..85bf64e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webflow.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webhint-icon.svg b/.claude/skills/logo-design/assets/library/svg/webhint-icon.svg new file mode 100644 index 0000000..598003b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webhint-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webhint.svg b/.claude/skills/logo-design/assets/library/svg/webhint.svg new file mode 100644 index 0000000..5125ae2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webhint.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webhooks.svg b/.claude/skills/logo-design/assets/library/svg/webhooks.svg new file mode 100644 index 0000000..b275fc8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webhooks.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webix-icon.svg b/.claude/skills/logo-design/assets/library/svg/webix-icon.svg new file mode 100644 index 0000000..f5b47ff --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webix-icon.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webix.svg b/.claude/skills/logo-design/assets/library/svg/webix.svg new file mode 100644 index 0000000..1169240 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webix.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webmin.svg b/.claude/skills/logo-design/assets/library/svg/webmin.svg new file mode 100644 index 0000000..783ce22 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webmin.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webpack.svg b/.claude/skills/logo-design/assets/library/svg/webpack.svg new file mode 100644 index 0000000..3d8441d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webpack.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webplatform.svg b/.claude/skills/logo-design/assets/library/svg/webplatform.svg new file mode 100644 index 0000000..b6a5300 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webplatform.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webrtc.svg b/.claude/skills/logo-design/assets/library/svg/webrtc.svg new file mode 100644 index 0000000..b9c6bed --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webrtc.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/websocket.svg b/.claude/skills/logo-design/assets/library/svg/websocket.svg new file mode 100644 index 0000000..e5f7629 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/websocket.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webstorm.svg b/.claude/skills/logo-design/assets/library/svg/webstorm.svg new file mode 100644 index 0000000..d071deb --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webstorm.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webtask.svg b/.claude/skills/logo-design/assets/library/svg/webtask.svg new file mode 100644 index 0000000..1b46385 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webtask.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/webtorrent.svg b/.claude/skills/logo-design/assets/library/svg/webtorrent.svg new file mode 100644 index 0000000..4c84bbf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/webtorrent.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/weebly.svg b/.claude/skills/logo-design/assets/library/svg/weebly.svg new file mode 100644 index 0000000..2634cfc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/weebly.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/whalar.svg b/.claude/skills/logo-design/assets/library/svg/whalar.svg new file mode 100644 index 0000000..c0f08d7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/whalar.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/whatsapp.svg b/.claude/skills/logo-design/assets/library/svg/whatsapp.svg new file mode 100644 index 0000000..0b43ed5 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/whatsapp.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/whatwg.svg b/.claude/skills/logo-design/assets/library/svg/whatwg.svg new file mode 100644 index 0000000..84b262e --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/whatwg.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wicket-icon.svg b/.claude/skills/logo-design/assets/library/svg/wicket-icon.svg new file mode 100644 index 0000000..d0d365d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wicket-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wicket.svg b/.claude/skills/logo-design/assets/library/svg/wicket.svg new file mode 100644 index 0000000..51e8dae --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wicket.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wifi.svg b/.claude/skills/logo-design/assets/library/svg/wifi.svg new file mode 100644 index 0000000..7349c62 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wifi.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wildfly.svg b/.claude/skills/logo-design/assets/library/svg/wildfly.svg new file mode 100644 index 0000000..9ec1896 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wildfly.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wire.svg b/.claude/skills/logo-design/assets/library/svg/wire.svg new file mode 100644 index 0000000..f1df309 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wire.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wix.svg b/.claude/skills/logo-design/assets/library/svg/wix.svg new file mode 100644 index 0000000..736a268 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wix.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wmr.svg b/.claude/skills/logo-design/assets/library/svg/wmr.svg new file mode 100644 index 0000000..d5a05d7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wmr.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/woocommerce-icon.svg b/.claude/skills/logo-design/assets/library/svg/woocommerce-icon.svg new file mode 100644 index 0000000..fcb1333 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/woocommerce-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/woocommerce.svg b/.claude/skills/logo-design/assets/library/svg/woocommerce.svg new file mode 100644 index 0000000..fc1b5cc --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/woocommerce.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/woopra.svg b/.claude/skills/logo-design/assets/library/svg/woopra.svg new file mode 100644 index 0000000..6a26f1b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/woopra.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wordpress-icon.svg b/.claude/skills/logo-design/assets/library/svg/wordpress-icon.svg new file mode 100644 index 0000000..d880bea --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wordpress-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wordpress.svg b/.claude/skills/logo-design/assets/library/svg/wordpress.svg new file mode 100644 index 0000000..0db7e11 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wordpress.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/workboard.svg b/.claude/skills/logo-design/assets/library/svg/workboard.svg new file mode 100644 index 0000000..5b31146 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/workboard.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/workplace.svg b/.claude/skills/logo-design/assets/library/svg/workplace.svg new file mode 100644 index 0000000..327f857 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/workplace.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wpengine.svg b/.claude/skills/logo-design/assets/library/svg/wpengine.svg new file mode 100644 index 0000000..fc48ab9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wpengine.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/wufoo.svg b/.claude/skills/logo-design/assets/library/svg/wufoo.svg new file mode 100644 index 0000000..13c0288 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/wufoo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/xamarin.svg b/.claude/skills/logo-design/assets/library/svg/xamarin.svg new file mode 100644 index 0000000..90dd2e2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/xamarin.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/xampp.svg b/.claude/skills/logo-design/assets/library/svg/xampp.svg new file mode 100644 index 0000000..ebcdf14 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/xampp.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/xcart.svg b/.claude/skills/logo-design/assets/library/svg/xcart.svg new file mode 100644 index 0000000..70c01cf --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/xcart.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/xero.svg b/.claude/skills/logo-design/assets/library/svg/xero.svg new file mode 100644 index 0000000..f37c4ed --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/xero.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/xplenty.svg b/.claude/skills/logo-design/assets/library/svg/xplenty.svg new file mode 100644 index 0000000..75bb523 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/xplenty.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/xstate.svg b/.claude/skills/logo-design/assets/library/svg/xstate.svg new file mode 100644 index 0000000..8dc056f --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/xstate.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/xtend.svg b/.claude/skills/logo-design/assets/library/svg/xtend.svg new file mode 100644 index 0000000..7539069 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/xtend.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/xwiki-icon.svg b/.claude/skills/logo-design/assets/library/svg/xwiki-icon.svg new file mode 100644 index 0000000..a449ff4 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/xwiki-icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/xwiki.svg b/.claude/skills/logo-design/assets/library/svg/xwiki.svg new file mode 100644 index 0000000..437b155 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/xwiki.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/yahoo.svg b/.claude/skills/logo-design/assets/library/svg/yahoo.svg new file mode 100644 index 0000000..ec0f042 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/yahoo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/yaml.svg b/.claude/skills/logo-design/assets/library/svg/yaml.svg new file mode 100644 index 0000000..cf49df9 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/yaml.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/yammer.svg b/.claude/skills/logo-design/assets/library/svg/yammer.svg new file mode 100644 index 0000000..5d33243 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/yammer.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/yandex-ru.svg b/.claude/skills/logo-design/assets/library/svg/yandex-ru.svg new file mode 100644 index 0000000..0d4fa90 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/yandex-ru.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/yarn.svg b/.claude/skills/logo-design/assets/library/svg/yarn.svg new file mode 100644 index 0000000..ab46e2d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/yarn.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/ycombinator.svg b/.claude/skills/logo-design/assets/library/svg/ycombinator.svg new file mode 100644 index 0000000..2c52df8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/ycombinator.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/yeoman.svg b/.claude/skills/logo-design/assets/library/svg/yeoman.svg new file mode 100644 index 0000000..90961c3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/yeoman.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/yii.svg b/.claude/skills/logo-design/assets/library/svg/yii.svg new file mode 100644 index 0000000..b5d3a8c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/yii.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/youtrack.svg b/.claude/skills/logo-design/assets/library/svg/youtrack.svg new file mode 100644 index 0000000..ce7d666 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/youtrack.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/youtube-icon.svg b/.claude/skills/logo-design/assets/library/svg/youtube-icon.svg new file mode 100644 index 0000000..b0602b6 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/youtube-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/youtube.svg b/.claude/skills/logo-design/assets/library/svg/youtube.svg new file mode 100644 index 0000000..b995211 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/youtube.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zapier-icon.svg b/.claude/skills/logo-design/assets/library/svg/zapier-icon.svg new file mode 100644 index 0000000..4f116a2 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zapier-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zapier.svg b/.claude/skills/logo-design/assets/library/svg/zapier.svg new file mode 100644 index 0000000..17f9f64 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zapier.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zend-framework.svg b/.claude/skills/logo-design/assets/library/svg/zend-framework.svg new file mode 100644 index 0000000..941c37d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zend-framework.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zendesk-icon.svg b/.claude/skills/logo-design/assets/library/svg/zendesk-icon.svg new file mode 100644 index 0000000..79eac75 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zendesk-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zendesk.svg b/.claude/skills/logo-design/assets/library/svg/zendesk.svg new file mode 100644 index 0000000..ab7beb7 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zendesk.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zenhub-icon.svg b/.claude/skills/logo-design/assets/library/svg/zenhub-icon.svg new file mode 100644 index 0000000..4071a19 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zenhub-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zenhub.svg b/.claude/skills/logo-design/assets/library/svg/zenhub.svg new file mode 100644 index 0000000..16211d3 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zenhub.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zeplin.svg b/.claude/skills/logo-design/assets/library/svg/zeplin.svg new file mode 100644 index 0000000..8362590 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zeplin.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zoho.svg b/.claude/skills/logo-design/assets/library/svg/zoho.svg new file mode 100644 index 0000000..5091c9a --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zoho.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zorin-os.svg b/.claude/skills/logo-design/assets/library/svg/zorin-os.svg new file mode 100644 index 0000000..2652b4c --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zorin-os.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zube.svg b/.claude/skills/logo-design/assets/library/svg/zube.svg new file mode 100644 index 0000000..090b80b --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zube.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zulip-icon.svg b/.claude/skills/logo-design/assets/library/svg/zulip-icon.svg new file mode 100644 index 0000000..f63aa9d --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zulip-icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zulip.svg b/.claude/skills/logo-design/assets/library/svg/zulip.svg new file mode 100644 index 0000000..7083060 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zulip.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/assets/library/svg/zwave.svg b/.claude/skills/logo-design/assets/library/svg/zwave.svg new file mode 100644 index 0000000..951fbc8 --- /dev/null +++ b/.claude/skills/logo-design/assets/library/svg/zwave.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.claude/skills/logo-design/references/color.md b/.claude/skills/logo-design/references/color.md new file mode 100644 index 0000000..0f7a4a5 --- /dev/null +++ b/.claude/skills/logo-design/references/color.md @@ -0,0 +1,142 @@ +# Colour + +Colour is the second memory hook after shape, the most basic form of non-verbal communication, and one of +the few things a brand can truly *own*. But it is secondary to form: design in black first, add colour after +the concept is chosen. + +## Contents +1. Order of operations +2. Associations (and their limits) +3. Owning a colour +4. Harmony systems +5. How many colours? +6. Practical reproduction (RGB, CMYK, Pantone, HEX) +7. Accessibility and contrast +8. Library data +9. Palette specification template + +--- + +## 1. Order of operations + +1. **Design in black and white.** A mark that only works because of its colours is not yet a mark. Monochrome + exposes form problems and forces the concept to stand on shape. +2. **Present concepts in greyscale first** so reactions are about the idea, not about a colour someone dislikes. +3. **Choose colour after the direction is selected** — research competitor colours and deliberately avoid their + palette unless there is a strategic reason. +4. **Specify every version**: full colour, one colour, black, white/reversed, and on the primary brand colour. + +## 2. Associations (and their limits) + +Common Western associations — useful as a starting vocabulary, never as a rule: + +| Colour | Frequently associated with | Watch out for | +|---|---|---| +| Red | energy, passion, boldness, urgency, appetite, leadership | danger, debt/loss (finance), aggression | +| Orange | friendliness, enthusiasm, playfulness, affordability, confidence | cheapness if overused; low contrast on white | +| Yellow | optimism, warmth, attention, originality, cheer | illegible on white; caution/warning | +| Green | growth, health, nature, balance, renewal, money (US) | "eco" cliché; hard in process print when vivid | +| Blue | trust, stability, calm, integrity, technology, loyalty | the default of tech, finance and healthcare — hard to stand out | +| Purple | creativity, imagination, wisdom, luxury, individuality | can feel immature or mystical | +| Pink | care, playfulness, youth, sweetness, boldness (hot pinks) | gender stereotypes | +| Black / grey | authority, sophistication, neutrality, strength, mystery | can feel cold, heavy or generic | +| White | purity, simplicity, space | mourning in parts of East Asia | +| Brown / earth | craft, reliability, warmth, organic | dullness; "you can't build equity in beige" | + +- **Culture changes meaning.** White is purity in much of Europe and mourning in parts of East Asia; red is luck and + celebration in China, danger in signage, and taboo for losses in financial reporting; green has religious + significance in some regions. Check the audience's cultures. +- **Learned conventions**: red = stop, green = go, blue links on screens, yellow/black = hazard. Use knowingly. +- **Personal memory** attaches emotions to colours unpredictably — another reason to anchor decisions in strategy, + not taste. +- **Demographic tendencies** (e.g. children's brands trending colourful and saturated) are only tendencies; a brand + strategy can deliberately contradict them. + +## 3. Owning a colour + +- Owning a colour is one of the highest priorities of an identity — a signature colour, used consistently across + every touchpoint, becomes recognisable even without the mark. +- **Subverting category norms makes a colour proprietary.** When every competitor is blue, a red, orange or green + brand is instantly distinguishable. A colour swap experiment makes the point: put a competitor's colours on a + famous logo and it immediately feels like a different company. +- Keep existing colour equity during redesigns unless there is a strong reason to drop it — colour is often what the + public remembers most. +- Pair a signature colour with a neutral (black, white, a dark tone) to give it room. + +## 4. Harmony systems + +Use the colour wheel as a generator, then refine by eye: +- **Complementary** — opposites (red/green, blue/orange, yellow/purple). High contrast, energetic; familiar, can feel + obvious. Shift hues slightly off the exact complement for sophistication. +- **Split-complementary** — a base plus the two neighbours of its complement. Contrast with less tension. +- **Analogous** — neighbours on the wheel. Calm, cohesive; needs value contrast to stay legible. +- **Triadic / tetradic** — rotate a triangle or rectangle on the wheel; vivid, playful, good for multi-colour + systems. Balance by letting one colour dominate. +- **Monochromatic** — one hue in several tints/shades. Elegant; relies on value contrast. +- Think in **hue, saturation, value**: most palette problems are value problems (two colours of similar lightness + blur together, especially in greyscale or for colour-blind viewers). + +## 5. How many colours? + +- The fewer the colours, the stronger the recall and the easier the reproduction. One or two colours is the sweet + spot for most marks; three is common; beyond four, colours must be justified by concept (e.g. a multi-product or + "diversity" story) and the mark must still work in one colour. +- Multi-colour marks: give each colour a role (segments of an idea, a sequence, a hierarchy), keep saturation and + value families consistent, and provide a single-colour fallback. +- Secondary palette: 3–5 complementary colours for the wider identity, used sparingly (accents often ≈ 5–10 % of a + layout) so the primary stays dominant. + +## 6. Practical reproduction + +- **Specify all four systems** for every brand colour: HEX (web), RGB (screen), CMYK (process print), and a Pantone + / spot equivalent for premium print. Whole-number CMYK percentages are cleaner to hand to printers. +- **RGB ≠ print.** Neon, saturated greens, electric blues and bright oranges can fall outside the CMYK gamut and print + dull. Check the CMYK conversion early; choose a spot colour if the signature colour must be vivid on paper. +- **Gradients**: see `visual-techniques.md` — keep a flat master. +- **Materials**: embroidery thread, vinyl, enamel, neon, laser-etched metal each shift colour; one-colour and + two-colour versions keep production affordable (screen printing charges per colour). +- **Dark mode / dark backgrounds**: the brand colour may need a lighter tint to keep contrast on dark UI; specify it. + +## 7. Accessibility and contrast + +- Test colour pairs for contrast. For logos, WCAG does not strictly apply, but any text within the lockup (and taglines) + should aim for at least **3 : 1** against its background; body-size text needs 4.5 : 1. +- Don't encode meaning in colour alone (red vs green segments may be indistinguishable to ~8 % of men). Check a + greyscale version: segments should still separate by value. +- Yellow, light cyan and pale pastels on white fail contrast; give them a dark companion or a dark version. + +## 8. Library data (1,400+ real-world logos) + +The bundled library skews heavily to technology brands, so treat these as *category conventions to be aware of*, +not recommendations: + +- **Colour count** (counting black/white when used): 1 colour ≈ 33 %, 2 colours ≈ 25 %, 3 colours ≈ 17 % — + **≈ 75 % of logos use three colours or fewer**. Among standalone icons, **≈ 47 % are a single colour** and + **≈ 82 % use three or fewer**. +- **Gradients** appear in ≈ 19 % of files — a minority, and mostly in digital-native brands. +- **Dominant single hue** among single-hue marks: blue is by far the most common (≈ 22 % of all logos), then red + (≈ 13 %) and black/grey monochrome (≈ 13 %); green, orange, cyan and purple follow at 4–7 % each; yellow and pink + are rare (≈ 2 % and ≈ 1 %). ≈ 28 % of logos are multi-hued. +- **Implication**: in tech, blue is the camouflage colour. A non-blue signature colour is an easy win for + distinction; if blue is strategically necessary, differentiate by hue shift (ultramarine, teal, periwinkle), + pairing, or form. + +Explore by colour: `python3 scripts/search_library.py --color orange --type pictorial --format table`. + +## 9. Palette specification template + +```markdown +### Primary +| Name | HEX | RGB | CMYK | Pantone (approx.) | Use | +|---|---|---|---|---|---| +| Harbor Teal | #0F7C80 | 15 124 128 | 88 23 44 5 | 7714 C | Logo, key UI, headings | +| Ink | #14212B | 20 33 43 | 83 67 49 64 | Black 7 C | Type, one-colour logo | + +### Secondary (≈ 10–20 % of any layout) +| Sand | #F2E6D0 | … | Backgrounds | +| Signal Coral | #FF6B4A | … | Accents, calls to action (sparingly) | + +### Logo colour versions +Full colour on white · Reversed (white) on Harbor Teal / Ink · One-colour Ink · One-colour white +``` +(Pantone matches are approximations — verify against a physical guide before print production.) diff --git a/.claude/skills/logo-design/references/critique.md b/.claude/skills/logo-design/references/critique.md new file mode 100644 index 0000000..b1f9f41 --- /dev/null +++ b/.claude/skills/logo-design/references/critique.md @@ -0,0 +1,66 @@ +# Critiquing a Logo + +Use when the user asks for feedback on a logo (theirs or anyone's), wants to compare options, or needs a diagnosis +before a redesign. Be specific, kind and useful: name what works, what doesn't, why, and exactly how to fix it. + +## Method + +1. **Understand the context first** — what the organisation does, for whom, what it should feel like. A logo can only + be judged against its purpose. If unknown, ask one question or state assumptions. +2. **First impression (2 seconds)** — what do you see, feel, and remember? What would a stranger call it? +3. **Technical pass** — if an SVG is available, run `scripts/svg_audit.py` and `scripts/preview_sheet.py`, then look at + the preview. For a raster image, reason visually about the same checks. +4. **Principles pass** — score each dimension below 1–5 with one-line evidence. +5. **Prioritise** — the 3 changes with the biggest impact, most important first. Make each actionable. +6. **Optionally demonstrate** — sketch the fix as an SVG revision when the user wants it. + +## Scorecard + +| Dimension | Question | Score (1–5) | Evidence | +|---|---|---|---| +| Idea | Is there one clear, relevant idea? Can it be said in a sentence? | | | +| Simplicity | Is anything unnecessary? Does it survive 16 px and a squint? | | | +| Distinction | Does it stand apart from competitors and famous marks? | | | +| Memorability | Is there one defining feature you'd recall tomorrow? | | | +| Relevance / tone | Does its character (shape, weight, colour, type) match the brand? | | | +| Craft | Clean geometry, optical corrections, consistent weights, good spacing/kerning? | | | +| Versatility | One colour, reversed, small, large, embroidery, app icon, lockups? | | | +| Longevity | Conceptual rather than trendy? Will it date soon? | | | +| Colour | Few, purposeful, ownable, accessible, reproducible? | | | +| Typography | Appropriate, customised, legible, well spaced, ≤ 2 families? | | | + +Total /50 is a rough guide only; one fatal flaw (illegible at small size, looks like a competitor, offensive reading) +outweighs a high total. + +## Common diagnoses and fixes + +| Symptom | Likely cause | Fix | +|---|---|---| +| Turns to mush at small sizes | Too many elements, thin lines, small gaps | Remove details, thicken strokes, open gaps; make a small-size version | +| Looks generic / like a template | Stock typeface, cliché symbol (globe, swoosh, lightbulb) | Customise letters, find an ownable twist, derive the idea from the name or promise | +| Looks dated | Effects (gradients, bevels, shadows), trendy fonts | Flatten, simplify, choose a more timeless type direction | +| Busy | Two or three ideas competing | Pick one idea; move the others into the identity system | +| Symbol and type feel unrelated | Different geometry/weight logic | Share radii, stroke weights, angles; rebalance sizes | +| Feels unstable | Accidental tilt, top-heavy mass | Widen the base, correct axes, check optical centre | +| Circle looks small next to letters | Missing overshoot | Enlarge round forms 1–3 % | +| Rounded rectangle looks pinched | Bone effect | Smooth curvature transitions | +| Reversed version looks bold | Irradiation | Thin the white version slightly | +| Fails on photos | No graphic device | Add an outline/container version | +| Hidden meaning nobody sees | Too subtle or too complex | Make it a bonus, not the point — or simplify until it reads | +| Unfortunate reading | Designer blindness after long exposure | Change the offending shape; test with fresh eyes | + +## Output format + +```markdown +## Logo critique — +**First impression:** <1–2 sentences> +**What works:** <2–3 bullets> +**Scorecard:** +**Top 3 changes (in priority order):** +1. — why, and how (specific: "open the counter of the e from 6 to 12 units") +2. … +3. … +**Optional next step:** +``` + +Tone: critique the work, never the person. Balance honesty with encouragement; the goal is a better mark. diff --git a/.claude/skills/logo-design/references/discovery-brief.md b/.claude/skills/logo-design/references/discovery-brief.md new file mode 100644 index 0000000..7450914 --- /dev/null +++ b/.claude/skills/logo-design/references/discovery-brief.md @@ -0,0 +1,187 @@ +# Discovery & the Design Brief + +Design is a strategic response to a business need, not decoration. Without clarity about the need, the work +lacks direction no matter how beautiful it is. This file covers how to gather that clarity quickly and turn it +into a brief that anchors every later decision. + +## Contents +1. Why discovery first +2. The fast path (when the user wants speed) +3. The full question bank +4. Research you do yourself +5. From answers to a brief (template) +6. Word mapping — turning language into symbols +7. Warning signs in a brief + +--- + +## 1. Why discovery first + +- Uncover and define the problem before attempting to solve it visually. Rushing into drawing raises the odds + of missing the mark, and a missed mark is expensive for everyone. +- The brief is a *contract of clarity*: a shared, written record of what success looks like. When + disagreements come (they will), return to the brief instead of arguing taste. That doesn't mean never + adjusting — it means adjustments are purposeful, not arbitrary. +- A strong brief doesn't constrain creativity; it channels it. +- The designer is hired as the expert who guides, creates and solves — not as a technician executing a + pre-drawn idea. If a client already has the exact design in mind, clarify the relationship early and honestly. + +--- + +## 2. The fast path (when the user wants speed) + +Ask **at most five** questions in one message, then proceed. If the user can't or won't answer, infer sensible +answers, **state your assumptions explicitly**, and continue — you can revise after they react to concepts. + +1. **Name & what you do** — exact spelling/casing of the name, one-line description, and any tagline. +2. **Audience** — who must notice and trust this (age, profession, mindset)? Where will they meet the logo? +3. **Three to five adjectives** the brand should feel like (e.g. calm, precise, rebellious, warm, premium). + Adjectives are the single most useful input for concepting. +4. **Competitors or look-alikes to avoid** — and any marks the user admires (and why). +5. **Constraints** — colours to keep/avoid, existing equity to preserve, where it must work (app icon, + embroidery, signage, favicon), deadline for decisions. + +Optional sixth when relevant: *Who makes the final decision?* (Always know who signs off.) + +--- + +## 3. The full question bank + +Use for substantial projects. Every business is different — adapt, don't recite. Allow time for answers; +off-topic remarks often open new avenues, but keep the conversation focused on outcomes. + +### The essential four +- Who are you? +- Who needs to know? +- How will they find out? +- Why should they care? + +### The business +- **Positioning** — compared with alternatives, where do you sit? What is your price point? How big is the + business and where is it heading (projected scale gives context for positioning)? +- **Purpose & mission** — beyond the economics, why is this worth doing? +- **Composition** — how is the organisation structured (parent/sub-brands, divisions, products)? +- **Culture** — what shared behaviours best express the mission? +- **Personality** — what style and manner? If the brand were a person, how would they speak and dress? +- **Goals** — five key goals over the next year / five years. +- **Growth** — where are the biggest opportunities for the business and its image? +- **Promises** — what does the organisation promise its audiences? (Promises synthesise what it stands for.) + +### The audience +- **Current audience** — who, where, when, why? +- **Desired audience** — a different or wider group? Demographics (age, gender, nationality, profession) + and psychographics (values, lifestyle). +- **Current perception** — how does the audience see the brand today? +- **Desired perception** — how should they see it? +- **Desired response** — what should they feel, think or do after encountering the brand? + +### The competition +- Who are the main competitors? How are you different? What visual cues, colours and typefaces dominate the + category? What marketing is gaining traction? + +### The project +- What are the goals for the new identity? What specific deliverables are needed? +- Why now? What's motivating the project and driving the timeline? +- Who is involved, with what roles? Any outside agencies or partners? +- What concerns or obstacles do you anticipate? Anything in the culture, structure or past experiences that + could make this easier or harder? +- Budget range? Are other designers being considered, and when will a decision be made? +- **Who makes the final decision?** Involve that person when presenting. +- Existing equity: current logo, colours, symbols people already recognise? What must survive a redesign? +- Applications: where will it appear first — and where might it appear in five years? Any production + constraints (embossing dies, embroidery, laser etching, signage regulations, single-colour printing)? +- Naming: is the name final? Is there a shorter name people already use? (A nickname the public already + uses can be a stronger communicative name than the legal one.) + +### After gathering answers, ask yourself +- What are the client's real concerns? +- What does the organisation want to emphasise? +- What is it *really* selling? (A tap sells convenience and kitchen pride; a gym sells confidence.) +- How does it want to be perceived in the market? Stylish identities win awards; relevant ones win market share. + +--- + +## 4. Research you do yourself + +- **The organisation's history**, its current identity, past identity efforts and how they shaped perception. + Previous logos often reveal useful patterns or pitfalls. +- **The competitive landscape**: collect competitor marks, note colours, shapes, type, and what they all share. + Map them (e.g. on axes like *traditional ↔ modern*, *playful ↔ serious*) to find open territory. +- **Category conventions** via the bundled library. Examples: + ```bash + python3 scripts/search_library.py --industry payments-fintech --format table + python3 scripts/search_library.py --subject shield --format table + python3 scripts/search_library.py --industry database-data --summary + ``` + `--summary` shows the dominant mark types, colours and techniques in a category — i.e. what to avoid + repeating and what cues signal "belonging". +- **Cultural checks**: meanings of candidate colours, symbols and gestures in the audience's cultures; + whether a symbol is sacred or owned by a community. +- **Name mechanics**: letter shapes (which letters have rich structure for a monogram — `a`, `s`, `w`, `g`, `k` + combine well; `i`, `l` offer little), ligature opportunities, symmetry, how the word sounds spoken. + +--- + +## 5. From answers to a brief (template) + +Write this before designing and show it to the user. Keep it short, jargon-free and specific — designers +must be editors too. + +```markdown +## Design brief — + +**Summary**: +**Audience**: +**Brand adjectives**: <3–5 words> **Avoid feeling**: <2–3 words> +**Promise / big idea**: +**Competitive landscape**: +**Mark type hypothesis**: (see mark-types.md) +**Must work on**: +**Constraints**: +**Success criteria**: +**Decision-maker**: **Deliverables**: +**Assumptions I made**: +``` + +--- + +## 6. Word mapping — turning language into symbols + +Good designers translate language into symbols. A word map bridges strategy and form. + +1. Write the core words: the name, the offering, the adjectives, the promise. +2. Branch from each word into **nouns** (things you can draw), then into associations, metaphors, opposites, + sounds, places, materials, processes, historical references. +3. Circle the intersections — where two branches meet is where distinctive ideas live (e.g. "trust" → shield; + name begins with T → a T that is also a shield; the name's meaning is a woodworking joint → precise fit). +4. Turn the best 6–10 intersections into one-sentence concept statements before drawing anything. + +Example (abridged): +``` +Brand: "Harbor" — a savings app. Adjectives: safe, calm, patient. + harbor → boat, anchor, lighthouse, breakwater, shelter, bay-shape, tide + safe → shield, lock, nest, roof, cupped hands, enclosure + calm → horizon line, still water, circle, slow wave + patient→ growth rings, stacking, tide rising, sunrise +Intersections: + • An "H" whose crossbar is a calm horizon/water line + • Stacked horizontal waves forming a rising bar chart (tide = growth) + • A bay-shaped enclosure (negative space) that shelters a coin +``` + +If neither the name nor the activity offers visual clues, use abstract keywords that do translate to form: +*connection, speed, unity, network, care, stability, balance, growth, openness, precision*. + +--- + +## 7. Warning signs in a brief + +- **"Total creative freedom."** Usually means the client has no vision and expects the designer to supply one + — which takes many more rounds. Ask for stylistic references (marks they like/dislike and why) to calibrate. +- **"It should show everything we do."** Explain *identify, don't explain*; offer a system (icons, imagery, + copy) to carry the detail instead of the mark. +- **"Make it pop / modern / clean."** Ask what those words mean to them; show references. +- **No decision-maker identified.** Presentations to the wrong person get re-litigated later. +- **The real problem isn't the logo.** If the product, service or message is broken, say so; a logo won't fix it. +- **Design by committee.** Plan to present to the smallest group that includes the decision-maker; many voices + produce an illusion of consensus and averaged, forgettable marks. See `presentation-delivery.md`. diff --git a/.claude/skills/logo-design/references/identity-system.md b/.claude/skills/logo-design/references/identity-system.md new file mode 100644 index 0000000..4179d3b --- /dev/null +++ b/.claude/skills/logo-design/references/identity-system.md @@ -0,0 +1,146 @@ +# From Logo to Identity System + +A logo is the foundation; the identity system is the framing built on it. The audience never meets a logo in a +void — always on a card, a van, a screen, a building, next to photography and words. Read this when the user needs +more than a mark: a kit of parts, sub-brands, patterns, a dynamic identity, motion, or guidelines. + +## Contents +1. Principles of a system +2. The kit of parts (checklist) +3. Logo systems and sub-brands +4. Static vs. changeable (dynamic) identities +5. Patterns and graphic devices +6. Motion and sound +7. Standards manual / brand guidelines +8. Rollout and stewardship + +--- + +## 1. Principles of a system + +- **Consistency of concept** — every element (visual and verbal) identifies the organisation to its audiences. + Consistency is central to branding; it doesn't preclude creativity. A predictable, lifeless system fails; power, + clarity and freshness must accompany consistency. +- **Clarity of message** — every element supports the logo and the intended perception; nothing competes with it. +- **Derived, not duplicated** — the system grows *from* the mark (its angles, radii, colours, a fragment) but + complements rather than copies it. +- **Accommodate the user** — understand who will use the system (in-house designers, agencies, printers, franchisees, + developers) and how; make it customisable within constraints. +- **Flexibility** — other creatives will use it; plan enough variables to keep it fresh, and make it damage-proof so + imperfect use still looks on-brand. At some point the original designer must let go; good rules make that safe. + +## 2. The kit of parts (checklist) + +**Logo & variations** +- Primary mark/signature (symbol + wordmark) and variations: horizontal, stacked, symbol-only, wordmark-only. +- Size variants: a simplified small-size version; redrawn details for very large use if needed. +- Media variants: e.g. heavier line weights for broadcast/screen, single-colour for embroidery. +- Brand extensions and product logos; relationship with partner or trademark symbols. + +**Colour palettes** +- Primary colour(s) and acceptable alternatives; black/white usage; can it be reversed, or reversed only out of a + containing shape? Exact Pantone, CMYK, RGB, HEX values. Secondary/accent palette. + +**Typography** +- Primary and secondary families, weights, italics; web/app fallbacks; rules for headlines vs body. + +**Taglines and modifying copy** +- Primary and alternative taglines, typeface, size ratio to the logo, legal lines, ™/® usage. + +**Imagery** +- Photography/illustration style, when and how used, ratio and proximity to the logo, image library access. + +**Containing shapes / graphic devices** +- Is the logo ever placed in a shape? Always or only in some contexts? Does the shape change? Can it hold other + content? + +**Patterns, icons, textures** +- Brand pattern(s), icon set built on the logo's geometry, supporting graphic elements. + +**Motion and sound** (screen, broadcast, product) +- How the logo moves and resolves; how it interacts with other elements; sonic signature if relevant. + +**Voice** +- Editorial tone — part of the identity even though it isn't visual. + +## 3. Logo systems and sub-brands + +- **Branded house**: one master mark; sub-brands expressed by descriptor text, colour, or a consistent modifier. + Maximum equity transfer, least flexibility. +- **Endorsed brands**: each sub-brand has its own mark with a visible link to the parent ("by Parent"), or shares a + structural element (frame, typeface, icon grid). +- **House of brands**: independent marks; the parent is invisible to consumers. +- Decide on hierarchy deliberately: is association with the parent an advantage or a liability for the product? + If association would position the product badly, that's a strategy problem to solve before any design. +- Keep repeated elements truly consistent (same typeface, same symbol proportions, same spacing rules); vary one + dimension at a time (colour *or* icon *or* descriptor). + +## 4. Static vs. changeable (dynamic) identities + +- A logo must provide a cohesive voice, but it need not be immutable. Screen media expects logos to move, react and + sometimes change. Someone will make it spin — better that the designer defines how. +- Dynamic identity patterns: + - **Fixed frame, changing content** — a container or grid that holds changing images, colours or patterns. + - **Fixed type, changing symbol** — consistent letterforms and colour; the accompanying shape varies per + application. + - **Approved sets** — e.g. a square of colour from 12 approved colours with the name set in one of 12 approved + typefaces; users combine freely within the sets. + - **Generative** — a rule (data, date, location, user input) that produces variants. + - **Many logos, one voice** — several marks used discreetly for sophisticated audiences who are weary of loud + branding; recognition comes from consistent attitude rather than one symbol. +- Whatever changes, keep at least two anchors constant (e.g. name typography + colour, or frame + position). +- The action of the logo must reinforce the concept; motion for its own sake dilutes it. + +## 5. Patterns and graphic devices + +- A pattern is often the most important branding element after the logo. It must complement the mark without + duplicating it and work from a business card to an aircraft, in signage and interiors. +- Build from components of the mark when possible (a fragment, the construction grid, the key angle); if the mark + offers nothing, develop a new visual language on par with or deliberately contrasting the logo. +- Grid choice drives character: square (versatile, common), triangular, hexagonal, rotated; see + `visual-techniques.md` §13. +- Graphic devices (containers, outlines, bands, frames) solve visibility on busy backgrounds and create recognisable + layouts; keep their proportions in sync with the logo's. + +## 6. Motion and sound + +- Define: entrance (how it builds), resolve (final static state, which must equal the master), exit, loop; duration + (logo stings are typically 1–3 s); easing character matching the brand (snappy vs. gentle). +- Build motion from the logo's construction (strokes drawing on, modules assembling, a rotation that reveals a + negative shape). +- Sound signature for broadcast/apps: short, ownable, consistent; specify when it plays. + +## 7. Standards manual / brand guidelines + +Useful to the widest group of users (in-house designers, agencies, PR, marketing, printers, signage fabricators, +packaging, vehicle and uniform suppliers, purchasing). Written in plain language for non-designers. Prefer friendly +rules and more "do"s than "don't"s. + +**Suggested anatomy** (scale down for a start-up; a one-page sheet can be enough): +1. **Introduction** — a short letter from leadership (drives buy-in), the brand idea, how to use the manual. +2. **Logo** — the mark and its rationale; versions and lockups; construction; **clear space** (defined by an element + of the logo, e.g. the height of the symbol's dot or the cap height, so it scales — never a fixed distance); + **minimum sizes** (px and mm); placement; logo on backgrounds (black on white, white on black, colour, photo); + **misuse** examples (stretching, recolouring, rotating, adding effects, rearranging lockups, outlining, placing on + busy backgrounds without a device). +3. **Colour** — primary and secondary palettes with all colour codes; proportions; approved logo/background pairs. +4. **Typography** — families, hierarchy, spacing; kerning of the wordmark at large sizes if relevant. +5. **Imagery, iconography, patterns, graphic devices** — rules and examples. +6. **Grids and layouts** — margins and gutters chosen deliberately (square-ish modules are the most versatile). +7. **Applications** — stationery (business cards: clean front with name, title, contact; pattern or colour on the back; + letterhead: nothing printed on the back), digital (web, social avatars, email signatures), signage, vehicles, + uniforms, packaging, advertising, merchandise. +8. **Motion and sound** if relevant. +9. **Contacts and files** — who to ask, where the master files live. + +Template for a compact guideline: `templates/brand-guidelines-template.md`. + +## 8. Rollout and stewardship + +- **Rollout**: plan the order of applications (digital first is cheap; signage and vehicles are expensive), supervise + early production (printing, fabrication), and coordinate with in-house teams and outside agencies. +- **Asset management**: one source of truth for master files, named clearly, accessible to all users. +- **Audit periodically** (monthly → quarterly → yearly after launch): review materials for consistency, production + quality and supplier compliance; interview users about friction; adapt the system to new needs; track changes in + the competitive landscape; report findings and celebrate good applications. A system that is never reviewed + decays within a year. diff --git a/.claude/skills/logo-design/references/library-guide.md b/.claude/skills/logo-design/references/library-guide.md new file mode 100644 index 0000000..7789e34 --- /dev/null +++ b/.claude/skills/logo-design/references/library-guide.md @@ -0,0 +1,164 @@ +# The Reference Library — Guide & Insights + +The skill ships with **1,400+ real-world SVG logos** (≈1,200 brands; 233 brands include both a full lockup and a +standalone `-icon` symbol), each visually classified by mark type, technique, geometry, subject, typography, mood and +industry. Use it to learn *how* marks are built and to see what a category already looks like. + +> **The logos are trademarks of their respective owners.** They are included only as study material. +> Never copy, trace or lightly modify them for a client. If your concept resembles one, change it. + +## Contents +1. What's inside & where +2. How to use it well +3. Data-driven insights +4. Curated lessons by technique (with example files) +5. Catalog schema & extending the library + +--- + +## 1. What's inside & where + +``` +assets/library/ + svg/ 1,400+ logo files (brand.svg = full logo, brand-icon.svg = standalone symbol) + catalog.json one record per file: structure + colours + complexity + visual classification + classifications.json the visual labels (source of truth for mark_type, techniques, subject, …) + stats.json distributions used by svg_audit.py (anchors, colours, types …) + gallery.html filterable visual browser for humans — open locally in a browser +``` +The collection skews heavily to technology brands (developer tools 21 %, frameworks/libraries 17 %, cloud 7 %, +databases 6 %, testing/monitoring 6 %…). Keep that bias in mind: its conventions are *tech* conventions. +Categories such as food & drink, fashion, hospitality, health or public services are barely represented: for those, +use `--subject`/`--query` to find marks that share a subject or technique (cups, leaves, arches, letter K…), build +the shelf test from hand-picked files with `preview_sheet.py --refs …`, and rely on your own knowledge of the +category's conventions. + +## 2. How to use it well + +- **Study a technique before using it**: pull 5–8 exemplary files and *read the SVG* to see how the geometry is + built (how few anchors, which primitives, how negative space is cut): + `python3 scripts/search_library.py --technique negative-space --exemplary --format paths` +- **Map a category's conventions** before designing, then decide where to conform and where to depart: + `python3 scripts/search_library.py --industry security-identity --summary` +- **Check your idea isn't already taken**: `python3 scripts/search_library.py --subject "rocket"` +- **Shelf test your concept** against real marks: + `python3 scripts/preview_sheet.py concept.svg --refs-industry developer-tools -o shelf.html` +- **Calibrate complexity**: `svg_audit.py` compares your anchor count and colour count with the library. +- For inspiration by feel: `--mood friendly`, `--mood technical`, `--type-style serif`, `--case lowercase`. + +Useful filters: `--type`, `--symbol-type`, `--technique`, `--geometry`, `--industry`, `--color`, `--primary-color`, +`--max-colors`, `--aspect`, `--variant icon`, `--type-style`, `--case`, `--mood`, `--subject`, `--query`, +`--exemplary`, `--no-gradient`, `--summary`, `--list-values`. + +## 3. Data-driven insights + +**Mark types (per file)** — abstract 23.5 %, combination 20.6 %, pictorial 20.2 %, letterform 15.2 %, wordmark 9.9 %, +emblem 3.8 %, mascot 3.8 %, lettermark 3.0 %. (Standalone icon files inflate symbol types.) +Inside combination marks, the symbol is abstract 43 %, pictorial 33 %, letterform 17 %, mascot 5 %. + +**Proportions** — 55 % of files are near-square (0.8–1.25 : 1). Of brands with both files, ~9 in 10 lockups are wide +(> 2.5 : 1) and ~3 in 4 icons are near-square: symbol + horizontal lockup is the standard pair. + +**Colour** — median 2 colours; ≈ 75 % use ≤ 3; ≈ 47 % of standalone icons are single-colour. Gradients in ≈ 19 % of +files. Dominant hue: blue ≈ 22 %, red ≈ 13 %, monochrome ≈ 13 %, multi-hue ≈ 28 %; yellow and pink are rare. +→ In tech, blue is camouflage; warm or unusual hues are an easy distinction win. + +**Geometry** — circle is the most common base (26 %), then organic (14 %), square (14 %), freeform (13 %), +triangle (8 %), hexagon (8 %; 10 % among developer/cloud/data brands — a category cliché), rounded square (7 %). + +**Techniques** — containment 32 %, negative space 20 %, monoline 17 %, colour segments 14 %, dimensional shading 10 %, +geometric construction 9 %, modular repetition 7.5 %, overlap/transparency 7 %, hidden meaning 7 %, isometric 6 %, +radial symmetry 6 %, letter substitution 3 %. +→ Containing a symbol in a circle/square is the most common move — useful for app icons, but also generic. Negative +space and hidden meaning appear in most of the strongest (exemplary) marks. + +**Typography (541 files containing type)** — geometric sans 49 %, custom/display 19 %, grotesque 13 %, humanist 8 %, +script 5 %, serif 3 %, slab 1 %, rounded 1 %. Case: lowercase 36 %, uppercase 32 %, title 20 %, mixed 13 %. +→ Lowercase geometric sans is the tech default; a serif, slab, humanist or truly custom wordmark stands out. + +**Complexity** — square symbols have a median of ~53 anchor points (p75 ≈ 96, p90 ≈ 194). The exemplary marks cluster +at the low end: great marks are built from few, deliberate points. + +**Mood labels** most used — technical, friendly, bold, modern, playful. "Friendly" is almost always carried by rounded +geometry and lowercase; "technical" by monoline, grids, brackets, isometric forms. + +## 4. Curated lessons by technique (with example files) + +Every file below is in `assets/library/svg/`. Read them as SVG to study construction. + +**Negative space** — figure and ground both carry meaning. +- `auth0-icon.svg` star carved from a shield · `apache-camel.svg` camel cut from a circle · `doctrine.svg` arrow cut + from a teardrop · `esdoc.svg` owl face entirely from negative space · `houndci.svg` dog profile in a square · + `npm-icon.svg` letter carved from a solid square · `khan_academy-icon.svg` sprout that reads as a person. + +**Hidden meaning / double reading** — one form, two ideas. +- `airbnb.svg` one loop = pin + heart + A · `amplitude-icon.svg` A = sound wave · `astro.svg` A = rocket · + `gnome-icon.svg` footprint = G · `spidermonkey-icon.svg` monkey = S · `kissmetrics.svg` heart + bar chart · + `botanalytics.svg` speech-bubble edge = chart line · `twitch.svg` speech bubble with eyes. + +**Letter substitution & custom wordmarks** — make a name ownable. +- `hubspot.svg` sprocket as the "o" · `fastly.svg` stopwatch in a letter · `tor.svg` onion as "o" · `sparkpost.svg` + flame for "O" · `mozilla.svg` URL syntax in the name · `100tb.svg` double zero as infinity · `adyen.svg` fully + custom squared letters · `nextjs.svg` extended X stroke · `go.svg` italic + speed lines · `stripe.svg` tight custom + lowercase. + +**Letterform symbols** — one letter, one idea. +- `kotlin-icon.svg` K from one triangular cut · `patreon.svg` P = bar + circle · `pagekit.svg` P from a notched square · + `gatsby.svg` G from circle + diagonal · `pinterest.svg` P as a pin · `zendesk-icon.svg` Z from triangles and + semicircles · `mesos.svg` M from triangles · `metabase.svg` M from a dot grid · `mobx.svg` `]v[` reads as M. + +**Geometric construction** — primitives, consistent radii, clean angles. +- `elm.svg` tangram square · `framer.svg` squares and triangles · `google-photos.svg` four half-circles · + `circleci.svg` notched ring · `vercel-icon.svg` a single triangle · `twitter.svg` bird from circle arcs · + `buck.svg` monoline deer from strict geometry · `tsuru.svg` origami crane · `figma.svg` modular circles. + +**Modular repetition & radial symmetry** +- `slack-icon.svg` rotated modules forming a hash · `dropbox.svg` five rhombi · `openai-icon.svg` one module rotated + six times · `cardano-icon.svg` graduated dots · `centos-icon.svg` pinwheel · `ibm.svg` stripes unifying letters · + `tidal-icon.svg` four diamonds · `ubuntu.svg` three figures in a ring. + +**Dimension with flat means** — depth without realism. +- `ethereum.svg` faceted octahedron · `sketch.svg` faceted gem · `codesandbox.svg` cube from cuts · `unity.svg` cube + from negative space · `webpack.svg` cube in cube · `tensorflow.svg` one form reads T and F · `laravel.svg` monoline + isometric L. + +**Overlap & colour segments** +- `mastercard.svg` two overlapping circles · `dreamhost.svg` crescent from two circles · `chrome.svg` three segments + + core · `google-icon.svg` segmented G · `lit-icon.svg` faceted flame · `playwright.svg` two masks. + +**Pictorial reduction** — objects reduced to their most characteristic silhouette. +- `apple.svg` · `redhat-icon.svg` · `couchbase.svg` · `docker-icon.svg` · `swift.svg` · `snowpack.svg` · + `stackoverflow-icon.svg` · `trello.svg` · `youtube-icon.svg` · `whatsapp.svg` · `gitlab.svg` (faceted animal). + +**Mascots done simply** +- `android-icon.svg` built from rounded primitives · `discord-icon.svg` controller = face · `github-icon.svg` strong + silhouette in a circle · `giantswarm.svg` terminal glyphs as eyes. + +**Emblems & containers** +- `markdown.svg` M + arrow in a frame · `jupyter.svg` orbits framing the name · `lua.svg` moon orbiting a planet. + +**Combination systems** +- `soundcloud.svg` cloud built from sound bars · `tableau.svg` plus-sign cluster echoed in the name · `aws.svg` smile + arrow under plain type · `arduino.svg` infinity loop holding − and + · `microsoft.svg` four squares. + +Get more: `python3 scripts/search_library.py --exemplary --type ` (141 files are flagged exemplary). + +## 5. Catalog schema & extending the library + +Each record in `catalog.json`: + +| Field | Meaning | +|---|---| +| `file`, `brand`, `variant` (`main`/`icon`), `pair` | identity of the file and its counterpart | +| `width`, `height`, `aspect`, `aspect_class` | canvas proportions | +| `bytes`, `shapes`, `anchors` | size and complexity | +| `colors`, `n_colors`, `color_families`, `primary_family`, `gradients`, `has_mask`, `has_filter` | colour data | +| `mark_type`, `symbol_type` | wordmark · lettermark · letterform · pictorial · abstract · mascot · emblem · combination | +| `subject` | what it depicts, in a few words | +| `geometry`, `techniques` | construction vocabulary (see `--list-values`) | +| `type_style`, `case` | typography, when present | +| `mood`, `industry`, `exemplary`, `note` | tone, sector, teaching flag and why | + +To add logos: place SVGs in `assets/library/svg/`, append classification objects with the same keys to +`classifications.json`, run `python3 scripts/build_catalog.py` (and `--check` to verify coverage). Only add marks you +have the right to redistribute for reference. diff --git a/.claude/skills/logo-design/references/mark-types.md b/.claude/skills/logo-design/references/mark-types.md new file mode 100644 index 0000000..3b8b75c --- /dev/null +++ b/.claude/skills/logo-design/references/mark-types.md @@ -0,0 +1,186 @@ +# Mark Types — What to Choose and When + +Choosing the type of mark is a strategic decision that comes before drawing. Each type has different +strengths, costs and failure modes. Library examples can be pulled with +`python3 scripts/search_library.py --type --exemplary --format paths`. + +## Contents +1. Overview table +2. Wordmark (logotype) +3. Lettermark / monogram +4. Letterform (single-letter symbol) +5. Pictorial mark +6. Abstract mark +7. Negative-space mark +8. Mascot / character +9. Emblem / badge +10. Combination mark & lockups +11. Pictograms, logo systems, dynamic marks, patterns +12. Decision guide + +--- + +## 1. Overview table + +| Type | What it is | Best when | Watch out for | +|---|---|---|---| +| Wordmark | Name set in distinctive type only | Name is short, distinctive, new (needs to be learned); limited media budget | Generic if type is stock; long names shrink badly | +| Lettermark / monogram | 2+ initials combined | Long or hard-to-say names; heritage/fashion/institutions | Woven initials carry little meaning; needs lots of exposure | +| Letterform | One initial as a symbol | App icons, tech, finance; need a compact avatar | Many brands share the same letter; needs a twist | +| Pictorial | Recognisable object/animal | Name or story has a vivid image; global/wordless recognition | Literalness; clichés; too much detail | +| Abstract | Non-representational form | Conceptual positioning (speed, connection); diversified companies | Meaningless without exposure/story | +| Negative space | Two silhouettes sharing an edge | A clever, conceptually linked pair exists | Hardest to do; forced results; ambiguity | +| Mascot | Character with personality | Family, food, games, community brands | Complexity, dating, poor small-size performance | +| Emblem | Type locked inside a badge/seal | Institutions, clubs, craft, heritage, sports | Illegible when small; inflexible | +| Combination | Symbol + wordmark lockup | Most new brands (symbol can later stand alone) | Two weak halves ≠ one strong mark | + +Library data point: of the 233 brands in the bundled library that ship both a full logo and a standalone +icon, about **9 in 10** full logos are wide horizontal lockups (aspect ratio above 2.5 : 1), while about +**3 in 4** icons are near-square (0.8–1.25 : 1). Designing the symbol and the lockup as a *pair* from day one +is the norm, not the exception. + +--- + +## 2. Wordmark (logotype) + +The brand name alone, in type with strong, defined character. + +- **Advantage**: sidesteps the recognition problem — the name is always visible, so there is no symbol to learn. +- **Disadvantage**: if not handled skilfully, it's generic and has little mnemonic value. +- **Make it ownable**: customise letterforms (cuts, joins, terminals, a distinctive `a`/`g`/`e`), build a ligature, + substitute one letter with a meaningful sign, hide a shape in the counters or between letters, adjust weight + contrast, or draw it from scratch. If using a neutral sans, some device (ligature, trick, hidden sign) is + necessary to make it memorable. +- **Extreme minimal wordmarks** — very clean, near-neutral type — can signal sophistication, useful in B2B and + premium sectors crowded by loud identities. +- **Case matters**: lowercase reads approachable and contemporary; uppercase reads stable, institutional, + monumental; title case reads conventional. Legibility depends on the typeface — test both. +- **Spoken sound**: letter rhythm should echo how the word sounds; a playful shift on the baseline can make + the viewer "hear" the word. +- **Length**: long names become thin, wide strips that shrink poorly — consider a stacked version or a + companion monogram/letterform for small sizes. + +## 3. Lettermark / monogram + +Two or more initials combined into one mark. + +- **Advantage**: solves long names and legibility in tight spaces (a quarter-page ad, an app icon). +- **Disadvantage**: generic initials treated in clever ways can look better on towels than on a business card; + woven initials have little inherent meaning and depend on large-scale exposure to be recognised. +- **Letter chemistry**: letters with rich structure (`a`, `s`, `w`, `g`, `k`, `R`, `M`, `W`) interlock in more + interesting ways; simple letters (`i`, `l`, `I`) offer little. Look for shared strokes, mirrored shapes, + and counters that can nest. +- **Numbers pair well** with letters when the name includes one (a `D` and a `4` share curves and diagonals). +- Traditionally strong in fashion, luxury, publishing, institutions — where a person's or house's name is the brand. + +## 4. Letterform (single-letter symbol) + +One initial treated as a symbol that conceptually, stylistically or metaphorically carries the brand. + +- Carries less information than pictorial marks, so it's more neutral and often more timeless. Favoured by + finance and technology. +- Many brands share the same initial — the concept must live in the *treatment*: a letter that is also an arrow, + a path, a fold, a spark, a bracket, a container, a person. +- Excellent as app icon / favicon / avatar; pair with a wordmark for the full lockup. + +## 5. Pictorial mark + +A meaningful, recognisable icon — object, animal, plant — as the primary identifier. + +- The most widespread and one of the most effective forms; ideally recognisable **without** the name. +- Can depict the brand directly (name = object) or metaphorically (an animal's qualities = brand's qualities). +- Because the image is visually dense and characterful, pair it with **neutral typography** to create contrast + and avoid overload. +- Work in silhouette first: an object's most characteristic view (front view of an apple, side view of a bird) + is the one that can't be mistaken for anything else. +- Reduce to geometry: a leaf is two quarter circles; a bird is a few arcs. Geometric reduction is what makes + pictorial marks feel designed rather than clip-art. + +## 6. Abstract mark + +A form that represents an idea in a suggestive, subjective way — a phenomenon rather than an object. + +- Useful when the business is diversified, the name gives no visual clue, or the brand wants a conceptual, + ownable shape. +- Some phenomena map naturally to form (connection → linking shapes; speed → tapering sweep; growth → + ascending/expanding forms; openness → broken circle). Others ("reliability", "quality") have no natural sign, + so meaning is assigned through story and repetition. +- An abstract mark is only meaningful after heavy exposure. It works for organisations with the reach to teach + it; it's risky for a small business with little media presence. +- Avoid unintended connotations (political, ethnic, religious, sexual) — broad institutions especially need + marks with no negative associations. + +## 7. Negative-space mark + +Uses the surrounding space as part of the concept: figure and ground both carry meaning. + +- The strongest versions merge **two strongly recognisable silhouettes that are conceptually related** — one + positive, one negative — so the whole becomes more than its parts (a Gestalt effect). +- They are rare and arguably the hardest marks to create; only simple elements with distinctive silhouettes + combine cleanly. +- Also usable at smaller scale: an arrow hidden between two letters, a shape formed inside a counter. +- Check readability both ways: some people see only one figure. The hidden figure should be a bonus, not a + requirement for understanding. +- In SVG, build with `fill-rule="evenodd"` or subtracted compound paths (see `svg-construction.md`). + +## 8. Mascot / character + +A character with a face and personality. + +- Creates warmth and story; strong for food, family, games, community and education brands. +- Risks: detail, dating, and poor performance at small sizes. Provide a simplified head/icon version. +- Keep the construction geometric and the expression clear at a distance; test at 24 px. + +## 9. Emblem / badge + +Text integrated inside a seal, crest, shield or enclosure — the parts cannot be separated. + +- Conveys tradition, authority, membership, craft. Common for universities, sports clubs, breweries, public bodies. +- Loses legibility quickly at small sizes; plan a simplified inner symbol for favicons and avatars. +- Containment also solves practical problems: a box behind a wordmark can give presence in cluttered + environments. + +## 10. Combination mark & lockups + +A symbol and a wordmark designed to work together and, eventually, apart. + +- The most common and flexible solution. Over time a well-exposed symbol can stand alone. +- The symbol and type should share DNA (stroke weight, corner radius, angles, x-height relationships) without + duplicating each other. Ornate symbol → plain type; bold symbol → lighter type; aim for complement, not contrast + for its own sake. +- Provide **multiple lockups**: horizontal (symbol left of name), stacked/vertical (symbol above name), + symbol-only, wordmark-only, and optionally with tagline. Lock the relative sizes and spacing once approved. +- Symbol-to-type size: optically, the symbol usually spans the cap height to about 1.5–2.5× the cap height in + horizontal lockups; verify by eye, not formula. + +## 11. Pictograms, logo systems, dynamic marks, patterns + +- **Pictograms**: pictures standing for a word or idea, understandable across languages. Built from the most + primary elements (line, circle, square, triangle). Useful as companion icon sets for an identity. +- **Logo systems / sub-brands**: a parent symbol as the primary identifier with sub-brands distinguished by colour, + naming, or a shared visual language. Consistency and repetition of key elements hold the family together. One of + the most complex tasks: requires problem-solving and a strong sense of balance. +- **Dynamic / changeable marks**: a consistent core (letterforms, grid, frame) with changing elements (colour, + pattern, inner image, typeface from an approved set). Keeps a system fresh and lets different users express + themselves while remaining recognisable. Define the rules as carefully as the mark. +- **Patterns**: complement the mark without duplicating it; derive from components of the mark where possible; + must scale from a business card to an aircraft. See `identity-system.md`. + +--- + +## 12. Decision guide + +Answer in order; the first strong "yes" usually wins. + +1. **Is the name short (≤ ~8 letters), distinctive, and not yet known?** → Wordmark or wordmark-led combination. +2. **Is the name long, multi-word, or hard to pronounce?** → Lettermark/monogram or letterform + wordmark. +3. **Does the name or story contain a vivid, ownable image?** → Pictorial (or pictorial combination). +4. **Is there a strong phenomenon/idea but no object?** → Abstract (only if exposure will be high). +5. **Will the mark mostly live as an app icon, favicon or avatar?** → Letterform or compact symbol first, + then the lockup. +6. **Heritage, membership, authority or craft positioning?** → Emblem, with a simplified inner symbol. +7. **Warmth, family, play?** → Mascot or friendly pictorial, with a simplified head version. +8. **Parent brand with many children?** → Logo system with a fixed core. + +When in doubt, explore **three different types** in the first round (e.g. a wordmark, a letterform, and a +pictorial/abstract symbol) so the choice is made by comparing real options. diff --git a/.claude/skills/logo-design/references/presentation-delivery.md b/.claude/skills/logo-design/references/presentation-delivery.md new file mode 100644 index 0000000..801a66d --- /dev/null +++ b/.claude/skills/logo-design/references/presentation-delivery.md @@ -0,0 +1,121 @@ +# Presentation, Feedback & Delivery + +How to present concepts so they are judged on the right criteria, how to handle feedback and committees, and what +to deliver at the end. Also covers the working relationship (fees, spec work, rights) for users who are designers. + +## Contents +1. Presentation rounds +2. Structure of a concept presentation +3. Talking about concepts +4. Feedback, committees and decision-makers +5. Final deliverables +6. The working relationship (for designer users) + +--- + +## 1. Presentation rounds + +A typical project has three presentations: +1. **Concepts (the checkpoint)** — three distinct directions at ~80 % finish, **in greyscale**, each with a one-sentence + idea and a short rationale tied to the brief, shown as one overview image (`scripts/concept_sheet.py`). End by + offering the full kit and wait. Goal: choose a direction. Nothing else is produced before this answer. +2. **Refinement** — the chosen direction refined (optical corrections, type, lockups) with **colour** options, + researched against competitors' palettes, shown in context with mockups (`scripts/presentation_board.py`). +3. **Final kit** — the approved mark with the system (palette, typography, variants), key applications, the file set + and the usage guide. + +In a chat with an AI designer, rounds 2 and 3 are often merged: once the user approves a direction and asks for the +kit, deliver the refined mark, colour, lockups, board, exports and guidelines together. Never merge round 1 into the +others unless the user explicitly asked you not to check in. + +Why three concepts? Enough for a real choice, few enough to develop properly. Three well-developed concepts beat a +dozen half-developed ones, and showing too many signals a lack of conviction. Make the three genuinely different +(e.g. a custom wordmark, a letterform symbol, a pictorial/abstract symbol) rather than three variations of one idea. + +Why greyscale first? Colour triggers personal preferences ("I hate green") that derail the conversation about the idea. +Form must stand on its own. + +## 2. Structure of a concept presentation + +For the checkpoint, the concept overview image plus a short chat message is enough (see SKILL.md). For a fuller +client presentation (round 2, or when the user asks for one), use `scripts/presentation_board.py` to generate an HTML board — set `"industry"` (coffee, food, retail, fashion, software, saas, finance, consumer-app, services, event, education, health) or an explicit `"mockups"` list so every context fits the business (`--list-mockups` shows all) — or follow this outline in chat/slides: + +1. **Title** — client, project, date, designer(s). +2. **What we heard** — the brief in a few lines: audience, adjectives, the problem, success criteria. This reminds + everyone of the agreed criteria before they see anything. +3. **Per concept** (one at a time, not all at once): + - Name the concept and give the **one-sentence idea**. + - Show the mark large, alone, in black on white. + - Explain *how it answers the brief* (2–4 bullets). Mention the craft decisions briefly (geometry, custom letters). + - Show it small (favicon/app icon) and reversed. + - Show 5–6 **mockups relevant to the business**, in a consistent style (a coffee brand on cups and a storefront, + a SaaS on an app icon, website header and a conference badge). +4. **Comparison** — all three side by side at the same size. +5. **Recommendation** — which one you recommend and why (the designer is the expert; have a point of view). +6. **Next steps** — what happens after a choice; what feedback you need. + +Keep the logo's role in perspective: a logo cannot carry deep brand stories. The aim is to communicate something about +the brand quickly and simply; the rest is the job of the identity system and the brand's actions. + +## 3. Talking about concepts + +- Lead with the idea and the brief, not with how long it took or which tool was used. +- Tie every choice to criteria: "Rounded terminals because 'approachable' was your first adjective." +- Show the system potential: patterns, icons, motion a concept could generate. A minimal mark often looks too simple + alone — shown in use, its simplicity becomes an asset that gives the wider identity room to breathe. +- Anticipate objections (resemblance to X, legibility at small size) and address them before they're raised. +- If a client asks for something that conflicts with the brief, return to the brief; explain trade-offs without + condescension. + +## 4. Feedback, committees and decision-makers + +- **Know who decides** and involve them directly in presentations. Feedback relayed through intermediaries loses + context; decisions made without the decision-maker get reversed. +- **Committees**: many voices tend toward consensus on the least objectionable (weakest) option, and people conform to + the loudest opinion. Present to the smallest group that includes the decision-maker; collect individual written + feedback against the criteria rather than open debate; keep focus groups for comprehension checks, not taste votes. +- **Value all feedback** — even irritating feedback contains information. Clients usually know their business better + than the designer. Don't fall in love with your own work, and never demonise the client. +- **Translate feedback into problems**: "Make it bigger" may mean "it lacks presence"; "I don't like the colour" may mean + "it feels cold". Ask *why* before changing anything. +- **Underpromise and overdeliver**; meet deadlines — reliability builds the trust that lets bolder ideas through. +- **Be strong, not stubborn**: hold the strategic line, concede on details, and remember the designer is the catalyst + for change — some discomfort is normal. The job is an effective logo, not making everyone feel good. + +## 5. Final deliverables + +**Master artwork (vector)** — SVG (web/dev), PDF (print), and, when the user has the tools, AI/EPS for printers and +agencies. **Raster** — PNG with transparency (e.g. 512, 1024, 2048 px) and JPG on white for office use. + +**Variants** (generate with `scripts/export_variants.py`): +- Full colour, one-colour black, one-colour white (reversed), one-colour brand colour. +- Lockups: horizontal, stacked, symbol-only, wordmark-only (+ with tagline if any). +- Favicon (SVG + 32/48 PNG; ICO if requested), app icon (1024 px square, platform tile), social avatar (circle-safe). + +**File naming**: `brand-logo-horizontal-color.svg`, `brand-logo-stacked-white.png`, `brand-symbol-black.svg` … +Organise folders by use: `print/`, `digital/`, `social/`, `source/`. + +**Mini guidelines** (at minimum one page, see `templates/brand-guidelines-template.md`): clear space, minimum sizes, +colour codes, approved backgrounds, typefaces, misuse examples, which file to use where (many clients send the digital +RGB file to their printer — spell it out). + +**Handover notes**: design rationale (one paragraph per key decision), test results, open items (trademark search, +Pantone proofing, outlines for any remaining type or strokes), and licence notes for fonts used. + +Final checklist before sending: see `process.md` §7 and `testing-checklist.md`. + +## 6. The working relationship (for designer users) + +- **Talk money early**; fees depend on scope (number of concepts, rounds, deliverables, usage/rights, timeline, the + client's size). Hourly rates suit beginners; experienced designers usually price per project (quick insight is + the result of years). Raise rates as demand and experience grow. +- **Get paid upfront** (e.g. a deposit before work starts), set revision limits and timelines in writing, and handle + print costs separately. +- **Avoid spec work** (free pitching/crowdsourcing): it devalues expertise and skips the discovery that makes logos + good. Pro bono work for causes you believe in is different — choose it deliberately. +- **Rights and ownership**: clarify when rights transfer (usually on full payment), and whether the designer may show + the work in a portfolio. Unused concepts usually remain the designer's. +- **Originality**: never pass off a light modification of existing work as original. If an unintentional similarity is + discovered, be honest, fix it, and make it right with the original creator if needed. +- **Stay involved** after launch: offer periodic audits and art direction; it protects the work and brings repeat + business. diff --git a/.claude/skills/logo-design/references/principles.md b/.claude/skills/logo-design/references/principles.md new file mode 100644 index 0000000..ef95acf --- /dev/null +++ b/.claude/skills/logo-design/references/principles.md @@ -0,0 +1,234 @@ +# Logo Design Principles + +The foundational thinking behind every decision in this skill. Read this when you need to justify a +direction, resolve a disagreement, critique a mark, or when a design "feels off" and you need a lens. + +## Contents +1. What a logo is (and is not) +2. The twelve principles +3. The mnemonic model — how marks get remembered +4. Simplicity, properly understood +5. Relevance vs. literalness +6. Distinction and originality +7. Longevity vs. trend +8. Tensions to manage +9. Quick diagnostic questions + +--- + +## 1. What a logo is (and is not) + +- **A logo is an identifier, not an explanation.** People are known by a name, not by a paragraph + describing where they live and what they do. A logo is a signpost: it points to the organisation and + hints at its attitude. It does not need to show the product, the service, the city and the founding + story at once. +- **A logo is not an illustration.** An illustration explains text. A logo is a shortcut that must be + recognised in a glance and remembered afterwards. +- **Logo ≠ identity ≠ brand.** + - *Logo*: the mark itself (symbol, wordmark, or both). + - *Identity*: the logo plus its visual system — typefaces, colours, imagery, patterns, tone of voice. + - *Brand*: the perception people hold about the organisation. It is formed by the audience from every + touchpoint — products, service, behaviour, communication. A designer cannot "make" a brand; a designer + builds the foundation the brand is perceived through. +- **A logo is not a magic lantern.** It cannot rescue a bad product or a poorly run organisation. A well- + designed mark, repeated consistently, helps a good product reach its potential. The logo supplies + attitude and direction; the organisation supplies the meaning, over time. +- **Meaning accrues.** Most marks are nearly empty when new; they become loaded through association and + exposure. Simple geometric forms carry whatever the organisation pours into them — which also means a + mark's meaning can be damaged by association. Choose forms that can hold the intended meaning for decades. +- **What a logo is for:** claim ownership and origin; differentiate from competitors; give the + organisation an internal rallying point; let the audience form a relationship; lend credibility; bring + order to many communications; create merchandising and recognition opportunities. + +--- + +## 2. The twelve principles + +These are synthesised from the whole body of logo-design practice. Treat them as a checklist of forces, +not as rigid laws — great marks sometimes break one principle deliberately to serve a stronger one. + +### 1. Start with who, what, why +Before any form: *Who is the client (values, attitude, goals)? Who is the audience (demographic and +psychographic)? What is actually needed — is a logo even the answer, or is the problem a bad product, +message, or team?* Let the problem dictate the solution rather than imposing a favourite idea onto it. This +does not mean obeying every client whim, nor suppressing the designer's vision — it means gathering enough +information to set criteria, then creating through the designer's filter. Also ask what the organisation +wants to be in one, five and ten years; design for where it is going, not only where it is. + +### 2. Identify, don't explain +Resist the urge to depict every facet of the business. Describing too much produces a cluttered mark and a +restraining identity that breaks the moment the business expands. The clearest, most direct voice wins. + +### 3. Keep it simple +A simple form is recognised faster, remembered longer, reproduced more reliably, and survives abuse — +bad printing, embroidery, tiny favicons, careless in-house designers. Many logos fail from their own +cleverness or overproduction. Let something be what it is. (See §4: simple is not the same as plain.) + +### 4. Make it relevant +The mark must fit the organisation, its industry, its audience and its personality. A florist's mark should +not look at home on a car dealership. Relevance is about *tone and fit*, not literal depiction (see §5). + +### 5. Aim for distinction +Study what competitors look like. If every mark in the category runs together (all blue, all globes, all +swooshes), that is an opportunity. Bucking category conventions makes a brand stand out — but keep the +general perception in mind so the mark still reads as belonging to the right world. + +### 6. Build memorability (mnemonic value) +Memory is built from shape and colour first, then context, then learned associations, then emotion (see §3). +A strong, singular silhouette and an ownable colour are the most reliable memory hooks. + +### 7. Focus on one thing +One clear idea, executed well, beats three ideas fighting for attention. A mark with a single defining +feature is easier to recall and describe. If you cannot explain the idea in one sentence, it will not work. + +### 8. Think small (and large) +Design for an inch, or 16 px. Intricate, layered forms that look superb at 400 % on screen become a +jumbled mess on a favicon or embroidered chest logo. Conversely, bad curves and sloppy kerning are +exaggerated on a building-sized sign. Test both extremes (see `testing-checklist.md`). + +### 9. Design for longevity +Marks that date quickly come from concentrating on *formal* ideas (a trendy effect, the typeface of the +moment) rather than *conceptual* ones. Style and trend rarely carry lasting emotional resonance. Aim for a +mark that can convey its message for decades and adapt to cultural change. + +### 10. Make the logo the foundation of a system +The audience never sees a logo in a void. It lives on cards, screens, vehicles, buildings, packaging, +next to photography and copy. Design the mark with its visual system in mind; the system should complement +the mark, not copy it. Guidelines protect the mark from party hats, wrong colours and floor decals. + +### 11. Design for every medium +Assume the logo must work in one-colour print, on screen, as a 3D sign, embroidered, animated, and in media +not yet invented. Most clients only picture their current use; the designer's job is to plan for the +unplanned. + +### 12. Be seductive — and be strong +Aesthetics matter. People would rather be drawn in by a mark than repelled by one; the message is primary but +the form must invite the viewer in. Simple, dynamic, well-crafted forms seduce. And "strong" applies to the +designer too: understand your role and the client's, keep a clear vision tied to the agreed goals, and +distinguish confidence from stubbornness. The designer is a catalyst for change; not everyone will be happy, +and that is not a failure. + +**Two supporting principles worth naming separately:** +- **Pose a question (lightly).** A mark that lets the viewer complete a small puzzle — a hidden arrow, a + letter doubling as an object, a figure/ground reversal — is looked at longer and remembered better. But + there is a fine line: a mark that needs hours to decode or accompanying text will fail. +- **Respect tradition where it exists.** Existing equity (a colour, a shape, a heritage detail) and + culturally significant symbols deserve respect. Borrowing a culture's sacred symbol requires permission + from its custodians; honouring tradition can create powerful, unexpected connections. + +--- + +## 3. The mnemonic model — how marks get remembered + +People process a mark in roughly this order: + +1. **Shape and colour.** All visual recognition starts here. Is it round and red? Square and green? + Consistency of shape inside the mark (counters echoing the outer form, repeated angles) strengthens it. +2. **Historical continuity / context.** The viewer places the form in time and culture: contemporary, + Victorian, retro-futurist, corporate, handmade. Signifiers of an era can intentionally evoke an attitude. +3. **Learned response.** Taught associations: red means stop, a green cross means pharmacy, a shield means + protection. Use them knowingly; they differ by culture. +4. **Emotional resonance.** The "wild card": personal memories attached to colours and forms. Hard to predict, + but it is where lasting attachment lives. + +Design implication: get the silhouette and the colour decision right first; everything else is secondary. + +--- + +## 4. Simplicity, properly understood + +- **Less information, more memory.** The fewer words a phrase has, the easier it is to memorise; the fewer + visual elements a mark has, the clearer and more memorable it is. +- **Simple is not plain.** Some shapes are too simple to be interesting — a bare circle or generic initials + in a stock typeface carry nothing ownable. Simplicity charms only when it carries a certain amount of + thought and detail: a clever junction, a precise proportion, an unexpected cut, a subtle light source. +- **Sculpt by subtraction.** Treat the process like sculpting: chip away weaker ideas, add and strip + elements, then strip some more. Don't stop at the first acceptable result; the longer you stay with the + form, the more correct it becomes. +- **The modernist vocabulary is shared ground.** Waves, stripes, stars, arrows, cubes, overlapping primitives + with exclusions, half- and quarter-circles, spirals, repetition. Knowing this alphabet lets you compose on + a solid foundation — but the vocabulary is shared, so push past its obvious combinations. +- **Minimalism as positioning.** Extreme reduction can itself be a differentiator — useful when a brand wants + conceptual sophistication in a market of loud identities (common in B2B and premium sectors). + +--- + +## 5. Relevance vs. literalness + +- **Avoid direct illustration of the subject.** A dentist logo that is a tooth, a plumber logo that is a + wrench, a software logo that is a laptop — these are forgettable because every competitor could use them. +- **Clichés are recognisable for a reason.** An apple, a shield, a leaf, a speech bubble — they read instantly. + Don't discard them; present them in a fresh form so the familiar sign is seen anew. +- **Where to find the idea:** the name (a letter, a word meaning, a sound); the brand's adjectives (fast, + warm, precise, rebellious); its promise; its origin, place or founder; a process or material it uses; an + abstract phenomenon it creates (connection, growth, flow, balance). +- **Literal naming shortcuts.** When the name is itself an object (e.g. a company named after a fruit), + using that object makes recall instant — the viewer sees the mark and the name surfaces automatically. That + directness is a legitimate choice; add craft and a twist so it is still ownable. +- **Abstract marks need assigned meaning and exposure.** Some ideas ("connection", "speed") have strong visual + analogues; others ("reliability", "trust") do not, so an abstract form gets meaning assigned by story and + repetition. Abstract marks only become meaningful with a great deal of exposure — factor media budget into + the choice. + +--- + +## 6. Distinction and originality + +- **The familiarity test.** If a solution feels familiar in even the slightest way and you know it isn't + yours, it is someone else's. Discard it or change it significantly. Memory is sneaky: marks you saw years ago + can resurface as "your" idea. +- **Basic shapes are common property; combinations are not.** Everyone can use circles and triangles; the + specific arrangement is what must be new. +- **Search before you commit.** Check the category, trademark databases, and a reverse image search. Use the + bundled library (`scripts/search_library.py`) to see what is already common for a subject or technique. +- **Never copy library marks.** The reference library exists to learn patterns and craft, not to trace. + If an accidental near-copy is discovered after delivery, be honest, change it, and make it right. + +--- + +## 7. Longevity vs. trend + +- Every era leaves fingerprints (gradients, drop shadows, glossy bevels, ultra-thin type, lowercase + everything). A trained eye can date a mark to its decade. Some brands deliberately want a current look — that + is valid if chosen knowingly and budgeted for refresh. +- Two viable ownership strategies: + - **Constancy**: one mark kept almost unchanged for generations; recognition compounds. + - **Managed evolution**: periodic refreshes that keep the core recognisable (colour, shape, key element) + while updating details. +- Custom letterforms add ownership, but the further they depart from recognisable letter shapes, the faster + they date. +- Conceptual ideas outlive formal ones. Build the mark on an idea, not on an effect. + +--- + +## 8. Tensions to manage + +| Tension | Guidance | +|---|---| +| Simple ↔ interesting | Reduce until the idea is clear, then make sure one detail is ownable. | +| Relevant ↔ literal | Evoke the attitude; don't depict the product. | +| Distinct ↔ appropriate | Break category conventions where they blur together, keep the cues that signal the right world. | +| Clever ↔ clear | A small puzzle helps; a riddle hurts. One-sentence test. | +| Symmetry ↔ energy | Perfect symmetry is stable but can bore; a subtle asymmetry keeps the eye moving. | +| Consistency ↔ flexibility | A fixed core (shape, colour, type) with rules for variation keeps systems fresh without losing recognition. | +| Client taste ↔ strategy | Return to the brief and the agreed criteria, not to personal preference — yours or theirs. | +| Perfection ↔ progress | Keep refining details, but know that no logo pleases everyone; even a mark loved by 99 % will have critics. | + +--- + +## 9. Quick diagnostic questions + +Run these on any concept (yours or one you're critiquing): + +1. Can I describe the idea in one sentence? +2. Is it recognisable as a silhouette, in one flat colour? +3. Does it still read at 16 px? At 16 m? +4. Would it survive a fax, an embroidery machine, a laser engraver? +5. Does it look like any competitor, or any famous mark? +6. Does its tone (sharp/round, heavy/light, warm/cool) match the brand's adjectives? +7. Is there one defining feature someone could describe from memory? +8. Is anything there only because it was fun to draw? +9. Will it look dated in ten years? Why not? +10. Does it work as the foundation of a system — can a pattern, icon set or motion idea grow from it? +11. Are there unintended readings (rotated, mirrored, at a distance, by someone who hasn't seen the brief)? +12. Would the audience — not the designer — understand and like it? diff --git a/.claude/skills/logo-design/references/process.md b/.claude/skills/logo-design/references/process.md new file mode 100644 index 0000000..0476757 --- /dev/null +++ b/.claude/skills/logo-design/references/process.md @@ -0,0 +1,131 @@ +# The Design Process in Detail + +The stages from brief to final artwork, adapted for an AI designer that works in SVG code as well as for a +human designer with a sketchbook. SKILL.md gives the short version; read this for the details of each stage. + +## Contents +1. Stage map +2. Concepting +3. Mood boards and reference gathering +4. Exploration ("sketching") — three stages +5. Development in vector +6. Refinement and gridding +7. Final artwork checklist +8. Working habits + +--- + +## 1. Stage map + +| Stage | Output | Gate | +|---|---|---| +| Collaboration / discovery | Brief, criteria, schedule, decision-maker | Brief agreed | +| Concepting | Word map, 6–10 one-sentence concepts | Concepts are distinct and on-brief | +| Exploration | Many rough forms per concept | 2–4 directions worth developing | +| Development | Clean black vector versions of 3 concepts | Presentable at ~80 % finish | +| Presentation 1 (checkpoint) | 3 concepts in greyscale as one overview image + kit offer | User picks a direction and asks for the kit | +| Refinement | Optical corrections, gridding, colour, type, lockups | Approved final mark | +| System & applications | Palette, typefaces, variants, patterns, key applications | System approved | +| Production | Final files, specifications, guidelines | Delivered; audit plan | + +Integrate existing equity (colours, shapes, heritage details) during exploration if it's a redesign. + +## 2. Concepting + +- Begin with the name and a detailed brief — from the brand's big idea down to how it operates. +- The most useful clues are **adjectives** describing the brand; they give abstract visual cues that can become + symbols. Also mine: the name's letters and meaning, the promise, the audience's world, the product's process + and materials, place and origin. +- If the name contains a visual (a letter + number with strong shapes, a word that is an object), the concept may be + hiding in plain sight. +- Write each concept as **one sentence** ("A 'T' whose crossbar is a shield's top edge, for a logistics firm whose + promise is protection"). If it can't be said in a sentence, it won't be understood in a glance. +- Aim for concepts that are clever *and* visually pleasing — marks with a clever idea and sound visual appeal make the + strongest first impression. +- Consider the audience's demographics and culture (colourful/rounded for children; bold for some audiences; + cultural symbols where relevant) — but the brand strategy decides; a children's product can have an adult identity. + +## 3. Mood boards and reference gathering + +- Not just logos: include nature, architecture, painting, materials, typography, photography, product details. +- Compartmentalise by direction — classic, futuristic/high-tech, colourful, monochrome — and by mark type + (pictorial, letterform, monogram), each with relevant imagery. Clear boundaries make choices easier. +- Use the library for logo references by technique and subject (`scripts/search_library.py --technique + negative-space --exemplary`). References are for learning construction and tone — never to be traced. +- Mood boards can be shared with the client to align on style, or kept private; clients can't always foresee how a + direction will develop, so don't let an early mood preference lock the outcome. + +## 4. Exploration — three stages + +A human designer does this with pencil and tracing paper; as an AI, do the equivalent with quick descriptions and +rough SVG thumbnails. The logic is the same. + +### Stage A — Initial (quantity over quality) +- Pour out ideas with no judgement about clarity, spacing, form or silhouette. Rough strokes, imperfect shapes, + careless curves. The page should look like a battlefield of half-formed ideas. +- Quantity matters because it lets unexpected accidents happen. For an AI: list 15–30 micro-variations across + the 6–10 concepts (different letter treatments, crops, containers, negative-space pairings, angles). +- Rough SVG thumbnails at 64–128 px are ideal: small size forces silhouette thinking. + +### Stage B — Refinement (from ~30 % to ~60 %) +- Pick the most promising concept by gut feel; it may be only ~30 % of the final. The goal is to reach 50–60 %. +- Redraw it as a reference, then make many similar versions, each trying one new improvement: how elements + interact, balanced flow, outline, proportion. Compare each version with the previous; keep what works, cut what + doesn't. + +### Stage C — Fine-tuning (clean and precise) +- Trace over the best version repeatedly with small improvements until the form is clean and precise. At the end, + few formal changes should remain for the vector stage. + +Designers who stop at the first acceptable result leave quality on the table. Keep adding and stripping. + +## 5. Development in vector + +- **Copy, then change.** Before every significant change, duplicate the current version and place it next to the + previous. When something goes wrong, you can see exactly where. (In SVG work: save `concept-a-v1.svg`, `-v2.svg` + … and compare them in `scripts/preview_sheet.py --compare`.) +- **Few anchor points.** Anchors have great power; too many make curves lumpy and jagged. Periodically delete + unnecessary ones. Clean curves come from few, well-placed anchors with handles aligned to the curve's tangent + (horizontal/vertical handles at extrema). +- **Build with shapes.** Use circles, rectangles and consistent radii to construct and to check curves and corners. +- **Black first.** Develop in solid black on white. Colour comes after the concept is chosen. +- Present at about **80 % finish** — refined enough to judge the idea, not so polished that effort is wasted on a + direction that gets dropped. + +## 6. Refinement and gridding + +After a direction is approved: +1. **Alignment**: check that all horizontals and verticals are true (not 1–2° off). Snap near-standard angles to + standard ones (43° → 45°). +2. **Primitives**: circles perfectly circular, squares square, consistent radii where intended. +3. **Consistency**: stroke weights, gap widths, corner radii, terminal angles. +4. **Optical corrections**: overshoot, bone effect, irradiation (reversed version), horizontal-stroke thinning, + optical centre (see `visual-techniques.md`). +5. **Colour**: build palette; test on backgrounds (see `color.md`). +6. **Type & lockups**: finalise wordmark, spacing and all lockups (see `typography.md`). +7. **Scale tests**: see `testing-checklist.md`. + +Don't grid organic curves that don't decompose into circles; leave them. + +## 7. Final artwork checklist + +- [ ] No duplicate, stray or unnecessary anchor points; no open paths in filled shapes. +- [ ] Angles accurate, especially on the outer silhouette. +- [ ] All text converted to outlines; no live fonts, no raster images, no filters or effects in the master. +- [ ] Strokes expanded to fills (unless a deliberately stroke-based variant). +- [ ] Shapes merged/compounded where they should be one shape (no hairline gaps or overlaps that show as seams). +- [ ] Artboard/viewBox tight to the mark with consistent padding; mark centred optically. +- [ ] Colours are exact brand values; one-colour and reversed versions provided. +- [ ] File set matches the agreed deliverables (see `presentation-delivery.md`). +- [ ] Working files archived; versions named clearly. + +## 8. Working habits + +- Carry a sketchbook (or a notes file): ideas arrive at odd moments and slip away quickly. Photograph interesting + shapes, architecture, and the negative spaces in signage. +- Experiment outside the brief: work in the opposite of your usual style (colour if you work in black and white, + lines if you work in solids, messy if you work clean). Accidents — a slipped stroke, a mis-set layer — can be + exactly what a project was missing. +- Treat client feedback as valuable information, not an attack; clients usually know their business better than + you. Don't fall in love with your creations, and don't demonise clients. +- Keep your process, not your mood, in charge: rested eyes, side-by-side comparisons, and returning to the brief. diff --git a/.claude/skills/logo-design/references/redesign.md b/.claude/skills/logo-design/references/redesign.md new file mode 100644 index 0000000..062d55b --- /dev/null +++ b/.claude/skills/logo-design/references/redesign.md @@ -0,0 +1,72 @@ +# Redesign, Refresh & Rebrand + +Changing an existing logo is riskier than creating a new one: people already know it, and recognition is an asset +built over years. Read this when the user asks to modernise, refresh, update or replace a logo. + +## 1. First: should it change at all? + +Good reasons: +- The business has changed (merger, new offering, new audience, new positioning — e.g. from discount to premium). +- The mark fails functionally: illegible small, unusable on screens, can't be embroidered, breaks in one colour. +- Many inconsistent versions are in circulation (the mark has been stretched, redrawn and recoloured by every vendor). +- It resembles a competitor or carries a harmful association. +- It looks dated in a way that contradicts the brand's promise (a tech firm looking decades old). + +Weak reasons: a new executive wants to leave a mark; boredom inside the company (the audience is rarely as bored as +the staff); chasing a trend. Remember the public may care deeply about a familiar mark — radical redesigns of loved +brands can trigger backlash and even be reversed. + +If the user is only *thinking* about change, that alone justifies exploring options — explore, then decide. + +## 2. Evolution vs. revolution + +| | Evolution (refresh) | Revolution (rebrand) | +|---|---|---| +| When | Equity is strong; problems are technical or stylistic | The business or its perception must change fundamentally | +| What changes | Proportions, weight, curves, spacing, colour tuning, simplification, cleaner digital version | Concept, name treatment, possibly colour and symbol | +| Risk | Low — recognition carries over | High — must rebuild recognition; plan launch & explanation | + +Most successful updates are evolutionary: cleaner, sleeker versions of the same idea. Even radical changes often keep +one anchor — usually the colour scheme (perhaps shifted in shade) or a signature shape. + +## 3. Equity audit + +List what the public recognises, in order of strength: colour, symbol shape, a distinctive letter, the name's +typography, a mascot, a slogan, a sound. Ask: +- What must survive? (Usually the strongest one or two.) +- What is incidental and can go? +- What causes problems (legibility, reproduction, negative associations)? +Two ownership strategies exist — constancy for decades, or managed evolution that keeps core elements while updating +details. Choose one explicitly. + +## 4. Refresh techniques + +- **Redraw** curves with fewer, cleaner anchors; fix the bone effect; add overshoot; unify stroke weights and radii. +- **Simplify**: remove bevels, shadows, gradients, outlines, tiny details; merge elements; reduce colours. +- **Retune typography**: re-space, redraw letters for legibility, customise so it can't be typed in a stock font, + or replace an overused typeface while keeping the character. +- **Soften or sharpen**: round terminals and lowercase letters feel friendlier; sharper forms and capitals feel more + authoritative. (A common modern move: from stark capitals to friendlier rounded forms.) +- **Colour**: keep the hue family, adjust saturation/value for screens and accessibility. +- **Add a container** when the old mark gets lost in cluttered environments. +- **Build the missing variants** (symbol-only, horizontal/stacked, favicon, reversed) — often the real problem. +- **Keep heritage elements as accents** (a classic ampersand, an old monogram) next to modern type to express + continuity and progress at once. + +## 5. Mergers and new structures + +Options: choose one existing mark; combine elements of both (rarely elegant); create a new mark that signals a new +entity; or a transitional endorsement ("X, a Y company"). Communicate tactfully — people identify with their old brand. +Find elements that both sides can recognise as theirs. + +## 6. Launch + +Explain the change: why, what stays, what it means. Show before/after side by side. Roll out consistently — mixing old +and new marks for long signals confusion. Update guidelines and asset libraries on day one, and audit usage after launch. + +## 7. Deliverable for a redesign proposal + +1. Diagnosis of the current mark (use the critique format in `critique.md`). +2. Equity audit (what stays, what goes). +3. 2–3 options along the evolution ↔ revolution spectrum, each with before/after at the same sizes. +4. Recommendation and rollout considerations (cost of signage/vehicles/packaging changes, timing). diff --git a/.claude/skills/logo-design/references/svg-construction.md b/.claude/skills/logo-design/references/svg-construction.md new file mode 100644 index 0000000..712124b --- /dev/null +++ b/.claude/skills/logo-design/references/svg-construction.md @@ -0,0 +1,193 @@ +# Building Logos in SVG + +How to turn a concept into clean, production-grade SVG code by hand (as an AI writing markup) — geometric, +minimal, and easy for printers, developers and vector editors to use. + +## Contents +1. File conventions +2. Construction strategy: think in primitives +3. Paths: writing clean geometry +4. Negative space and compound shapes +5. Strokes vs fills +6. Type in SVG +7. Colour, gradients, variants +8. Common construction recipes +9. What to avoid in a master file +10. Outlines and boolean unions +11. Validation + +--- + +## 1. File conventions + +```svg + + Harbor logo + + +``` +- **viewBox first**: work on a clean integer canvas. 256 × 256 (or 512 × 512) for symbols; for lockups keep the + height 256 and let the width follow (e.g. `0 0 960 256`). The bundled library uses the same convention (width + 256 or 512 in ~99 % of files). +- **Padding**: leave consistent padding inside the viewBox (≈ 4–8 % of the size for symbols) or crop tight and let + the clear-space rule handle spacing — be consistent across the set. +- **Integer or 1–2 decimal coordinates**. Excess precision (`127.99999`) bloats files and hides misalignment. +- **Include ``** for accessibility; keep IDs meaningful (`symbol`, `wordmark`). +- **Group logically**: `<g id="symbol">`, `<g id="wordmark">` so lockups can be recomposed. +- One file per variant (see §7), named predictably: `brand-logo-horizontal-color.svg`, `brand-symbol-black.svg`. + +## 2. Construction strategy: think in primitives + +Before writing path data, describe the construction in words: +- *"Circle r=96 centred at (128,128); remove a 45° wedge from the upper right; a smaller circle r=28 sits in the + gap as a 'dot'."* +- *"Letter M from three 40-unit-wide bars on a 256 grid; the middle vertex rises to y=96; outer stems are extended + 4 units below the baseline for overshoot of the pointed vertex."* + +Then choose the simplest element that expresses each part: +- `<circle>`, `<ellipse>`, `<rect rx>` for primitives (easy to read and adjust). +- `<path>` for everything else, and for the final merged silhouette. +- `<polygon>` for straight-edged shapes. + +Pick a **unit** (e.g. 8 or 16 on a 256 canvas) and snap key dimensions to multiples of it; the mark will feel +systematic and gridding later is trivial. Keep a list of the radii and angles you use — reuse them. + +## 3. Paths: writing clean geometry + +- **Commands**: `M` move, `L`/`H`/`V` lines, `A` elliptical arc (perfect for circle segments), `C` cubic Bézier, + `Q` quadratic, `Z` close. Uppercase = absolute (prefer while designing), lowercase = relative. +- **Arcs for circular geometry**: `A r r 0 largeArc sweep x y`. Circle-based curves keep radii consistent and + are easy to verify. Example — a semicircle cap: `M 64 128 A 64 64 0 0 1 192 128`. +- **Béziers for organic curves**: place anchors at extrema (top, bottom, left, right of a curve) with handles + horizontal or vertical there; this gives smooth, predictable curves with few points. A quarter circle as a cubic + uses handle length ≈ 0.5523 × radius. +- **Few anchors**. Every extra point is a chance for a wobble. If a curve needs many points, split it into arcs. +- **Angles**: compute diagonal endpoints from exact angles. For 30°/60°: offsets use sin/cos (0.5, 0.866); + for 45°: equal x and y offsets. Avoid "almost" angles like 44° or 2° off vertical (the audit script flags them). +- **Smooth corners (anti bone effect)**: instead of a plain arc joining a straight side, extend the curve's handles + so curvature ramps gradually. A good squircle corner of size `s` starts ~1.3 × s before the corner, with handles + ~0.6 × s. +- **Closed shapes**: always end filled paths with `Z`. + +## 4. Negative space and compound shapes + +- Put outer contour and holes in **one path** and use `fill-rule="evenodd"` — holes appear where subpaths overlap + an odd number of times. Or wind holes in the opposite direction with the default `nonzero` rule. + ```svg + <path fill-rule="evenodd" d="M128 16 A112 112 0 1 1 127.9 16 Z M128 80 A48 48 0 1 0 128.1 80 Z"/> + ``` +- For a hidden figure between two shapes, design the **negative shape first** (the arrow, the letter), then build the + positive shapes around it; this guarantees the negative form is clean. +- Avoid `<mask>` and `<clipPath>` in the master unless essential — some tools and embroidery/cutting software handle + them poorly. Bake the geometry into paths for final files. (In exploration, masks are fine for speed.) +- Where two filled shapes of the same colour touch, merge them into one path so there is no hairline seam when + rendered or cut. + +## 5. Strokes vs fills + +- Explore with strokes (`stroke-width`, `stroke-linecap="round"`, `stroke-linejoin="round"`) — they're quick. +- In the master, **convert strokes to filled outlines** so the mark scales proportionally everywhere and survives + tools that ignore stroke settings. As an AI without an outline tool, either construct the outlined geometry + directly (offset curves by half the stroke width), or keep strokes but set `vector-effect` nowhere and verify that + scaling the whole SVG scales stroke width proportionally (it does when the stroke is inside the scaled viewBox). + Flag remaining strokes in the delivery notes so a vector editor can expand them. +- Monoline marks: pick stroke width relative to size (≥ 8 % of the mark's width if it must read at 24 px). + +## 6. Type in SVG + +- Final logos must not depend on installed fonts: `<text>` renders differently (or not at all) on other machines. +- Options, in order of preference: + 1. **Construct letterforms geometrically** as paths (ideal for short wordmarks, monograms, letterform symbols — + and it forces ownable, custom letters). + 2. If the user has a font file and a vector tool, set the word, customise, and **convert to outlines**; paste the + path data. + 3. For exploration/presentation only, use `<text>` with a clearly named font stack and a note that the wordmark + must be outlined before delivery. Never ship `<text>` as the final master. +- When drawing letters: consistent stem width, overshoot on round letters, thinner horizontals, optical spacing + (see `typography.md`). + +## 7. Colour, gradients, variants + +- Use exact HEX values from the palette; limit to the approved colours. +- Put colours directly on elements (`fill="#…"`) rather than in `<style>` blocks for maximum compatibility; optionally + use `currentColor` for a UI-friendly one-colour variant. +- Gradients: define in `<defs>` with `gradientUnits="userSpaceOnUse"` and explicit coordinates so they render + identically everywhere; always keep a flat-colour master alongside. +- **Variant set** to generate from the master (`scripts/export_variants.py` automates the colour swaps): + - `*-color.svg` (full colour), `*-black.svg`, `*-white.svg` (reversed; consider slightly thinner geometry), + `*-mono-<hex>.svg` (one brand colour). + - Lockups: `horizontal`, `stacked`, `symbol`, `wordmark`. + - App/favicon: symbol on a solid rounded-square or circle container, with the symbol optically sized + (typically 60–70 % of the container). + +## 8. Common construction recipes + +**Perfect circle with a notch (open ring)** +```svg +<path fill="none" stroke="#111" stroke-width="32" stroke-linecap="round" + d="M 201.5 54.5 A 104 104 0 1 0 232 128"/> <!-- exploration; expand for master --> +``` + +**Rounded square container (app icon), 22 % radius** +```svg +<rect x="0" y="0" width="256" height="256" rx="56" fill="#0F7C80"/> +``` + +**Equilateral triangle (side 203.2, height 176), centred on its bounding box** — its visual mass (centroid) +sits low, so nudge it up a few units if it looks bottom-heavy inside a container. +```svg +<polygon points="128,40 229.6,216 26.4,216" fill="#111"/> +``` + +**Letter "A" as a letterform symbol** — flat apex, every edge on the same 1 : 2 slope, and a constant +48-unit stroke (legs, crossbar and apex all measure 48) +```svg +<path fill="#111" fill-rule="evenodd" + d="M104 32 H152 L248 224 H200 L184 192 H72 L56 224 H8 Z M96 144 H160 L128 80 Z"/> +``` + +**Speech bubble from a circle + tail (merged)** +```svg +<path fill="#111" d="M128 24 A104 104 0 1 1 61.6 208 L28 236 L37.9 180 A104 104 0 0 1 128 24 Z"/> +``` + +These are starting points; refine proportions and add the concept's twist. + +## 9. What to avoid in a master file + +| Avoid | Why | Instead | +|---|---|---| +| `<text>` | font dependence | outlined paths | +| `<image>` / embedded PNG | not vector, blurry | vector paths | +| `filter` (blur, shadow, glow) | inconsistent rendering, not printable | flat shapes; simulate shadow with a darker shape | +| many `<mask>`/`clipPath` | tool compatibility | bake into paths | +| transforms nested deeply | hard to edit, rounding errors | apply transforms to coordinates (one wrapper `translate/scale`, as `export_variants.py` writes, is fine) | +| 20+ colours / many gradients | poor reproduction, weak recall | ≤ 3 flat colours; stepped gradients | +| micro-details < 1/64 of size | vanish when small | merge or remove | +| off-by-a-degree angles | look accidental | exact angles | +| editor metadata, huge precision | bloat | clean markup | + +## 10. Outlines and boolean unions (production) + +Without a vector editor you can't boolean-unite shapes, but you can get close: +- Overlapping sub-paths inside **one** `<path>` with the default `nonzero` rule (all wound the same way) render as a + seamless union on screen and in print — acceptable for web and most print masters. +- Cutters, vinyl plotters and embroidery software prefer truly merged outlines. If Inkscape is installed, it can + expand strokes and union everything from the command line: + ```bash + inkscape logo.svg --actions="select-all:all;object-stroke-to-path;path-union;export-plain-svg;export-filename:logo-outlined.svg;export-do" + ``` + Otherwise note in the handover that a designer should run *Outline Stroke* + *Unite* in a vector editor. + +## 11. Validation + +Run after every significant iteration: +```bash +python3 scripts/svg_audit.py path/to/logo.svg # structure, colours, complexity, angles, text/raster checks +python3 scripts/preview_sheet.py path/to/logo.svg -o preview.html # sizes, backgrounds, mono, blur, mirror, favicon +python3 scripts/render_png.py path/to/logo.svg --size 512 -o look.png # quick render to view +``` +Open the preview in a browser and look at it (use the available browser/screenshot tool if you are an agent). The +audit compares the file's complexity with the reference library's distribution so you can see if a mark is unusually +complex for a logo. diff --git a/.claude/skills/logo-design/references/testing-checklist.md b/.claude/skills/logo-design/references/testing-checklist.md new file mode 100644 index 0000000..5d90d07 --- /dev/null +++ b/.claude/skills/logo-design/references/testing-checklist.md @@ -0,0 +1,75 @@ +# Testing Checklist + +A logo is only finished when it has survived these tests. Most can be run with +`scripts/svg_audit.py` (structure and geometry) and `scripts/preview_sheet.py` (visual tests); the rest need +judgement. Run them on every concept before presenting and again on the final artwork. + +## 1. Scale +- [ ] **16 px favicon**: the core idea survives; no mush. If not, design a simplified small-size version + (fewer elements, thicker strokes, bigger gaps) — detailed marks may keep a reduced companion. +- [ ] **24–32 px** (app lists, social avatars): recognisable at a glance. +- [ ] **Very large** (billboard, building): curves are smooth, no lumpy anchors, kerning holds up; flaws + invisible at small sizes become glaring. +- [ ] **Minimum size**: shrink until the mark loses its identifying features; the size just above that is the + documented minimum (in px for screen and mm for print). + +## 2. Colour and value +- [ ] Works in **one-colour black** on white. +- [ ] Works in **one-colour white** on black — and doesn't look heavier than the black version (irradiation). If it + does, provide a slightly thinned reversed file. +- [ ] Works on the **brand colour**, on **photos** and on **patterns** (use a graphic device — outline or container — + if not). +- [ ] **Greyscale**: colour segments still separate by value; nothing relies on hue alone. +- [ ] Colours reproduce in **CMYK** and have spot/Pantone equivalents if vivid. + +## 3. Form +- [ ] **Squint/blur test**: the silhouette alone is distinctive. +- [ ] **Mirror test**: flipping reveals no proportion errors you'd adapted to. +- [ ] **Rotation / unintended readings**: view rotated 90° and 180°, tiny, and at a distance; show it to someone who + hasn't seen the brief. Check for accidental letters, body parts, offensive or sexual readings, political or + religious symbols, and resemblance to hazard signs. +- [ ] **Optical corrections** done: overshoot, bone effect, horizontal stroke thinning, optical centre. +- [ ] **Geometry clean**: no near-miss angles, perfect primitives, consistent radii and stroke widths + (`svg_audit.py` flags near-miss angles and tiny details). +- [ ] **Balance**: not accidentally tilted; weight distributed; proportions close to square for symbols. + +- [ ] **Letter test**: every customised letter still reads as the intended letter at first glance (ask: "what + letter is this?"). A K that reads as an h, or an N that reads as a lightning bolt, needs revising. +- [ ] **Junction check**: zoom in on every place strokes meet or overlap — no accidental notches, slivers, lumps, + hairline gaps or ink traps. +- [ ] **Peer test**: next to 3–4 exemplary library marks at the same size, yours looks equally resolved. + +## 4. Distinctiveness and originality +- [ ] **Shelf test**: placed among competitors (`preview_sheet.py --refs-industry <industry>`), it stands out + rather than blending in. +- [ ] **Familiarity test**: it doesn't remind you (or anyone you ask) of an existing mark. If it feels familiar and + it isn't yours, it's someone else's. +- [ ] **Library check**: search the bundled library for the same subject/technique + (`search_library.py --subject <thing>`); make sure yours is clearly different. +- [ ] **Trademark check** (recommend to the user): search the relevant trademark databases and do a reverse image + search before launch. You cannot give legal clearance — say so. + +## 5. Meaning and fit +- [ ] The idea can be explained in **one sentence**. +- [ ] Tone matches the brand adjectives (sharp/round, heavy/light, warm/cool, classic/modern). +- [ ] It identifies rather than explains; it will still fit if the business expands. +- [ ] Cultural meaning of colours and symbols checked for the audience's cultures. +- [ ] It works without the tagline and, for symbols, eventually without the name. + +## 6. Media and production +- [ ] One-colour printing, embroidery (no hairlines, gaps ≥ ~1 mm at chest-logo size), laser engraving, vinyl + cutting, signage, dark mode, animation. +- [ ] App icon: optically sized inside the platform's rounded tile; no fine text. +- [ ] Social avatars: survives circular crop. +- [ ] Master file: vector only, text outlined, strokes expanded, no filters/raster, clean viewBox + (`svg_audit.py` score ≥ ~90 with no FAIL). + +## 7. Context +- [ ] Shown in 5–6 **realistic mockups relevant to the business** (a café's cup, not a gym bag), in a consistent + style. Never judge a logo only in isolation on a white artboard. +- [ ] Lockups (horizontal, stacked, symbol-only) all tested at their intended sizes. + +## Recording results +Summarise test outcomes when presenting: what passed, what was adjusted (e.g. "thinned the reversed version by 3 %; +opened the counter gap from 6 to 10 units so it survives 16 px"), and what the user must still do (trademark search, +Pantone proofing). diff --git a/.claude/skills/logo-design/references/typography.md b/.claude/skills/logo-design/references/typography.md new file mode 100644 index 0000000..d4e3086 --- /dev/null +++ b/.claude/skills/logo-design/references/typography.md @@ -0,0 +1,135 @@ +# Typography for Logos + +Typography is pictures of words. We decode letterforms the way we decode images: their shapes carry attitude, +history and culture before a single word is read. Read this when designing wordmarks, lettermarks, lockups, or +choosing brand typefaces. + +## Contents +1. Choosing a direction: type study +2. Classification and what each voice says +3. Custom vs. existing type +4. Letterform craft (spacing, kerning, optical fixes) +5. Lockups: symbol + type +6. Brand typefaces beyond the logo +7. Licensing and technical checks +8. Common mistakes + +--- + +## 1. Choosing a direction: type study + +1. Set the name in 20–40 candidate typefaces across categories, in lowercase, uppercase and title case. + Starting with type is a legitimate way to begin a logo — once the type is right, the rest can flow from it. +2. Judge by: the shape of the letters *in combination* (not individually), legibility, the rhythm of the word, + how the letters echo the way the word sounds, and how it reads at small size. +3. Shortlist 3–5 and look for **opportunities**: interesting letter pairs, shared strokes, counters that can hold a + shape, a letter that can become a sign, repeated letters that can create rhythm, a natural ligature. +4. Only then customise (see §3). + +Legibility varies with case: some typefaces read better in upper and lower case, others in capitals. Test. + +## 2. Classification and what each voice says + +| Class | Character | Typical voice | +|---|---|---| +| Humanist / Venetian serif | calligraphic stress, low contrast | literary, traditional, warm | +| Old-style serif | moderate contrast, diagonal stress | classic, trustworthy, bookish | +| Transitional serif | sharper, more vertical stress | refined, institutional | +| Modern / Didone | extreme thick–thin contrast, hairlines | fashion, luxury, drama (fragile when small) | +| Slab serif | heavy, block serifs | sturdy, industrial, confident, retro | +| Grotesque / neo-grotesque sans | even, rational | neutral, corporate, modern, "Swiss" | +| Geometric sans | built on circles/squares | modern, clean, tech, optimistic | +| Humanist sans | calligraphic proportions | friendly, readable, approachable | +| Rounded sans | soft terminals | playful, gentle, youthful | +| Script / handwritten | cursive, personal | personal, crafted, elegant or casual | +| Display / custom | idiosyncratic shapes | highly specific personality (dates fastest) | +| Monospace | fixed widths | technical, code, systematic | + +Tone rules of thumb: +- Heavier weights read strong/confident; lighter weights read elegant/quiet (but fragile at small sizes). +- Wide proportions feel stable and expansive; condensed feel efficient, urgent, editorial. +- Lowercase feels approachable; uppercase feels monumental. Title case is the neutral default. +- Serif ↔ sans pairing in one mark can express "heritage + modern" (e.g. a classic ampersand in a modern gothic name). + +## 3. Custom vs. existing type + +- Most viewers can't tell a custom face from a stock one, yet it's precisely the unique attributes of custom + letters that give the client ownership and protect against imitation. An unmodified stock font can be typed by + anyone — including competitors and counterfeiters. +- Levels of customisation, from light to heavy: + 1. Tight custom spacing and kerning of an existing face. + 2. Modify a few letters (a distinctive `a`, `g`, `e`, `R`, a cut terminal, a joined pair, a swapped dot). + 3. Redraw the whole word with a consistent logic (shared radius, stroke contrast, terminal angle). + 4. Draw from scratch on a system (e.g. built on a square grid, or with the symbol's curvature applied to the type). +- **Warning**: the further letterforms depart from familiar shapes, the more quickly they date and the harder they + are to read. +- Reflect the symbol in the type subtly (a corner radius, a cut angle, a stroke ending) — echo, don't duplicate. +- Redraw and re-space existing marks for legibility when refreshing an old logo; making it impossible to reproduce + by typing in any existing font is itself protective. + +## 4. Letterform craft + +- **Spacing is optical, not metric.** Equalise the *area* of space between letters, not the distance. Round letters + (`O`, `C`) sit closer to neighbours than straight ones (`H`, `I`); diagonals (`A`, `V`, `W`) need kerning. +- **Kern for the size of use.** Spacing that works in a book heading may look loose at logo scale or on a building. + Check key pairs (`AV`, `To`, `LT`, `r.`, `ye`). +- **Overshoot**: round letters must extend slightly above cap height/x-height and below the baseline to look equal + in height. +- **Horizontal strokes thinner** than verticals to look equal; thin strokes where they meet at junctions to avoid dark + spots. +- **Consistent stroke logic**: contrast axis, terminal angles, corner radii and aperture should follow one rule. +- **Tittles and dots** (on `i`, `j`) are tempting substitution points; use them only if the substitute reads at small + size and doesn't feel like a cliché. +- **Small-size fixes**: open apertures, larger counters, slightly heavier weight and looser spacing for a + small-use version (optical size) of the wordmark. +- In SVG, final logo type must be **outlined paths**, not `<text>` — see `svg-construction.md`. + +## 5. Lockups: symbol + type + +- A lockup fixes the positions and relative sizes of all elements (symbol, wordmark, tagline). Once locked, they are + never rearranged ad hoc. +- Create several lockups for different formats: **horizontal** (most common for headers/signage), **stacked / + vertical** (square formats, social), **symbol only** (app icon, favicon, avatar), **wordmark only**, **with + tagline**. Simplify complexity as size shrinks — a letterhead lockup may carry more than a mobile header. +- **Balance**: an ornate or detailed symbol pairs with plain, neutral type; a bold symbol pairs with a lighter type + weight. The goal is complement, not contrast for its own sake. +- **Alignment**: align the symbol optically — typically centred on the cap height or x-height band, or spanning + baseline to cap height/ascender. Check by eye; geometric centring often looks low. +- **Spacing**: the gap between symbol and wordmark is usually derived from an element of the mark (e.g. the width + of a stem, the height of the x-height, or a fraction of the symbol's width) so it scales consistently. +- **Tagline**: significantly smaller, a lighter or contrasting style, aligned to the wordmark; define the size ratio + and specify a version without it. Taglines rarely survive at small sizes — drop them there. +- Details like "bold vs slightly more bold" or a small kerning tweak aren't noticed consciously, but they are the + difference between good and great. + +## 6. Brand typefaces beyond the logo + +- Corporate typography is often a different entity from the logo's letterforms. +- **Body/text face**: simple, highly readable, ideally a neutral sans with many weights; consider system/web + availability and cost. +- **Display/headline face**: more freedom, providing contrast with the body text. +- **Limit to two families** in most identities (weights and italics within them are fine). More families dilute + the voice. +- Specify web fallbacks and which faces are licensed for which uses. + +## 7. Licensing and technical checks + +- Free fonts are frequently **personal-use only**. A logo is commercial use: confirm the licence allows logo / + trademark use (some licences restrict it or require a separate logo licence). Open-licence families (e.g. SIL Open + Font License) are generally safe for logos. +- Check glyph coverage: accented characters for all the brand's languages, punctuation, `@`, `&`, numerals, currency + symbols. Incomplete fonts silently substitute or show boxes. +- Prefer professional OpenType fonts with proper kerning tables. +- Once outlined in the logo file, the font is no longer needed to display the logo — but the brand typefaces still + need licences for everyday use. + +## 8. Common mistakes + +- Using the default weight and spacing of a popular geometric sans with no modification — instantly generic. +- Too many typefaces in one mark (a script + a serif + a sans). +- Tracking lowercase text very wide (lowercase is designed to be read tight). +- Effects on type (outlines, drop shadows, bevels, distortion via horizontal/vertical scaling). Never scale type + non-uniformly to fit — choose a condensed/extended width instead. +- Overused faces chosen because they are fashionable this year. +- Thin hairlines or tiny counters that close up at small sizes. +- Letters so customised the name becomes a puzzle. diff --git a/.claude/skills/logo-design/references/visual-techniques.md b/.claude/skills/logo-design/references/visual-techniques.md new file mode 100644 index 0000000..9dd2f45 --- /dev/null +++ b/.claude/skills/logo-design/references/visual-techniques.md @@ -0,0 +1,226 @@ +# Visual Techniques & Optical Corrections + +The craft layer: how forms are perceived, and the small corrections that separate a good mark from a +perfect one. Read during development and refinement (phases 4–5), and when critiquing. + +## Contents +1. Geometry, grids and the golden ratio +2. Balance (stability, proportion, composition, consistency, scalability) +3. Optical corrections: overshoot, bone effect, irradiation, same-size look +4. Composition dynamics between shapes +5. Symmetry vs. asymmetry +6. Solid vs. line +7. Sharp vs. round +8. Negative space & figure/ground +9. Visual paradoxes: impossible figures, ambiguity, motion +10. Gradients, light and shading +11. Dimension +12. Visibility devices (outline, container) +13. Patterns +14. Reviewing with fresh eyes + +--- + +## 1. Geometry, grids and the golden ratio + +- **See the world as simple geometry.** Train yourself to reduce objects to circles, squares, triangles and + their parts. Once you feel the structure behind things, composition becomes easier and the results feel + inevitable. +- **Construct from primitives.** Circles, arcs of consistent radii, straight lines at deliberate angles. + Curves built from circle segments are easy to grid and reproduce; free-drawn curves are harder to justify + and to fix. +- **Golden ratio (≈1.618) and Fibonacci proportions** (1, 2, 3, 5, 8, 13, 21 …) are useful as a standard of + organisation — e.g. circle radii in a construction following 1 : 1.618 or Fibonacci multiples. Use them where + they help; never let numbers overpower a form that already feels right. If a form feels right, the maths + should not get in the way. +- **Whole-number angles.** Aim for clean angles: 0°, 15°, 30°, 45°, 60°, 90°. An element at 43° should be 45°; + 33.46° should become 30° or 35°. Lines that are 1–2° off horizontal/vertical read as mistakes, and clean + angles show the elements were placed deliberately. (Colour values too: prefer whole-number CMYK percentages.) +- **Perfect primitives.** A circle must be a perfect circle and a square a perfect square — unless the deviation + is an intentional optical correction. +- **Gridding is for finishing, not for starting.** Apply construction grids after the concept is approved to find + and fix misalignments, uneven radii and stray angles. The changes are usually too small for viewers to notice + consciously — but they feel the difference. +- **Don't over-grid.** Complex organic curves may not decompose into circles; it's fine to leave them ungridded. + If something doesn't work within the grid, make it work outside the grid. A construction drawing cluttered with + dozens of meaningless circles is a presentation gimmick, not rigour. + +## 2. Balance + +1. **Stability** — the mark should not feel accidentally tilted. There should be a sense of gravity; where the + concept allows, a heavier or wider base feels grounded. +2. **Proportion** — aim for an overall footprint closer to a square than a long rectangle. Very tall or very wide + symbols are awkward to use and to lock up with type. (Library data: ~76 % of standalone icons are between + 0.8 : 1 and 1.25 : 1.) +3. **Composition** — distribute elements and gaps evenly. Clusters in one area and emptiness in another create + dissonance (unless tension is the intent). +4. **Consistency** — keep weights related. Very thick next to very thin reads as imbalance; in line marks, keep + stroke width consistent throughout. Repeat radii and angles. +5. **Scalability** — every decision must survive enlargement and reduction. + +## 3. Optical corrections + +### Overshoot +Round and pointed shapes look smaller than flat-edged shapes of the same measured height. A circle placed +between squares of equal height looks too small; an `O` beside an `H` looks short. Let curves and apexes extend +slightly past the baseline/cap line/edge — typically **1–3 % of the height** for curves and more for sharp points +(triangles/apexes can need 3–6 %). Do it in the final stage, with one or two anchor tweaks. This is the +difference between great and perfect. + +### Bone effect +Where a curve meets a straight line tangentially (a capsule: two semicircles joined by straight sides; rounded +rectangles; rounded triangles), the straight segment appears to pinch inward like a bone. Fixes, from quick to best: +1. Stretch the end curves into ellipses (softens but doesn't remove it). +2. Pull the curve handles so curvature ramps up gradually instead of jumping from zero to the full circle. +3. Use a smooth curvature transition (a "squircle"/superellipse-like corner): extra anchors that ease from straight + to curved; copy the tuned curve to the symmetrical corners. +Not every instance needs fixing — sometimes the bone effect is expressive (bulkiness in a figure). Fixing it often +frees up interior space and makes rounded marks crisper at small sizes. In SVG, prefer continuous-curvature +corners (cubic Béziers with handles ≈ 0.55–0.65 of the corner size, extended past the tangent point) over plain +`rx` arcs when the corner is prominent. + +### Irradiation: white on black looks bigger +A light shape on a dark background appears larger and bolder than the identical dark shape on a light background. +Consequences: +- A reversed (white-on-dark) logo looks heavier. Provide a **reversed version with slightly thinned strokes** + (roughly 2–5 % of stroke weight), or scale the reversed version down slightly. Achieve it by offsetting the path + inward (expand a thin stroke and subtract it from the shape). +- Test both versions side by side until they look equal; record which file to use in the guidelines. +- Thin white lines on dark grounds can visually "bloom" and fill in when printed; keep counters open. + +### Same-size look for mixed shapes +Circles, squares and triangles of the same bounding box do not look the same size. Equalise by eye: circles +slightly larger than squares; triangles larger still. Same for icons in a set. + +### Horizontal vs. vertical strokes +Horizontal strokes look heavier than vertical strokes of equal thickness. In lettering and geometric marks, make +horizontals slightly thinner (often 5–10 %) to look equal. Where strokes meet at acute angles, thin them near the +junction to avoid dark ink traps and blobs at small sizes. + +### Optical centre +The optical centre of an area sits slightly above the geometric centre. A mark centred mathematically in a +container often looks low; nudge it up a little. Asymmetric shapes (a triangle pointing right, a play button) need +to be shifted toward their visual mass, not their bounding box. + +## 4. Composition dynamics between shapes + +Shapes interacting create feelings. First define the goal — harmony, tension, dynamism, balance, dissonance, +entropy — then arrange. +- Circle resting on a square of the same width → harmony, stability. +- Square balanced on a circle → tension, instability. +- Circle beside the apex of a triangle → motion. +- Circle exactly on top of a triangle's apex → balanced tension. +- Diagonals and tapering forms → movement; horizontals → calm; verticals → aspiration, strength. +- Density increasing across a form (sparse → dense lines or dots) → implied motion. + +Years of playing with forms build the intuition; in the meantime, test variations side by side. + +## 5. Symmetry vs. asymmetry + +- Perfect mirror symmetry is stable and formal but often boring; repetition by mirroring can feel mechanical. +- A subtle asymmetry keeps the eye travelling: a change in colour on one side, a detail added or removed, an + offset element, a mirrored-then-shifted part. +- Especially useful when the overall silhouette is symmetrical — let one detail break it. +- Symmetry still has its place for institutions and marks that must feel absolute (seals, public bodies). + +## 6. Solid vs. line + +- **Solid marks** look stable and strong; silhouettes stay clear when small and from a distance; bold shapes reproduce + well across media. +- **Line (monoline/outline) marks** look light and elegant; good for passive or refined brands, UI iconography and + interior signage. Downsides: weak from a distance and at small sizes unless strokes are thick enough; they are + more vulnerable to bad reproduction. +- If a mark works both ways, choose one as **primary** and the other as secondary. +- In the final SVG, expand strokes into filled outlines (see `svg-construction.md`), so scaling does not change the + line-to-size ratio unpredictably. + +## 7. Sharp vs. round + +- Sharp, angular forms read as assertive, authoritative, technical, sometimes threatening — we instinctively treat + sharp objects with caution. +- Rounded forms read as friendly, inviting, soft, safe — we want to touch and hold them. +- Keep sharp elements out of the silhouette unless the brand needs edge (security, sport, performance, luxury + precision). Most brands want to feel approachable, so rounded corners are a sensible default — but a slightly + rounded corner (small radius) often reads more premium than fully pill-shaped forms. +- Mixing: a sharp exterior with soft interior details (or vice versa) can express duality ("secure but friendly"). + +## 8. Negative space & figure/ground + +- Every silhouette has surrounding space. Treat the negative shapes (counters, gaps, space between elements) with the + same care as the positive shapes — the inner shapes of letters echoing the outer form create coherence. +- Clever negative space (a hidden arrow, an animal between two shapes, a letter carved out of an object) creates a + moment of discovery. Keep it simple: two elements with distinct silhouettes, conceptually related. +- Gaps must be large enough to survive reduction; a 1 px gap at 32 px disappears. As a rule of thumb, make the + smallest gap ≥ 1/32 of the mark's width if it must read at favicon sizes. + +## 9. Visual paradoxes + +When something appears to be one thing and becomes another on closer inspection, the mind solves a small problem and +enjoys the solution. Three families: +1. **Impossible figures** — shapes that can't exist in 3D (reversed perspective, manipulated line connections, + misaligned layers). Study the concept, don't copy famous figures; transpose the principle (e.g. a letter whose + perspective switches direction halfway). +2. **Ambiguous forms** — one image that reads as two. Rare to succeed intentionally. The bigger risk is the + *unintended* reading: after hours of work a designer stops seeing what is obvious to others (including sexual or + offensive readings). Always ask fresh eyes, rotate the mark 90/180°, view it tiny and mirrored. +3. **Motion illusions** — tapering sweeps, speed lines, progressive repetition. For speed, run the form from thin to + thick in the reading direction (left to right in Latin-script cultures); consider right-to-left audiences. + +Other tools for turning a mundane shape into something memorable: layering, interlacing, overlapping with +transparency, juxtaposing flat and dimensional, and playing with colour at intersections. + +## 10. Gradients, light and shading + +- **Gradients are easy and therefore cliché.** They can soften a mark and add depth, but they reproduce poorly: + vivid RGB gradients lose vigour in CMYK print and blur at small sizes. Unless the logo is digital-only, keep a flat + version as the master and treat gradients as an optional enhancement. +- **Simplify gradation.** Replace a smooth gradient with a few distinct steps (3–5 flat bands of related hues). At + small sizes the steps read as seamless; at large sizes they look crafted rather than default. +- **Light and shading for plain marks.** Simple is not always attractive — some marks look plain because they lack + content. Introducing a light source (a fold, an overlap shadow, a highlight) can add depth and sophistication. If the + mark is interesting in its reduced state, don't add light. +- **Few tones.** Many shades of grey kill sharpness at small sizes. Use at most highlight, one mid-tone, shadow and + background ("light–dark" chiaroscuro reduction). For letterforms and abstract marks, one mid-tone applied to the + parts that fold under or overlap others is usually enough. +- **Structure of light on a sphere**: highlight, midtone, core shadow, reflected light, cast shadow, occlusion shadow. + Understand it to shade any form convincingly; then reduce to 2–3 tones. +- **Tapered strokes (engraving style)**: tonal gradation built from arrow-like strokes that thin toward the tip — a + versatile way to render volume on organic forms. Time-consuming; reserve for brands where craft is the message. + +## 11. Dimension + +- Realistic 3D renders carry too much detail for logos. +- Dimension achieved by the simplest means — two or three flat faces, an isometric fold, an overlap — can be striking + and widens the space of original solutions, since flat combinations of primitives are largely exhausted. +- Always keep a version that works flat and in one colour. + +## 12. Visibility devices + +A logo designed for light backgrounds may not invert well (a white swan inverted becomes a black swan — maybe desired, +maybe not). For busy, photographic or multicoloured backgrounds use a **graphic device**: +- An outline (a sufficiently thick light stroke around the silhouette), or +- A containing shape: circle for circular marks; square or rounded square for most others (the safest for rectangular + formats and app icons). A basic container may not be the most beautiful, but it is functional. +- The device's proportions should match the mark's (square mark → square device; wide mark → wide device); mismatches + create distracting empty space. + +## 13. Patterns + +- A grid is the heart of a pattern. Square grids are the most versatile but most common → sameness. Try triangles, + hexagons, rotated squares (diamonds), or grids derived from the mark's angles. +- Plain tessellations are straightforward but get boring; prefer grids that allow variation. +- Distribute colour evenly; too much contrast disrupts flow, too little makes it invisible. +- Derive components from the mark when possible so the pattern and logo feel related without duplicating. +- Test at multiple scales (card, wall, vehicle) and, for print, keep ink coverage reasonable. + +## 14. Reviewing with fresh eyes (the dialectical approach) + +- **Save every meaningful iteration** side by side instead of overwriting. Designers often favour a lesser variant + in the moment of excitement and lose the better one. +- **Compare pairs** directly and pick the stronger; then iterate from the winner. +- **Rest before deciding** — fatigue makes judgement less objective. +- **Mirror the mark.** Flipping horizontally reveals proportion problems the eye has adapted to (especially in + animals and figures). +- **Blur/squint and shrink.** If the silhouette is unclear when blurred, the idea is not strong enough. +- **Physical aids**: for complex figures, references and simple 3D mock-ups (paper, clay, wire) reveal better + viewpoints and inconsistencies. diff --git a/.claude/skills/logo-design/scripts/build_catalog.py b/.claude/skills/logo-design/scripts/build_catalog.py new file mode 100644 index 0000000..bbaa1d5 --- /dev/null +++ b/.claude/skills/logo-design/scripts/build_catalog.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 +"""Rebuild the reference-library catalog from the SVG files + visual classifications. + +Maintainer tool. Produces, inside assets/library/: + catalog.json one record per SVG (structure, colours, complexity + visual classification) + stats.json distribution statistics used by svg_audit.py for comparisons + gallery.html a self-contained, filterable browser for humans (open it locally) + +Usage: + python3 scripts/build_catalog.py # rebuild everything + python3 scripts/build_catalog.py --check # verify every SVG has a classification + +To add logos: drop SVGs into assets/library/svg/, add matching objects to +assets/library/classifications.json (schema: see references/library-guide.md), then rerun. +""" +import argparse +import json +import os +import statistics +import sys +from collections import Counter + +sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import svglib # noqa: E402 + +CLASS_PATH = os.path.join(svglib.LIBRARY_DIR, "classifications.json") +GALLERY_PATH = os.path.join(svglib.LIBRARY_DIR, "gallery.html") + + +def analyse(path, names): + fname = os.path.basename(path) + base = fname[:-4] + is_icon = base.endswith("-icon") + brand = base[:-5] if is_icon else base + raw, root = svglib.load_svg(path) + vb = svglib.view_box(root) + w, h = (vb[2], vb[3]) if vb else (None, None) + aspect = round(w / h, 3) if w and h else None + counts = svglib.element_counts(root) + geo = svglib.document_geometry(root) + colors = svglib.collect_colors(root) + fams = Counter(svglib.hue_family(c) for c in colors) + chroma = sorted({f for f in fams if f not in ("black", "white", "gray")}) + if len(chroma) == 1: + primary = chroma[0] + elif len(chroma) > 1: + primary = "multi" + else: + primary = "mono" + pair = None + if is_icon and brand in names: + pair = brand + ".svg" + elif not is_icon and (brand + "-icon") in names: + pair = brand + "-icon.svg" + return { + "file": fname, + "brand": brand, + "variant": "icon" if is_icon else "main", + "pair": pair, + "width": w, + "height": h, + "aspect": aspect, + "aspect_class": svglib.aspect_class(aspect), + "bytes": os.path.getsize(path), + "shapes": sum(counts.get(t, 0) for t in svglib.SHAPE_TAGS), + "anchors": geo["anchors"], + "colors": colors, + "n_colors": len(colors), + "color_families": sorted(fams), + "primary_family": primary, + "gradients": counts.get("linearGradient", 0) + counts.get("radialGradient", 0), + "has_mask": counts.get("mask", 0) > 0, + "has_filter": counts.get("filter", 0) > 0, + } + + +def pct(values, q): + values = sorted(values) + if not values: + return None + k = (len(values) - 1) * q + f, c = int(k), min(int(k) + 1, len(values) - 1) + return round(values[f] + (values[c] - values[f]) * (k - f), 2) + + +def build_stats(records): + def dist(vals): + return {"p10": pct(vals, .1), "p25": pct(vals, .25), "median": pct(vals, .5), + "p75": pct(vals, .75), "p90": pct(vals, .9), "p95": pct(vals, .95)} + icons = [r for r in records if r["aspect_class"] == "square"] + n = len(records) + return { + "count": n, + "anchors_all": dist([r["anchors"] for r in records]), + "anchors_square": dist([r["anchors"] for r in icons]), + "shapes_all": dist([r["shapes"] for r in records]), + "n_colors_all": dist([r["n_colors"] for r in records]), + "n_colors_square": dist([r["n_colors"] for r in icons]), + "gradient_share": round(sum(1 for r in records if r["gradients"]) / n, 3), + "mark_types": Counter(r.get("mark_type") for r in records).most_common(), + "primary_family": Counter(r["primary_family"] for r in records).most_common(), + "aspect_class": Counter(r["aspect_class"] for r in records).most_common(), + "techniques": Counter(t for r in records for t in r.get("techniques", [])).most_common(), + "geometry": Counter(g for r in records for g in r.get("geometry", [])).most_common(), + "industries": Counter(r.get("industry") for r in records).most_common(), + } + + +GALLERY_TEMPLATE = """<!doctype html> +<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"> +<title>Logo Reference Library + +

Logo Reference Library — for studying patterns; all marks are trademarks of their owners. Never copy.

+
+ + + + + + + + +
+
+ +""" + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--check", action="store_true", help="only verify classification coverage") + args = ap.parse_args() + + files = sorted(f for f in os.listdir(svglib.LIBRARY_SVG_DIR) if f.lower().endswith(".svg")) + names = {f[:-4] for f in files} + classes = {} + if os.path.exists(CLASS_PATH): + with open(CLASS_PATH, encoding="utf-8") as fh: + classes = {c["file"]: c for c in json.load(fh)} + missing = [f for f in files if f not in classes] + if args.check: + print(f"{len(files)} SVGs, {len(classes)} classifications, {len(missing)} missing") + for f in missing: + print(" missing:", f) + return 1 if missing else 0 + + records = [] + for f in files: + try: + rec = analyse(os.path.join(svglib.LIBRARY_SVG_DIR, f), names) + except Exception as exc: # keep going; report broken files + print(" ! could not parse", f, exc, file=sys.stderr) + continue + c = classes.get(f, {}) + for key in ("mark_type", "symbol_type", "subject", "geometry", "techniques", "type_style", "case", + "mood", "industry", "exemplary", "note"): + rec[key] = c.get(key) + rec["techniques"] = rec["techniques"] or [] + rec["geometry"] = rec["geometry"] or [] + rec["mood"] = rec["mood"] or [] + rec["exemplary"] = bool(rec["exemplary"]) + records.append(rec) + + with open(svglib.CATALOG_PATH, "w", encoding="utf-8") as fh: + json.dump(records, fh, ensure_ascii=False, separators=(",", ":")) + stats = build_stats(records) + with open(svglib.STATS_PATH, "w", encoding="utf-8") as fh: + json.dump(stats, fh, ensure_ascii=False, indent=1) + slim = [{k: r[k] for k in ("file", "brand", "mark_type", "symbol_type", "subject", "techniques", "geometry", + "industry", "exemplary", "note", "n_colors", "primary_family", "aspect_class")} + for r in records] + with open(GALLERY_PATH, "w", encoding="utf-8") as fh: + fh.write(GALLERY_TEMPLATE.replace("__DATA__", json.dumps(slim, ensure_ascii=False))) + print(f"catalog: {len(records)} records -> {svglib.CATALOG_PATH}") + print(f"stats -> {svglib.STATS_PATH}") + print(f"gallery -> {GALLERY_PATH}") + if missing: + print(f"warning: {len(missing)} SVGs have no classification (run with --check)") + print("median anchors (square):", stats["anchors_square"]["median"], "| p90:", stats["anchors_square"]["p90"]) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.claude/skills/logo-design/scripts/concept_sheet.py b/.claude/skills/logo-design/scripts/concept_sheet.py new file mode 100644 index 0000000..bac44cb --- /dev/null +++ b/.claude/skills/logo-design/scripts/concept_sheet.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +"""Build a one-page concept overview (SVG + PNG) to show the user BEFORE any kit is produced. + +Each concept gets a card: the artwork large, the same mark at 64 / 32 / 16 px (so scale is judged honestly), +a letter + name, and a one-line idea. Optionally a secondary file per concept (e.g. the lockup) under the symbol. +The PNG is rendered with render_png.py's backends (cairosvg, rsvg-convert, Inkscape, Chrome, Quick Look); +the SVG is always written. + +Usage: + python3 scripts/concept_sheet.py a.svg b.svg c.svg --names "Next Block" "Ranked F" "Forward f" \\ + --notes "One block steps forward: the next move." "An F of ranked priority bars." "The i-dot steps ahead." \\ + --title "Fabbit — logo concepts" --recommend 1 -o concepts.png + python3 scripts/concept_sheet.py a.svg b.svg c.svg --lockups a-h.svg b-h.svg c-h.svg --greyscale -o round1.png + +Show the resulting PNG to the user (view it yourself first), then stop and ask how to proceed. +""" +import argparse +import html +import os +import re +import sys + +sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import render_png # noqa: E402 +import svglib # noqa: E402 + + +def embed(path, key, x, y, w, h): + """Nested that fits the file into the box; ids are prefixed so several files can coexist.""" + raw = open(path, encoding="utf-8", errors="ignore").read() + raw = re.sub(r"<\?xml[^>]*\?>|]*>", "", raw, flags=re.I) + raw = re.sub(r'\bid="([^"]+)"', lambda m: f'id="{key}-{m.group(1)}"', raw) + raw = re.sub(r"url\(#([^)]+)\)", lambda m: f"url(#{key}-{m.group(1)})", raw) + raw = re.sub(r'(xlink:href|href)="#([^"]+)"', lambda m: f'{m.group(1)}="#{key}-{m.group(2)}"', raw) + m = re.search(r"]*>", raw) + tag = m.group(0) + root_vb = svglib.view_box(svglib.load_svg(path)[1]) + vb = f' viewBox="{root_vb[0]:g} {root_vb[1]:g} {root_vb[2]:g} {root_vb[3]:g}"' if root_vb else "" + new_tag = re.sub(r'\s(width|height|x|y|viewBox|preserveAspectRatio)\s*=\s*"[^"]*"', "", tag) + new_tag = new_tag[:-1].rstrip("/") + f'{vb} x="{x:g}" y="{y:g}" width="{w:g}" height="{h:g}" preserveAspectRatio="xMidYMid meet">' + return raw.replace(tag, new_tag, 1) + + +def wrap(text, limit): + words, lines, line = text.split(), [], "" + for w in words: + if len(line) + len(w) + 1 > limit and line: + lines.append(line) + line = "" + line += (" " if line else "") + w + if line: + lines.append(line) + return lines + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("files", nargs="+", help="one SVG per concept (usually the symbol)") + ap.add_argument("--lockups", nargs="*", default=[], help="optional second file per concept (lockup/wordmark)") + ap.add_argument("--names", nargs="*", default=[]) + ap.add_argument("--notes", nargs="*", default=[], help="one-sentence idea per concept") + ap.add_argument("--title", default="Logo concepts") + ap.add_argument("--subtitle", default="Concepts for review — pick a direction (or tell me what you like in each).") + ap.add_argument("--recommend", type=int, help="1-based index of the recommended concept") + ap.add_argument("--greyscale", action="store_true", help="show everything in greyscale (first-round rule)") + ap.add_argument("--width", type=int, default=1600) + ap.add_argument("-o", "--out", default="concepts.png", help="output .png (an .svg is written next to it)") + a = ap.parse_args() + + n = len(a.files) + cols = min(n, 3) + rows = (n + cols - 1) // cols + W, pad, gap = a.width, 60, 28 + card_w = (W - 2 * pad - (cols - 1) * gap) / cols + has_lock = bool(a.lockups) + art_h = 300 + lock_h = 0 + if has_lock: + ratios = [] + for lp in a.lockups: + if lp: + vb = svglib.view_box(svglib.load_svg(lp)[1]) + if vb and vb[3]: + ratios.append(vb[2] / vb[3]) + # wide lockups fit a short slot; squarish ones (emblems, stacked lockups) need more height + lock_h = 120 if not ratios or min(ratios) >= 2.2 else (170 if min(ratios) >= 1.4 else 210) + card_h = 40 + art_h + (lock_h + 24 if has_lock else 0) + 90 + 150 + (30 if a.recommend else 0) + 20 + header = 150 + H = header + rows * card_h + (rows - 1) * gap + pad + parts = [] + filt = ('' if a.greyscale else "") + gattr = ' filter="url(#grey)"' if a.greyscale else "" + font = "font-family=\"system-ui,-apple-system,'Segoe UI',Helvetica,Arial,sans-serif\"" + parts.append(f'') + parts.append(f'{html.escape(a.title)}') + parts.append(f'{html.escape(a.subtitle)}') + for i, f in enumerate(a.files): + r, c = divmod(i, cols) + x = pad + c * (card_w + gap) + y = header + r * (card_h + gap) + rec = a.recommend == i + 1 + parts.append(f'') + inner_x, inner_w = x + 30, card_w - 60 + parts.append(f"" + embed(f, f"c{i}", inner_x, y + 40, inner_w, art_h) + "") + yy = y + 40 + art_h + if has_lock and i < len(a.lockups) and a.lockups[i]: + yy += 24 + parts.append(f"" + embed(a.lockups[i], f"l{i}", inner_x, yy, inner_w, lock_h) + "") + yy += lock_h + # small sizes: 64 / 32 / 16 px, as they would appear + sx = inner_x + yy += 26 + for s in (64, 32, 16): + parts.append(f"" + embed(f, f"s{i}{s}", sx, yy + (64 - s), s, s) + "") + parts.append(f'{s}px') + sx += s + 26 + yy += 120 + label = f"{chr(65 + i)} · {a.names[i] if i < len(a.names) else os.path.splitext(os.path.basename(f))[0]}" + parts.append(f'{html.escape(label)}') + if rec: + parts.append(f'RECOMMENDED') + yy += 28 + note = a.notes[i] if i < len(a.notes) else "" + for k, line in enumerate(wrap(note, int(inner_w / 9.6))[:3]): + parts.append(f'{html.escape(line)}') + doc = (f'{filt}{"".join(parts)}\n') + base = os.path.splitext(a.out)[0] + svg_path = base + ".svg" + with open(svg_path, "w", encoding="utf-8") as fh: + fh.write(doc) + print("wrote", svg_path) + png_path = base + ".png" + used = render_png.render(svg_path, png_path, W, int(round(H))) + if used: + print(f"wrote {png_path} via {used} — view it, show it to the user, then stop and ask") + else: + print("PNG skipped (no renderer; see render_png.py --which) — show the SVG instead") + + +if __name__ == "__main__": + main() diff --git a/.claude/skills/logo-design/scripts/export_variants.py b/.claude/skills/logo-design/scripts/export_variants.py new file mode 100644 index 0000000..897c909 --- /dev/null +++ b/.claude/skills/logo-design/scripts/export_variants.py @@ -0,0 +1,233 @@ +#!/usr/bin/env python3 +"""Export the standard delivery variants of a logo from one master SVG (no required dependencies). + +SVG variants (next to the master, or in --out-dir): + -black.svg one-colour black (all paint -> #000000; gradients flattened) + -white.svg one-colour white, for dark backgrounds + -mono-.svg one-colour in a brand colour (repeatable --mono) + -square.svg mark centred on a 256×256 canvas with padding (avatar / social master) + -favicon.svg tight square version for browser tabs (works as favicon.svg) + -app-icon.svg mark in white (or --icon-fg) on a rounded-square tile (--icon-bg) + +Raster (needs any backend of render_png.py: cairosvg, rsvg-convert, inkscape, Chrome/Chromium, or macOS Quick Look): + --png 32 512 1024 PNGs of every SVG variant written (transparent) + --web-icons favicon.ico (16/32/48), favicon-16/32/48.png, apple-touch-icon.png (180), + icon-192.png, icon-512.png, maskable-512.png, plus site.webmanifest and + head-snippet.html — the full web/PWA icon set + +Usage: + python3 scripts/export_variants.py brand-symbol.svg --mono "#0F7C80" --icon-bg "#0F7C80" --title "Brand" + python3 scripts/export_variants.py brand-horizontal.svg --only black white mono --mono "#0F7C80" + python3 scripts/export_variants.py brand-symbol.svg --web-icons --icon-bg "#0F7C80" --out-dir dist/web + python3 scripts/export_variants.py brand-symbol.svg --favicon-source brand-symbol-small.svg --web-icons + +Notes: +- One-colour conversion replaces every fill/stroke/stop colour. White shapes used as fake cut-outs become + blobs: fix the master with real holes (fill-rule="evenodd"), or use --keep-white. +- Reversed (white) marks look heavier (irradiation); for critical uses thin the white geometry by hand. +- Small sizes deserve a simplified drawing: pass it with --favicon-source (used for favicon/app icon/web icons). +- Optical centring: --optical-offset -0.02 nudges square/app-icon/favicon marks up by 2 % of the canvas. +""" +import argparse +import html +import json +import os +import re +import sys +import tempfile + +sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import svglib # noqa: E402 +import render_png # noqa: E402 + +PAINT_ATTR = re.compile(r'\b(fill|stroke|stop-color)\s*=\s*"([^"]*)"') +PAINT_CSS = re.compile(r'\b(fill|stroke|stop-color)\s*:\s*([^;"}]+)') + + +def recolor(raw, color, keep_white=False): + def swap(value): + v = value.strip() + low = v.lower() + if low in ("none", "transparent") or low.startswith("url("): + return v + norm = svglib.normalize_color(v) or (low if low == "currentcolor" else None) + if norm is None: + return v + if keep_white and norm == "#ffffff": + return v + return color + + raw = PAINT_ATTR.sub(lambda m: f'{m.group(1)}="{swap(m.group(2))}"', raw) + raw = PAINT_CSS.sub(lambda m: f"{m.group(1)}:{swap(m.group(2))}", raw) + # Unpainted shapes default to black; give the root a fill so they follow the new colour. + raw = re.sub(r"]*\bfill=)", f'.*?", "", raw, flags=re.S) + return re.sub(r"(]*>)", lambda m: m.group(1) + f"{html.escape(title)}", raw, count=1) + + +def inner_markup(raw): + m = re.search(r"]*>(.*)", raw, re.S) + body = m.group(1) if m else raw + return re.sub(r".*?", "", body, flags=re.S) + + +def square_wrap(raw, root, padding=0.1, bg=None, radius=0.0, fg=None, symbol_scale=None, offset=0.0, title=None): + """Centre the artwork's real bounding box on a 256×256 canvas (optionally on a rounded tile).""" + vb = svglib.view_box(root) + geo = svglib.document_geometry(root) + bb = geo["bbox"] or (vb[0], vb[1], vb[0] + vb[2], vb[1] + vb[3]) + w, h = bb[2] - bb[0], bb[3] - bb[1] + side = max(w, h) + canvas = 256.0 + target = symbol_scale if symbol_scale else (1 - 2 * padding) + s = round(canvas * target / side, 3) + tx = round((canvas - w * s) / 2 - bb[0] * s, 2) + ty = round((canvas - h * s) / 2 - bb[1] * s + offset * canvas, 2) + src = recolor(raw, fg) if fg else raw + body = inner_markup(src) + root_tag = re.search(r"]*>", src) + carried = "" + if root_tag: + for attr in ("fill", "stroke", "fill-rule", "clip-rule", "stroke-width", "stroke-linecap", "stroke-linejoin", "style"): + m = re.search(r'\s%s\s*=\s*"([^"]*)"' % re.escape(attr), root_tag.group(0)) + if m: + carried += f' {attr}="{m.group(1)}"' + tile = f'' if bg else "" + t = f"{html.escape(title)}" if title else "" + return (f'{t}' + f'{tile}{body}') + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("master") + ap.add_argument("--out-dir") + ap.add_argument("--name", help="base name for outputs (default: master file name)") + ap.add_argument("--title", help="accessible for every output, e.g. 'Harbor logo'") + ap.add_argument("--mono", action="append", default=[], help="extra one-colour version(s), e.g. '#0F7C80'") + ap.add_argument("--icon-bg", default="#111111", help="app-icon / apple-touch / maskable tile colour") + ap.add_argument("--icon-fg", default="#ffffff", help="mark colour on tiles ('keep' = original colours)") + ap.add_argument("--icon-scale", type=float, default=0.62, help="mark size on the app-icon tile (0.55–0.7 typical)") + ap.add_argument("--optical-offset", type=float, default=0.0, help="vertical nudge for square outputs (fraction; negative = up)") + ap.add_argument("--favicon-source", help="simplified small-size drawing used for favicon/app-icon/web icons") + ap.add_argument("--keep-white", action="store_true", help="leave pure-white paint untouched in one-colour versions") + ap.add_argument("--only", nargs="*", help="subset: black white mono square favicon app-icon") + ap.add_argument("--png", nargs="*", type=int, default=[], help="PNG sizes for every SVG variant written") + ap.add_argument("--web-icons", action="store_true", help="favicon.ico + PNG icon set + webmanifest + head snippet") + a = ap.parse_args() + + raw, root = svglib.load_svg(a.master) + small_raw, small_root = svglib.load_svg(a.favicon_source) if a.favicon_source else (raw, root) + out_dir = a.out_dir or os.path.dirname(os.path.abspath(a.master)) + os.makedirs(out_dir, exist_ok=True) + base = a.name or os.path.splitext(os.path.basename(a.master))[0] + want = set(a.only) if a.only else {"black", "white", "mono", "square", "favicon", "app-icon"} + fg = None if a.icon_fg == "keep" else a.icon_fg + written = [] + + def write(suffix, content): + p = os.path.join(out_dir, f"{base}-{suffix}.svg") + with open(p, "w", encoding="utf-8") as fh: + fh.write(content) + written.append(p) + return p + + if "black" in want: + write("black", set_title(recolor(raw, "#000000", a.keep_white), a.title)) + if "white" in want: + write("white", set_title(recolor(raw, "#ffffff"), a.title)) + if "mono" in want: + for c in a.mono: + hx = svglib.normalize_color(c) + if not hx: + print("skip invalid colour", c) + continue + write(f"mono-{hx[1:]}", set_title(recolor(raw, hx, a.keep_white), a.title)) + if "square" in want: + write("square", square_wrap(raw, root, padding=0.08, offset=a.optical_offset, title=a.title)) + if "favicon" in want: + write("favicon", square_wrap(small_raw, small_root, padding=0.02, offset=a.optical_offset, title=a.title)) + if "app-icon" in want: + write("app-icon", square_wrap(small_raw, small_root, bg=a.icon_bg, radius=0.225, fg=fg, + symbol_scale=a.icon_scale, offset=a.optical_offset, title=a.title)) + + colors = svglib.collect_colors(root) + if any(svglib.lightness(c) > 0.97 for c in colors) and len(colors) > 1: + print("note: master contains white paint — check the one-colour files for blobs (fake cut-outs).") + + raster = [] + if a.png: + for p in list(written): + for size in a.png: + txt = open(p, encoding="utf-8").read() + vb = re.search(r'viewBox\s*=\s*"[\d.\-]+[ ,]+[\d.\-]+[ ,]+([\d.]+)[ ,]+([\d.]+)"', txt) + ratio = float(vb.group(1)) / float(vb.group(2)) if vb else 1.0 + w, h = (size, max(1, round(size / ratio))) if ratio >= 1 else (max(1, round(size * ratio)), size) + png = p[:-4] + f"-{size}.png" + if render_png.render(p, png, w, h): + raster.append(png) + else: + print("PNG export skipped: no rendering backend (see: python3 scripts/render_png.py --which)") + break + + if a.web_icons: + with tempfile.TemporaryDirectory() as tmp: + fav_svg = os.path.join(tmp, "fav.svg") + with open(fav_svg, "w", encoding="utf-8") as fh: + fh.write(square_wrap(small_raw, small_root, padding=0.02, offset=a.optical_offset, title=a.title)) + tile_svg = os.path.join(tmp, "tile.svg") + with open(tile_svg, "w", encoding="utf-8") as fh: + fh.write(square_wrap(small_raw, small_root, bg=a.icon_bg, radius=0.0, fg=fg, + symbol_scale=a.icon_scale, offset=a.optical_offset)) + mask_svg = os.path.join(tmp, "mask.svg") # maskable: keep the mark inside the 80 % safe zone + with open(mask_svg, "w", encoding="utf-8") as fh: + fh.write(square_wrap(small_raw, small_root, bg=a.icon_bg, radius=0.0, fg=fg, + symbol_scale=min(a.icon_scale, 0.5), offset=a.optical_offset)) + jobs = [(fav_svg, "favicon-16.png", 16), (fav_svg, "favicon-32.png", 32), (fav_svg, "favicon-48.png", 48), + (tile_svg, "apple-touch-icon.png", 180), (tile_svg, "icon-192.png", 192), + (tile_svg, "icon-512.png", 512), (mask_svg, "maskable-512.png", 512)] + ok = True + for src, fname, size in jobs: + dst = os.path.join(out_dir, fname) + if render_png.render(src, dst, size, size): + raster.append(dst) + else: + ok = False + print(f"web icons skipped: could not render {fname} (see: python3 scripts/render_png.py --which)") + break + if ok: + ico = os.path.join(out_dir, "favicon.ico") + render_png.write_ico([os.path.join(out_dir, f"favicon-{s}.png") for s in (16, 32, 48)], ico) + raster.append(ico) + fav_copy = os.path.join(out_dir, "favicon.svg") + with open(fav_svg, encoding="utf-8") as src, open(fav_copy, "w", encoding="utf-8") as dst: + dst.write(src.read()) + raster.append(fav_copy) + manifest = {"name": a.title or base, "icons": [ + {"src": "/icon-192.png", "sizes": "192x192", "type": "image/png"}, + {"src": "/icon-512.png", "sizes": "512x512", "type": "image/png"}, + {"src": "/maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable"}], + "theme_color": a.icon_bg, "background_color": a.icon_bg, "display": "standalone"} + with open(os.path.join(out_dir, "site.webmanifest"), "w", encoding="utf-8") as fh: + json.dump(manifest, fh, indent=2) + with open(os.path.join(out_dir, "head-snippet.html"), "w", encoding="utf-8") as fh: + fh.write('\n' + '\n' + '\n' + '\n' + f'\n') + raster += [os.path.join(out_dir, "site.webmanifest"), os.path.join(out_dir, "head-snippet.html")] + + for p in written + raster: + print("wrote", p) + + +if __name__ == "__main__": + main() diff --git a/.claude/skills/logo-design/scripts/presentation_board.py b/.claude/skills/logo-design/scripts/presentation_board.py new file mode 100644 index 0000000..5a40195 --- /dev/null +++ b/.claude/skills/logo-design/scripts/presentation_board.py @@ -0,0 +1,409 @@ +#!/usr/bin/env python3 +"""Build a client-ready concept presentation (single HTML file, no dependencies). + +Follows references/presentation-delivery.md: title, "what we heard", then each concept with its +one-sentence idea, rationale, the mark large / small / reversed, and six mockups chosen for the client's +industry, followed by a side-by-side comparison and a recommendation. Greyscale by default for a first +round; set "greyscale": false for colour, and "final": true for a single final-design board. + +Usage: + python3 scripts/presentation_board.py spec.json -o presentation.html + python3 scripts/presentation_board.py spec.json -o board.html --png-dir slides # + one PNG per slide + python3 scripts/presentation_board.py --list-mockups + +spec.json (paths relative to the spec file; see templates/presentation-spec.example.json): +{ + "brand": "Kiln", "tagline": "Small-batch roasters", "brief": "…", "adjectives": ["warm", "crafted"], + "industry": "coffee", # picks relevant mockups (see --list-mockups) + "mockups": ["cup", "bag", "social"], # optional explicit list (overrides industry preset) + "nav": ["Shop", "Cafés", "Story"], # optional website menu items + "brand_color": "#B5532F", "greyscale": true, "final": false, "round": 1, + "concepts": [ + {"name": "Kiln K", "symbol": "b-symbol.svg", "lockup": "b-horizontal.svg", "stacked": "b-stacked.svg", "avatar": "b-avatar.svg", + "idea": "One sentence.", "rationale": ["…", "…"]} + ], + "recommendation": "…" +} +Each concept needs at least one of symbol / lockup / avatar; "stacked" (optional) is used on bags, signs and badges. +Optional colour artwork (otherwise the mark is forced to white on those surfaces): + "symbol_on_tile" / "stacked_on_tile" (or "lockup_on_tile") — for brand-colour tiles (cards, app icon, cup, shirt, bag); + "symbol_on_dark" / "lockup_on_dark" / "stacked_on_dark" — for the near-black signage, README, terminal and reversed strip. +Top-level "tile_color" overrides brand_color for the tiles (e.g. a dark ink so a bright second colour can show). +Missing ones fall back sensibly +(a wordmark-only concept can provide just "lockup" plus an "avatar" for small uses). +""" +import argparse +import datetime +import html +import json +import os +import re +import sys +import unicodedata + +sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import svglib # noqa: E402 + +PRESETS = { + "software": ["readme", "app-icon", "website", "terminal", "sticker", "social"], + "consumer-app": ["app-icon", "website", "social", "favicon-tab", "sticker", "business-card"], + "coffee": ["cup", "bag", "signage", "business-card", "social", "tote"], + "food": ["bag", "cup", "signage", "box", "social", "business-card"], + "retail": ["shopping-bag", "signage", "website", "box", "social", "tote"], + "fashion": ["shopping-bag", "tshirt", "signage", "social", "business-card", "tote"], + "services": ["business-card", "website", "signage", "social", "badge", "app-icon"], + "event": ["badge", "tshirt", "website", "social", "sticker", "signage"], + "education": ["website", "badge", "tshirt", "social", "business-card", "app-icon"], + "health": ["website", "app-icon", "signage", "business-card", "social", "box"], + "finance": ["payment-card", "app-icon", "website", "social", "business-card", "favicon-tab"], + "saas": ["website", "favicon-tab", "app-icon", "social", "sticker", "business-card"], +} +ALIASES = { + "fintech": "finance", "bank": "finance", "banking": "finance", "payments": "finance", "insurance": "finance", + "accounting": "finance", "b2b-saas": "saas", "startup": "saas", + "developer": "software", "developer-tools": "software", "devtool": "software", "tech": "software", + "open-source": "software", "ai": "software", "app": "consumer-app", "mobile": "consumer-app", "cafe": "coffee", + "café": "coffee", "roaster": "coffee", "restaurant": "food", "bakery": "food", "beverage": "food", "drink": "food", + "ecommerce": "retail", "shop": "retail", "store": "retail", "agency": "services", "consulting": "services", + "legal": "services", "conference": "event", "festival": "event", "school": "education", + "university": "education", "clinic": "health", "wellness": "health", +} +DEFAULT_NAV = {"software": ["Docs", "Pricing", "GitHub"], "coffee": ["Shop", "Cafés", "Story"], + "food": ["Menu", "Order", "About"], "retail": ["Shop", "New in", "Stores"]} + +CSS = """ +:root{--ink:#161616;--muted:#6b6b6b;--line:#e6e6e2;--paper:#f7f7f4} +*{box-sizing:border-box}body{margin:0;background:#dcdcd6;font:15px/1.5 system-ui,-apple-system,Segoe UI,sans-serif;color:var(--ink)} +.slide{width:1280px;min-height:720px;margin:28px auto;background:#fff;box-shadow:0 8px 30px rgba(0,0,0,.12);padding:56px 64px 70px;position:relative;overflow:hidden} +.slide h1{font-size:44px;margin:0 0 8px;letter-spacing:-.02em}.slide h2{font-size:30px;margin:0 0 6px;letter-spacing:-.01em} +.kicker{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);margin-bottom:14px} +.idea{font-size:22px;max-width:900px;margin:6px 0 18px}.muted{color:var(--muted)} +.foot{position:absolute;left:64px;right:64px;bottom:24px;display:flex;justify-content:space-between;font-size:12px;color:var(--muted)} +.hero{display:grid;grid-template-columns:1.3fr 1fr;gap:40px;align-items:center} +.stage{height:420px;background:var(--paper);border-radius:14px;display:flex;align-items:center;justify-content:center} +.stage img{max-width:70%;max-height:62%} +ul.rat{padding-left:18px;margin:0}ul.rat li{margin:6px 0} +.sizes{display:flex;gap:18px;align-items:flex-end;margin-top:18px}.sizes div{display:flex;flex-direction:column;align-items:center;gap:4px;font-size:11px;color:var(--muted)} +.rev{background:#161616;border-radius:10px;padding:18px 22px;display:inline-flex;margin-top:14px} +.mock{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:10px} +.m{height:270px;border-radius:12px;overflow:hidden;position:relative;display:flex;align-items:center;justify-content:center} +.m .lbl{position:absolute;left:12px;bottom:10px;font-size:11px;color:rgba(0,0,0,.6);background:rgba(255,255,255,.75);padding:2px 8px;border-radius:20px} +.bc{width:250px;height:143px;background:#fff;border-radius:5px;box-shadow:0 10px 26px rgba(0,0,0,.22);padding:16px;display:flex;flex-direction:column;justify-content:space-between;transform:translate(-50px,-38px) rotate(-4deg)} +.bc2{position:absolute;width:250px;height:143px;border-radius:5px;transform:translate(70px,52px) rotate(6deg);box-shadow:0 10px 26px rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center} +.bc .t{font-size:9px;line-height:1.5;color:#333} +.phone{width:150px;height:224px;margin-bottom:14px;border-radius:24px;background:#10151c;padding:9px;box-shadow:0 10px 30px rgba(0,0,0,.3)} +.screen{width:100%;height:100%;border-radius:16px;background:linear-gradient(170deg,#e9edf1,#cfd7df);display:grid;grid-template-columns:repeat(3,1fr);gap:9px;padding:16px 10px;align-content:start} +.ai{width:32px;height:32px;border-radius:8px;background:rgba(0,0,0,.08);justify-self:center} +.bigapp{display:flex;flex-direction:column;align-items:center;gap:10px;font-size:12px;font-weight:600;color:#333;margin-left:30px} +.bigapp .bi{width:108px;height:108px;border-radius:25px;display:flex;align-items:center;justify-content:center;box-shadow:0 12px 26px rgba(0,0,0,.2)} +.web{width:340px;height:210px;background:#fff;border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.15);overflow:hidden} +.web .bar{height:22px;background:#eceff2;display:flex;gap:5px;align-items:center;padding:0 8px}.web .bar i{width:7px;height:7px;border-radius:50%;background:#c9ced4} +.web .nav{height:44px;display:flex;align-items:center;padding:0 16px;gap:14px;font-size:9px;color:#666;border-bottom:1px solid #eee} +.web .hero2{padding:18px 16px}.web .hero2 b{display:block;font-size:17px;line-height:1.2;margin-bottom:8px}.web .hero2 span{display:block;height:6px;background:#eee;border-radius:3px;margin:5px 0;width:80%} +.sign{width:300px;height:190px;background:linear-gradient(#8c8f93,#6f7276);display:flex;flex-direction:column;align-items:center;padding-top:18px} +.sign .board{width:230px;height:74px;border-radius:6px;display:flex;align-items:center;justify-content:center;box-shadow:0 6px 16px rgba(0,0,0,.3)} +.sign .door{width:80px;height:80px;margin-top:18px;background:#3d4146;border-radius:3px 3px 0 0} +.tote{width:180px;height:210px;background:#efe7d8;border-radius:4px 4px 10px 10px;position:relative;display:flex;align-items:center;justify-content:center;box-shadow:0 8px 20px rgba(0,0,0,.15);margin-top:40px} +.tote:before{content:"";position:absolute;top:-46px;left:50%;transform:translateX(-50%);width:84px;height:70px;border:9px solid #e3d8c3;border-bottom:none;border-radius:50px 50px 0 0} +.social{width:300px;background:#fff;border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.14);overflow:hidden} +.social .cover{height:70px}.social .av{width:74px;height:74px;border-radius:50%;background:#fff;border:4px solid #fff;margin:-38px 0 0 16px;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 8px rgba(0,0,0,.12);overflow:hidden} +.social .meta{padding:8px 16px 16px;font-size:11px;color:#555}.social .meta b{font-size:14px;color:#111;display:block} +.cup{position:relative;width:150px;height:200px;margin-top:30px} +.cup .body{position:absolute;inset:0;background:#f4f1ea;clip-path:polygon(0 0,100% 0,86% 100%,14% 100%);display:flex;align-items:center;justify-content:center;box-shadow:inset -18px 0 24px rgba(0,0,0,.06)} +.cup .lid{position:absolute;left:-8px;right:-8px;top:-22px;height:24px;border-radius:8px 8px 3px 3px;background:#2b2b2b} +.cup .sleeve{position:absolute;left:6%;right:6%;top:36%;height:34%;clip-path:polygon(0 0,100% 0,96% 100%,4% 100%);display:flex;align-items:center;justify-content:center} +.bag{position:relative;width:170px;height:230px;background:#e9e2d6;border-radius:6px 6px 10px 10px;box-shadow:0 12px 26px rgba(0,0,0,.2);display:flex;flex-direction:column;align-items:center;padding-top:38px;gap:14px} +.bag:before{content:"";position:absolute;top:0;left:0;right:0;height:22px;background:repeating-linear-gradient(90deg,rgba(0,0,0,.08) 0 4px,transparent 4px 8px);border-radius:6px 6px 0 0} +.bag .label{width:118px;height:118px;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center} +.bag .t{font-size:8px;letter-spacing:.14em;color:#555;text-transform:uppercase;padding:0 12px;text-align:center;line-height:1.4} +.sbag{position:relative;width:180px;height:210px;box-shadow:0 12px 26px rgba(0,0,0,.2);display:flex;align-items:center;justify-content:center;margin-top:30px} +.sbag:before{content:"";position:absolute;top:-40px;left:50%;transform:translateX(-50%);width:70px;height:56px;border:5px solid #333;border-bottom:none;border-radius:40px 40px 0 0} +.box{width:220px;height:150px;background:#f3efe6;box-shadow:14px 14px 0 rgba(0,0,0,.08),0 12px 26px rgba(0,0,0,.18);display:flex;align-items:center;justify-content:center;border-top:14px solid rgba(0,0,0,.06)} +.readme{width:360px;background:#0d1117;border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.25);padding:18px 20px;color:#c9d1d9;font-size:10px} +.readme .rh{display:flex;align-items:center;gap:10px;border-bottom:1px solid #30363d;padding-bottom:12px;margin-bottom:10px} +.readme .badges{display:flex;gap:6px;margin:8px 0}.readme .badges i{display:block;width:54px;height:12px;border-radius:3px;background:#238636}.readme .badges i:nth-child(2){background:#1f6feb}.readme .badges i:nth-child(3){background:#6e7681} +.readme .ln{height:6px;background:#21262d;border-radius:3px;margin:6px 0} +.term{width:360px;background:#1e1e1e;border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.3);overflow:hidden;font:10px/1.6 ui-monospace,Menlo,monospace;color:#d4d4d4} +.term .tb{height:22px;background:#2d2d2d;display:flex;gap:5px;align-items:center;padding:0 8px}.term .tb i{width:8px;height:8px;border-radius:50%;background:#555} +.term .tbody{padding:14px 16px;display:flex;gap:14px;align-items:center} +.sticker{width:250px;height:170px;background:linear-gradient(135deg,#9aa0a6,#6b7177);border-radius:12px;display:flex;align-items:center;justify-content:center;box-shadow:0 10px 24px rgba(0,0,0,.25)} +.sticker .s{width:100px;height:100px;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px rgba(0,0,0,.25)} +.shirt{width:210px;height:220px;display:flex;align-items:center;justify-content:center;position:relative} +.shirt svg{position:absolute;inset:0} +.badge{width:170px;height:235px;background:#fff;border-radius:10px;box-shadow:0 10px 24px rgba(0,0,0,.2);display:flex;flex-direction:column;align-items:center;padding:20px 14px;gap:14px;position:relative;margin-top:30px} +.badge:before{content:"";position:absolute;top:-60px;left:50%;width:22px;height:62px;transform:translateX(-50%)} +.badge .hole{width:40px;height:8px;border-radius:4px;background:#ddd}.badge .nm{font-size:15px;font-weight:600}.badge .rl{font-size:10px;color:#777} +.pcard{position:relative;width:300px;height:189px;border-radius:14px;box-shadow:0 14px 30px rgba(0,0,0,.28);font:600 12px ui-monospace,Menlo,monospace} +.pcard .chip{position:absolute;left:22px;top:76px;width:40px;height:30px;border-radius:6px;background:linear-gradient(135deg,#e9d8a6,#c9a95c)} +.pcard .num{position:absolute;left:22px;top:122px;letter-spacing:.12em;font-size:14px} +.pcard .holder{position:absolute;left:22px;bottom:18px;font-size:10px;letter-spacing:.14em;opacity:.85} +.pcard .brandline{position:absolute;right:20px;bottom:16px;font:700 13px system-ui,sans-serif;opacity:.9} +.tabbar{width:340px;background:#dfe1e5;border-radius:10px;padding:8px 8px 0} +.tab{width:230px;height:36px;background:#fff;border-radius:10px 10px 0 0;display:flex;align-items:center;gap:8px;padding:0 12px;font-size:11px;color:#333} +.addr{height:40px;background:#fff;display:flex;align-items:center;padding:0 12px;font-size:10px;color:#777;border-top:1px solid #eee} +.cmp{display:grid;gap:22px;margin-top:20px}.cmp .c{background:var(--paper);border-radius:12px;padding:22px;display:flex;flex-direction:column;align-items:center;gap:12px} +.cmp img{max-height:120px;max-width:80%} +img.g{filter:grayscale(1)}img.w{filter:brightness(0) invert(1)}img.k{filter:brightness(0)} +.adj span{display:inline-block;border:1px solid var(--line);border-radius:20px;padding:4px 14px;margin:0 8px 8px 0;font-size:14px} +""" + + +def uri(path, base): + p = path if os.path.isabs(path) else os.path.join(base, path) + return svglib.svg_data_uri(p) + + +def text_on(bg): + """White text while it keeps 3:1 on the background, near-black below that (white if the colour can't be parsed).""" + h = (bg or "").strip().lstrip("#") + if len(h) == 3: + h = "".join(ch * 2 for ch in h) + try: + rgb = [int(h[i:i + 2], 16) / 255 for i in (0, 2, 4)] + except ValueError: + return "#fff" + lin = [v / 12.92 if v <= 0.04045 else ((v + 0.055) / 1.055) ** 2.4 for v in rgb] + lum = 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2] + return "#fff" if 1.05 / (lum + 0.05) >= 3 else "#161616" + + +def mock_html(kind, c): + """c: dict with sym, lock, avatar, color, cls, name, tag, nav.""" + sym, lock, av, cls, name, tag = c["sym"], c["lock"], c["avatar"], c["cls"], c["name"], c["tag"] + stack = c.get("stacked") or lock # stacked lockup for tall/boxy surfaces (bags, signs, badges) when provided + # Artwork on brand-colour tiles ("on_tile") and on the fixed near-black surfaces ("on_dark"): use the dedicated + # colour files when given (keeps multi-colour marks), otherwise force the mark to white. + avt, wat = (c["avatar_tile"], "") if c.get("avatar_tile") else (av, "w") + avd, wav = (c["avatar_dark"], "") if c.get("avatar_dark") else (av, "w") + skt, wst = (c["stack_tile"], "") if c.get("stack_tile") else (stack, "w") + lkd, wlk = (c["lock_dark"], "") if c.get("lock_dark") else (lock, "w") + skd, wsk = ((c.get("stack_dark") or c["lock_dark"]), "") if (c.get("stack_dark") or c.get("lock_dark")) else (stack, "w") + tile = c["tile"] + # e-mail / social handle / domain: plain ASCII letters and digits ("Marlow & Finch" -> "marlowfinch") + handle = re.sub(r"[^a-z0-9]", "", unicodedata.normalize("NFKD", name).encode("ascii", "ignore").decode().lower()) + n = html.escape(name) + if kind == "business-card": + return (f'
' + f'
Alex Morgan
Founder
alex@{handle}.com
' + f'
Business cards
') + if kind == "app-icon": + cells = "".join('
' for _ in range(4)) + icon = (f'
' + f'
') + # the home screen shows the icon among others; the large tile beside it shows it at store size + big = (f'
{n}
') + return (f'
{cells}{icon}' + + "".join('
' for _ in range(7)) + f'
{big}App icon
') + if kind == "website": + nav = "".join(f"{html.escape(x)}" for x in c["nav"]) + return (f'
' + f'' + f'
{html.escape(tag) or n}
Website
') + if kind == "signage": + return (f'
' + f'
Storefront / signage
') + if kind == "tote": + return (f'
' + 'Tote bag
') + if kind == "social": + return (f'
Social profile
') + if kind == "cup": + return (f'
' + f'
' + 'Paper cup
') + if kind == "bag": + return (f'
' + f'
{html.escape(tag)[:40]}
' + 'Packaging bag
') + if kind == "shopping-bag": + return (f'
' + 'Shopping bag
') + if kind == "box": + return (f'
' + 'Packaging
') + if kind == "readme": + return (f'
' + f'
{html.escape(tag) or n}
' + '
GitHub README
') + if kind == "terminal": + return (f'
' + f'
$ {handle} --version
' + f'{n} 1.0.0
$ {handle} search "error"
Terminal
') + if kind == "sticker": + return (f'
' + 'Laptop sticker
') + if kind == "tshirt": + shirt = ('') + return (f'
{shirt}
' + 'T-shirt
') + if kind == "badge": + return (f'
' + '
Alex Morgan
Speaker
Event badge
') + if kind == "payment-card": + return (f'
' + f'' + f'
•••• •••• •••• 4821
' + f'
ALEX MORGAN
{n}
' + 'Payment card
') + if kind == "favicon-tab": + return (f'
' + f'{n} — Home✕
https://{handle}.com
Browser tab
') + raise KeyError(kind) + + +ALL_MOCKUPS = ["payment-card", "business-card", "app-icon", "website", "signage", "tote", "social", "cup", "bag", "shopping-bag", "box", + "readme", "terminal", "sticker", "tshirt", "badge", "favicon-tab"] + + +def pick_mockups(spec): + if spec.get("mockups"): + chosen = [m for m in spec["mockups"] if m in ALL_MOCKUPS] + else: + ind = str(spec.get("industry", "")).lower() + key = ind if ind in PRESETS else ALIASES.get(ind, ind) # a real preset name always wins over an alias + chosen = PRESETS.get(key, PRESETS["services"]) + return chosen[:6] if len(chosen) >= 6 else (chosen + [m for m in PRESETS["services"] if m not in chosen])[:6] + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("spec", nargs="?") + ap.add_argument("-o", "--out", default="presentation.html") + ap.add_argument("--list-mockups", action="store_true") + ap.add_argument("--png-dir", help="also export every slide as slide-NN.png (needs Chrome/Chromium)") + a = ap.parse_args() + if a.list_mockups: + print("mockups:", ", ".join(ALL_MOCKUPS)) + for k, v in PRESETS.items(): + print(f" industry '{k}': {', '.join(v)}") + print(" aliases:", ", ".join(f"{k}→{v}" for k, v in ALIASES.items())) + return + if not a.spec: + ap.error("spec.json required") + with open(a.spec, encoding="utf-8") as fh: + spec = json.load(fh) + base = os.path.dirname(os.path.abspath(a.spec)) + brand = spec.get("brand", "Brand") + color = spec.get("brand_color", "#161616") + grey = spec.get("greyscale", True) + final = spec.get("final", False) + cls = "g" if grey else "" + tile = "#161616" if grey else (spec.get("tile_color") or color) + date = spec.get("date") or datetime.date.today().isoformat() + designer = spec.get("designer", "") + concepts = spec.get("concepts", []) + ind = str(spec.get("industry", "")).lower() + nav = spec.get("nav") or DEFAULT_NAV.get(ALIASES.get(ind, ind), ["Products", "About", "Contact"]) + mockups = pick_mockups(spec) + deck_title = spec.get("deck_title", "final identity" if final else "identity concepts") + + def foot(i): + return f'
{html.escape(brand)} — {html.escape(deck_title)}{i}
' + + slides = [] + custom_title = spec.get("deck_title") + cover_mark = "" + if final and concepts: + c0 = concepts[0] + first = c0.get("lockup") or c0.get("symbol") or c0.get("avatar") + if first: + cover_mark = (f'
' + f'
') + kicker = (custom_title.capitalize() if (final and custom_title) else "Final identity") if final \ + else f"Logo design · round {spec.get('round', 1)}" + note = ("Concepts are shown in greyscale so the conversation stays on form and idea; colour follows once a " + "direction is chosen." if grey and not final else "") + slides.append(f"""
{kicker}
+

{html.escape(brand)}

{html.escape(deck_title.capitalize())}{(' · ' + html.escape(designer)) if designer else ''} · {date}

+{cover_mark}

{note}

{foot(1)}
""") + adj = "".join(f"{html.escape(x)}" for x in spec.get("adjectives", [])) + crit = spec.get("criteria", "Success: distinctive in its category, recognisable at 16 px, works in one colour, " + "and feels like the words above.") + slides.append(f"""
What we heard

The brief

+

{html.escape(spec.get('brief', ''))}

{adj}
+

{html.escape(crit)}

{foot(2)}
""") + items = [] + for i, c in enumerate(concepts): + paths = [c.get("symbol"), c.get("lockup"), c.get("avatar")] + if not any(paths): + print(f"skip concept {i}: needs symbol, lockup or avatar") + continue + sym = uri(c.get("symbol") or c.get("avatar") or c.get("lockup"), base) + lock = uri(c.get("lockup") or c.get("symbol") or c.get("avatar"), base) + av = uri(c.get("avatar") or c.get("symbol") or c.get("lockup"), base) + stacked = uri(c["stacked"], base) if c.get("stacked") else None + dark = {} + if not grey: + pick = lambda *keys: next((c[k] for k in keys if c.get(k)), None) + if c.get("symbol_on_dark") and not c.get("symbol_on_tile"): + print(f"note: concept {chr(65 + i)} has no symbol_on_tile; symbol_on_dark is used on the {tile} tiles " + "(app icon, cards) — check its contrast there, or pass a dedicated tile file") + for k, src in (("avatar_tile", pick("symbol_on_tile", "symbol_on_dark")), + ("stack_tile", pick("stacked_on_tile", "lockup_on_tile")), + ("avatar_dark", pick("symbol_on_dark")), ("lock_dark", pick("lockup_on_dark")), + ("stack_dark", pick("stacked_on_dark"))): + if src: + dark[k] = uri(src, base) + items.append((c, sym, lock)) + label = spec.get("label") or ((custom_title.capitalize() if custom_title else "Final design") if final + else f"Concept {chr(65 + i)}") + rat = "".join(f"
  • {html.escape(r)}
  • " for r in c.get("rationale", [])) + sizes = "".join(f'
    {s}px
    ' for s in (16, 24, 32, 64)) + slides.append(f"""
    {label}

    {html.escape(c.get('name', ''))}

    +

    {html.escape(c.get('idea', ''))}

    +
    +
      {rat}
    {sizes}
    +{foot(len(slides) + 1)}
    """) + ctx = {"sym": sym, "lock": lock, "avatar": av, "cls": cls, "name": brand, "tag": spec.get("tagline", ""), + "tile": tile, "nav": nav, "stacked": stacked, **dark} + cells = "".join(mock_html(k, ctx) for k in mockups) + slides.append(f"""
    {label} · in use

    {html.escape(c.get('name', ''))}

    +
    {cells}
    {foot(len(slides) + 1)}
    """) + if len(items) > 1: + cells = "".join(f'
    ' + f'{chr(65 + i)} · {html.escape(c.get("name", ""))}{html.escape(c.get("idea", ""))}
    ' + for i, (c, sym, lock) in enumerate(items)) + slides.append(f"""
    Side by side

    {len(items)} directions

    +
    {cells}
    {foot(len(slides) + 1)}
    """) + if spec.get("recommendation"): + steps = spec.get("next_steps") or ([] if final else ["Choose a direction (or name what you like in each).", + "We refine it: geometry, optical corrections, lockups.", + "Colour and typography options for the chosen direction.", + "Final artwork, variants and mini guidelines."]) + title = "Notes" if final else "Our recommendation" + slides.append(f"""
    {'Next steps' if final else 'Recommendation & next steps'}

    {title}

    +

    {html.escape(spec['recommendation'])}

    +
      {''.join(f'
    • {html.escape(s)}
    • ' for s in steps)}
    {foot(len(slides) + 1)}
    """) + doc = (f"{html.escape(brand)} — {html.escape(deck_title)}" + f"{''.join(slides)}") + with open(a.out, "w", encoding="utf-8") as fh: + fh.write(doc) + print(f"wrote {a.out} ({len(slides)} slides; mockups: {', '.join(mockups)})") + if a.png_dir: + import tempfile + import render_png + os.makedirs(a.png_dir, exist_ok=True) + solo_css = CSS + "body{background:#fff}.slide{margin:0;box-shadow:none;min-height:800px}" + for i, sl in enumerate(slides, 1): + with tempfile.NamedTemporaryFile("w", suffix=".html", delete=False, encoding="utf-8") as fh: + fh.write(f"{sl}") + tmp_html = fh.name + out = os.path.join(a.png_dir, f"slide-{i:02d}.png") + try: + render_png.screenshot_html(tmp_html, out, 1280, 800) + print("wrote", out) + except Exception as exc: + print(f"slide PNG export failed ({exc}); open the HTML instead") + break + finally: + os.unlink(tmp_html) + + +if __name__ == "__main__": + main() diff --git a/.claude/skills/logo-design/scripts/preview_sheet.py b/.claude/skills/logo-design/scripts/preview_sheet.py new file mode 100644 index 0000000..ead60d5 --- /dev/null +++ b/.claude/skills/logo-design/scripts/preview_sheet.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python3 +"""Generate an HTML test sheet for one or more logo SVGs (no dependencies). + +Shows every concept at a ladder of sizes (16 px upward), a pixel-level favicon test, on light / dark / +brand-colour / photographic / patterned backgrounds, in treatments that expose weaknesses (greyscale, +one-colour black and white, squint blur, mirror, 180° rotation), in real contexts (browser tab, app icon, +avatar crop, website header, business card), side by side with other concepts, and on a "shelf" next to +reference logos (competitors or library examples) to judge distinctiveness. + +Usage: + python3 scripts/preview_sheet.py concept-a.svg concept-b.svg -o preview.html + python3 scripts/preview_sheet.py logo.svg --brand-color "#0F7C80" --name "Harbor" -o preview.html + python3 scripts/preview_sheet.py logo.svg --refs-industry payments-fintech -o shelf.html + python3 scripts/preview_sheet.py logo.svg --refs a.svg b.svg c.svg -o shelf.html + python3 scripts/preview_sheet.py v1.svg v2.svg v3.svg --compare-only -o compare.html + +Open the HTML in a browser (agents: use the browser/screenshot tool) and actually look at it. +""" +import argparse +import html +import json +import os +import random +import sys + +sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import svglib # noqa: E402 + +SIZES = [16, 20, 24, 32, 48, 64, 96, 128, 256] + +CSS = """ +:root{--ink:#1b1b1b;--muted:#6d6d6d;--line:#e4e4e0;--paper:#fafaf8} +*{box-sizing:border-box}body{margin:0;font:14px/1.45 system-ui,-apple-system,Segoe UI,sans-serif;color:var(--ink);background:var(--paper)} +header{padding:20px 24px;border-bottom:1px solid var(--line);background:#fff}h1{margin:0 0 4px;font-size:20px} +h2{font-size:17px;margin:28px 0 10px}h3{font-size:13px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin:18px 0 8px} +.wrap{padding:0 24px 40px;max-width:1400px}.row{display:flex;flex-wrap:wrap;gap:14px;align-items:flex-end}.row>.cell{flex:0 0 auto;max-width:100%} +.cell{display:flex;flex-direction:column;align-items:center;gap:6px}.cap{font-size:11px;color:var(--muted);text-align:center} +.tile{display:flex;align-items:center;justify-content:center;border-radius:10px;border:1px solid var(--line);overflow:hidden} +.checklist{background:#fff;border:1px solid var(--line);border-radius:10px;padding:12px 16px;margin-top:14px;columns:2;font-size:13px} +.checklist li{margin:2px 0} +.concept{border-top:2px solid var(--ink);margin-top:34px} +.pix canvas{image-rendering:pixelated;image-rendering:crisp-edges;border:1px solid var(--line);background:#fff} +.tab{width:260px;height:38px;background:#dfe1e5;border-radius:10px 10px 0 0;display:flex;align-items:center;gap:8px;padding:0 12px;font-size:12px;color:#333} +.tab img{width:16px;height:16px;object-fit:contain} +.phone{width:250px;padding:18px;border-radius:28px;background:linear-gradient(160deg,#3a4a5e,#1d2733);display:grid;grid-template-columns:repeat(4,1fr);gap:14px} +.app{display:flex;flex-direction:column;align-items:center;gap:4px;font-size:9px;color:#fff} +.app .ico{width:46px;height:46px;border-radius:11px;background:rgba(255,255,255,.18)} +.nav{width:520px;max-width:100%;height:64px;background:#fff;border:1px solid var(--line);border-radius:8px;display:flex;align-items:center;padding:0 18px;gap:26px;font-size:13px;color:#444} +.nav .sp{flex:1}.nav .btn{background:#1b1b1b;color:#fff;padding:7px 12px;border-radius:6px} +.card{width:336px;height:192px;border-radius:6px;box-shadow:0 6px 24px rgba(0,0,0,.15);background:#fff;padding:22px;display:flex;flex-direction:column;justify-content:space-between} +.card .t{font-size:11px;color:#444;line-height:1.5} +.avatar{width:96px;height:96px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;border:1px solid var(--line)} +.shelf{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px} +.shelf .cell{align-items:stretch}.shelf .tile{height:110px;width:100%;background:#fff}.shelf .me{outline:3px solid #e8505b;outline-offset:2px} +.grey img{filter:grayscale(1)} +img.mono-black{filter:brightness(0)}img.mono-white{filter:brightness(0) invert(1)} +""" + +CHECKLIST = """
      +
    • Is the idea still clear at 16–24 px? Which details disappear first?
    • +
    • Does the silhouette survive the squint (blur) test?
    • +
    • Does the one-colour black version still carry the concept?
    • +
    • Does the reversed (white on dark) version look heavier? (irradiation → thin it)
    • +
    • Any unintended readings when mirrored or rotated 180°?
    • +
    • Does it hold up on the brand colour, a photo and a pattern?
    • +
    • In the favicon/app-icon tests, is the symbol optically sized and centred?
    • +
    • On the shelf: does it stand out from the references, or blend in?
    • +
    • Greyscale: do colour segments still separate by value?
    • +
    • Would you recognise it again tomorrow from memory?
    """ + +PIX_JS = """ +document.querySelectorAll('canvas[data-src]').forEach(c=>{ + const img=new Image(); const n=+c.dataset.n, k=+c.dataset.k; c.width=n*k; c.height=n*k; + img.onload=()=>{const t=document.createElement('canvas'); t.width=n; t.height=n; const x=t.getContext('2d'); + x.fillStyle=c.dataset.bg; x.fillRect(0,0,n,n); + const r=Math.min(n/img.width,n/img.height)*0.9, w=img.width*r, h=img.height*r; x.drawImage(img,(n-w)/2,(n-h)/2,w,h); + const g=c.getContext('2d'); g.imageSmoothingEnabled=false; g.drawImage(t,0,0,n*k,n*k);}; + img.src=c.dataset.src;}); +""" + + +def img(uri, h=None, w=None, cls="", style=""): + dims = "" + if h: + dims += f"height:{h}px;" + if w: + dims += f"max-width:{w}px;" + return f'' + + +def tile(inner, w, h, bg, extra=""): + return f'
    {inner}
    ' + + +def concept_block(name, uri, aspect, brand, idx): + square = aspect is None or aspect <= 1.35 + out = [f'

    {html.escape(name)}

    '] + # scale ladder + out.append("

    Scale ladder (height in px)

    ") + for s in SIZES: + out.append(f"
    {tile(img(uri, h=s), max(40, int(s * (aspect or 1)) + 16), s + 16, '#fff')}" + f"
    {s}px
    ") + out.append("
    ") + # pixel test + out.append("

    Pixel test — rendered at 16 / 32 / 48 px, enlarged

    ") + for n, k in ((16, 8), (32, 4), (48, 3)): + for bg in ("#ffffff", "#111111"): + out.append(f"
    " + f"
    {n}px on {bg}
    ") + out.append("
    ") + # backgrounds + photo = "radial-gradient(circle at 30% 30%,#e7b889,#8a5a3c 45%,#2d3b2f 80%)" + pattern = "repeating-linear-gradient(45deg,#e9e4da 0 10px,#d4cbbd 10px 20px)" + bgs = [("#ffffff", "white", ""), ("#f1f1ee", "light grey", ""), ("#111111", "black", "mono-white"), + ("#111111", "black (original colours)", ""), (brand, f"brand {brand}", ""), (brand, "brand (white)", "mono-white"), + (photo, "photo-like", ""), (pattern, "pattern", "")] + out.append("

    Backgrounds

    ") + for bg, cap, cls in bgs: + out.append(f"
    {tile(img(uri, h=72, w=200, cls=cls), 220, 120, bg)}
    {cap}
    ") + out.append("
    ") + # treatments + treats = [("original", "", ""), ("greyscale", "", "filter:grayscale(1)"), ("one-colour black", "mono-black", ""), + ("one-colour white", "mono-white", ""), ("squint (blur 2px)", "", "filter:blur(2px)"), + ("squint small (blur 1px @48)", "", "filter:blur(1px)"), ("mirrored", "", "transform:scaleX(-1)"), + ("rotated 180°", "", "transform:rotate(180deg)")] + out.append("

    Treatments

    ") + for cap, cls, st in treats: + bg = "#111" if cls == "mono-white" else "#fff" + h = 48 if "@48" in cap else 96 + out.append(f"
    {tile(img(uri, h=h, w=200, cls=cls, style=st), 220, 140, bg)}
    {cap}
    ") + out.append("
    ") + # contexts + out.append("

    Contexts

    ") + out.append(f"
    {img(uri)}{html.escape(name)} — Home" + f"✕
    browser tab (16 px favicon)
    ") + icon = (f"
    " + f"{img(uri, h=28, w=30, cls='mono-white')}
    ") + apps = "".join("
    app
    " for _ in range(6)) + out.append(f"
    {apps}
    {icon}{html.escape(name[:10])}
    {apps[:0]}" + + "".join("
    app
    " for _ in range(5)) + + "
    app icon (white symbol on brand colour)
    ") + out.append(f"
    {img(uri, h=58, w=70)}
    " + f"
    avatar circle crop
    ") + out.append(f"
    " + f"
    website header
    ") + out.append(f"
    {img(uri, h=40, w=160)}
    Alex Morgan
    Founder
    " + f"alex@example.com · +00 000 000 000
    business card (3.5 × 2 in)
    ") + out.append("
    ") + return "\n".join(out) + + +def compare_block(items): + out = ["

    Side by side

    "] + for h, cls, bg, cap in ((96, "", "#fff", "96 px"), (32, "", "#fff", "32 px"), (64, "mono-black", "#fff", "one-colour"), + (64, "mono-white", "#111", "reversed")): + out.append(f"

    {cap}

    ") + for name, uri, aspect in items: + w = max(60, int(h * (aspect or 1)) + 30) + out.append(f"
    {tile(img(uri, h=h, cls=cls), w, h + 30, bg)}
    {html.escape(name)}
    ") + out.append("
    ") + out.append("
    ") + return "\n".join(out) + + +def shelf_block(items, refs): + cells = [] + for name, uri, _ in items: + cells.append((name, uri, True)) + for p in refs: + cells.append((os.path.basename(p), svglib.svg_data_uri(p), False)) + random.Random(7).shuffle(cells) + out = ["

    Shelf test

    Your concept(s) outlined in red among " + "reference logos at equal height. Squint: does it stand out, or blend in? Second row repeats in greyscale.

    "] + for grey in (False, True): + out.append(f"
    ") + for name, uri, me in cells: + out.append(f"
    {img(uri, h=56, w=130)}
    " + f"
    {html.escape(name)}
    ") + out.append("
    ") + out.append("
    ") + return "\n".join(out) + + +def refs_for_industry(industry, n): + with open(svglib.CATALOG_PATH, encoding="utf-8") as fh: + cat = json.load(fh) + rows = [r for r in cat if r.get("industry") == industry and r.get("variant") == "main"] + rows.sort(key=lambda r: (not r.get("exemplary"), r["file"])) + return [os.path.join(svglib.LIBRARY_SVG_DIR, r["file"]) for r in rows[:n]] + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("files", nargs="+", help="logo SVG(s) to test") + ap.add_argument("-o", "--out", default="logo-preview.html") + ap.add_argument("--name", help="brand name (used in mock contexts)") + ap.add_argument("--names", nargs="*", help="labels per file (default: file names)") + ap.add_argument("--brand-color", help="brand colour for background/app-icon tests (default: most saturated colour in the first logo, else dark grey)") + ap.add_argument("--refs", nargs="*", default=[], help="reference SVGs for the shelf test") + ap.add_argument("--refs-industry", help="pull shelf references from the library by industry") + ap.add_argument("--refs-count", type=int, default=11) + ap.add_argument("--compare-only", action="store_true", help="only the side-by-side section") + a = ap.parse_args() + + items = [] + for i, p in enumerate(a.files): + _, root = svglib.load_svg(p) + vb = svglib.view_box(root) + aspect = (vb[2] / vb[3]) if vb and vb[3] else None + label = (a.names[i] if a.names and i < len(a.names) else os.path.splitext(os.path.basename(p))[0]) + items.append((label, svglib.svg_data_uri(p), aspect)) + brand_name = a.name or items[0][0] + color_note = "given" + if not a.brand_color: + _, r0 = svglib.load_svg(a.files[0]) + cols = [c for c in svglib.collect_colors(r0) if 0.12 < svglib.lightness(c) < 0.9] + if cols: + import colorsys + a.brand_color = max(cols, key=lambda c: colorsys.rgb_to_hls(*[v / 255 for v in svglib.hex_to_rgb(c)])[2]) + color_note = "taken from the logo" + else: + a.brand_color, color_note = "#3a3a3a", "none given — neutral grey; pass --brand-color" + refs = list(a.refs) + if a.refs_industry: + refs += refs_for_industry(a.refs_industry, a.refs_count) + + body = [f"

    Logo test sheet — {html.escape(brand_name)}

    " + f"
    {len(items)} file(s) · brand colour {a.brand_color} ({color_note}). " + f"Look critically; fix what fails, then re-run.
    {CHECKLIST}
    "] + if len(items) > 1 or a.compare_only: + body.append(compare_block(items)) + if not a.compare_only: + for i, (label, uri, aspect) in enumerate(items): + body.append(concept_block(label, uri, aspect, a.brand_color, i)) + if refs: + body.append(shelf_block(items, refs)) + body.append("
    ") + doc = (f"Logo test — {html.escape(brand_name)}" + f"" + f"{''.join(body)}") + with open(a.out, "w", encoding="utf-8") as fh: + fh.write(doc) + print(f"wrote {a.out} ({len(items)} logo(s), {len(refs)} reference(s)) — open it in a browser") + + +if __name__ == "__main__": + main() diff --git a/.claude/skills/logo-design/scripts/render_png.py b/.claude/skills/logo-design/scripts/render_png.py new file mode 100644 index 0000000..e0d3eb0 --- /dev/null +++ b/.claude/skills/logo-design/scripts/render_png.py @@ -0,0 +1,381 @@ +#!/usr/bin/env python3 +"""Render SVG logos to PNG (transparent by default) and build favicon.ico files — no required dependencies. + +Use it to *look* at your work (render, then view the PNG) and to produce raster deliverables. +The SVG is fitted ("contain") into an exact WIDTH×HEIGHT box with optional padding and background. + +Backends are tried in order until one works: + 1. cairosvg (python package) 2. rsvg-convert 3. inkscape + 4. headless Chrome / Chromium / Edge / Brave 5. macOS Quick Look (qlmanage) — last resort +Quick Look renders on opaque white; transparency is recovered by rendering on white and black +("difference matting") when Pillow is installed, otherwise the PNG stays opaque white. + +Usage: + python3 scripts/render_png.py logo.svg -o logo.png --size 512 + python3 scripts/render_png.py lockup.svg -o lockup.png --width 1200 --height 400 --padding 0.05 + python3 scripts/render_png.py symbol.svg -o preview.png --size 256 --bg "#ffffff" + python3 scripts/render_png.py a.svg b.svg c.svg --out-dir renders --size 400 # batch, for viewing + python3 scripts/render_png.py favicon.svg --ico favicon.ico --ico-sizes 16 32 48 + python3 scripts/render_png.py preview.html -o preview.png --width 1400 --height 3000 # screenshot an HTML page (Chrome) + python3 scripts/render_png.py --which # show available backends +""" +import argparse +import base64 +import contextlib +import os +import re +import shutil +import struct +import subprocess +import sys +import tempfile +import time + +sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import svglib # noqa: E402,F401 (sets UTF-8 console output) + +CHROME_CANDIDATES = [ + "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", + "/Applications/Chromium.app/Contents/MacOS/Chromium", + "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge", + "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser", + "google-chrome", "google-chrome-stable", "chromium", "chromium-browser", "microsoft-edge", "brave-browser", + r"C:\Program Files\Google\Chrome\Application\chrome.exe", + r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe", +] + + +# ----------------------------------------------------------------------------- helpers + +def png_size(path): + with open(path, "rb") as fh: + head = fh.read(24) + if head[:8] != b"\x89PNG\r\n\x1a\n": + return None + return struct.unpack(">II", head[16:24]) + + +def wrap_svg(svg_path, width, height, padding=0.0, bg=None): + """Return SVG markup that fits the source into an exact width×height canvas (contain + padding).""" + with open(svg_path, encoding="utf-8", errors="ignore") as fh: + raw = fh.read() + raw = re.sub(r"<\?xml[^>]*\?>", "", raw) + raw = re.sub(r"]*>", "", raw, flags=re.I) + m = re.search(r"]*>", raw) + if not m: + raise ValueError(f"not an SVG: {svg_path}") + tag = m.group(0) + vb = re.search(r'viewBox\s*=\s*"([^"]+)"', tag) + if not vb: + w = re.search(r'\swidth\s*=\s*"([\d.]+)', tag) + h = re.search(r'\sheight\s*=\s*"([\d.]+)', tag) + if w and h: + tag2 = tag[:-1] + f' viewBox="0 0 {w.group(1)} {h.group(1)}">' + raw = raw.replace(tag, tag2, 1) + tag = tag2 + pw, ph = width * padding, height * padding + new_tag = re.sub(r'\s(width|height|x|y|preserveAspectRatio)\s*=\s*"[^"]*"', "", tag) + new_tag = new_tag[:-1].rstrip("/") + (f' x="{pw:g}" y="{ph:g}" width="{width - 2 * pw:g}" height="{height - 2 * ph:g}"' + ' preserveAspectRatio="xMidYMid meet">') + raw = raw.replace(tag, new_tag, 1) + bg_rect = f'' if bg else "" + return (f'{bg_rect}{raw}') + + +def find_chrome(): + for c in CHROME_CANDIDATES: + if os.path.isabs(c) and os.path.exists(c): + return c + if not os.path.isabs(c) and shutil.which(c): + return shutil.which(c) + return None + + +def available_backends(): + out = [] + try: + import cairosvg # noqa: F401 + out.append("cairosvg") + except Exception: + pass + if shutil.which("rsvg-convert"): + out.append("rsvg-convert") + if shutil.which("inkscape"): + out.append("inkscape") + if find_chrome(): + out.append("chrome") + if shutil.which("qlmanage"): + out.append("qlmanage") + return out + + +# ----------------------------------------------------------------------------- backends + +def _cairosvg(svg_file, png, w, h): + import cairosvg # type: ignore + cairosvg.svg2png(url=svg_file, write_to=png, output_width=w, output_height=h) + + +def _rsvg(svg_file, png, w, h): + subprocess.run(["rsvg-convert", "-w", str(w), "-h", str(h), "-o", png, svg_file], check=True, + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + +def _inkscape(svg_file, png, w, h): + subprocess.run(["inkscape", svg_file, "--export-type=png", f"--export-filename={png}", "-w", str(w), "-h", str(h)], + check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + +@contextlib.contextmanager +def _tempdir(): + """Like tempfile.TemporaryDirectory, but cleanup never raises (Windows can keep Chrome's files locked).""" + path = tempfile.mkdtemp() + try: + yield path + finally: + for _ in range(10): + shutil.rmtree(path, ignore_errors=True) + if not os.path.exists(path): + break + time.sleep(0.3) + + +def _stop(proc): + """Stop a browser process and its children (Chrome keeps helper processes alive on Windows).""" + if proc.poll() is not None: + return + if os.name == "nt": + subprocess.run(["taskkill", "/PID", str(proc.pid), "/T", "/F"], stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + else: + proc.terminate() + try: + proc.wait(timeout=5) + except subprocess.TimeoutExpired: + proc.kill() + + +def _chrome(svg_file, png, w, h): + with open(svg_file, "rb") as fh: + data = base64.b64encode(fh.read()).decode("ascii") + page = (f"" + f"") + with _tempdir() as tmp: + html_path = os.path.join(tmp, "render.html") + with open(html_path, "w", encoding="utf-8") as fh: + fh.write(page) + screenshot_html(html_path, png, w, h) + + +def screenshot_html(html_path, png, w, h): + """Screenshot an HTML page (viewport w×h, transparent where the page is) with headless Chrome/Chromium.""" + chrome = find_chrome() + if not chrome: + raise RuntimeError("no Chromium-based browser found for HTML screenshots") + html_path = os.path.abspath(html_path) + with _tempdir() as tmp: + shot = os.path.join(tmp, "shot.png") # never poll the destination: an older file may already exist there + cmd = [chrome, "--headless=new", "--disable-gpu", "--hide-scrollbars", "--no-first-run", + "--no-default-browser-check", "--use-mock-keychain", "--password-store=basic", "--disable-extensions", + "--default-background-color=00000000", f"--window-size={w},{h}", f"--screenshot={shot}", + f"--user-data-dir={os.path.join(tmp, 'profile')}", "file://" + html_path] + proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + deadline = time.time() + 45 + last = -1 + while time.time() < deadline: + if os.path.exists(shot): + size = os.path.getsize(shot) + if size > 0 and size == last: + break + last = size + if proc.poll() is not None and os.path.exists(shot): + break + time.sleep(0.25) + try: + proc.wait(timeout=0.5) # it may exit by itself after --screenshot; otherwise stop the whole tree + except subprocess.TimeoutExpired: + pass + _stop(proc) + if not os.path.exists(shot): + raise RuntimeError("chrome produced no file") + shutil.move(shot, png) + + +def _qlmanage_once(svg_markup, w, h, tmp, name): + side = max(w, h) + p = os.path.join(tmp, name + ".svg") + with open(p, "w", encoding="utf-8") as fh: + fh.write(svg_markup) + subprocess.run(["qlmanage", "-t", "-s", str(side), "-o", tmp, p], check=True, + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=60) + out = p + ".png" + if not os.path.exists(out): + raise RuntimeError("qlmanage produced no file") + return out + + +def _qlmanage(svg_file, png, w, h, want_alpha=True): + # Quick Look crops non-square canvases and ignores transparency: render a square canvas, crop after. + side = max(w, h) + with open(svg_file, encoding="utf-8") as fh: + markup = fh.read() + ox, oy = (side - w) / 2, (side - h) / 2 + square = re.sub(r"^]*>", f'', markup, count=1) + with tempfile.TemporaryDirectory() as tmp: + white = _qlmanage_once(square, w, h, tmp, "white") + try: + from PIL import Image # type: ignore + except Exception: + shutil.copy(white, png) + print(" note: Quick Look output is opaque white (install Pillow for transparency).", file=sys.stderr) + return + black_markup = re.sub(r"(]*>)", r'\1', + square, count=1) + black = _qlmanage_once(black_markup, w, h, tmp, "black") + iw = Image.open(white).convert("RGB") + ib = Image.open(black).convert("RGB").resize(iw.size) + if want_alpha: + flat = lambda im: list(im.get_flattened_data() if hasattr(im, "get_flattened_data") else im.getdata()) + wd, bd = flat(iw), flat(ib) + px = [] + for (wr, wg, wb), (br, bg_, bb) in zip(wd, bd): + a = 255 - max(wr - br, wg - bg_, wb - bb) + if a >= 255: + px.append((br, bg_, bb, 255)) + elif a <= 0: + px.append((0, 0, 0, 0)) + else: + px.append((min(255, br * 255 // a), min(255, bg_ * 255 // a), min(255, bb * 255 // a), a)) + out = Image.new("RGBA", iw.size) + out.putdata(px) + else: + out = iw + s = out.size[0] / side + box = (round(ox * s), round(oy * s), round((ox + w) * s), round((oy + h) * s)) + out.crop(box).resize((w, h)).save(png) + + +BACKENDS = {"cairosvg": _cairosvg, "rsvg-convert": _rsvg, "inkscape": _inkscape, "chrome": _chrome, "qlmanage": _qlmanage} + + +def render(svg_path, png_path, width, height, padding=0.0, bg=None, backend=None): + """Render svg_path into png_path at exactly width×height. Returns the backend used, or None.""" + markup = wrap_svg(svg_path, width, height, padding, bg) + order = [backend] if backend else available_backends() + with _tempdir() as tmp: + wrapped = os.path.join(tmp, "wrapped.svg") + with open(wrapped, "w", encoding="utf-8") as fh: + fh.write(markup) + for name in order: + for _attempt in range(2 if name == "chrome" else 1): # a browser can fail once on a busy machine + try: + BACKENDS[name](wrapped, png_path, width, height) + if os.path.exists(png_path): + return name + except Exception: # retry, then try the next backend + continue + return None + + +def write_ico(png_paths, ico_path): + """Write a .ico that embeds PNG images (supported by all modern browsers and Windows Vista+).""" + entries, blobs = [], [] + for p in png_paths: + with open(p, "rb") as fh: + blobs.append(fh.read()) + w, h = png_size(p) + entries.append((w, h)) + offset = 6 + 16 * len(blobs) + header = struct.pack(" a.max_colors: + return False + if a.min_colors is not None and r.get("n_colors", 0) < a.min_colors: + return False + if a.aspect and r.get("aspect_class") != a.aspect: + return False + if a.variant and r.get("variant") != a.variant: + return False + if a.type_style and r.get("type_style") != a.type_style: + return False + if a.case and r.get("case") != a.case: + return False + if a.mood and a.mood.lower() not in [m.lower() for m in r.get("mood", [])]: + return False + if a.exemplary and not r.get("exemplary"): + return False + if a.no_gradient and r.get("gradients"): + return False + if a.subject and a.subject.lower() not in (r.get("subject") or "").lower(): + return False + if a.query: + hay = " ".join([r.get("file", ""), r.get("subject") or "", r.get("note") or "", " ".join(r.get("mood", []))]).lower() + if not all(w in hay for w in a.query.lower().split()): + return False + return True + + +def summary(rows, total): + n = len(rows) + print(f"{n} logos match (of {total}).\n") + if not n: + return + + def block(title, counter, k=10): + print(title) + for key, cnt in counter.most_common(k): + print(f" {str(key):24s} {cnt:4d} {cnt / n * 100:5.1f}%") + print() + block("Mark types", Counter(r.get("mark_type") for r in rows)) + block("Symbol type (combination marks)", Counter(r.get("symbol_type") for r in rows if r.get("symbol_type"))) + block("Primary colour family", Counter(r.get("primary_family") for r in rows)) + block("Techniques", Counter(t for r in rows for t in r.get("techniques", [])), 12) + block("Geometry", Counter(g for r in rows for g in r.get("geometry", []))) + block("Type style (when type present)", Counter(r.get("type_style") for r in rows if r.get("type_style"))) + cols = Counter(r.get("n_colors") for r in rows) + few = sum(v for k, v in cols.items() if k is not None and k <= 2) + print(f"Colour count: {few / n * 100:.0f}% use 1-2 colours; gradients in " + f"{sum(1 for r in rows if r.get('gradients')) / n * 100:.0f}%.") + ex = [r["file"] for r in rows if r.get("exemplary")][:12] + if ex: + print("Exemplary examples:", ", ".join(ex)) + print("\nReading: the most frequent types/colours/techniques are the category's conventions. " + "Repeating them signals belonging; departing from them creates distinction.") + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--type", help="mark type: wordmark|lettermark|letterform|pictorial|abstract|mascot|emblem|combination") + ap.add_argument("--symbol-type", help="symbol type inside combination marks") + ap.add_argument("--technique", help="e.g. negative-space, geometric-construction, letter-substitution (comma = AND)") + ap.add_argument("--geometry", help="e.g. circle, hexagon, triangle, organic (comma = AND)") + ap.add_argument("--industry", help="e.g. developer-tools, payments-fintech, database-data") + ap.add_argument("--color", help="colour family present anywhere: red|orange|yellow|green|cyan|blue|purple|pink|black|white|gray") + ap.add_argument("--primary-color", help="dominant family: a hue, 'multi' or 'mono'") + ap.add_argument("--max-colors", type=int) + ap.add_argument("--min-colors", type=int) + ap.add_argument("--aspect", help="square|wide|horizontal|extra-wide|tall") + ap.add_argument("--variant", help="main|icon (icon = standalone symbol of a brand that also has a lockup)") + ap.add_argument("--type-style", help="geometric-sans|grotesque-sans|humanist-sans|rounded-sans|serif|slab|script|display-custom|monospace") + ap.add_argument("--case", help="lowercase|uppercase|titlecase|mixed") + ap.add_argument("--mood", help="single mood adjective, e.g. friendly, technical, playful") + ap.add_argument("--subject", help="substring of the visual subject, e.g. bird, shield, cloud, letter a") + ap.add_argument("--query", help="free-text words matched against file name, subject, note, mood") + ap.add_argument("--exemplary", action="store_true", help="only strong teaching examples") + ap.add_argument("--no-gradient", action="store_true") + ap.add_argument("--limit", type=int, default=25) + ap.add_argument("--format", choices=("table", "paths", "json"), default="table") + ap.add_argument("--summary", action="store_true", help="aggregate view: conventions of the matching set") + ap.add_argument("--list-values", action="store_true", help="print allowed values for every filter") + a = ap.parse_args() + + cat = load_catalog() + if a.list_values: + for key in ("mark_type", "symbol_type", "industry", "primary_family", "aspect_class", "type_style", "case"): + print(f"{key}: {', '.join(sorted({str(r.get(key)) for r in cat if r.get(key)}))}") + for key in ("techniques", "geometry"): + vals = Counter(v for r in cat for v in r.get(key, [])) + print(f"{key}: {', '.join(f'{k}({c})' for k, c in vals.most_common())}") + moods = Counter(m.lower() for r in cat for m in r.get("mood", [])) + print("mood (top 40):", ", ".join(k for k, _ in moods.most_common(40))) + return + + # forgive near-miss filter values: "security" -> "security-identity", "fintech" -> "payments-fintech" + for attr, field in (("industry", "industry"), ("type", "mark_type"), ("symbol_type", "symbol_type"), + ("type_style", "type_style"), ("aspect", "aspect_class"), ("primary_color", "primary_family")): + val = getattr(a, attr) + if not val: + continue + known = sorted({str(r.get(field)) for r in cat if r.get(field)}) + if val in known: + continue + close = [k for k in known if val.lower() in k.lower() or k.lower() in val.lower()] + if len(close) == 1: + print(f"(--{attr.replace('_', '-')} '{val}' → using '{close[0]}')") + setattr(a, attr, close[0]) + else: + hint = ", ".join(close) if close else ", ".join(known) + sys.exit(f"unknown --{attr.replace('_', '-')} '{val}'. Did you mean: {hint}") + for attr, field in (("technique", "techniques"), ("geometry", "geometry")): + val = getattr(a, attr) + if not val: + continue + known = sorted({v for r in cat for v in r.get(field, [])}) + fixed = [] + for part in val.split(","): + if part in known: + fixed.append(part) + continue + close = [k for k in known if part.lower() in k.lower()] + if len(close) == 1: + print(f"(--{attr} '{part}' → using '{close[0]}')") + fixed.append(close[0]) + else: + sys.exit(f"unknown --{attr} '{part}'. Did you mean: {', '.join(close) if close else ', '.join(known)}") + setattr(a, attr, ",".join(fixed)) + + rows = [r for r in cat if matches(r, a)] + rows.sort(key=lambda r: (not r.get("exemplary"), r.get("anchors", 0))) + if a.summary: + summary(rows, len(cat)) + return + shown = rows[: a.limit] + if a.format == "json": + print(json.dumps(shown, ensure_ascii=False, indent=1)) + elif a.format == "paths": + for r in shown: + print(os.path.join(svglib.LIBRARY_SVG_DIR, r["file"])) + else: + print(f"{len(rows)} match, showing {len(shown)} (★ = exemplary; files in {svglib.LIBRARY_SVG_DIR})") + for r in shown: + star = "★" if r.get("exemplary") else " " + kind = r.get("mark_type") or "?" + if r.get("symbol_type"): + kind += "/" + r["symbol_type"] + print(f"{star} {r['file']:34s} {kind:22s} {r.get('n_colors', 0):2d}c {(r.get('subject') or '')[:48]}") + if r.get("note") and r.get("exemplary"): + print(f" ↳ {r['note']}") + + +if __name__ == "__main__": + main() diff --git a/.claude/skills/logo-design/scripts/svg_audit.py b/.claude/skills/logo-design/scripts/svg_audit.py new file mode 100644 index 0000000..676d6ff --- /dev/null +++ b/.claude/skills/logo-design/scripts/svg_audit.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python3 +"""Audit a logo SVG against logo-design principles and production rules. + +Checks structure (viewBox, title, text/raster/filters), colour discipline, complexity versus the +reference library, near-miss angles (lines 0.3–3° off a clean angle), tiny details that vanish when small, +padding/centring inside the viewBox, strokes that should be expanded, and white "fake knockouts". + +Usage: + python3 scripts/svg_audit.py logo.svg [more.svg ...] + python3 scripts/svg_audit.py logo.svg --json # machine-readable + python3 scripts/svg_audit.py logo.svg --bg "#0F7C80" # also report contrast of colours on a background + +Exit code is 0 unless a file cannot be parsed. Findings are advice, not law: a deliberate choice can +override a warning — but you should be able to say why. +""" +import argparse +import json +import math +import os +import re +import sys + +sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import svglib # noqa: E402 + +CLEAN_ANGLES = [0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180] + + +def load_stats(): + try: + with open(svglib.STATS_PATH, encoding="utf-8") as fh: + return json.load(fh) + except OSError: + return None + + +def audit(path, bg=None): + findings = [] # (level, code, message) + + def add(level, code, msg): + findings.append({"level": level, "code": code, "message": msg}) + + raw, root = svglib.load_svg(path) + counts = svglib.element_counts(root) + vb = svglib.view_box(root) + info = {"file": os.path.basename(path), "bytes": os.path.getsize(path)} + + # --- structure ------------------------------------------------------------------------- + if not root.get("viewBox"): + add("WARN", "no-viewbox", "No viewBox: the logo will not scale predictably. Add viewBox=\"0 0 W H\".") + if vb: + info["viewBox"] = vb + w, h = vb[2], vb[3] + info["aspect"] = round(w / h, 3) if h else None + info["aspect_class"] = svglib.aspect_class(info["aspect"]) + if any(abs(v - round(v)) > 1e-6 for v in vb): + add("INFO", "fractional-viewbox", "viewBox has fractional values; integer canvases are easier to grid.") + if counts.get("text", 0) or counts.get("tspan", 0): + add("FAIL", "live-text", "Contains : final logos must use outlined paths (fonts differ per machine).") + if counts.get("image", 0): + add("FAIL", "raster-image", "Contains (embedded raster). A logo master must be pure vector.") + if counts.get("filter", 0): + add("WARN", "filter", "Uses filters (blur/shadow/glow). They render inconsistently and cannot be printed; use flat shapes.") + if counts.get("mask", 0): + add("INFO", "mask", "Uses . Fine for exploration; bake into paths for production (cutters/embroidery).") + if counts.get("foreignObject", 0): + add("FAIL", "foreign-object", "Contains (HTML inside SVG). Not portable.") + if counts.get("style", 0): + add("INFO", "style-block", "Uses a -

    Logo Reference Library — for studying patterns; all marks are trademarks of their owners. Never copy.

    -
    - - - - - - - - -
    -
    - diff --git a/.claude/skills/logo-design/assets/library/stats.json b/.claude/skills/logo-design/assets/library/stats.json deleted file mode 100644 index 385ae86..0000000 --- a/.claude/skills/logo-design/assets/library/stats.json +++ /dev/null @@ -1,392 +0,0 @@ -{ - "count": 1432, - "anchors_all": { - "p10": 23.0, - "p25": 37.0, - "median": 75.0, - "p75": 155.0, - "p90": 257.8, - "p95": 379.45 - }, - "anchors_square": { - "p10": 21.0, - "p25": 31.0, - "median": 53.0, - "p75": 95.5, - "p90": 194.0, - "p95": 274.0 - }, - "shapes_all": { - "p10": 2.0, - "p25": 2.0, - "median": 3.0, - "p75": 6.0, - "p90": 12.0, - "p95": 19.0 - }, - "n_colors_all": { - "p10": 1.0, - "p25": 1.0, - "median": 2.0, - "p75": 4.0, - "p90": 7.0, - "p95": 10.0 - }, - "n_colors_square": { - "p10": 1.0, - "p25": 1.0, - "median": 2.0, - "p75": 4.0, - "p90": 7.0, - "p95": 10.0 - }, - "gradient_share": 0.19, - "mark_types": [ - [ - "abstract", - 337 - ], - [ - "combination", - 295 - ], - [ - "pictorial", - 289 - ], - [ - "letterform", - 218 - ], - [ - "wordmark", - 142 - ], - [ - "emblem", - 54 - ], - [ - "mascot", - 54 - ], - [ - "lettermark", - 43 - ] - ], - "primary_family": [ - [ - "multi", - 397 - ], - [ - "blue", - 319 - ], - [ - "mono", - 185 - ], - [ - "red", - 180 - ], - [ - "green", - 93 - ], - [ - "orange", - 92 - ], - [ - "cyan", - 66 - ], - [ - "purple", - 60 - ], - [ - "yellow", - 28 - ], - [ - "pink", - 12 - ] - ], - "aspect_class": [ - [ - "square", - 791 - ], - [ - "horizontal", - 223 - ], - [ - "wide", - 187 - ], - [ - "extra-wide", - 133 - ], - [ - "tall", - 98 - ] - ], - "techniques": [ - [ - "containment", - 453 - ], - [ - "negative-space", - 284 - ], - [ - "line-monoline", - 249 - ], - [ - "gradient", - 218 - ], - [ - "color-segments", - 204 - ], - [ - "dimensional-shading", - 147 - ], - [ - "geometric-construction", - 127 - ], - [ - "modular-repetition", - 107 - ], - [ - "overlap-transparency", - 104 - ], - [ - "hidden-meaning", - 103 - ], - [ - "isometric-3d", - 90 - ], - [ - "radial-symmetry", - 87 - ], - [ - "motion-lines", - 65 - ], - [ - "mirror-symmetry", - 64 - ], - [ - "arrow", - 57 - ], - [ - "letter-substitution", - 49 - ], - [ - "stacked-layers", - 49 - ], - [ - "bracket-code", - 46 - ], - [ - "hand-drawn", - 38 - ], - [ - "speech-bubble", - 29 - ], - [ - "ligature", - 16 - ], - [ - "infinity-loop", - 15 - ], - [ - "pixel", - 5 - ], - [ - "impossible-figure", - 2 - ] - ], - "geometry": [ - [ - "circle", - 367 - ], - [ - "organic", - 197 - ], - [ - "square", - 196 - ], - [ - "freeform", - 179 - ], - [ - "triangle", - 116 - ], - [ - "hexagon", - 114 - ], - [ - "rounded-square", - 99 - ], - [ - "radial", - 92 - ], - [ - "grid-modular", - 56 - ], - [ - "diamond", - 51 - ], - [ - "shield", - 16 - ], - [ - "star", - 11 - ] - ], - "industries": [ - [ - "developer-tools", - 295 - ], - [ - "framework-library", - 247 - ], - [ - "cloud-infrastructure", - 97 - ], - [ - "database-data", - 90 - ], - [ - "testing-monitoring", - 89 - ], - [ - "productivity-collaboration", - 81 - ], - [ - "marketing-analytics", - 78 - ], - [ - "programming-language", - 70 - ], - [ - "social-communication", - 61 - ], - [ - "os-platform", - 46 - ], - [ - "payments-fintech", - 37 - ], - [ - "design-creative", - 35 - ], - [ - "security-identity", - 34 - ], - [ - "hosting-cdn", - 32 - ], - [ - "media-entertainment", - 30 - ], - [ - "education", - 23 - ], - [ - "ecommerce-retail", - 20 - ], - [ - "open-source-community", - 16 - ], - [ - "hardware-devices", - 14 - ], - [ - "ai-ml", - 12 - ], - [ - "other", - 11 - ], - [ - "gaming", - 5 - ], - [ - "travel-transport", - 4 - ], - [ - "finance-banking", - 4 - ], - [ - "health", - 1 - ] - ] -} \ No newline at end of file diff --git a/.claude/skills/logo-design/assets/library/svg/100tb.svg b/.claude/skills/logo-design/assets/library/svg/100tb.svg deleted file mode 100644 index 1185fe5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/100tb.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/500px.svg b/.claude/skills/logo-design/assets/library/svg/500px.svg deleted file mode 100644 index 7d3b360..0000000 --- a/.claude/skills/logo-design/assets/library/svg/500px.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/active-campaign-icon.svg b/.claude/skills/logo-design/assets/library/svg/active-campaign-icon.svg deleted file mode 100644 index 9794529..0000000 --- a/.claude/skills/logo-design/assets/library/svg/active-campaign-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/active-campaign.svg b/.claude/skills/logo-design/assets/library/svg/active-campaign.svg deleted file mode 100644 index 2e3062b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/active-campaign.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/adonisjs-icon.svg b/.claude/skills/logo-design/assets/library/svg/adonisjs-icon.svg deleted file mode 100644 index e42f9bf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/adonisjs-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/adonisjs.svg b/.claude/skills/logo-design/assets/library/svg/adonisjs.svg deleted file mode 100644 index 4735e04..0000000 --- a/.claude/skills/logo-design/assets/library/svg/adonisjs.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/adroll.svg b/.claude/skills/logo-design/assets/library/svg/adroll.svg deleted file mode 100644 index 333e49e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/adroll.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/adyen.svg b/.claude/skills/logo-design/assets/library/svg/adyen.svg deleted file mode 100644 index f6c68d5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/adyen.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aerospike-icon.svg b/.claude/skills/logo-design/assets/library/svg/aerospike-icon.svg deleted file mode 100644 index 351a351..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aerospike-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aerospike.svg b/.claude/skills/logo-design/assets/library/svg/aerospike.svg deleted file mode 100644 index e7bbcb5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aerospike.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/airbnb.svg b/.claude/skills/logo-design/assets/library/svg/airbnb.svg deleted file mode 100644 index 08f9ee8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/airbnb.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/airbrake.svg b/.claude/skills/logo-design/assets/library/svg/airbrake.svg deleted file mode 100644 index 5fcc679..0000000 --- a/.claude/skills/logo-design/assets/library/svg/airbrake.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/airflow.svg b/.claude/skills/logo-design/assets/library/svg/airflow.svg deleted file mode 100644 index aeb3662..0000000 --- a/.claude/skills/logo-design/assets/library/svg/airflow.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/airtable.svg b/.claude/skills/logo-design/assets/library/svg/airtable.svg deleted file mode 100644 index ce297b9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/airtable.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/akamai.svg b/.claude/skills/logo-design/assets/library/svg/akamai.svg deleted file mode 100644 index 5078b5f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/akamai.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/akka.svg b/.claude/skills/logo-design/assets/library/svg/akka.svg deleted file mode 100644 index 9905561..0000000 --- a/.claude/skills/logo-design/assets/library/svg/akka.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/alfresco.svg b/.claude/skills/logo-design/assets/library/svg/alfresco.svg deleted file mode 100644 index 627fa1d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/alfresco.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/algolia.svg b/.claude/skills/logo-design/assets/library/svg/algolia.svg deleted file mode 100644 index c5f1db4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/algolia.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/alpinejs-icon.svg b/.claude/skills/logo-design/assets/library/svg/alpinejs-icon.svg deleted file mode 100644 index 4a96b6a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/alpinejs-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/alpinejs.svg b/.claude/skills/logo-design/assets/library/svg/alpinejs.svg deleted file mode 100644 index bfeb142..0000000 --- a/.claude/skills/logo-design/assets/library/svg/alpinejs.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/altair.svg b/.claude/skills/logo-design/assets/library/svg/altair.svg deleted file mode 100644 index 8c9514f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/altair.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/amazon-chime.svg b/.claude/skills/logo-design/assets/library/svg/amazon-chime.svg deleted file mode 100644 index d877b4b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/amazon-chime.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/amazon-connect.svg b/.claude/skills/logo-design/assets/library/svg/amazon-connect.svg deleted file mode 100644 index e44cfc8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/amazon-connect.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/amex.svg b/.claude/skills/logo-design/assets/library/svg/amex.svg deleted file mode 100644 index 6aa4f4e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/amex.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/amp-icon.svg b/.claude/skills/logo-design/assets/library/svg/amp-icon.svg deleted file mode 100644 index ff1c1bb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/amp-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/amp.svg b/.claude/skills/logo-design/assets/library/svg/amp.svg deleted file mode 100644 index 027adec..0000000 --- a/.claude/skills/logo-design/assets/library/svg/amp.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ampersand.svg b/.claude/skills/logo-design/assets/library/svg/ampersand.svg deleted file mode 100644 index d207f01..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ampersand.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/amplication-icon.svg b/.claude/skills/logo-design/assets/library/svg/amplication-icon.svg deleted file mode 100644 index d34493d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/amplication-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/amplication.svg b/.claude/skills/logo-design/assets/library/svg/amplication.svg deleted file mode 100644 index b81ff70..0000000 --- a/.claude/skills/logo-design/assets/library/svg/amplication.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/amplitude-icon.svg b/.claude/skills/logo-design/assets/library/svg/amplitude-icon.svg deleted file mode 100644 index 7b98e42..0000000 --- a/.claude/skills/logo-design/assets/library/svg/amplitude-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/amplitude.svg b/.claude/skills/logo-design/assets/library/svg/amplitude.svg deleted file mode 100644 index 801d30a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/amplitude.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/android-icon.svg b/.claude/skills/logo-design/assets/library/svg/android-icon.svg deleted file mode 100644 index 1954e37..0000000 --- a/.claude/skills/logo-design/assets/library/svg/android-icon.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/android.svg b/.claude/skills/logo-design/assets/library/svg/android.svg deleted file mode 100644 index e390835..0000000 --- a/.claude/skills/logo-design/assets/library/svg/android.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/angellist.svg b/.claude/skills/logo-design/assets/library/svg/angellist.svg deleted file mode 100644 index b9d9e55..0000000 --- a/.claude/skills/logo-design/assets/library/svg/angellist.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/angular-icon.svg b/.claude/skills/logo-design/assets/library/svg/angular-icon.svg deleted file mode 100644 index 5dfcee3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/angular-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/angular.svg b/.claude/skills/logo-design/assets/library/svg/angular.svg deleted file mode 100644 index dc024a9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/angular.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ansible.svg b/.claude/skills/logo-design/assets/library/svg/ansible.svg deleted file mode 100644 index 7e2616a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ansible.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ant-design.svg b/.claude/skills/logo-design/assets/library/svg/ant-design.svg deleted file mode 100644 index 45b04fd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ant-design.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/apache-camel.svg b/.claude/skills/logo-design/assets/library/svg/apache-camel.svg deleted file mode 100644 index 7020caf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/apache-camel.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/apache.svg b/.claude/skills/logo-design/assets/library/svg/apache.svg deleted file mode 100644 index 93e9413..0000000 --- a/.claude/skills/logo-design/assets/library/svg/apache.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/apache_cloudstack.svg b/.claude/skills/logo-design/assets/library/svg/apache_cloudstack.svg deleted file mode 100644 index 0e0d8b1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/apache_cloudstack.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/apiary.svg b/.claude/skills/logo-design/assets/library/svg/apiary.svg deleted file mode 100644 index 155984a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/apiary.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/apollostack.svg b/.claude/skills/logo-design/assets/library/svg/apollostack.svg deleted file mode 100644 index 15eed98..0000000 --- a/.claude/skills/logo-design/assets/library/svg/apollostack.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/apostrophe.svg b/.claude/skills/logo-design/assets/library/svg/apostrophe.svg deleted file mode 100644 index 5eeb009..0000000 --- a/.claude/skills/logo-design/assets/library/svg/apostrophe.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/appbaseio-icon.svg b/.claude/skills/logo-design/assets/library/svg/appbaseio-icon.svg deleted file mode 100644 index 4266e02..0000000 --- a/.claude/skills/logo-design/assets/library/svg/appbaseio-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/appbaseio.svg b/.claude/skills/logo-design/assets/library/svg/appbaseio.svg deleted file mode 100644 index 4f604cb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/appbaseio.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/appcircle-icon.svg b/.claude/skills/logo-design/assets/library/svg/appcircle-icon.svg deleted file mode 100644 index cee02d2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/appcircle-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/appcircle.svg b/.claude/skills/logo-design/assets/library/svg/appcircle.svg deleted file mode 100644 index 57150be..0000000 --- a/.claude/skills/logo-design/assets/library/svg/appcircle.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/appcode.svg b/.claude/skills/logo-design/assets/library/svg/appcode.svg deleted file mode 100644 index a2588c7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/appcode.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/appdynamics.svg b/.claude/skills/logo-design/assets/library/svg/appdynamics.svg deleted file mode 100644 index 4d076a3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/appdynamics.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/appium.svg b/.claude/skills/logo-design/assets/library/svg/appium.svg deleted file mode 100644 index 04656bc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/appium.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/apple-app-store.svg b/.claude/skills/logo-design/assets/library/svg/apple-app-store.svg deleted file mode 100644 index fd3013c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/apple-app-store.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/apple-pay.svg b/.claude/skills/logo-design/assets/library/svg/apple-pay.svg deleted file mode 100644 index 398449d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/apple-pay.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/apple.svg b/.claude/skills/logo-design/assets/library/svg/apple.svg deleted file mode 100644 index 7df4759..0000000 --- a/.claude/skills/logo-design/assets/library/svg/apple.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/appsignal-icon.svg b/.claude/skills/logo-design/assets/library/svg/appsignal-icon.svg deleted file mode 100644 index 3677db9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/appsignal-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/appsignal.svg b/.claude/skills/logo-design/assets/library/svg/appsignal.svg deleted file mode 100644 index 50728df..0000000 --- a/.claude/skills/logo-design/assets/library/svg/appsignal.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/apptentive.svg b/.claude/skills/logo-design/assets/library/svg/apptentive.svg deleted file mode 100644 index 8ce72c9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/apptentive.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/appveyor.svg b/.claude/skills/logo-design/assets/library/svg/appveyor.svg deleted file mode 100644 index a56fea7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/appveyor.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/arangodb.svg b/.claude/skills/logo-design/assets/library/svg/arangodb.svg deleted file mode 100644 index 2bdc560..0000000 --- a/.claude/skills/logo-design/assets/library/svg/arangodb.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/archlinux.svg b/.claude/skills/logo-design/assets/library/svg/archlinux.svg deleted file mode 100644 index 0918af8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/archlinux.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/arduino.svg b/.claude/skills/logo-design/assets/library/svg/arduino.svg deleted file mode 100644 index 6e3ae9f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/arduino.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/argo-icon.svg b/.claude/skills/logo-design/assets/library/svg/argo-icon.svg deleted file mode 100644 index 68c93c5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/argo-icon.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/argo.svg b/.claude/skills/logo-design/assets/library/svg/argo.svg deleted file mode 100644 index 4c88f7d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/argo.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/armory.svg b/.claude/skills/logo-design/assets/library/svg/armory.svg deleted file mode 100644 index 0277c9b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/armory.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/asana.svg b/.claude/skills/logo-design/assets/library/svg/asana.svg deleted file mode 100644 index 0d25e24..0000000 --- a/.claude/skills/logo-design/assets/library/svg/asana.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/asciidoctor.svg b/.claude/skills/logo-design/assets/library/svg/asciidoctor.svg deleted file mode 100644 index bec60ae..0000000 --- a/.claude/skills/logo-design/assets/library/svg/asciidoctor.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/assembla-icon.svg b/.claude/skills/logo-design/assets/library/svg/assembla-icon.svg deleted file mode 100644 index f14f087..0000000 --- a/.claude/skills/logo-design/assets/library/svg/assembla-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/assembla.svg b/.claude/skills/logo-design/assets/library/svg/assembla.svg deleted file mode 100644 index ca90d7a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/assembla.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/astro.svg b/.claude/skills/logo-design/assets/library/svg/astro.svg deleted file mode 100644 index 46df279..0000000 --- a/.claude/skills/logo-design/assets/library/svg/astro.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/astronomer.svg b/.claude/skills/logo-design/assets/library/svg/astronomer.svg deleted file mode 100644 index 26afb9c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/astronomer.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/atlassian.svg b/.claude/skills/logo-design/assets/library/svg/atlassian.svg deleted file mode 100644 index 9342b52..0000000 --- a/.claude/skills/logo-design/assets/library/svg/atlassian.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/atom-icon.svg b/.claude/skills/logo-design/assets/library/svg/atom-icon.svg deleted file mode 100644 index 1c7b923..0000000 --- a/.claude/skills/logo-design/assets/library/svg/atom-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/atom.svg b/.claude/skills/logo-design/assets/library/svg/atom.svg deleted file mode 100644 index 76ef302..0000000 --- a/.claude/skills/logo-design/assets/library/svg/atom.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/atomic-icon.svg b/.claude/skills/logo-design/assets/library/svg/atomic-icon.svg deleted file mode 100644 index 5144e69..0000000 --- a/.claude/skills/logo-design/assets/library/svg/atomic-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/atomic.svg b/.claude/skills/logo-design/assets/library/svg/atomic.svg deleted file mode 100644 index e93226b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/atomic.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aurelia.svg b/.claude/skills/logo-design/assets/library/svg/aurelia.svg deleted file mode 100644 index 4b8c27e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aurelia.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aurora.svg b/.claude/skills/logo-design/assets/library/svg/aurora.svg deleted file mode 100644 index 3ae76ca..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aurora.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/auth0-icon.svg b/.claude/skills/logo-design/assets/library/svg/auth0-icon.svg deleted file mode 100644 index 39fc597..0000000 --- a/.claude/skills/logo-design/assets/library/svg/auth0-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/auth0.svg b/.claude/skills/logo-design/assets/library/svg/auth0.svg deleted file mode 100644 index 24a9c78..0000000 --- a/.claude/skills/logo-design/assets/library/svg/auth0.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/authy.svg b/.claude/skills/logo-design/assets/library/svg/authy.svg deleted file mode 100644 index 2501d63..0000000 --- a/.claude/skills/logo-design/assets/library/svg/authy.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/autoit.svg b/.claude/skills/logo-design/assets/library/svg/autoit.svg deleted file mode 100644 index b5f4d26..0000000 --- a/.claude/skills/logo-design/assets/library/svg/autoit.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/autoprefixer.svg b/.claude/skills/logo-design/assets/library/svg/autoprefixer.svg deleted file mode 100644 index c8bbcc1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/autoprefixer.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ava.svg b/.claude/skills/logo-design/assets/library/svg/ava.svg deleted file mode 100644 index f6a3df1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ava.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/awesome.svg b/.claude/skills/logo-design/assets/library/svg/awesome.svg deleted file mode 100644 index 34c89ca..0000000 --- a/.claude/skills/logo-design/assets/library/svg/awesome.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-amplify.svg b/.claude/skills/logo-design/assets/library/svg/aws-amplify.svg deleted file mode 100644 index 94f4181..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-amplify.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-api-gateway.svg b/.claude/skills/logo-design/assets/library/svg/aws-api-gateway.svg deleted file mode 100644 index c92875e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-api-gateway.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-app-mesh.svg b/.claude/skills/logo-design/assets/library/svg/aws-app-mesh.svg deleted file mode 100644 index 9a15d3e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-app-mesh.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-appflow.svg b/.claude/skills/logo-design/assets/library/svg/aws-appflow.svg deleted file mode 100644 index 3d00fe8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-appflow.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-appsync.svg b/.claude/skills/logo-design/assets/library/svg/aws-appsync.svg deleted file mode 100644 index 2c07eae..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-appsync.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-athena.svg b/.claude/skills/logo-design/assets/library/svg/aws-athena.svg deleted file mode 100644 index 32a0e25..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-athena.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-aurora.svg b/.claude/skills/logo-design/assets/library/svg/aws-aurora.svg deleted file mode 100644 index 29fab41..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-aurora.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-backup.svg b/.claude/skills/logo-design/assets/library/svg/aws-backup.svg deleted file mode 100644 index 54ee04f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-backup.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-batch.svg b/.claude/skills/logo-design/assets/library/svg/aws-batch.svg deleted file mode 100644 index e2dc790..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-batch.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-certificate-manager.svg b/.claude/skills/logo-design/assets/library/svg/aws-certificate-manager.svg deleted file mode 100644 index ae2f384..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-certificate-manager.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cloudformation.svg b/.claude/skills/logo-design/assets/library/svg/aws-cloudformation.svg deleted file mode 100644 index 589ef2e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-cloudformation.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cloudfront.svg b/.claude/skills/logo-design/assets/library/svg/aws-cloudfront.svg deleted file mode 100644 index 2ec3290..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-cloudfront.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cloudsearch.svg b/.claude/skills/logo-design/assets/library/svg/aws-cloudsearch.svg deleted file mode 100644 index 611a209..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-cloudsearch.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cloudtrail.svg b/.claude/skills/logo-design/assets/library/svg/aws-cloudtrail.svg deleted file mode 100644 index 83ca66d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-cloudtrail.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cloudwatch.svg b/.claude/skills/logo-design/assets/library/svg/aws-cloudwatch.svg deleted file mode 100644 index d9c362e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-cloudwatch.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-codebuild.svg b/.claude/skills/logo-design/assets/library/svg/aws-codebuild.svg deleted file mode 100644 index b4f7b3c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-codebuild.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-codecommit.svg b/.claude/skills/logo-design/assets/library/svg/aws-codecommit.svg deleted file mode 100644 index d0ae4d6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-codecommit.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-codedeploy.svg b/.claude/skills/logo-design/assets/library/svg/aws-codedeploy.svg deleted file mode 100644 index d8b1c92..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-codedeploy.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-codepipeline.svg b/.claude/skills/logo-design/assets/library/svg/aws-codepipeline.svg deleted file mode 100644 index 3cdce33..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-codepipeline.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-codestar.svg b/.claude/skills/logo-design/assets/library/svg/aws-codestar.svg deleted file mode 100644 index 2539bcb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-codestar.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-cognito.svg b/.claude/skills/logo-design/assets/library/svg/aws-cognito.svg deleted file mode 100644 index d477834..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-cognito.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-config.svg b/.claude/skills/logo-design/assets/library/svg/aws-config.svg deleted file mode 100644 index 47c6464..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-config.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-documentdb.svg b/.claude/skills/logo-design/assets/library/svg/aws-documentdb.svg deleted file mode 100644 index 0edb67b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-documentdb.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-dynamodb.svg b/.claude/skills/logo-design/assets/library/svg/aws-dynamodb.svg deleted file mode 100644 index b0cdfbe..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-dynamodb.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-ec2.svg b/.claude/skills/logo-design/assets/library/svg/aws-ec2.svg deleted file mode 100644 index 7fb0c8d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-ec2.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-ecs.svg b/.claude/skills/logo-design/assets/library/svg/aws-ecs.svg deleted file mode 100644 index feddc5b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-ecs.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-eks.svg b/.claude/skills/logo-design/assets/library/svg/aws-eks.svg deleted file mode 100644 index c12d201..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-eks.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-elastic-beanstalk.svg b/.claude/skills/logo-design/assets/library/svg/aws-elastic-beanstalk.svg deleted file mode 100644 index f105019..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-elastic-beanstalk.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-elasticache.svg b/.claude/skills/logo-design/assets/library/svg/aws-elasticache.svg deleted file mode 100644 index 11b9e0d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-elasticache.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-elb.svg b/.claude/skills/logo-design/assets/library/svg/aws-elb.svg deleted file mode 100644 index d4fa7f6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-elb.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-eventbridge.svg b/.claude/skills/logo-design/assets/library/svg/aws-eventbridge.svg deleted file mode 100644 index 8edd382..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-eventbridge.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-fargate.svg b/.claude/skills/logo-design/assets/library/svg/aws-fargate.svg deleted file mode 100644 index 03fe19c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-fargate.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-glacier.svg b/.claude/skills/logo-design/assets/library/svg/aws-glacier.svg deleted file mode 100644 index ef5e82d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-glacier.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-glue.svg b/.claude/skills/logo-design/assets/library/svg/aws-glue.svg deleted file mode 100644 index 328862b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-glue.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-iam.svg b/.claude/skills/logo-design/assets/library/svg/aws-iam.svg deleted file mode 100644 index 251ddb2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-iam.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-keyspaces.svg b/.claude/skills/logo-design/assets/library/svg/aws-keyspaces.svg deleted file mode 100644 index 6777cde..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-keyspaces.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-kinesis.svg b/.claude/skills/logo-design/assets/library/svg/aws-kinesis.svg deleted file mode 100644 index 378fe79..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-kinesis.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-kms.svg b/.claude/skills/logo-design/assets/library/svg/aws-kms.svg deleted file mode 100644 index b8228fd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-kms.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-lake-formation.svg b/.claude/skills/logo-design/assets/library/svg/aws-lake-formation.svg deleted file mode 100644 index a7a6e0d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-lake-formation.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-lambda.svg b/.claude/skills/logo-design/assets/library/svg/aws-lambda.svg deleted file mode 100644 index 6c166d4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-lambda.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-lightsail.svg b/.claude/skills/logo-design/assets/library/svg/aws-lightsail.svg deleted file mode 100644 index c4f62b5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-lightsail.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-mq.svg b/.claude/skills/logo-design/assets/library/svg/aws-mq.svg deleted file mode 100644 index 96dfd0a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-mq.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-msk.svg b/.claude/skills/logo-design/assets/library/svg/aws-msk.svg deleted file mode 100644 index 0c83d0f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-msk.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-neptune.svg b/.claude/skills/logo-design/assets/library/svg/aws-neptune.svg deleted file mode 100644 index 4a9c1a3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-neptune.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-open-search.svg b/.claude/skills/logo-design/assets/library/svg/aws-open-search.svg deleted file mode 100644 index 4cff6b4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-open-search.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-opsworks.svg b/.claude/skills/logo-design/assets/library/svg/aws-opsworks.svg deleted file mode 100644 index fc08827..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-opsworks.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-quicksight.svg b/.claude/skills/logo-design/assets/library/svg/aws-quicksight.svg deleted file mode 100644 index 2624e2c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-quicksight.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-rds.svg b/.claude/skills/logo-design/assets/library/svg/aws-rds.svg deleted file mode 100644 index cfd258b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-rds.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-redshift.svg b/.claude/skills/logo-design/assets/library/svg/aws-redshift.svg deleted file mode 100644 index 1ad29b9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-redshift.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-route53.svg b/.claude/skills/logo-design/assets/library/svg/aws-route53.svg deleted file mode 100644 index e51e4fa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-route53.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-s3.svg b/.claude/skills/logo-design/assets/library/svg/aws-s3.svg deleted file mode 100644 index d7fd723..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-s3.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-secrets-manager.svg b/.claude/skills/logo-design/assets/library/svg/aws-secrets-manager.svg deleted file mode 100644 index 38cb97a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-secrets-manager.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-ses.svg b/.claude/skills/logo-design/assets/library/svg/aws-ses.svg deleted file mode 100644 index 968dad3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-ses.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-shield.svg b/.claude/skills/logo-design/assets/library/svg/aws-shield.svg deleted file mode 100644 index 0d4e63f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-shield.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-sns.svg b/.claude/skills/logo-design/assets/library/svg/aws-sns.svg deleted file mode 100644 index 77ffedb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-sns.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-sqs.svg b/.claude/skills/logo-design/assets/library/svg/aws-sqs.svg deleted file mode 100644 index a1fb7b5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-sqs.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-step-functions.svg b/.claude/skills/logo-design/assets/library/svg/aws-step-functions.svg deleted file mode 100644 index 4ba08e8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-step-functions.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-systems-manager.svg b/.claude/skills/logo-design/assets/library/svg/aws-systems-manager.svg deleted file mode 100644 index a1c575f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-systems-manager.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-timestream.svg b/.claude/skills/logo-design/assets/library/svg/aws-timestream.svg deleted file mode 100644 index 4da73ca..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-timestream.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-vpc.svg b/.claude/skills/logo-design/assets/library/svg/aws-vpc.svg deleted file mode 100644 index 9182bed..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-vpc.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-waf.svg b/.claude/skills/logo-design/assets/library/svg/aws-waf.svg deleted file mode 100644 index 4e20810..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-waf.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws-xray.svg b/.claude/skills/logo-design/assets/library/svg/aws-xray.svg deleted file mode 100644 index 5ffc0ac..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws-xray.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/aws.svg b/.claude/skills/logo-design/assets/library/svg/aws.svg deleted file mode 100644 index 5d367be..0000000 --- a/.claude/skills/logo-design/assets/library/svg/aws.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/axios.svg b/.claude/skills/logo-design/assets/library/svg/axios.svg deleted file mode 100644 index 07e8d28..0000000 --- a/.claude/skills/logo-design/assets/library/svg/axios.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/babel.svg b/.claude/skills/logo-design/assets/library/svg/babel.svg deleted file mode 100644 index 9a3fd35..0000000 --- a/.claude/skills/logo-design/assets/library/svg/babel.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/backbone-icon.svg b/.claude/skills/logo-design/assets/library/svg/backbone-icon.svg deleted file mode 100644 index 94cd948..0000000 --- a/.claude/skills/logo-design/assets/library/svg/backbone-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/backbone.svg b/.claude/skills/logo-design/assets/library/svg/backbone.svg deleted file mode 100644 index a5bd0a7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/backbone.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/backerkit.svg b/.claude/skills/logo-design/assets/library/svg/backerkit.svg deleted file mode 100644 index 0807d55..0000000 --- a/.claude/skills/logo-design/assets/library/svg/backerkit.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/baker-street.svg b/.claude/skills/logo-design/assets/library/svg/baker-street.svg deleted file mode 100644 index a7bd632..0000000 --- a/.claude/skills/logo-design/assets/library/svg/baker-street.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/balena.svg b/.claude/skills/logo-design/assets/library/svg/balena.svg deleted file mode 100644 index 7e52088..0000000 --- a/.claude/skills/logo-design/assets/library/svg/balena.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bamboo.svg b/.claude/skills/logo-design/assets/library/svg/bamboo.svg deleted file mode 100644 index 272298b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bamboo.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/basecamp.svg b/.claude/skills/logo-design/assets/library/svg/basecamp.svg deleted file mode 100644 index cc7c508..0000000 --- a/.claude/skills/logo-design/assets/library/svg/basecamp.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/basekit.svg b/.claude/skills/logo-design/assets/library/svg/basekit.svg deleted file mode 100644 index 23f6884..0000000 --- a/.claude/skills/logo-design/assets/library/svg/basekit.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bash-icon.svg b/.claude/skills/logo-design/assets/library/svg/bash-icon.svg deleted file mode 100644 index 6278eac..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bash-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bash.svg b/.claude/skills/logo-design/assets/library/svg/bash.svg deleted file mode 100644 index 1c79b18..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bash.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/batch.svg b/.claude/skills/logo-design/assets/library/svg/batch.svg deleted file mode 100644 index d590c7e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/batch.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/beats.svg b/.claude/skills/logo-design/assets/library/svg/beats.svg deleted file mode 100644 index 710f0f4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/beats.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/behance.svg b/.claude/skills/logo-design/assets/library/svg/behance.svg deleted file mode 100644 index bf4f5c8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/behance.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bem-2.svg b/.claude/skills/logo-design/assets/library/svg/bem-2.svg deleted file mode 100644 index d4cdb78..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bem-2.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bem.svg b/.claude/skills/logo-design/assets/library/svg/bem.svg deleted file mode 100644 index 4e3499b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bem.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bigpanda.svg b/.claude/skills/logo-design/assets/library/svg/bigpanda.svg deleted file mode 100644 index 98a7d12..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bigpanda.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bing.svg b/.claude/skills/logo-design/assets/library/svg/bing.svg deleted file mode 100644 index 750f1f2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bing.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bitbucket.svg b/.claude/skills/logo-design/assets/library/svg/bitbucket.svg deleted file mode 100644 index 54d8681..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bitbucket.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bitcoin.svg b/.claude/skills/logo-design/assets/library/svg/bitcoin.svg deleted file mode 100644 index a140fe3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bitcoin.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bitnami.svg b/.claude/skills/logo-design/assets/library/svg/bitnami.svg deleted file mode 100644 index 5727987..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bitnami.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bitrise-icon.svg b/.claude/skills/logo-design/assets/library/svg/bitrise-icon.svg deleted file mode 100644 index 140928d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bitrise-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bitrise.svg b/.claude/skills/logo-design/assets/library/svg/bitrise.svg deleted file mode 100644 index 4047ddd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bitrise.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/blender.svg b/.claude/skills/logo-design/assets/library/svg/blender.svg deleted file mode 100644 index c062924..0000000 --- a/.claude/skills/logo-design/assets/library/svg/blender.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/blitzjs-icon.svg b/.claude/skills/logo-design/assets/library/svg/blitzjs-icon.svg deleted file mode 100644 index 24a5c4f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/blitzjs-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/blitzjs.svg b/.claude/skills/logo-design/assets/library/svg/blitzjs.svg deleted file mode 100644 index b62e846..0000000 --- a/.claude/skills/logo-design/assets/library/svg/blitzjs.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/blocs.svg b/.claude/skills/logo-design/assets/library/svg/blocs.svg deleted file mode 100644 index 001c5ed..0000000 --- a/.claude/skills/logo-design/assets/library/svg/blocs.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/blogger.svg b/.claude/skills/logo-design/assets/library/svg/blogger.svg deleted file mode 100644 index 5de87ff..0000000 --- a/.claude/skills/logo-design/assets/library/svg/blogger.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/blossom.svg b/.claude/skills/logo-design/assets/library/svg/blossom.svg deleted file mode 100644 index f2d2819..0000000 --- a/.claude/skills/logo-design/assets/library/svg/blossom.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/blueprint.svg b/.claude/skills/logo-design/assets/library/svg/blueprint.svg deleted file mode 100644 index 7edc06f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/blueprint.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bluetooth.svg b/.claude/skills/logo-design/assets/library/svg/bluetooth.svg deleted file mode 100644 index 05e51f5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bluetooth.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/booqable-icon.svg b/.claude/skills/logo-design/assets/library/svg/booqable-icon.svg deleted file mode 100644 index 5b0334c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/booqable-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/booqable.svg b/.claude/skills/logo-design/assets/library/svg/booqable.svg deleted file mode 100644 index 7debde9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/booqable.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bootstrap.svg b/.claude/skills/logo-design/assets/library/svg/bootstrap.svg deleted file mode 100644 index f91cfe6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bootstrap.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bosun.svg b/.claude/skills/logo-design/assets/library/svg/bosun.svg deleted file mode 100644 index 49d911a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bosun.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/botanalytics.svg b/.claude/skills/logo-design/assets/library/svg/botanalytics.svg deleted file mode 100644 index 9e6c161..0000000 --- a/.claude/skills/logo-design/assets/library/svg/botanalytics.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bourbon.svg b/.claude/skills/logo-design/assets/library/svg/bourbon.svg deleted file mode 100644 index 422822a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bourbon.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bower.svg b/.claude/skills/logo-design/assets/library/svg/bower.svg deleted file mode 100644 index c88f3e5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bower.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/box.svg b/.claude/skills/logo-design/assets/library/svg/box.svg deleted file mode 100644 index 8e6d7d8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/box.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/brackets.svg b/.claude/skills/logo-design/assets/library/svg/brackets.svg deleted file mode 100644 index 419544c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/brackets.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/brainjs.svg b/.claude/skills/logo-design/assets/library/svg/brainjs.svg deleted file mode 100644 index bb46892..0000000 --- a/.claude/skills/logo-design/assets/library/svg/brainjs.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/branch.svg b/.claude/skills/logo-design/assets/library/svg/branch.svg deleted file mode 100644 index 52103e0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/branch.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/brandfolder-icon.svg b/.claude/skills/logo-design/assets/library/svg/brandfolder-icon.svg deleted file mode 100644 index 5cc4e7f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/brandfolder-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/brandfolder.svg b/.claude/skills/logo-design/assets/library/svg/brandfolder.svg deleted file mode 100644 index feda0c0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/brandfolder.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/brave.svg b/.claude/skills/logo-design/assets/library/svg/brave.svg deleted file mode 100644 index 606628c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/brave.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/braze.svg b/.claude/skills/logo-design/assets/library/svg/braze.svg deleted file mode 100644 index a3a0286..0000000 --- a/.claude/skills/logo-design/assets/library/svg/braze.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/broccoli.svg b/.claude/skills/logo-design/assets/library/svg/broccoli.svg deleted file mode 100644 index bafb03c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/broccoli.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/brotli.svg b/.claude/skills/logo-design/assets/library/svg/brotli.svg deleted file mode 100644 index f49a226..0000000 --- a/.claude/skills/logo-design/assets/library/svg/brotli.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/browserify-icon.svg b/.claude/skills/logo-design/assets/library/svg/browserify-icon.svg deleted file mode 100644 index 4554828..0000000 --- a/.claude/skills/logo-design/assets/library/svg/browserify-icon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/browserify.svg b/.claude/skills/logo-design/assets/library/svg/browserify.svg deleted file mode 100644 index 235f4e2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/browserify.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/browserling.svg b/.claude/skills/logo-design/assets/library/svg/browserling.svg deleted file mode 100644 index ce96585..0000000 --- a/.claude/skills/logo-design/assets/library/svg/browserling.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/browserslist.svg b/.claude/skills/logo-design/assets/library/svg/browserslist.svg deleted file mode 100644 index ac0efac..0000000 --- a/.claude/skills/logo-design/assets/library/svg/browserslist.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/browserstack.svg b/.claude/skills/logo-design/assets/library/svg/browserstack.svg deleted file mode 100644 index bc5c164..0000000 --- a/.claude/skills/logo-design/assets/library/svg/browserstack.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/browsersync.svg b/.claude/skills/logo-design/assets/library/svg/browsersync.svg deleted file mode 100644 index 08315f6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/browsersync.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/brunch.svg b/.claude/skills/logo-design/assets/library/svg/brunch.svg deleted file mode 100644 index 5562f78..0000000 --- a/.claude/skills/logo-design/assets/library/svg/brunch.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/buck.svg b/.claude/skills/logo-design/assets/library/svg/buck.svg deleted file mode 100644 index 90e8790..0000000 --- a/.claude/skills/logo-design/assets/library/svg/buck.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/buddy.svg b/.claude/skills/logo-design/assets/library/svg/buddy.svg deleted file mode 100644 index 1764223..0000000 --- a/.claude/skills/logo-design/assets/library/svg/buddy.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/buffer.svg b/.claude/skills/logo-design/assets/library/svg/buffer.svg deleted file mode 100644 index 13b682b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/buffer.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bugherd.svg b/.claude/skills/logo-design/assets/library/svg/bugherd.svg deleted file mode 100644 index 2ff15ff..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bugherd.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bugsee.svg b/.claude/skills/logo-design/assets/library/svg/bugsee.svg deleted file mode 100644 index eaf8bcf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bugsee.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bugsnag-icon.svg b/.claude/skills/logo-design/assets/library/svg/bugsnag-icon.svg deleted file mode 100644 index 087d9e2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bugsnag-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bugsnag.svg b/.claude/skills/logo-design/assets/library/svg/bugsnag.svg deleted file mode 100644 index 2068d3f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bugsnag.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/buildkite-icon.svg b/.claude/skills/logo-design/assets/library/svg/buildkite-icon.svg deleted file mode 100644 index 07c4e16..0000000 --- a/.claude/skills/logo-design/assets/library/svg/buildkite-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/buildkite.svg b/.claude/skills/logo-design/assets/library/svg/buildkite.svg deleted file mode 100644 index d9e3401..0000000 --- a/.claude/skills/logo-design/assets/library/svg/buildkite.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/bulma.svg b/.claude/skills/logo-design/assets/library/svg/bulma.svg deleted file mode 100644 index 8a7ca38..0000000 --- a/.claude/skills/logo-design/assets/library/svg/bulma.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/c-plusplus.svg b/.claude/skills/logo-design/assets/library/svg/c-plusplus.svg deleted file mode 100644 index 91c25d3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/c-plusplus.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/c-sharp.svg b/.claude/skills/logo-design/assets/library/svg/c-sharp.svg deleted file mode 100644 index ba9cad6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/c-sharp.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/c.svg b/.claude/skills/logo-design/assets/library/svg/c.svg deleted file mode 100644 index f5812f4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/c.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cachet.svg b/.claude/skills/logo-design/assets/library/svg/cachet.svg deleted file mode 100644 index 1f41727..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cachet.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/caffe2.svg b/.claude/skills/logo-design/assets/library/svg/caffe2.svg deleted file mode 100644 index e8bb3f4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/caffe2.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cakephp-icon.svg b/.claude/skills/logo-design/assets/library/svg/cakephp-icon.svg deleted file mode 100644 index f4933c7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cakephp-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cakephp.svg b/.claude/skills/logo-design/assets/library/svg/cakephp.svg deleted file mode 100644 index 88ee12d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cakephp.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/campaignmonitor-icon.svg b/.claude/skills/logo-design/assets/library/svg/campaignmonitor-icon.svg deleted file mode 100644 index 59e4046..0000000 --- a/.claude/skills/logo-design/assets/library/svg/campaignmonitor-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/campaignmonitor.svg b/.claude/skills/logo-design/assets/library/svg/campaignmonitor.svg deleted file mode 100644 index e2534cd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/campaignmonitor.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/canjs.svg b/.claude/skills/logo-design/assets/library/svg/canjs.svg deleted file mode 100644 index 54f02a3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/canjs.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/capacitorjs-icon.svg b/.claude/skills/logo-design/assets/library/svg/capacitorjs-icon.svg deleted file mode 100644 index 641803c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/capacitorjs-icon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/capacitorjs.svg b/.claude/skills/logo-design/assets/library/svg/capacitorjs.svg deleted file mode 100644 index 6245076..0000000 --- a/.claude/skills/logo-design/assets/library/svg/capacitorjs.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/capistrano.svg b/.claude/skills/logo-design/assets/library/svg/capistrano.svg deleted file mode 100644 index 47b7ed9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/capistrano.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/carbide.svg b/.claude/skills/logo-design/assets/library/svg/carbide.svg deleted file mode 100644 index 42fb54a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/carbide.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cardano-icon.svg b/.claude/skills/logo-design/assets/library/svg/cardano-icon.svg deleted file mode 100644 index 323e020..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cardano-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cardano.svg b/.claude/skills/logo-design/assets/library/svg/cardano.svg deleted file mode 100644 index e53cfdb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cardano.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cassandra.svg b/.claude/skills/logo-design/assets/library/svg/cassandra.svg deleted file mode 100644 index 9ff5291..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cassandra.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/centos-icon.svg b/.claude/skills/logo-design/assets/library/svg/centos-icon.svg deleted file mode 100644 index f02f9ec..0000000 --- a/.claude/skills/logo-design/assets/library/svg/centos-icon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/centos.svg b/.claude/skills/logo-design/assets/library/svg/centos.svg deleted file mode 100644 index a9ad316..0000000 --- a/.claude/skills/logo-design/assets/library/svg/centos.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/certbot.svg b/.claude/skills/logo-design/assets/library/svg/certbot.svg deleted file mode 100644 index ddf2a6b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/certbot.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ceylon.svg b/.claude/skills/logo-design/assets/library/svg/ceylon.svg deleted file mode 100644 index a2c2186..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ceylon.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/chai.svg b/.claude/skills/logo-design/assets/library/svg/chai.svg deleted file mode 100644 index 41d346b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/chai.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/chalk.svg b/.claude/skills/logo-design/assets/library/svg/chalk.svg deleted file mode 100644 index ee527ae..0000000 --- a/.claude/skills/logo-design/assets/library/svg/chalk.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/chargebee-icon.svg b/.claude/skills/logo-design/assets/library/svg/chargebee-icon.svg deleted file mode 100644 index 6fbe07b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/chargebee-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/chargebee.svg b/.claude/skills/logo-design/assets/library/svg/chargebee.svg deleted file mode 100644 index 73858e7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/chargebee.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/chef.svg b/.claude/skills/logo-design/assets/library/svg/chef.svg deleted file mode 100644 index bf1004a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/chef.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/chevereto.svg b/.claude/skills/logo-design/assets/library/svg/chevereto.svg deleted file mode 100644 index 9aa6263..0000000 --- a/.claude/skills/logo-design/assets/library/svg/chevereto.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/chromatic-icon.svg b/.claude/skills/logo-design/assets/library/svg/chromatic-icon.svg deleted file mode 100644 index 50b7ccb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/chromatic-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/chromatic.svg b/.claude/skills/logo-design/assets/library/svg/chromatic.svg deleted file mode 100644 index 58b179d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/chromatic.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/chrome.svg b/.claude/skills/logo-design/assets/library/svg/chrome.svg deleted file mode 100644 index 1ba8fd3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/chrome.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cinder.svg b/.claude/skills/logo-design/assets/library/svg/cinder.svg deleted file mode 100644 index 33f3c00..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cinder.svg +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/circleci.svg b/.claude/skills/logo-design/assets/library/svg/circleci.svg deleted file mode 100644 index ca1c013..0000000 --- a/.claude/skills/logo-design/assets/library/svg/circleci.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cirrus-ci.svg b/.claude/skills/logo-design/assets/library/svg/cirrus-ci.svg deleted file mode 100644 index 57cec4a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cirrus-ci.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cirrus.svg b/.claude/skills/logo-design/assets/library/svg/cirrus.svg deleted file mode 100644 index fa8f122..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cirrus.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/clion.svg b/.claude/skills/logo-design/assets/library/svg/clion.svg deleted file mode 100644 index 3417019..0000000 --- a/.claude/skills/logo-design/assets/library/svg/clion.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cljs.svg b/.claude/skills/logo-design/assets/library/svg/cljs.svg deleted file mode 100644 index 517648b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cljs.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/clojure.svg b/.claude/skills/logo-design/assets/library/svg/clojure.svg deleted file mode 100644 index 4ae06d5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/clojure.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/close.svg b/.claude/skills/logo-design/assets/library/svg/close.svg deleted file mode 100644 index 59afaa8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/close.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cloud9.svg b/.claude/skills/logo-design/assets/library/svg/cloud9.svg deleted file mode 100644 index cf74819..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cloud9.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cloudacademy-icon.svg b/.claude/skills/logo-design/assets/library/svg/cloudacademy-icon.svg deleted file mode 100644 index d8fcf68..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cloudacademy-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cloudacademy.svg b/.claude/skills/logo-design/assets/library/svg/cloudacademy.svg deleted file mode 100644 index b697f72..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cloudacademy.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cloudcraft.svg b/.claude/skills/logo-design/assets/library/svg/cloudcraft.svg deleted file mode 100644 index 33fae1b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cloudcraft.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cloudflare.svg b/.claude/skills/logo-design/assets/library/svg/cloudflare.svg deleted file mode 100644 index f7cff0b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cloudflare.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cloudinary.svg b/.claude/skills/logo-design/assets/library/svg/cloudinary.svg deleted file mode 100644 index 3be3f04..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cloudinary.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cloudlinux.svg b/.claude/skills/logo-design/assets/library/svg/cloudlinux.svg deleted file mode 100644 index f30c816..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cloudlinux.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cobalt.svg b/.claude/skills/logo-design/assets/library/svg/cobalt.svg deleted file mode 100644 index 1a949ca..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cobalt.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cockpit.svg b/.claude/skills/logo-design/assets/library/svg/cockpit.svg deleted file mode 100644 index 5e21ddc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cockpit.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cocoapods.svg b/.claude/skills/logo-design/assets/library/svg/cocoapods.svg deleted file mode 100644 index 71aace0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cocoapods.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codacy.svg b/.claude/skills/logo-design/assets/library/svg/codacy.svg deleted file mode 100644 index 2201c1a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codacy.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codebase.svg b/.claude/skills/logo-design/assets/library/svg/codebase.svg deleted file mode 100644 index e66dd1d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codebase.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codebeat.svg b/.claude/skills/logo-design/assets/library/svg/codebeat.svg deleted file mode 100644 index f4a6f12..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codebeat.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codecademy.svg b/.claude/skills/logo-design/assets/library/svg/codecademy.svg deleted file mode 100644 index 4012db6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codecademy.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codeception.svg b/.claude/skills/logo-design/assets/library/svg/codeception.svg deleted file mode 100644 index 121fe5e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codeception.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codeclimate.svg b/.claude/skills/logo-design/assets/library/svg/codeclimate.svg deleted file mode 100644 index 8ec5aea..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codeclimate.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codecov.svg b/.claude/skills/logo-design/assets/library/svg/codecov.svg deleted file mode 100644 index 947b8aa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codecov.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codefactor-icon.svg b/.claude/skills/logo-design/assets/library/svg/codefactor-icon.svg deleted file mode 100644 index 6bb0f60..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codefactor-icon.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codefactor.svg b/.claude/skills/logo-design/assets/library/svg/codefactor.svg deleted file mode 100644 index 5114198..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codefactor.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codeigniter.svg b/.claude/skills/logo-design/assets/library/svg/codeigniter.svg deleted file mode 100644 index e1cbc9e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codeigniter.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codepen-icon.svg b/.claude/skills/logo-design/assets/library/svg/codepen-icon.svg deleted file mode 100644 index b0cf125..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codepen-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codepen.svg b/.claude/skills/logo-design/assets/library/svg/codepen.svg deleted file mode 100644 index 571595c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codepen.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codepush.svg b/.claude/skills/logo-design/assets/library/svg/codepush.svg deleted file mode 100644 index 8c8dd71..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codepush.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codersrank.svg b/.claude/skills/logo-design/assets/library/svg/codersrank.svg deleted file mode 100644 index d646450..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codersrank.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/coderwall.svg b/.claude/skills/logo-design/assets/library/svg/coderwall.svg deleted file mode 100644 index 7713930..0000000 --- a/.claude/skills/logo-design/assets/library/svg/coderwall.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codesandbox.svg b/.claude/skills/logo-design/assets/library/svg/codesandbox.svg deleted file mode 100644 index 6a4ed45..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codesandbox.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codeship.svg b/.claude/skills/logo-design/assets/library/svg/codeship.svg deleted file mode 100644 index 0fa6edd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codeship.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codio.svg b/.claude/skills/logo-design/assets/library/svg/codio.svg deleted file mode 100644 index af46d1a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codio.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/codrops.svg b/.claude/skills/logo-design/assets/library/svg/codrops.svg deleted file mode 100644 index 4c6277f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/codrops.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/coffeescript.svg b/.claude/skills/logo-design/assets/library/svg/coffeescript.svg deleted file mode 100644 index 6f46e94..0000000 --- a/.claude/skills/logo-design/assets/library/svg/coffeescript.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/commitizen.svg b/.claude/skills/logo-design/assets/library/svg/commitizen.svg deleted file mode 100644 index a74f825..0000000 --- a/.claude/skills/logo-design/assets/library/svg/commitizen.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/compass.svg b/.claude/skills/logo-design/assets/library/svg/compass.svg deleted file mode 100644 index 89b8c3e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/compass.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/componentkit.svg b/.claude/skills/logo-design/assets/library/svg/componentkit.svg deleted file mode 100644 index 12d75c7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/componentkit.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/compose.svg b/.claude/skills/logo-design/assets/library/svg/compose.svg deleted file mode 100644 index bbbc9cb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/compose.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/composer.svg b/.claude/skills/logo-design/assets/library/svg/composer.svg deleted file mode 100644 index 110fab2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/composer.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/conan-io.svg b/.claude/skills/logo-design/assets/library/svg/conan-io.svg deleted file mode 100644 index a9f6d93..0000000 --- a/.claude/skills/logo-design/assets/library/svg/conan-io.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/concourse.svg b/.claude/skills/logo-design/assets/library/svg/concourse.svg deleted file mode 100644 index 498d204..0000000 --- a/.claude/skills/logo-design/assets/library/svg/concourse.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/concrete5.svg b/.claude/skills/logo-design/assets/library/svg/concrete5.svg deleted file mode 100644 index 6d2392c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/concrete5.svg +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/confluence.svg b/.claude/skills/logo-design/assets/library/svg/confluence.svg deleted file mode 100644 index 7e405d1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/confluence.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/consul.svg b/.claude/skills/logo-design/assets/library/svg/consul.svg deleted file mode 100644 index be5b64d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/consul.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/contentful.svg b/.claude/skills/logo-design/assets/library/svg/contentful.svg deleted file mode 100644 index e532abb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/contentful.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/convox.svg b/.claude/skills/logo-design/assets/library/svg/convox.svg deleted file mode 100644 index 9354ff4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/convox.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/copyleft-pirate.svg b/.claude/skills/logo-design/assets/library/svg/copyleft-pirate.svg deleted file mode 100644 index 4cf91a6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/copyleft-pirate.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/copyleft.svg b/.claude/skills/logo-design/assets/library/svg/copyleft.svg deleted file mode 100644 index 1446861..0000000 --- a/.claude/skills/logo-design/assets/library/svg/copyleft.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/corda.svg b/.claude/skills/logo-design/assets/library/svg/corda.svg deleted file mode 100644 index 59ecd72..0000000 --- a/.claude/skills/logo-design/assets/library/svg/corda.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cordova.svg b/.claude/skills/logo-design/assets/library/svg/cordova.svg deleted file mode 100644 index 820bff5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cordova.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/coreos-icon.svg b/.claude/skills/logo-design/assets/library/svg/coreos-icon.svg deleted file mode 100644 index 11d6ed0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/coreos-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/coreos.svg b/.claude/skills/logo-design/assets/library/svg/coreos.svg deleted file mode 100644 index 95c1c24..0000000 --- a/.claude/skills/logo-design/assets/library/svg/coreos.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/couchbase.svg b/.claude/skills/logo-design/assets/library/svg/couchbase.svg deleted file mode 100644 index 7def85b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/couchbase.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/couchdb-icon.svg b/.claude/skills/logo-design/assets/library/svg/couchdb-icon.svg deleted file mode 100644 index f4e706e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/couchdb-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/couchdb.svg b/.claude/skills/logo-design/assets/library/svg/couchdb.svg deleted file mode 100644 index 51581e3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/couchdb.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/coursera.svg b/.claude/skills/logo-design/assets/library/svg/coursera.svg deleted file mode 100644 index b120c44..0000000 --- a/.claude/skills/logo-design/assets/library/svg/coursera.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/coveralls.svg b/.claude/skills/logo-design/assets/library/svg/coveralls.svg deleted file mode 100644 index 282636d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/coveralls.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cpanel.svg b/.claude/skills/logo-design/assets/library/svg/cpanel.svg deleted file mode 100644 index e6683e5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cpanel.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/craftcms.svg b/.claude/skills/logo-design/assets/library/svg/craftcms.svg deleted file mode 100644 index 40e7e3c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/craftcms.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/crashlytics.svg b/.claude/skills/logo-design/assets/library/svg/crashlytics.svg deleted file mode 100644 index b9fc905..0000000 --- a/.claude/skills/logo-design/assets/library/svg/crashlytics.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/crateio.svg b/.claude/skills/logo-design/assets/library/svg/crateio.svg deleted file mode 100644 index 24613bd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/crateio.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/create-react-app.svg b/.claude/skills/logo-design/assets/library/svg/create-react-app.svg deleted file mode 100644 index 92da438..0000000 --- a/.claude/skills/logo-design/assets/library/svg/create-react-app.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/createjs.svg b/.claude/skills/logo-design/assets/library/svg/createjs.svg deleted file mode 100644 index 5f08ce8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/createjs.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cross-browser-testing.svg b/.claude/skills/logo-design/assets/library/svg/cross-browser-testing.svg deleted file mode 100644 index 9275789..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cross-browser-testing.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/crucible.svg b/.claude/skills/logo-design/assets/library/svg/crucible.svg deleted file mode 100644 index 527ae73..0000000 --- a/.claude/skills/logo-design/assets/library/svg/crucible.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/crystal.svg b/.claude/skills/logo-design/assets/library/svg/crystal.svg deleted file mode 100644 index ebd969e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/crystal.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/css-3.svg b/.claude/skills/logo-design/assets/library/svg/css-3.svg deleted file mode 100644 index 1526f3b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/css-3.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/css-3_official.svg b/.claude/skills/logo-design/assets/library/svg/css-3_official.svg deleted file mode 100644 index f1c9939..0000000 --- a/.claude/skills/logo-design/assets/library/svg/css-3_official.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cssnext.svg b/.claude/skills/logo-design/assets/library/svg/cssnext.svg deleted file mode 100644 index fc432d4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cssnext.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cucumber.svg b/.claude/skills/logo-design/assets/library/svg/cucumber.svg deleted file mode 100644 index 937acc8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cucumber.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/curl.svg b/.claude/skills/logo-design/assets/library/svg/curl.svg deleted file mode 100644 index 104ba3c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/curl.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/customerio-icon.svg b/.claude/skills/logo-design/assets/library/svg/customerio-icon.svg deleted file mode 100644 index 88229c3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/customerio-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/customerio.svg b/.claude/skills/logo-design/assets/library/svg/customerio.svg deleted file mode 100644 index b3c7271..0000000 --- a/.claude/skills/logo-design/assets/library/svg/customerio.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cyclejs.svg b/.claude/skills/logo-design/assets/library/svg/cyclejs.svg deleted file mode 100644 index ef4bc9d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cyclejs.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/cypress.svg b/.claude/skills/logo-design/assets/library/svg/cypress.svg deleted file mode 100644 index 17230b4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/cypress.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/d3.svg b/.claude/skills/logo-design/assets/library/svg/d3.svg deleted file mode 100644 index 24e21be..0000000 --- a/.claude/skills/logo-design/assets/library/svg/d3.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dart.svg b/.claude/skills/logo-design/assets/library/svg/dart.svg deleted file mode 100644 index 9cbc429..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dart.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dashlane-icon.svg b/.claude/skills/logo-design/assets/library/svg/dashlane-icon.svg deleted file mode 100644 index 457ec11..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dashlane-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dashlane.svg b/.claude/skills/logo-design/assets/library/svg/dashlane.svg deleted file mode 100644 index 2641b30..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dashlane.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/database-labs.svg b/.claude/skills/logo-design/assets/library/svg/database-labs.svg deleted file mode 100644 index 34e7b56..0000000 --- a/.claude/skills/logo-design/assets/library/svg/database-labs.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/datadog.svg b/.claude/skills/logo-design/assets/library/svg/datadog.svg deleted file mode 100644 index 8000a38..0000000 --- a/.claude/skills/logo-design/assets/library/svg/datadog.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/datocms-icon.svg b/.claude/skills/logo-design/assets/library/svg/datocms-icon.svg deleted file mode 100644 index eeeb417..0000000 --- a/.claude/skills/logo-design/assets/library/svg/datocms-icon.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/datocms.svg b/.claude/skills/logo-design/assets/library/svg/datocms.svg deleted file mode 100644 index fdb0554..0000000 --- a/.claude/skills/logo-design/assets/library/svg/datocms.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dbt-icon.svg b/.claude/skills/logo-design/assets/library/svg/dbt-icon.svg deleted file mode 100644 index fa33326..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dbt-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dbt.svg b/.claude/skills/logo-design/assets/library/svg/dbt.svg deleted file mode 100644 index c72cabe..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dbt.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dcos-icon.svg b/.claude/skills/logo-design/assets/library/svg/dcos-icon.svg deleted file mode 100644 index 13399a2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dcos-icon.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dcos.svg b/.claude/skills/logo-design/assets/library/svg/dcos.svg deleted file mode 100644 index 001f44b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dcos.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/debian.svg b/.claude/skills/logo-design/assets/library/svg/debian.svg deleted file mode 100644 index fe8c457..0000000 --- a/.claude/skills/logo-design/assets/library/svg/debian.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/delighted-icon.svg b/.claude/skills/logo-design/assets/library/svg/delighted-icon.svg deleted file mode 100644 index b36dece..0000000 --- a/.claude/skills/logo-design/assets/library/svg/delighted-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/delighted.svg b/.claude/skills/logo-design/assets/library/svg/delighted.svg deleted file mode 100644 index c1ffe25..0000000 --- a/.claude/skills/logo-design/assets/library/svg/delighted.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/deno.svg b/.claude/skills/logo-design/assets/library/svg/deno.svg deleted file mode 100644 index 7687e66..0000000 --- a/.claude/skills/logo-design/assets/library/svg/deno.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/deployhq.svg b/.claude/skills/logo-design/assets/library/svg/deployhq.svg deleted file mode 100644 index 8dd8f85..0000000 --- a/.claude/skills/logo-design/assets/library/svg/deployhq.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/derby.svg b/.claude/skills/logo-design/assets/library/svg/derby.svg deleted file mode 100644 index b9380c7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/derby.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/designernews.svg b/.claude/skills/logo-design/assets/library/svg/designernews.svg deleted file mode 100644 index 34590e3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/designernews.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/deviantart.svg b/.claude/skills/logo-design/assets/library/svg/deviantart.svg deleted file mode 100644 index fb96b7a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/deviantart.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dgraph-icon.svg b/.claude/skills/logo-design/assets/library/svg/dgraph-icon.svg deleted file mode 100644 index b2182da..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dgraph-icon.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dgraph.svg b/.claude/skills/logo-design/assets/library/svg/dgraph.svg deleted file mode 100644 index 32679d1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dgraph.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dialogflow.svg b/.claude/skills/logo-design/assets/library/svg/dialogflow.svg deleted file mode 100644 index faad495..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dialogflow.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/digital-ocean.svg b/.claude/skills/logo-design/assets/library/svg/digital-ocean.svg deleted file mode 100644 index 5132fac..0000000 --- a/.claude/skills/logo-design/assets/library/svg/digital-ocean.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dimer.svg b/.claude/skills/logo-design/assets/library/svg/dimer.svg deleted file mode 100644 index 5db2147..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dimer.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dinersclub.svg b/.claude/skills/logo-design/assets/library/svg/dinersclub.svg deleted file mode 100644 index 776932b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dinersclub.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/discord-icon.svg b/.claude/skills/logo-design/assets/library/svg/discord-icon.svg deleted file mode 100644 index ff33841..0000000 --- a/.claude/skills/logo-design/assets/library/svg/discord-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/discord.svg b/.claude/skills/logo-design/assets/library/svg/discord.svg deleted file mode 100644 index f1c6b71..0000000 --- a/.claude/skills/logo-design/assets/library/svg/discord.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/discover.svg b/.claude/skills/logo-design/assets/library/svg/discover.svg deleted file mode 100644 index c9f2e7a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/discover.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/disqus.svg b/.claude/skills/logo-design/assets/library/svg/disqus.svg deleted file mode 100644 index b19e165..0000000 --- a/.claude/skills/logo-design/assets/library/svg/disqus.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/django-icon.svg b/.claude/skills/logo-design/assets/library/svg/django-icon.svg deleted file mode 100644 index b5cf35f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/django-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/django.svg b/.claude/skills/logo-design/assets/library/svg/django.svg deleted file mode 100644 index a41b5ff..0000000 --- a/.claude/skills/logo-design/assets/library/svg/django.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dockbit.svg b/.claude/skills/logo-design/assets/library/svg/dockbit.svg deleted file mode 100644 index 40b470d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dockbit.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/docker-icon.svg b/.claude/skills/logo-design/assets/library/svg/docker-icon.svg deleted file mode 100644 index 0bddc6d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/docker-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/docker.svg b/.claude/skills/logo-design/assets/library/svg/docker.svg deleted file mode 100644 index a9c64d1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/docker.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/doctrine.svg b/.claude/skills/logo-design/assets/library/svg/doctrine.svg deleted file mode 100644 index 6368c28..0000000 --- a/.claude/skills/logo-design/assets/library/svg/doctrine.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/docusaurus.svg b/.claude/skills/logo-design/assets/library/svg/docusaurus.svg deleted file mode 100644 index 0f87958..0000000 --- a/.claude/skills/logo-design/assets/library/svg/docusaurus.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dojo-icon.svg b/.claude/skills/logo-design/assets/library/svg/dojo-icon.svg deleted file mode 100644 index d397cca..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dojo-icon.svg +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dojo-toolkit.svg b/.claude/skills/logo-design/assets/library/svg/dojo-toolkit.svg deleted file mode 100644 index 3df4a1e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dojo-toolkit.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dojo.svg b/.claude/skills/logo-design/assets/library/svg/dojo.svg deleted file mode 100644 index 3fdbbd5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dojo.svg +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dotnet.svg b/.claude/skills/logo-design/assets/library/svg/dotnet.svg deleted file mode 100644 index 99f8c40..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dotnet.svg +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dreamhost.svg b/.claude/skills/logo-design/assets/library/svg/dreamhost.svg deleted file mode 100644 index 6d4d5ad..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dreamhost.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dribbble-icon.svg b/.claude/skills/logo-design/assets/library/svg/dribbble-icon.svg deleted file mode 100644 index 05b5dc7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dribbble-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dribbble.svg b/.claude/skills/logo-design/assets/library/svg/dribbble.svg deleted file mode 100644 index 00b1de5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dribbble.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/drift.svg b/.claude/skills/logo-design/assets/library/svg/drift.svg deleted file mode 100644 index 2ecd366..0000000 --- a/.claude/skills/logo-design/assets/library/svg/drift.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/drip.svg b/.claude/skills/logo-design/assets/library/svg/drip.svg deleted file mode 100644 index 028411a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/drip.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/drizzle-icon.svg b/.claude/skills/logo-design/assets/library/svg/drizzle-icon.svg deleted file mode 100644 index 31646b6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/drizzle-icon.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/drizzle.svg b/.claude/skills/logo-design/assets/library/svg/drizzle.svg deleted file mode 100644 index d46e121..0000000 --- a/.claude/skills/logo-design/assets/library/svg/drizzle.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/drone-icon.svg b/.claude/skills/logo-design/assets/library/svg/drone-icon.svg deleted file mode 100644 index a767866..0000000 --- a/.claude/skills/logo-design/assets/library/svg/drone-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/drone.svg b/.claude/skills/logo-design/assets/library/svg/drone.svg deleted file mode 100644 index b18d097..0000000 --- a/.claude/skills/logo-design/assets/library/svg/drone.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dropbox.svg b/.claude/skills/logo-design/assets/library/svg/dropbox.svg deleted file mode 100644 index 630fb89..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dropbox.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dropmark.svg b/.claude/skills/logo-design/assets/library/svg/dropmark.svg deleted file mode 100644 index 48b77a5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dropmark.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dropzone.svg b/.claude/skills/logo-design/assets/library/svg/dropzone.svg deleted file mode 100644 index a15f8a5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dropzone.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/drupal-icon.svg b/.claude/skills/logo-design/assets/library/svg/drupal-icon.svg deleted file mode 100644 index 07a1afa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/drupal-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/drupal.svg b/.claude/skills/logo-design/assets/library/svg/drupal.svg deleted file mode 100644 index 2039693..0000000 --- a/.claude/skills/logo-design/assets/library/svg/drupal.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/duckduckgo.svg b/.claude/skills/logo-design/assets/library/svg/duckduckgo.svg deleted file mode 100644 index 194e4a1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/duckduckgo.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dynatrace-icon.svg b/.claude/skills/logo-design/assets/library/svg/dynatrace-icon.svg deleted file mode 100644 index d483e8d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dynatrace-icon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dynatrace.svg b/.claude/skills/logo-design/assets/library/svg/dynatrace.svg deleted file mode 100644 index 63983ad..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dynatrace.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/dyndns.svg b/.claude/skills/logo-design/assets/library/svg/dyndns.svg deleted file mode 100644 index 85c1a54..0000000 --- a/.claude/skills/logo-design/assets/library/svg/dyndns.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ebanx.svg b/.claude/skills/logo-design/assets/library/svg/ebanx.svg deleted file mode 100644 index 93dfaeb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ebanx.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/eclipse-icon.svg b/.claude/skills/logo-design/assets/library/svg/eclipse-icon.svg deleted file mode 100644 index 48a77e4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/eclipse-icon.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/eclipse.svg b/.claude/skills/logo-design/assets/library/svg/eclipse.svg deleted file mode 100644 index fdddda0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/eclipse.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/editorconfig.svg b/.claude/skills/logo-design/assets/library/svg/editorconfig.svg deleted file mode 100644 index 79a3074..0000000 --- a/.claude/skills/logo-design/assets/library/svg/editorconfig.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/egghead.svg b/.claude/skills/logo-design/assets/library/svg/egghead.svg deleted file mode 100644 index ded1975..0000000 --- a/.claude/skills/logo-design/assets/library/svg/egghead.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/elasticsearch.svg b/.claude/skills/logo-design/assets/library/svg/elasticsearch.svg deleted file mode 100644 index 819bfe2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/elasticsearch.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/electron.svg b/.claude/skills/logo-design/assets/library/svg/electron.svg deleted file mode 100644 index 419190d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/electron.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/element.svg b/.claude/skills/logo-design/assets/library/svg/element.svg deleted file mode 100644 index 63d8aeb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/element.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/elemental-ui.svg b/.claude/skills/logo-design/assets/library/svg/elemental-ui.svg deleted file mode 100644 index e22e066..0000000 --- a/.claude/skills/logo-design/assets/library/svg/elemental-ui.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/elementary.svg b/.claude/skills/logo-design/assets/library/svg/elementary.svg deleted file mode 100644 index ebc3e06..0000000 --- a/.claude/skills/logo-design/assets/library/svg/elementary.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ello.svg b/.claude/skills/logo-design/assets/library/svg/ello.svg deleted file mode 100644 index 6319338..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ello.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/elm.svg b/.claude/skills/logo-design/assets/library/svg/elm.svg deleted file mode 100644 index fa2072e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/elm.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/elo.svg b/.claude/skills/logo-design/assets/library/svg/elo.svg deleted file mode 100644 index 0625e7f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/elo.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/emacs.svg b/.claude/skills/logo-design/assets/library/svg/emacs.svg deleted file mode 100644 index efd4af4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/emacs.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/embedly.svg b/.claude/skills/logo-design/assets/library/svg/embedly.svg deleted file mode 100644 index 6abc463..0000000 --- a/.claude/skills/logo-design/assets/library/svg/embedly.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ember-tomster.svg b/.claude/skills/logo-design/assets/library/svg/ember-tomster.svg deleted file mode 100644 index 99c057c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ember-tomster.svg +++ /dev/null @@ -1,220 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ember.svg b/.claude/skills/logo-design/assets/library/svg/ember.svg deleted file mode 100644 index 50eb492..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ember.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/emmet.svg b/.claude/skills/logo-design/assets/library/svg/emmet.svg deleted file mode 100644 index b396080..0000000 --- a/.claude/skills/logo-design/assets/library/svg/emmet.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/engine-yard-icon.svg b/.claude/skills/logo-design/assets/library/svg/engine-yard-icon.svg deleted file mode 100644 index 76461f7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/engine-yard-icon.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/engine-yard.svg b/.claude/skills/logo-design/assets/library/svg/engine-yard.svg deleted file mode 100644 index ee5da2a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/engine-yard.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/envato.svg b/.claude/skills/logo-design/assets/library/svg/envato.svg deleted file mode 100644 index 7354dc1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/envato.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/envoy-icon.svg b/.claude/skills/logo-design/assets/library/svg/envoy-icon.svg deleted file mode 100644 index 6316043..0000000 --- a/.claude/skills/logo-design/assets/library/svg/envoy-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/envoy.svg b/.claude/skills/logo-design/assets/library/svg/envoy.svg deleted file mode 100644 index 689a7d2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/envoy.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/envoyer.svg b/.claude/skills/logo-design/assets/library/svg/envoyer.svg deleted file mode 100644 index 81848c6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/envoyer.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/enyo.svg b/.claude/skills/logo-design/assets/library/svg/enyo.svg deleted file mode 100644 index 0bdf154..0000000 --- a/.claude/skills/logo-design/assets/library/svg/enyo.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/erlang.svg b/.claude/skills/logo-design/assets/library/svg/erlang.svg deleted file mode 100644 index bcee379..0000000 --- a/.claude/skills/logo-design/assets/library/svg/erlang.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/es6.svg b/.claude/skills/logo-design/assets/library/svg/es6.svg deleted file mode 100644 index a101dee..0000000 --- a/.claude/skills/logo-design/assets/library/svg/es6.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/esbuild.svg b/.claude/skills/logo-design/assets/library/svg/esbuild.svg deleted file mode 100644 index eabdcbe..0000000 --- a/.claude/skills/logo-design/assets/library/svg/esbuild.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/esdoc.svg b/.claude/skills/logo-design/assets/library/svg/esdoc.svg deleted file mode 100644 index afd1090..0000000 --- a/.claude/skills/logo-design/assets/library/svg/esdoc.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/eslint-old.svg b/.claude/skills/logo-design/assets/library/svg/eslint-old.svg deleted file mode 100644 index efa6ee1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/eslint-old.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/eslint.svg b/.claude/skills/logo-design/assets/library/svg/eslint.svg deleted file mode 100644 index 3b1b2af..0000000 --- a/.claude/skills/logo-design/assets/library/svg/eslint.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/eta-lang.svg b/.claude/skills/logo-design/assets/library/svg/eta-lang.svg deleted file mode 100644 index 6994e28..0000000 --- a/.claude/skills/logo-design/assets/library/svg/eta-lang.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/etcd.svg b/.claude/skills/logo-design/assets/library/svg/etcd.svg deleted file mode 100644 index d719d36..0000000 --- a/.claude/skills/logo-design/assets/library/svg/etcd.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ethereum-color.svg b/.claude/skills/logo-design/assets/library/svg/ethereum-color.svg deleted file mode 100644 index e0de4f5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ethereum-color.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ethereum.svg b/.claude/skills/logo-design/assets/library/svg/ethereum.svg deleted file mode 100644 index 5b15d72..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ethereum.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ethers.svg b/.claude/skills/logo-design/assets/library/svg/ethers.svg deleted file mode 100644 index 303ae58..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ethers.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ethnio.svg b/.claude/skills/logo-design/assets/library/svg/ethnio.svg deleted file mode 100644 index 62b71db..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ethnio.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/eventbrite-icon.svg b/.claude/skills/logo-design/assets/library/svg/eventbrite-icon.svg deleted file mode 100644 index 78713a0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/eventbrite-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/eventbrite.svg b/.claude/skills/logo-design/assets/library/svg/eventbrite.svg deleted file mode 100644 index 3116c7a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/eventbrite.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/eventsentry.svg b/.claude/skills/logo-design/assets/library/svg/eventsentry.svg deleted file mode 100644 index e7e147d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/eventsentry.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/evergreen-icon.svg b/.claude/skills/logo-design/assets/library/svg/evergreen-icon.svg deleted file mode 100644 index e104f7b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/evergreen-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/evergreen.svg b/.claude/skills/logo-design/assets/library/svg/evergreen.svg deleted file mode 100644 index d3d4197..0000000 --- a/.claude/skills/logo-design/assets/library/svg/evergreen.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/expo-icon.svg b/.claude/skills/logo-design/assets/library/svg/expo-icon.svg deleted file mode 100644 index f1ece3f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/expo-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/expo.svg b/.claude/skills/logo-design/assets/library/svg/expo.svg deleted file mode 100644 index 5f9b07c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/expo.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/express.svg b/.claude/skills/logo-design/assets/library/svg/express.svg deleted file mode 100644 index d8572a9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/express.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fabric.svg b/.claude/skills/logo-design/assets/library/svg/fabric.svg deleted file mode 100644 index e612338..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fabric.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/facebook.svg b/.claude/skills/logo-design/assets/library/svg/facebook.svg deleted file mode 100644 index 9a51a1a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/facebook.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/falcor.svg b/.claude/skills/logo-design/assets/library/svg/falcor.svg deleted file mode 100644 index 4586f8a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/falcor.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fastify-icon.svg b/.claude/skills/logo-design/assets/library/svg/fastify-icon.svg deleted file mode 100644 index 7d939fd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fastify-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fastify.svg b/.claude/skills/logo-design/assets/library/svg/fastify.svg deleted file mode 100644 index 26b053d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fastify.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fastlane.svg b/.claude/skills/logo-design/assets/library/svg/fastlane.svg deleted file mode 100644 index a8037af..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fastlane.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fastly.svg b/.claude/skills/logo-design/assets/library/svg/fastly.svg deleted file mode 100644 index 0853c72..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fastly.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/feathersjs.svg b/.claude/skills/logo-design/assets/library/svg/feathersjs.svg deleted file mode 100644 index 937739e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/feathersjs.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fedora.svg b/.claude/skills/logo-design/assets/library/svg/fedora.svg deleted file mode 100644 index 5cad205..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fedora.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fetch.svg b/.claude/skills/logo-design/assets/library/svg/fetch.svg deleted file mode 100644 index 7ba15b2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fetch.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/figma.svg b/.claude/skills/logo-design/assets/library/svg/figma.svg deleted file mode 100644 index 10aa0a1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/figma.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/firebase.svg b/.claude/skills/logo-design/assets/library/svg/firebase.svg deleted file mode 100644 index 9e03039..0000000 --- a/.claude/skills/logo-design/assets/library/svg/firebase.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/firefox.svg b/.claude/skills/logo-design/assets/library/svg/firefox.svg deleted file mode 100644 index 94305c6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/firefox.svg +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flannel.svg b/.claude/skills/logo-design/assets/library/svg/flannel.svg deleted file mode 100644 index b8d074f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flannel.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flarum.svg b/.claude/skills/logo-design/assets/library/svg/flarum.svg deleted file mode 100644 index 16540c4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flarum.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flask.svg b/.claude/skills/logo-design/assets/library/svg/flask.svg deleted file mode 100644 index 921d1ac..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flask.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flat-ui.svg b/.claude/skills/logo-design/assets/library/svg/flat-ui.svg deleted file mode 100644 index 16047d3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flat-ui.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flattr-icon.svg b/.claude/skills/logo-design/assets/library/svg/flattr-icon.svg deleted file mode 100644 index cbed4e9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flattr-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flattr.svg b/.claude/skills/logo-design/assets/library/svg/flattr.svg deleted file mode 100644 index 0caf16c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flattr.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fleep.svg b/.claude/skills/logo-design/assets/library/svg/fleep.svg deleted file mode 100644 index e328ac6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fleep.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flickr.svg b/.claude/skills/logo-design/assets/library/svg/flickr.svg deleted file mode 100644 index 4d43d7e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flickr.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flight.svg b/.claude/skills/logo-design/assets/library/svg/flight.svg deleted file mode 100644 index e2099a1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flight.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/floodio.svg b/.claude/skills/logo-design/assets/library/svg/floodio.svg deleted file mode 100644 index 665eb59..0000000 --- a/.claude/skills/logo-design/assets/library/svg/floodio.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flow.svg b/.claude/skills/logo-design/assets/library/svg/flow.svg deleted file mode 100644 index c5c5972..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flow.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flowxo.svg b/.claude/skills/logo-design/assets/library/svg/flowxo.svg deleted file mode 100644 index 058b9ce..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flowxo.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/floydhub.svg b/.claude/skills/logo-design/assets/library/svg/floydhub.svg deleted file mode 100644 index 906c997..0000000 --- a/.claude/skills/logo-design/assets/library/svg/floydhub.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flutter.svg b/.claude/skills/logo-design/assets/library/svg/flutter.svg deleted file mode 100644 index cd0318d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flutter.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/flux.svg b/.claude/skills/logo-design/assets/library/svg/flux.svg deleted file mode 100644 index 64e3c29..0000000 --- a/.claude/skills/logo-design/assets/library/svg/flux.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fluxxor.svg b/.claude/skills/logo-design/assets/library/svg/fluxxor.svg deleted file mode 100644 index 159c103..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fluxxor.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fly.svg b/.claude/skills/logo-design/assets/library/svg/fly.svg deleted file mode 100644 index 2811057..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fly.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fomo.svg b/.claude/skills/logo-design/assets/library/svg/fomo.svg deleted file mode 100644 index bf3a5f2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fomo.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/font-awesome.svg b/.claude/skills/logo-design/assets/library/svg/font-awesome.svg deleted file mode 100644 index 36692ef..0000000 --- a/.claude/skills/logo-design/assets/library/svg/font-awesome.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/forestadmin-icon.svg b/.claude/skills/logo-design/assets/library/svg/forestadmin-icon.svg deleted file mode 100644 index f71e21d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/forestadmin-icon.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/forestadmin.svg b/.claude/skills/logo-design/assets/library/svg/forestadmin.svg deleted file mode 100644 index caa2808..0000000 --- a/.claude/skills/logo-design/assets/library/svg/forestadmin.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/forever.svg b/.claude/skills/logo-design/assets/library/svg/forever.svg deleted file mode 100644 index 8394d7c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/forever.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/formkeep.svg b/.claude/skills/logo-design/assets/library/svg/formkeep.svg deleted file mode 100644 index ab79081..0000000 --- a/.claude/skills/logo-design/assets/library/svg/formkeep.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fortran.svg b/.claude/skills/logo-design/assets/library/svg/fortran.svg deleted file mode 100644 index 560da96..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fortran.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/foundation.svg b/.claude/skills/logo-design/assets/library/svg/foundation.svg deleted file mode 100644 index 281a79a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/foundation.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/framer.svg b/.claude/skills/logo-design/assets/library/svg/framer.svg deleted file mode 100644 index 19a3b1d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/framer.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/framework7-icon.svg b/.claude/skills/logo-design/assets/library/svg/framework7-icon.svg deleted file mode 100644 index 8e05692..0000000 --- a/.claude/skills/logo-design/assets/library/svg/framework7-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/framework7.svg b/.claude/skills/logo-design/assets/library/svg/framework7.svg deleted file mode 100644 index da2c15d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/framework7.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/freebsd.svg b/.claude/skills/logo-design/assets/library/svg/freebsd.svg deleted file mode 100644 index 6dcb05c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/freebsd.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/freedcamp-icon.svg b/.claude/skills/logo-design/assets/library/svg/freedcamp-icon.svg deleted file mode 100644 index 92878be..0000000 --- a/.claude/skills/logo-design/assets/library/svg/freedcamp-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/freedcamp.svg b/.claude/skills/logo-design/assets/library/svg/freedcamp.svg deleted file mode 100644 index 1cf4a33..0000000 --- a/.claude/skills/logo-design/assets/library/svg/freedcamp.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/freedomdefined.svg b/.claude/skills/logo-design/assets/library/svg/freedomdefined.svg deleted file mode 100644 index b7a8098..0000000 --- a/.claude/skills/logo-design/assets/library/svg/freedomdefined.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/frontapp.svg b/.claude/skills/logo-design/assets/library/svg/frontapp.svg deleted file mode 100644 index 9bf4a5b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/frontapp.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fsharp.svg b/.claude/skills/logo-design/assets/library/svg/fsharp.svg deleted file mode 100644 index f171162..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fsharp.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/fuchsia.svg b/.claude/skills/logo-design/assets/library/svg/fuchsia.svg deleted file mode 100644 index d526d72..0000000 --- a/.claude/skills/logo-design/assets/library/svg/fuchsia.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/galliumos.svg b/.claude/skills/logo-design/assets/library/svg/galliumos.svg deleted file mode 100644 index 43f70a2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/galliumos.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/game-analytics-icon.svg b/.claude/skills/logo-design/assets/library/svg/game-analytics-icon.svg deleted file mode 100644 index c4dcd97..0000000 --- a/.claude/skills/logo-design/assets/library/svg/game-analytics-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/game-analytics.svg b/.claude/skills/logo-design/assets/library/svg/game-analytics.svg deleted file mode 100644 index 9ead890..0000000 --- a/.claude/skills/logo-design/assets/library/svg/game-analytics.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ganache-icon.svg b/.claude/skills/logo-design/assets/library/svg/ganache-icon.svg deleted file mode 100644 index 54a58b8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ganache-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ganache.svg b/.claude/skills/logo-design/assets/library/svg/ganache.svg deleted file mode 100644 index d5bedce..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ganache.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gatsby.svg b/.claude/skills/logo-design/assets/library/svg/gatsby.svg deleted file mode 100644 index 1a68fb0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gatsby.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/geekbot.svg b/.claude/skills/logo-design/assets/library/svg/geekbot.svg deleted file mode 100644 index 410ce0a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/geekbot.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/getyourguide.svg b/.claude/skills/logo-design/assets/library/svg/getyourguide.svg deleted file mode 100644 index da58566..0000000 --- a/.claude/skills/logo-design/assets/library/svg/getyourguide.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ghost.svg b/.claude/skills/logo-design/assets/library/svg/ghost.svg deleted file mode 100644 index e341d88..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ghost.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/giantswarm.svg b/.claude/skills/logo-design/assets/library/svg/giantswarm.svg deleted file mode 100644 index 34ba436..0000000 --- a/.claude/skills/logo-design/assets/library/svg/giantswarm.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/git-icon.svg b/.claude/skills/logo-design/assets/library/svg/git-icon.svg deleted file mode 100644 index e7bc933..0000000 --- a/.claude/skills/logo-design/assets/library/svg/git-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/git.svg b/.claude/skills/logo-design/assets/library/svg/git.svg deleted file mode 100644 index 90992c3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/git.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gitboard.svg b/.claude/skills/logo-design/assets/library/svg/gitboard.svg deleted file mode 100644 index eb7b523..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gitboard.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/github-actions.svg b/.claude/skills/logo-design/assets/library/svg/github-actions.svg deleted file mode 100644 index 6876a3d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/github-actions.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/github-copilot.svg b/.claude/skills/logo-design/assets/library/svg/github-copilot.svg deleted file mode 100644 index e3af5dc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/github-copilot.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/github-icon.svg b/.claude/skills/logo-design/assets/library/svg/github-icon.svg deleted file mode 100644 index 1bff607..0000000 --- a/.claude/skills/logo-design/assets/library/svg/github-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/github-octocat.svg b/.claude/skills/logo-design/assets/library/svg/github-octocat.svg deleted file mode 100644 index f8687ac..0000000 --- a/.claude/skills/logo-design/assets/library/svg/github-octocat.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/github.svg b/.claude/skills/logo-design/assets/library/svg/github.svg deleted file mode 100644 index a8a6b01..0000000 --- a/.claude/skills/logo-design/assets/library/svg/github.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gitkraken.svg b/.claude/skills/logo-design/assets/library/svg/gitkraken.svg deleted file mode 100644 index eefc658..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gitkraken.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gitlab.svg b/.claude/skills/logo-design/assets/library/svg/gitlab.svg deleted file mode 100644 index e85ce31..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gitlab.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gitter.svg b/.claude/skills/logo-design/assets/library/svg/gitter.svg deleted file mode 100644 index 68dd8cf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gitter.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gitup.svg b/.claude/skills/logo-design/assets/library/svg/gitup.svg deleted file mode 100644 index 69ab7eb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gitup.svg +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/glamorous.svg b/.claude/skills/logo-design/assets/library/svg/glamorous.svg deleted file mode 100644 index 8a9bbb4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/glamorous.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gleam.svg b/.claude/skills/logo-design/assets/library/svg/gleam.svg deleted file mode 100644 index 50a7016..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gleam.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/glimmerjs.svg b/.claude/skills/logo-design/assets/library/svg/glimmerjs.svg deleted file mode 100644 index 3064f5c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/glimmerjs.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/glint.svg b/.claude/skills/logo-design/assets/library/svg/glint.svg deleted file mode 100644 index 5741c1f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/glint.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/glitch-icon.svg b/.claude/skills/logo-design/assets/library/svg/glitch-icon.svg deleted file mode 100644 index 3c98004..0000000 --- a/.claude/skills/logo-design/assets/library/svg/glitch-icon.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/glitch.svg b/.claude/skills/logo-design/assets/library/svg/glitch.svg deleted file mode 100644 index 9aae661..0000000 --- a/.claude/skills/logo-design/assets/library/svg/glitch.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gnome-icon.svg b/.claude/skills/logo-design/assets/library/svg/gnome-icon.svg deleted file mode 100644 index c18e475..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gnome-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gnome.svg b/.claude/skills/logo-design/assets/library/svg/gnome.svg deleted file mode 100644 index b0c82e8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gnome.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gnu-net.svg b/.claude/skills/logo-design/assets/library/svg/gnu-net.svg deleted file mode 100644 index 91e9cf3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gnu-net.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gnu.svg b/.claude/skills/logo-design/assets/library/svg/gnu.svg deleted file mode 100644 index 0f9e18e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gnu.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/go.svg b/.claude/skills/logo-design/assets/library/svg/go.svg deleted file mode 100644 index 6154429..0000000 --- a/.claude/skills/logo-design/assets/library/svg/go.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gocd.svg b/.claude/skills/logo-design/assets/library/svg/gocd.svg deleted file mode 100644 index 5eda9a7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gocd.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gohorse.svg b/.claude/skills/logo-design/assets/library/svg/gohorse.svg deleted file mode 100644 index a904949..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gohorse.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-360suite.svg b/.claude/skills/logo-design/assets/library/svg/google-360suite.svg deleted file mode 100644 index d33e26c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-360suite.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-admob.svg b/.claude/skills/logo-design/assets/library/svg/google-admob.svg deleted file mode 100644 index e0a2bf0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-admob.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-ads.svg b/.claude/skills/logo-design/assets/library/svg/google-ads.svg deleted file mode 100644 index 22a982a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-ads.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-adsense.svg b/.claude/skills/logo-design/assets/library/svg/google-adsense.svg deleted file mode 100644 index 20d8a6b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-adsense.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-analytics.svg b/.claude/skills/logo-design/assets/library/svg/google-analytics.svg deleted file mode 100644 index ba6e282..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-analytics.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-calendar.svg b/.claude/skills/logo-design/assets/library/svg/google-calendar.svg deleted file mode 100644 index 18d222f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-calendar.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-cloud-functions.svg b/.claude/skills/logo-design/assets/library/svg/google-cloud-functions.svg deleted file mode 100644 index f06c5db..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-cloud-functions.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-cloud-run.svg b/.claude/skills/logo-design/assets/library/svg/google-cloud-run.svg deleted file mode 100644 index a863549..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-cloud-run.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-cloud.svg b/.claude/skills/logo-design/assets/library/svg/google-cloud.svg deleted file mode 100644 index 4400bec..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-cloud.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-currents.svg b/.claude/skills/logo-design/assets/library/svg/google-currents.svg deleted file mode 100644 index a7de376..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-currents.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-data-studio.svg b/.claude/skills/logo-design/assets/library/svg/google-data-studio.svg deleted file mode 100644 index 01a95ef..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-data-studio.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-developers.svg b/.claude/skills/logo-design/assets/library/svg/google-developers.svg deleted file mode 100644 index c8006cc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-developers.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-drive.svg b/.claude/skills/logo-design/assets/library/svg/google-drive.svg deleted file mode 100644 index 52b2749..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-drive.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-fit.svg b/.claude/skills/logo-design/assets/library/svg/google-fit.svg deleted file mode 100644 index d8fd735..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-fit.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-gmail.svg b/.claude/skills/logo-design/assets/library/svg/google-gmail.svg deleted file mode 100644 index a84c5f6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-gmail.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-gsuite.svg b/.claude/skills/logo-design/assets/library/svg/google-gsuite.svg deleted file mode 100644 index 2ae6ff9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-gsuite.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-home.svg b/.claude/skills/logo-design/assets/library/svg/google-home.svg deleted file mode 100644 index 6cbe3e1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-home.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-icon.svg b/.claude/skills/logo-design/assets/library/svg/google-icon.svg deleted file mode 100644 index a479328..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-keep.svg b/.claude/skills/logo-design/assets/library/svg/google-keep.svg deleted file mode 100644 index 19f67d7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-keep.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-maps.svg b/.claude/skills/logo-design/assets/library/svg/google-maps.svg deleted file mode 100644 index 633d4eb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-maps.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-marketing-platform.svg b/.claude/skills/logo-design/assets/library/svg/google-marketing-platform.svg deleted file mode 100644 index 5a355fe..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-marketing-platform.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-meet.svg b/.claude/skills/logo-design/assets/library/svg/google-meet.svg deleted file mode 100644 index 6896e30..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-meet.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-one.svg b/.claude/skills/logo-design/assets/library/svg/google-one.svg deleted file mode 100644 index 495a054..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-one.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-optimize.svg b/.claude/skills/logo-design/assets/library/svg/google-optimize.svg deleted file mode 100644 index 6f01e34..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-optimize.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-pay-icon.svg b/.claude/skills/logo-design/assets/library/svg/google-pay-icon.svg deleted file mode 100644 index 6b5739d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-pay-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-pay.svg b/.claude/skills/logo-design/assets/library/svg/google-pay.svg deleted file mode 100644 index ac46f5e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-pay.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-photos.svg b/.claude/skills/logo-design/assets/library/svg/google-photos.svg deleted file mode 100644 index 02ff1dc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-photos.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-play-icon.svg b/.claude/skills/logo-design/assets/library/svg/google-play-icon.svg deleted file mode 100644 index dc0a586..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-play-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-play.svg b/.claude/skills/logo-design/assets/library/svg/google-play.svg deleted file mode 100644 index 93da986..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-play.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google-tag-manager.svg b/.claude/skills/logo-design/assets/library/svg/google-tag-manager.svg deleted file mode 100644 index 88bebaa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google-tag-manager.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/google.svg b/.claude/skills/logo-design/assets/library/svg/google.svg deleted file mode 100644 index f2626bd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/google.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gopher.svg b/.claude/skills/logo-design/assets/library/svg/gopher.svg deleted file mode 100644 index bc14364..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gopher.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gradle.svg b/.claude/skills/logo-design/assets/library/svg/gradle.svg deleted file mode 100644 index 469ab00..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gradle.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/grafana.svg b/.claude/skills/logo-design/assets/library/svg/grafana.svg deleted file mode 100644 index 145bf4f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/grafana.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/grails.svg b/.claude/skills/logo-design/assets/library/svg/grails.svg deleted file mode 100644 index 2e1394a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/grails.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/graphene.svg b/.claude/skills/logo-design/assets/library/svg/graphene.svg deleted file mode 100644 index 915ce56..0000000 --- a/.claude/skills/logo-design/assets/library/svg/graphene.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/graphql.svg b/.claude/skills/logo-design/assets/library/svg/graphql.svg deleted file mode 100644 index ae53e93..0000000 --- a/.claude/skills/logo-design/assets/library/svg/graphql.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/grav.svg b/.claude/skills/logo-design/assets/library/svg/grav.svg deleted file mode 100644 index 6caa1a2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/grav.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gravatar.svg b/.claude/skills/logo-design/assets/library/svg/gravatar.svg deleted file mode 100644 index 2c8c66f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gravatar.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/graylog-icon.svg b/.claude/skills/logo-design/assets/library/svg/graylog-icon.svg deleted file mode 100644 index e797ecb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/graylog-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/graylog.svg b/.claude/skills/logo-design/assets/library/svg/graylog.svg deleted file mode 100644 index 682bf21..0000000 --- a/.claude/skills/logo-design/assets/library/svg/graylog.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gridsome-icon.svg b/.claude/skills/logo-design/assets/library/svg/gridsome-icon.svg deleted file mode 100644 index 8a65249..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gridsome-icon.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gridsome.svg b/.claude/skills/logo-design/assets/library/svg/gridsome.svg deleted file mode 100644 index 73253e3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gridsome.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/grommet.svg b/.claude/skills/logo-design/assets/library/svg/grommet.svg deleted file mode 100644 index 9aff533..0000000 --- a/.claude/skills/logo-design/assets/library/svg/grommet.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/groovehq.svg b/.claude/skills/logo-design/assets/library/svg/groovehq.svg deleted file mode 100644 index 8895085..0000000 --- a/.claude/skills/logo-design/assets/library/svg/groovehq.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/grove.svg b/.claude/skills/logo-design/assets/library/svg/grove.svg deleted file mode 100644 index 952b706..0000000 --- a/.claude/skills/logo-design/assets/library/svg/grove.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/grpc.svg b/.claude/skills/logo-design/assets/library/svg/grpc.svg deleted file mode 100644 index c04e2b6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/grpc.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/grunt.svg b/.claude/skills/logo-design/assets/library/svg/grunt.svg deleted file mode 100644 index 8e5cd70..0000000 --- a/.claude/skills/logo-design/assets/library/svg/grunt.svg +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gulp.svg b/.claude/skills/logo-design/assets/library/svg/gulp.svg deleted file mode 100644 index 214d10f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gulp.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gunicorn.svg b/.claude/skills/logo-design/assets/library/svg/gunicorn.svg deleted file mode 100644 index 2f78a8c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gunicorn.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gusto.svg b/.claude/skills/logo-design/assets/library/svg/gusto.svg deleted file mode 100644 index 5e0039c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gusto.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/gwt.svg b/.claude/skills/logo-design/assets/library/svg/gwt.svg deleted file mode 100644 index 7d26f73..0000000 --- a/.claude/skills/logo-design/assets/library/svg/gwt.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hack.svg b/.claude/skills/logo-design/assets/library/svg/hack.svg deleted file mode 100644 index 8685927..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hack.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hacker-one.svg b/.claude/skills/logo-design/assets/library/svg/hacker-one.svg deleted file mode 100644 index 7474b74..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hacker-one.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/haiku-icon.svg b/.claude/skills/logo-design/assets/library/svg/haiku-icon.svg deleted file mode 100644 index 8de48db..0000000 --- a/.claude/skills/logo-design/assets/library/svg/haiku-icon.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/haml.svg b/.claude/skills/logo-design/assets/library/svg/haml.svg deleted file mode 100644 index ce0de17..0000000 --- a/.claude/skills/logo-design/assets/library/svg/haml.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hanami.svg b/.claude/skills/logo-design/assets/library/svg/hanami.svg deleted file mode 100644 index d1a65bf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hanami.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/handlebars.svg b/.claude/skills/logo-design/assets/library/svg/handlebars.svg deleted file mode 100644 index e0a18e9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/handlebars.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hapi.svg b/.claude/skills/logo-design/assets/library/svg/hapi.svg deleted file mode 100644 index d05c5c5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hapi.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hardhat-icon.svg b/.claude/skills/logo-design/assets/library/svg/hardhat-icon.svg deleted file mode 100644 index 711de57..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hardhat-icon.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hardhat.svg b/.claude/skills/logo-design/assets/library/svg/hardhat.svg deleted file mode 100644 index 0c31f49..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hardhat.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hashnode-icon.svg b/.claude/skills/logo-design/assets/library/svg/hashnode-icon.svg deleted file mode 100644 index 90414e8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hashnode-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hashnode.svg b/.claude/skills/logo-design/assets/library/svg/hashnode.svg deleted file mode 100644 index ab96cd6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hashnode.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/haskell-icon.svg b/.claude/skills/logo-design/assets/library/svg/haskell-icon.svg deleted file mode 100644 index 7ce8106..0000000 --- a/.claude/skills/logo-design/assets/library/svg/haskell-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/haskell.svg b/.claude/skills/logo-design/assets/library/svg/haskell.svg deleted file mode 100644 index bd178d3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/haskell.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hasura.svg b/.claude/skills/logo-design/assets/library/svg/hasura.svg deleted file mode 100644 index f80a2e1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hasura.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/haxe.svg b/.claude/skills/logo-design/assets/library/svg/haxe.svg deleted file mode 100644 index 6ce9dbe..0000000 --- a/.claude/skills/logo-design/assets/library/svg/haxe.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/haxl.svg b/.claude/skills/logo-design/assets/library/svg/haxl.svg deleted file mode 100644 index b3d8c34..0000000 --- a/.claude/skills/logo-design/assets/library/svg/haxl.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hbase.svg b/.claude/skills/logo-design/assets/library/svg/hbase.svg deleted file mode 100644 index a06f999..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hbase.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/headlessui-icon.svg b/.claude/skills/logo-design/assets/library/svg/headlessui-icon.svg deleted file mode 100644 index 251b750..0000000 --- a/.claude/skills/logo-design/assets/library/svg/headlessui-icon.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/headlessui.svg b/.claude/skills/logo-design/assets/library/svg/headlessui.svg deleted file mode 100644 index 262879c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/headlessui.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/heap.svg b/.claude/skills/logo-design/assets/library/svg/heap.svg deleted file mode 100644 index 50687a7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/heap.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/helm.svg b/.claude/skills/logo-design/assets/library/svg/helm.svg deleted file mode 100644 index e192c6c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/helm.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/helpscout-icon.svg b/.claude/skills/logo-design/assets/library/svg/helpscout-icon.svg deleted file mode 100644 index 8d3a66c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/helpscout-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/helpscout.svg b/.claude/skills/logo-design/assets/library/svg/helpscout.svg deleted file mode 100644 index 3c8914c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/helpscout.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hermes.svg b/.claude/skills/logo-design/assets/library/svg/hermes.svg deleted file mode 100644 index 5624411..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hermes.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/heroku-icon.svg b/.claude/skills/logo-design/assets/library/svg/heroku-icon.svg deleted file mode 100644 index 4ade08f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/heroku-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/heroku-redis.svg b/.claude/skills/logo-design/assets/library/svg/heroku-redis.svg deleted file mode 100644 index e907257..0000000 --- a/.claude/skills/logo-design/assets/library/svg/heroku-redis.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/heroku.svg b/.claude/skills/logo-design/assets/library/svg/heroku.svg deleted file mode 100644 index 30a3ed7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/heroku.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hexo.svg b/.claude/skills/logo-design/assets/library/svg/hexo.svg deleted file mode 100644 index 7c042af..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hexo.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hhvm.svg b/.claude/skills/logo-design/assets/library/svg/hhvm.svg deleted file mode 100644 index 699db00..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hhvm.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hibernate.svg b/.claude/skills/logo-design/assets/library/svg/hibernate.svg deleted file mode 100644 index 545ce17..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hibernate.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/highcharts.svg b/.claude/skills/logo-design/assets/library/svg/highcharts.svg deleted file mode 100644 index f599a71..0000000 --- a/.claude/skills/logo-design/assets/library/svg/highcharts.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hipercard.svg b/.claude/skills/logo-design/assets/library/svg/hipercard.svg deleted file mode 100644 index 28a35c1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hipercard.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hoa.svg b/.claude/skills/logo-design/assets/library/svg/hoa.svg deleted file mode 100644 index 71a2b6f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hoa.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/homebrew.svg b/.claude/skills/logo-design/assets/library/svg/homebrew.svg deleted file mode 100644 index 200f49f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/homebrew.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hoodie.svg b/.claude/skills/logo-design/assets/library/svg/hoodie.svg deleted file mode 100644 index b68f287..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hoodie.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hosted-graphite.svg b/.claude/skills/logo-design/assets/library/svg/hosted-graphite.svg deleted file mode 100644 index ab7b104..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hosted-graphite.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hostgator-icon.svg b/.claude/skills/logo-design/assets/library/svg/hostgator-icon.svg deleted file mode 100644 index 2958e53..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hostgator-icon.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hostgator.svg b/.claude/skills/logo-design/assets/library/svg/hostgator.svg deleted file mode 100644 index aeafbbf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hostgator.svg +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hotjar.svg b/.claude/skills/logo-design/assets/library/svg/hotjar.svg deleted file mode 100644 index 7f9cbbf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hotjar.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/houndci.svg b/.claude/skills/logo-design/assets/library/svg/houndci.svg deleted file mode 100644 index 9d15237..0000000 --- a/.claude/skills/logo-design/assets/library/svg/houndci.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/html-5.svg b/.claude/skills/logo-design/assets/library/svg/html-5.svg deleted file mode 100644 index 868366e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/html-5.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/html5-boilerplate.svg b/.claude/skills/logo-design/assets/library/svg/html5-boilerplate.svg deleted file mode 100644 index 900f746..0000000 --- a/.claude/skills/logo-design/assets/library/svg/html5-boilerplate.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/httpie-icon.svg b/.claude/skills/logo-design/assets/library/svg/httpie-icon.svg deleted file mode 100644 index 5fc7839..0000000 --- a/.claude/skills/logo-design/assets/library/svg/httpie-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/httpie.svg b/.claude/skills/logo-design/assets/library/svg/httpie.svg deleted file mode 100644 index d878030..0000000 --- a/.claude/skills/logo-design/assets/library/svg/httpie.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hubspot.svg b/.claude/skills/logo-design/assets/library/svg/hubspot.svg deleted file mode 100644 index 7ae4311..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hubspot.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/huggy.svg b/.claude/skills/logo-design/assets/library/svg/huggy.svg deleted file mode 100644 index d3ba903..0000000 --- a/.claude/skills/logo-design/assets/library/svg/huggy.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hugo.svg b/.claude/skills/logo-design/assets/library/svg/hugo.svg deleted file mode 100644 index fa5474d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hugo.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/humongous.svg b/.claude/skills/logo-design/assets/library/svg/humongous.svg deleted file mode 100644 index 541d20a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/humongous.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hyper.svg b/.claude/skills/logo-design/assets/library/svg/hyper.svg deleted file mode 100644 index 64d0d73..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hyper.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/hyperapp.svg b/.claude/skills/logo-design/assets/library/svg/hyperapp.svg deleted file mode 100644 index 564db67..0000000 --- a/.claude/skills/logo-design/assets/library/svg/hyperapp.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ibm.svg b/.claude/skills/logo-design/assets/library/svg/ibm.svg deleted file mode 100644 index ac73276..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ibm.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ieee.svg b/.claude/skills/logo-design/assets/library/svg/ieee.svg deleted file mode 100644 index a254f3c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ieee.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ifttt.svg b/.claude/skills/logo-design/assets/library/svg/ifttt.svg deleted file mode 100644 index 3bc6cde..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ifttt.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/imagemin.svg b/.claude/skills/logo-design/assets/library/svg/imagemin.svg deleted file mode 100644 index 1187b78..0000000 --- a/.claude/skills/logo-design/assets/library/svg/imagemin.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/imba-icon.svg b/.claude/skills/logo-design/assets/library/svg/imba-icon.svg deleted file mode 100644 index 5f2286d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/imba-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/imba.svg b/.claude/skills/logo-design/assets/library/svg/imba.svg deleted file mode 100644 index 3ccb93e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/imba.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/immer-icon.svg b/.claude/skills/logo-design/assets/library/svg/immer-icon.svg deleted file mode 100644 index 9a0d1fa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/immer-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/immer.svg b/.claude/skills/logo-design/assets/library/svg/immer.svg deleted file mode 100644 index af3766a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/immer.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/immutable.svg b/.claude/skills/logo-design/assets/library/svg/immutable.svg deleted file mode 100644 index 5a040c3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/immutable.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/impala.svg b/.claude/skills/logo-design/assets/library/svg/impala.svg deleted file mode 100644 index 062b778..0000000 --- a/.claude/skills/logo-design/assets/library/svg/impala.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/importio.svg b/.claude/skills/logo-design/assets/library/svg/importio.svg deleted file mode 100644 index 45b8a68..0000000 --- a/.claude/skills/logo-design/assets/library/svg/importio.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/infer.svg b/.claude/skills/logo-design/assets/library/svg/infer.svg deleted file mode 100644 index 9b06c76..0000000 --- a/.claude/skills/logo-design/assets/library/svg/infer.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/inferno.svg b/.claude/skills/logo-design/assets/library/svg/inferno.svg deleted file mode 100644 index 0dd5849..0000000 --- a/.claude/skills/logo-design/assets/library/svg/inferno.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/influxdb.svg b/.claude/skills/logo-design/assets/library/svg/influxdb.svg deleted file mode 100644 index fc1a698..0000000 --- a/.claude/skills/logo-design/assets/library/svg/influxdb.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ink.svg b/.claude/skills/logo-design/assets/library/svg/ink.svg deleted file mode 100644 index 03ae637..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ink.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/insomnia.svg b/.claude/skills/logo-design/assets/library/svg/insomnia.svg deleted file mode 100644 index 2e7654e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/insomnia.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/instagram-icon.svg b/.claude/skills/logo-design/assets/library/svg/instagram-icon.svg deleted file mode 100644 index 64cd8d3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/instagram-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/instagram.svg b/.claude/skills/logo-design/assets/library/svg/instagram.svg deleted file mode 100644 index 0346bba..0000000 --- a/.claude/skills/logo-design/assets/library/svg/instagram.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/intellij-idea.svg b/.claude/skills/logo-design/assets/library/svg/intellij-idea.svg deleted file mode 100644 index 6e03c5a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/intellij-idea.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/intercom-icon.svg b/.claude/skills/logo-design/assets/library/svg/intercom-icon.svg deleted file mode 100644 index 401c098..0000000 --- a/.claude/skills/logo-design/assets/library/svg/intercom-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/intercom.svg b/.claude/skills/logo-design/assets/library/svg/intercom.svg deleted file mode 100644 index ee11e20..0000000 --- a/.claude/skills/logo-design/assets/library/svg/intercom.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/internetexplorer.svg b/.claude/skills/logo-design/assets/library/svg/internetexplorer.svg deleted file mode 100644 index 7cf54ba..0000000 --- a/.claude/skills/logo-design/assets/library/svg/internetexplorer.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/invision-icon.svg b/.claude/skills/logo-design/assets/library/svg/invision-icon.svg deleted file mode 100644 index 97c723c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/invision-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/invision.svg b/.claude/skills/logo-design/assets/library/svg/invision.svg deleted file mode 100644 index 1247726..0000000 --- a/.claude/skills/logo-design/assets/library/svg/invision.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ionic-icon.svg b/.claude/skills/logo-design/assets/library/svg/ionic-icon.svg deleted file mode 100644 index b6f661f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ionic-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ionic.svg b/.claude/skills/logo-design/assets/library/svg/ionic.svg deleted file mode 100644 index eccf11a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ionic.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ios.svg b/.claude/skills/logo-design/assets/library/svg/ios.svg deleted file mode 100644 index 7fb0f8e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ios.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/iron-icon.svg b/.claude/skills/logo-design/assets/library/svg/iron-icon.svg deleted file mode 100644 index c20cbdd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/iron-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/iron.svg b/.claude/skills/logo-design/assets/library/svg/iron.svg deleted file mode 100644 index f786a49..0000000 --- a/.claude/skills/logo-design/assets/library/svg/iron.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/itsalive-icon.svg b/.claude/skills/logo-design/assets/library/svg/itsalive-icon.svg deleted file mode 100644 index 6d773ba..0000000 --- a/.claude/skills/logo-design/assets/library/svg/itsalive-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/itsalive.svg b/.claude/skills/logo-design/assets/library/svg/itsalive.svg deleted file mode 100644 index 6ca758f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/itsalive.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jade.svg b/.claude/skills/logo-design/assets/library/svg/jade.svg deleted file mode 100644 index 906369b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jade.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jamstack-icon.svg b/.claude/skills/logo-design/assets/library/svg/jamstack-icon.svg deleted file mode 100644 index ecad994..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jamstack-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jamstack.svg b/.claude/skills/logo-design/assets/library/svg/jamstack.svg deleted file mode 100644 index 264a41c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jamstack.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jasmine.svg b/.claude/skills/logo-design/assets/library/svg/jasmine.svg deleted file mode 100644 index c9e46e4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jasmine.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/java.svg b/.claude/skills/logo-design/assets/library/svg/java.svg deleted file mode 100644 index 64d8cc4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/java.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/javascript.svg b/.claude/skills/logo-design/assets/library/svg/javascript.svg deleted file mode 100644 index 3ed055d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/javascript.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jcb.svg b/.claude/skills/logo-design/assets/library/svg/jcb.svg deleted file mode 100644 index 469c22c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jcb.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jekyll.svg b/.claude/skills/logo-design/assets/library/svg/jekyll.svg deleted file mode 100644 index 63fcacc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jekyll.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jelastic-icon.svg b/.claude/skills/logo-design/assets/library/svg/jelastic-icon.svg deleted file mode 100644 index 2a3f5fb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jelastic-icon.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jelastic.svg b/.claude/skills/logo-design/assets/library/svg/jelastic.svg deleted file mode 100644 index c1c416a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jelastic.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jenkins.svg b/.claude/skills/logo-design/assets/library/svg/jenkins.svg deleted file mode 100644 index f576e5e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jenkins.svg +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jest.svg b/.claude/skills/logo-design/assets/library/svg/jest.svg deleted file mode 100644 index 384baa8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jest.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jetbrains.svg b/.claude/skills/logo-design/assets/library/svg/jetbrains.svg deleted file mode 100644 index 0b20b7e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jetbrains.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jfrog.svg b/.claude/skills/logo-design/assets/library/svg/jfrog.svg deleted file mode 100644 index 7d0fd06..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jfrog.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jhipster-icon.svg b/.claude/skills/logo-design/assets/library/svg/jhipster-icon.svg deleted file mode 100644 index 658daf0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jhipster-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jhipster.svg b/.claude/skills/logo-design/assets/library/svg/jhipster.svg deleted file mode 100644 index d2c3daa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jhipster.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jira.svg b/.claude/skills/logo-design/assets/library/svg/jira.svg deleted file mode 100644 index 5889efc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jira.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/joomla.svg b/.claude/skills/logo-design/assets/library/svg/joomla.svg deleted file mode 100644 index 9a8f28f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/joomla.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jquery-mobile.svg b/.claude/skills/logo-design/assets/library/svg/jquery-mobile.svg deleted file mode 100644 index bfcad24..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jquery-mobile.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jquery.svg b/.claude/skills/logo-design/assets/library/svg/jquery.svg deleted file mode 100644 index d684a9a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jquery.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jruby.svg b/.claude/skills/logo-design/assets/library/svg/jruby.svg deleted file mode 100644 index 9d697de..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jruby.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jsbin.svg b/.claude/skills/logo-design/assets/library/svg/jsbin.svg deleted file mode 100644 index bf99926..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jsbin.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jsdelivr.svg b/.claude/skills/logo-design/assets/library/svg/jsdelivr.svg deleted file mode 100644 index 19964d8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jsdelivr.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jsdom.svg b/.claude/skills/logo-design/assets/library/svg/jsdom.svg deleted file mode 100644 index 0f29ac3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jsdom.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jsfiddle.svg b/.claude/skills/logo-design/assets/library/svg/jsfiddle.svg deleted file mode 100644 index 072b6e7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jsfiddle.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/json.svg b/.claude/skills/logo-design/assets/library/svg/json.svg deleted file mode 100644 index 88b3698..0000000 --- a/.claude/skills/logo-design/assets/library/svg/json.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jspm.svg b/.claude/skills/logo-design/assets/library/svg/jspm.svg deleted file mode 100644 index 4d79a6b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jspm.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jss.svg b/.claude/skills/logo-design/assets/library/svg/jss.svg deleted file mode 100644 index a3f2418..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jss.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/juju.svg b/.claude/skills/logo-design/assets/library/svg/juju.svg deleted file mode 100644 index c87e979..0000000 --- a/.claude/skills/logo-design/assets/library/svg/juju.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/julia.svg b/.claude/skills/logo-design/assets/library/svg/julia.svg deleted file mode 100644 index 124c07a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/julia.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jupyter.svg b/.claude/skills/logo-design/assets/library/svg/jupyter.svg deleted file mode 100644 index b31d595..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jupyter.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jwt-icon.svg b/.claude/skills/logo-design/assets/library/svg/jwt-icon.svg deleted file mode 100644 index 2127928..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jwt-icon.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/jwt.svg b/.claude/skills/logo-design/assets/library/svg/jwt.svg deleted file mode 100644 index 38d577a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/jwt.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kafka-icon.svg b/.claude/skills/logo-design/assets/library/svg/kafka-icon.svg deleted file mode 100644 index 5558563..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kafka-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kafka.svg b/.claude/skills/logo-design/assets/library/svg/kafka.svg deleted file mode 100644 index 52d6ff5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kafka.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kaios.svg b/.claude/skills/logo-design/assets/library/svg/kaios.svg deleted file mode 100644 index 4f71d68..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kaios.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kallithea.svg b/.claude/skills/logo-design/assets/library/svg/kallithea.svg deleted file mode 100644 index a593739..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kallithea.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/karma.svg b/.claude/skills/logo-design/assets/library/svg/karma.svg deleted file mode 100644 index 22a5873..0000000 --- a/.claude/skills/logo-design/assets/library/svg/karma.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kde.svg b/.claude/skills/logo-design/assets/library/svg/kde.svg deleted file mode 100644 index 844a701..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kde.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/keen.svg b/.claude/skills/logo-design/assets/library/svg/keen.svg deleted file mode 100644 index 9640e2a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/keen.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kemal.svg b/.claude/skills/logo-design/assets/library/svg/kemal.svg deleted file mode 100644 index ee531c3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kemal.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/keycdn-icon.svg b/.claude/skills/logo-design/assets/library/svg/keycdn-icon.svg deleted file mode 100644 index 57df5d2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/keycdn-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/keycdn.svg b/.claude/skills/logo-design/assets/library/svg/keycdn.svg deleted file mode 100644 index 66841d2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/keycdn.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/keystonejs.svg b/.claude/skills/logo-design/assets/library/svg/keystonejs.svg deleted file mode 100644 index 5b10a9b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/keystonejs.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/khan_academy-icon.svg b/.claude/skills/logo-design/assets/library/svg/khan_academy-icon.svg deleted file mode 100644 index c344357..0000000 --- a/.claude/skills/logo-design/assets/library/svg/khan_academy-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/khan_academy.svg b/.claude/skills/logo-design/assets/library/svg/khan_academy.svg deleted file mode 100644 index 873e793..0000000 --- a/.claude/skills/logo-design/assets/library/svg/khan_academy.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kibana.svg b/.claude/skills/logo-design/assets/library/svg/kibana.svg deleted file mode 100644 index 17de3ed..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kibana.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kickstarter-icon.svg b/.claude/skills/logo-design/assets/library/svg/kickstarter-icon.svg deleted file mode 100644 index c80cbe7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kickstarter-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kickstarter.svg b/.claude/skills/logo-design/assets/library/svg/kickstarter.svg deleted file mode 100644 index b7adf1d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kickstarter.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kinto-icon.svg b/.claude/skills/logo-design/assets/library/svg/kinto-icon.svg deleted file mode 100644 index 5f32720..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kinto-icon.svg +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kinto.svg b/.claude/skills/logo-design/assets/library/svg/kinto.svg deleted file mode 100644 index 4070817..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kinto.svg +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kirby-icon.svg b/.claude/skills/logo-design/assets/library/svg/kirby-icon.svg deleted file mode 100644 index e5738a0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kirby-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kirby.svg b/.claude/skills/logo-design/assets/library/svg/kirby.svg deleted file mode 100644 index cbd59b3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kirby.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kissmetrics.svg b/.claude/skills/logo-design/assets/library/svg/kissmetrics.svg deleted file mode 100644 index 092333c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kissmetrics.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kitematic.svg b/.claude/skills/logo-design/assets/library/svg/kitematic.svg deleted file mode 100644 index 798fcd2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kitematic.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kloudless.svg b/.claude/skills/logo-design/assets/library/svg/kloudless.svg deleted file mode 100644 index 10daefb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kloudless.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/knex.svg b/.claude/skills/logo-design/assets/library/svg/knex.svg deleted file mode 100644 index 9b87f02..0000000 --- a/.claude/skills/logo-design/assets/library/svg/knex.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/knockout.svg b/.claude/skills/logo-design/assets/library/svg/knockout.svg deleted file mode 100644 index 51ed358..0000000 --- a/.claude/skills/logo-design/assets/library/svg/knockout.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/koa.svg b/.claude/skills/logo-design/assets/library/svg/koa.svg deleted file mode 100644 index c90e049..0000000 --- a/.claude/skills/logo-design/assets/library/svg/koa.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kong-icon.svg b/.claude/skills/logo-design/assets/library/svg/kong-icon.svg deleted file mode 100644 index 6941065..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kong-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kong.svg b/.claude/skills/logo-design/assets/library/svg/kong.svg deleted file mode 100644 index 8fc47a0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kong.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kops.svg b/.claude/skills/logo-design/assets/library/svg/kops.svg deleted file mode 100644 index 0e6938a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kops.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/koreio.svg b/.claude/skills/logo-design/assets/library/svg/koreio.svg deleted file mode 100644 index ca998b1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/koreio.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kotlin-icon.svg b/.claude/skills/logo-design/assets/library/svg/kotlin-icon.svg deleted file mode 100644 index 9f09ba8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kotlin-icon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kotlin.svg b/.claude/skills/logo-design/assets/library/svg/kotlin.svg deleted file mode 100644 index 3327b44..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kotlin.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kraken.svg b/.claude/skills/logo-design/assets/library/svg/kraken.svg deleted file mode 100644 index e961a06..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kraken.svg +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/krakenjs.svg b/.claude/skills/logo-design/assets/library/svg/krakenjs.svg deleted file mode 100644 index efe346f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/krakenjs.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kubernetes.svg b/.claude/skills/logo-design/assets/library/svg/kubernetes.svg deleted file mode 100644 index 409db4c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kubernetes.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/kustomer.svg b/.claude/skills/logo-design/assets/library/svg/kustomer.svg deleted file mode 100644 index 4a96c11..0000000 --- a/.claude/skills/logo-design/assets/library/svg/kustomer.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/laravel.svg b/.claude/skills/logo-design/assets/library/svg/laravel.svg deleted file mode 100644 index 882b99f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/laravel.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lastfm.svg b/.claude/skills/logo-design/assets/library/svg/lastfm.svg deleted file mode 100644 index 8b98a87..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lastfm.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lateral.svg b/.claude/skills/logo-design/assets/library/svg/lateral.svg deleted file mode 100644 index ca92db0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lateral.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/launchrock.svg b/.claude/skills/logo-design/assets/library/svg/launchrock.svg deleted file mode 100644 index 4b85cb0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/launchrock.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/leaflet.svg b/.claude/skills/logo-design/assets/library/svg/leaflet.svg deleted file mode 100644 index db09c89..0000000 --- a/.claude/skills/logo-design/assets/library/svg/leaflet.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/leankit-icon.svg b/.claude/skills/logo-design/assets/library/svg/leankit-icon.svg deleted file mode 100644 index 0fa5072..0000000 --- a/.claude/skills/logo-design/assets/library/svg/leankit-icon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/leankit.svg b/.claude/skills/logo-design/assets/library/svg/leankit.svg deleted file mode 100644 index 0c26d59..0000000 --- a/.claude/skills/logo-design/assets/library/svg/leankit.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lerna.svg b/.claude/skills/logo-design/assets/library/svg/lerna.svg deleted file mode 100644 index 1f0cc76..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lerna.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/less.svg b/.claude/skills/logo-design/assets/library/svg/less.svg deleted file mode 100644 index dab4d59..0000000 --- a/.claude/skills/logo-design/assets/library/svg/less.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lets-cloud.svg b/.claude/skills/logo-design/assets/library/svg/lets-cloud.svg deleted file mode 100644 index 4b8ff3f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lets-cloud.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/letsencrypt.svg b/.claude/skills/logo-design/assets/library/svg/letsencrypt.svg deleted file mode 100644 index d91eefd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/letsencrypt.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/leveldb.svg b/.claude/skills/logo-design/assets/library/svg/leveldb.svg deleted file mode 100644 index 899c002..0000000 --- a/.claude/skills/logo-design/assets/library/svg/leveldb.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/liftweb.svg b/.claude/skills/logo-design/assets/library/svg/liftweb.svg deleted file mode 100644 index 1025912..0000000 --- a/.claude/skills/logo-design/assets/library/svg/liftweb.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lighthouse.svg b/.claude/skills/logo-design/assets/library/svg/lighthouse.svg deleted file mode 100644 index 89dd3e5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lighthouse.svg +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lightstep-icon.svg b/.claude/skills/logo-design/assets/library/svg/lightstep-icon.svg deleted file mode 100644 index 64b5b77..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lightstep-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lightstep.svg b/.claude/skills/logo-design/assets/library/svg/lightstep.svg deleted file mode 100644 index 5be9dc9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lightstep.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lighttpd.svg b/.claude/skills/logo-design/assets/library/svg/lighttpd.svg deleted file mode 100644 index 38511fd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lighttpd.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/linkedin-icon.svg b/.claude/skills/logo-design/assets/library/svg/linkedin-icon.svg deleted file mode 100644 index 2ca0751..0000000 --- a/.claude/skills/logo-design/assets/library/svg/linkedin-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/linkedin.svg b/.claude/skills/logo-design/assets/library/svg/linkedin.svg deleted file mode 100644 index 40c40a0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/linkedin.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/linkerd.svg b/.claude/skills/logo-design/assets/library/svg/linkerd.svg deleted file mode 100644 index eda1f3e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/linkerd.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/linode.svg b/.claude/skills/logo-design/assets/library/svg/linode.svg deleted file mode 100644 index e2ec7d5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/linode.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/linux-mint.svg b/.claude/skills/logo-design/assets/library/svg/linux-mint.svg deleted file mode 100644 index 59cf86a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/linux-mint.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/linux-tux.svg b/.claude/skills/logo-design/assets/library/svg/linux-tux.svg deleted file mode 100644 index 1ed7b7c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/linux-tux.svg +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lit-icon.svg b/.claude/skills/logo-design/assets/library/svg/lit-icon.svg deleted file mode 100644 index 1074a9d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lit-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lit.svg b/.claude/skills/logo-design/assets/library/svg/lit.svg deleted file mode 100644 index 6d398ec..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lit.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/litmus.svg b/.claude/skills/logo-design/assets/library/svg/litmus.svg deleted file mode 100644 index 302edbd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/litmus.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/loader.svg b/.claude/skills/logo-design/assets/library/svg/loader.svg deleted file mode 100644 index 0a8277a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/loader.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lodash.svg b/.claude/skills/logo-design/assets/library/svg/lodash.svg deleted file mode 100644 index 6f987fa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lodash.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/logentries.svg b/.claude/skills/logo-design/assets/library/svg/logentries.svg deleted file mode 100644 index 90c715e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/logentries.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/logstash.svg b/.claude/skills/logo-design/assets/library/svg/logstash.svg deleted file mode 100644 index 705937b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/logstash.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lookback.svg b/.claude/skills/logo-design/assets/library/svg/lookback.svg deleted file mode 100644 index 91e9bb8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lookback.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/looker-icon.svg b/.claude/skills/logo-design/assets/library/svg/looker-icon.svg deleted file mode 100644 index 987eac7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/looker-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/looker.svg b/.claude/skills/logo-design/assets/library/svg/looker.svg deleted file mode 100644 index 9556317..0000000 --- a/.claude/skills/logo-design/assets/library/svg/looker.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/loom.svg b/.claude/skills/logo-design/assets/library/svg/loom.svg deleted file mode 100644 index 1357c2d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/loom.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/loopback-icon.svg b/.claude/skills/logo-design/assets/library/svg/loopback-icon.svg deleted file mode 100644 index c5634bb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/loopback-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/loopback.svg b/.claude/skills/logo-design/assets/library/svg/loopback.svg deleted file mode 100644 index 797ffe2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/loopback.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/losant.svg b/.claude/skills/logo-design/assets/library/svg/losant.svg deleted file mode 100644 index faa12fe..0000000 --- a/.claude/skills/logo-design/assets/library/svg/losant.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lua.svg b/.claude/skills/logo-design/assets/library/svg/lua.svg deleted file mode 100644 index e7ea089..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lua.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lucene.net.svg b/.claude/skills/logo-design/assets/library/svg/lucene.net.svg deleted file mode 100644 index a1e5b93..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lucene.net.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lucene.svg b/.claude/skills/logo-design/assets/library/svg/lucene.svg deleted file mode 100644 index bb5961b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lucene.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/lumen.svg b/.claude/skills/logo-design/assets/library/svg/lumen.svg deleted file mode 100644 index 139d183..0000000 --- a/.claude/skills/logo-design/assets/library/svg/lumen.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/macOS.svg b/.claude/skills/logo-design/assets/library/svg/macOS.svg deleted file mode 100644 index 5f0e7d7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/macOS.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/madge.svg b/.claude/skills/logo-design/assets/library/svg/madge.svg deleted file mode 100644 index a476b17..0000000 --- a/.claude/skills/logo-design/assets/library/svg/madge.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/maestro.svg b/.claude/skills/logo-design/assets/library/svg/maestro.svg deleted file mode 100644 index 150a551..0000000 --- a/.claude/skills/logo-design/assets/library/svg/maestro.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mageia.svg b/.claude/skills/logo-design/assets/library/svg/mageia.svg deleted file mode 100644 index 95ab8b0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mageia.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/magento.svg b/.claude/skills/logo-design/assets/library/svg/magento.svg deleted file mode 100644 index cbaea9f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/magento.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mailchimp-freddie.svg b/.claude/skills/logo-design/assets/library/svg/mailchimp-freddie.svg deleted file mode 100644 index e53777e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mailchimp-freddie.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mailchimp.svg b/.claude/skills/logo-design/assets/library/svg/mailchimp.svg deleted file mode 100644 index 61313a2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mailchimp.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/maildeveloper.svg b/.claude/skills/logo-design/assets/library/svg/maildeveloper.svg deleted file mode 100644 index 2ab7fc6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/maildeveloper.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mailgun-icon.svg b/.claude/skills/logo-design/assets/library/svg/mailgun-icon.svg deleted file mode 100644 index d80b579..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mailgun-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mailgun.svg b/.claude/skills/logo-design/assets/library/svg/mailgun.svg deleted file mode 100644 index 6d3353a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mailgun.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mailjet.svg b/.claude/skills/logo-design/assets/library/svg/mailjet.svg deleted file mode 100644 index fc95144..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mailjet.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/malinajs.svg b/.claude/skills/logo-design/assets/library/svg/malinajs.svg deleted file mode 100644 index c8384ae..0000000 --- a/.claude/skills/logo-design/assets/library/svg/malinajs.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/manjaro.svg b/.claude/skills/logo-design/assets/library/svg/manjaro.svg deleted file mode 100644 index 483e9fd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/manjaro.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/manuscript.svg b/.claude/skills/logo-design/assets/library/svg/manuscript.svg deleted file mode 100644 index 33afbb2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/manuscript.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mapbox-icon.svg b/.claude/skills/logo-design/assets/library/svg/mapbox-icon.svg deleted file mode 100644 index c395042..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mapbox-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mapbox.svg b/.claude/skills/logo-design/assets/library/svg/mapbox.svg deleted file mode 100644 index 1268613..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mapbox.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/maps-me.svg b/.claude/skills/logo-design/assets/library/svg/maps-me.svg deleted file mode 100644 index 634e5e4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/maps-me.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mapzen-icon.svg b/.claude/skills/logo-design/assets/library/svg/mapzen-icon.svg deleted file mode 100644 index 897a510..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mapzen-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mapzen.svg b/.claude/skills/logo-design/assets/library/svg/mapzen.svg deleted file mode 100644 index b09a727..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mapzen.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mariadb-icon.svg b/.claude/skills/logo-design/assets/library/svg/mariadb-icon.svg deleted file mode 100644 index a757f94..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mariadb-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mariadb.svg b/.claude/skills/logo-design/assets/library/svg/mariadb.svg deleted file mode 100644 index dd02b93..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mariadb.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/marionette.svg b/.claude/skills/logo-design/assets/library/svg/marionette.svg deleted file mode 100644 index b60576c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/marionette.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/markdown.svg b/.claude/skills/logo-design/assets/library/svg/markdown.svg deleted file mode 100644 index 870805a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/markdown.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/marko.svg b/.claude/skills/logo-design/assets/library/svg/marko.svg deleted file mode 100644 index 2e393df..0000000 --- a/.claude/skills/logo-design/assets/library/svg/marko.svg +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/marvel.svg b/.claude/skills/logo-design/assets/library/svg/marvel.svg deleted file mode 100644 index 3facf3b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/marvel.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mastercard.svg b/.claude/skills/logo-design/assets/library/svg/mastercard.svg deleted file mode 100644 index 777ae18..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mastercard.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mastodon-icon.svg b/.claude/skills/logo-design/assets/library/svg/mastodon-icon.svg deleted file mode 100644 index d8a71d0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mastodon-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mastodon.svg b/.claude/skills/logo-design/assets/library/svg/mastodon.svg deleted file mode 100644 index 34edf17..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mastodon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/material-ui.svg b/.claude/skills/logo-design/assets/library/svg/material-ui.svg deleted file mode 100644 index 6a514fa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/material-ui.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/materializecss.svg b/.claude/skills/logo-design/assets/library/svg/materializecss.svg deleted file mode 100644 index 1e0a132..0000000 --- a/.claude/skills/logo-design/assets/library/svg/materializecss.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/matplotlib-icon.svg b/.claude/skills/logo-design/assets/library/svg/matplotlib-icon.svg deleted file mode 100644 index d95764b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/matplotlib-icon.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/matplotlib.svg b/.claude/skills/logo-design/assets/library/svg/matplotlib.svg deleted file mode 100644 index abd80fe..0000000 --- a/.claude/skills/logo-design/assets/library/svg/matplotlib.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mattermost-icon.svg b/.claude/skills/logo-design/assets/library/svg/mattermost-icon.svg deleted file mode 100644 index 23673e0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mattermost-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mattermost.svg b/.claude/skills/logo-design/assets/library/svg/mattermost.svg deleted file mode 100644 index 847698f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mattermost.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/maven.svg b/.claude/skills/logo-design/assets/library/svg/maven.svg deleted file mode 100644 index c8f24f8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/maven.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/maxcdn.svg b/.claude/skills/logo-design/assets/library/svg/maxcdn.svg deleted file mode 100644 index 4d78536..0000000 --- a/.claude/skills/logo-design/assets/library/svg/maxcdn.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mdn.svg b/.claude/skills/logo-design/assets/library/svg/mdn.svg deleted file mode 100644 index e98a502..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mdn.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mdx.svg b/.claude/skills/logo-design/assets/library/svg/mdx.svg deleted file mode 100644 index bc6b194..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mdx.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/medium-icon.svg b/.claude/skills/logo-design/assets/library/svg/medium-icon.svg deleted file mode 100644 index 99ec825..0000000 --- a/.claude/skills/logo-design/assets/library/svg/medium-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/medium.svg b/.claude/skills/logo-design/assets/library/svg/medium.svg deleted file mode 100644 index 2156479..0000000 --- a/.claude/skills/logo-design/assets/library/svg/medium.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/memcached.svg b/.claude/skills/logo-design/assets/library/svg/memcached.svg deleted file mode 100644 index 066bb31..0000000 --- a/.claude/skills/logo-design/assets/library/svg/memcached.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/memsql-icon.svg b/.claude/skills/logo-design/assets/library/svg/memsql-icon.svg deleted file mode 100644 index b98b901..0000000 --- a/.claude/skills/logo-design/assets/library/svg/memsql-icon.svg +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/memsql.svg b/.claude/skills/logo-design/assets/library/svg/memsql.svg deleted file mode 100644 index 105ce77..0000000 --- a/.claude/skills/logo-design/assets/library/svg/memsql.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mention.svg b/.claude/skills/logo-design/assets/library/svg/mention.svg deleted file mode 100644 index 7e868cd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mention.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mercurial.svg b/.claude/skills/logo-design/assets/library/svg/mercurial.svg deleted file mode 100644 index 8446537..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mercurial.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mesos.svg b/.claude/skills/logo-design/assets/library/svg/mesos.svg deleted file mode 100644 index 53c86d2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mesos.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/metabase.svg b/.claude/skills/logo-design/assets/library/svg/metabase.svg deleted file mode 100644 index 3312bb3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/metabase.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/metamask-icon.svg b/.claude/skills/logo-design/assets/library/svg/metamask-icon.svg deleted file mode 100644 index 1f42b16..0000000 --- a/.claude/skills/logo-design/assets/library/svg/metamask-icon.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/metamask.svg b/.claude/skills/logo-design/assets/library/svg/metamask.svg deleted file mode 100644 index b9b72ab..0000000 --- a/.claude/skills/logo-design/assets/library/svg/metamask.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/meteor-icon.svg b/.claude/skills/logo-design/assets/library/svg/meteor-icon.svg deleted file mode 100644 index 4e4089e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/meteor-icon.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/meteor.svg b/.claude/skills/logo-design/assets/library/svg/meteor.svg deleted file mode 100644 index 3fbc6ef..0000000 --- a/.claude/skills/logo-design/assets/library/svg/meteor.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/microcosm.svg b/.claude/skills/logo-design/assets/library/svg/microcosm.svg deleted file mode 100644 index 1a0a64d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/microcosm.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-azure.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-azure.svg deleted file mode 100644 index 886ed29..0000000 --- a/.claude/skills/logo-design/assets/library/svg/microsoft-azure.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-edge.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-edge.svg deleted file mode 100644 index c4cd320..0000000 --- a/.claude/skills/logo-design/assets/library/svg/microsoft-edge.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-onedrive.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-onedrive.svg deleted file mode 100644 index 6c78633..0000000 --- a/.claude/skills/logo-design/assets/library/svg/microsoft-onedrive.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-power-bi.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-power-bi.svg deleted file mode 100644 index 2bebf9d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/microsoft-power-bi.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-teams.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-teams.svg deleted file mode 100644 index da7fee0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/microsoft-teams.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft-windows.svg b/.claude/skills/logo-design/assets/library/svg/microsoft-windows.svg deleted file mode 100644 index b4a7fdc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/microsoft-windows.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/microsoft.svg b/.claude/skills/logo-design/assets/library/svg/microsoft.svg deleted file mode 100644 index c6cb96f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/microsoft.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/middleman.svg b/.claude/skills/logo-design/assets/library/svg/middleman.svg deleted file mode 100644 index 7156f12..0000000 --- a/.claude/skills/logo-design/assets/library/svg/middleman.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/milligram.svg b/.claude/skills/logo-design/assets/library/svg/milligram.svg deleted file mode 100644 index 60fadda..0000000 --- a/.claude/skills/logo-design/assets/library/svg/milligram.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mint-lang.svg b/.claude/skills/logo-design/assets/library/svg/mint-lang.svg deleted file mode 100644 index 6a9a7d8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mint-lang.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mio.svg b/.claude/skills/logo-design/assets/library/svg/mio.svg deleted file mode 100644 index 1c5ca83..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mio.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mist.svg b/.claude/skills/logo-design/assets/library/svg/mist.svg deleted file mode 100644 index e0abc29..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mist.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mithril.svg b/.claude/skills/logo-design/assets/library/svg/mithril.svg deleted file mode 100644 index 73d1a52..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mithril.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mixmax.svg b/.claude/skills/logo-design/assets/library/svg/mixmax.svg deleted file mode 100644 index 9e25858..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mixmax.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mixpanel.svg b/.claude/skills/logo-design/assets/library/svg/mixpanel.svg deleted file mode 100644 index ef7c67f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mixpanel.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mlab.svg b/.claude/skills/logo-design/assets/library/svg/mlab.svg deleted file mode 100644 index 2fd5236..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mlab.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mobx.svg b/.claude/skills/logo-design/assets/library/svg/mobx.svg deleted file mode 100644 index f9e7ba0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mobx.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mocha.svg b/.claude/skills/logo-design/assets/library/svg/mocha.svg deleted file mode 100644 index 28a3aaf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mocha.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mockflow-icon.svg b/.claude/skills/logo-design/assets/library/svg/mockflow-icon.svg deleted file mode 100644 index a9b4df1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mockflow-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mockflow.svg b/.claude/skills/logo-design/assets/library/svg/mockflow.svg deleted file mode 100644 index 7fdfc79..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mockflow.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/modernizr.svg b/.claude/skills/logo-design/assets/library/svg/modernizr.svg deleted file mode 100644 index 6a16c67..0000000 --- a/.claude/skills/logo-design/assets/library/svg/modernizr.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/modx-icon.svg b/.claude/skills/logo-design/assets/library/svg/modx-icon.svg deleted file mode 100644 index 2bac2e8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/modx-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/modx.svg b/.claude/skills/logo-design/assets/library/svg/modx.svg deleted file mode 100644 index 4018dbb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/modx.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/moltin-icon.svg b/.claude/skills/logo-design/assets/library/svg/moltin-icon.svg deleted file mode 100644 index 7d911ef..0000000 --- a/.claude/skills/logo-design/assets/library/svg/moltin-icon.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/moltin.svg b/.claude/skills/logo-design/assets/library/svg/moltin.svg deleted file mode 100644 index d2adc4a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/moltin.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/momentjs.svg b/.claude/skills/logo-design/assets/library/svg/momentjs.svg deleted file mode 100644 index b4c8990..0000000 --- a/.claude/skills/logo-design/assets/library/svg/momentjs.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/monday-icon.svg b/.claude/skills/logo-design/assets/library/svg/monday-icon.svg deleted file mode 100644 index 7274668..0000000 --- a/.claude/skills/logo-design/assets/library/svg/monday-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/monday.svg b/.claude/skills/logo-design/assets/library/svg/monday.svg deleted file mode 100644 index dd571a3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/monday.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/monero.svg b/.claude/skills/logo-design/assets/library/svg/monero.svg deleted file mode 100644 index 43a959a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/monero.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mongodb.svg b/.claude/skills/logo-design/assets/library/svg/mongodb.svg deleted file mode 100644 index 9bd8279..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mongodb.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mono.svg b/.claude/skills/logo-design/assets/library/svg/mono.svg deleted file mode 100644 index 2773cd3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mono.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/moon.svg b/.claude/skills/logo-design/assets/library/svg/moon.svg deleted file mode 100644 index 0f19391..0000000 --- a/.claude/skills/logo-design/assets/library/svg/moon.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mootools.svg b/.claude/skills/logo-design/assets/library/svg/mootools.svg deleted file mode 100644 index 1702a30..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mootools.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/morpheus-icon.svg b/.claude/skills/logo-design/assets/library/svg/morpheus-icon.svg deleted file mode 100644 index 187c772..0000000 --- a/.claude/skills/logo-design/assets/library/svg/morpheus-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/morpheus.svg b/.claude/skills/logo-design/assets/library/svg/morpheus.svg deleted file mode 100644 index eb744f5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/morpheus.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mozilla.svg b/.claude/skills/logo-design/assets/library/svg/mozilla.svg deleted file mode 100644 index 5971a41..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mozilla.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mparticle-icon.svg b/.claude/skills/logo-design/assets/library/svg/mparticle-icon.svg deleted file mode 100644 index ca081ba..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mparticle-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mparticle.svg b/.claude/skills/logo-design/assets/library/svg/mparticle.svg deleted file mode 100644 index 9b80d21..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mparticle.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/multipass.svg b/.claude/skills/logo-design/assets/library/svg/multipass.svg deleted file mode 100644 index 52d35e9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/multipass.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mysql-icon.svg b/.claude/skills/logo-design/assets/library/svg/mysql-icon.svg deleted file mode 100644 index 6313821..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mysql-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/mysql.svg b/.claude/skills/logo-design/assets/library/svg/mysql.svg deleted file mode 100644 index 778d3f0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/mysql.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/naiveui.svg b/.claude/skills/logo-design/assets/library/svg/naiveui.svg deleted file mode 100644 index b4dd837..0000000 --- a/.claude/skills/logo-design/assets/library/svg/naiveui.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/namecheap.svg b/.claude/skills/logo-design/assets/library/svg/namecheap.svg deleted file mode 100644 index 27d84e2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/namecheap.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nanonets.svg b/.claude/skills/logo-design/assets/library/svg/nanonets.svg deleted file mode 100644 index 251984b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nanonets.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nativescript.svg b/.claude/skills/logo-design/assets/library/svg/nativescript.svg deleted file mode 100644 index b5baf98..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nativescript.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nats-icon.svg b/.claude/skills/logo-design/assets/library/svg/nats-icon.svg deleted file mode 100644 index 44b9578..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nats-icon.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nats.svg b/.claude/skills/logo-design/assets/library/svg/nats.svg deleted file mode 100644 index 1cc68ca..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nats.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/neat.svg b/.claude/skills/logo-design/assets/library/svg/neat.svg deleted file mode 100644 index 971ed8c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/neat.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/neo4j.svg b/.claude/skills/logo-design/assets/library/svg/neo4j.svg deleted file mode 100644 index 4c88c51..0000000 --- a/.claude/skills/logo-design/assets/library/svg/neo4j.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/neovim.svg b/.claude/skills/logo-design/assets/library/svg/neovim.svg deleted file mode 100644 index 58aef20..0000000 --- a/.claude/skills/logo-design/assets/library/svg/neovim.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nestjs.svg b/.claude/skills/logo-design/assets/library/svg/nestjs.svg deleted file mode 100644 index 3a60db0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nestjs.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/netbeans.svg b/.claude/skills/logo-design/assets/library/svg/netbeans.svg deleted file mode 100644 index 50d20e1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/netbeans.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/netflix-icon.svg b/.claude/skills/logo-design/assets/library/svg/netflix-icon.svg deleted file mode 100644 index 2abe549..0000000 --- a/.claude/skills/logo-design/assets/library/svg/netflix-icon.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/netflix.svg b/.claude/skills/logo-design/assets/library/svg/netflix.svg deleted file mode 100644 index abe8054..0000000 --- a/.claude/skills/logo-design/assets/library/svg/netflix.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/netlify.svg b/.claude/skills/logo-design/assets/library/svg/netlify.svg deleted file mode 100644 index aaec220..0000000 --- a/.claude/skills/logo-design/assets/library/svg/netlify.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/new-relic.svg b/.claude/skills/logo-design/assets/library/svg/new-relic.svg deleted file mode 100644 index 1b3791e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/new-relic.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nextjs-icon.svg b/.claude/skills/logo-design/assets/library/svg/nextjs-icon.svg deleted file mode 100644 index 1d7a84a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nextjs-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nextjs.svg b/.claude/skills/logo-design/assets/library/svg/nextjs.svg deleted file mode 100644 index 17fdf85..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nextjs.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nginx.svg b/.claude/skills/logo-design/assets/library/svg/nginx.svg deleted file mode 100644 index a30e0b2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nginx.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nightwatch.svg b/.claude/skills/logo-design/assets/library/svg/nightwatch.svg deleted file mode 100644 index 57f860d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nightwatch.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nim-lang.svg b/.claude/skills/logo-design/assets/library/svg/nim-lang.svg deleted file mode 100644 index 4ebd2cb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nim-lang.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nocodb.svg b/.claude/skills/logo-design/assets/library/svg/nocodb.svg deleted file mode 100644 index 2f801cb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nocodb.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nodal.svg b/.claude/skills/logo-design/assets/library/svg/nodal.svg deleted file mode 100644 index d8c57bd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nodal.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/node-sass.svg b/.claude/skills/logo-design/assets/library/svg/node-sass.svg deleted file mode 100644 index bd0f5bc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/node-sass.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nodebots.svg b/.claude/skills/logo-design/assets/library/svg/nodebots.svg deleted file mode 100644 index 16c6765..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nodebots.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nodejs-icon.svg b/.claude/skills/logo-design/assets/library/svg/nodejs-icon.svg deleted file mode 100644 index c048a4d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nodejs-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nodejs.svg b/.claude/skills/logo-design/assets/library/svg/nodejs.svg deleted file mode 100644 index c95bfef..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nodejs.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nodemon.svg b/.claude/skills/logo-design/assets/library/svg/nodemon.svg deleted file mode 100644 index fe32b29..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nodemon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nodeos.svg b/.claude/skills/logo-design/assets/library/svg/nodeos.svg deleted file mode 100644 index e417311..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nodeos.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nodewebkit.svg b/.claude/skills/logo-design/assets/library/svg/nodewebkit.svg deleted file mode 100644 index 4ddf547..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nodewebkit.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nomad.svg b/.claude/skills/logo-design/assets/library/svg/nomad.svg deleted file mode 100644 index a559f38..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nomad.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/noysi.svg b/.claude/skills/logo-design/assets/library/svg/noysi.svg deleted file mode 100644 index 4fb0014..0000000 --- a/.claude/skills/logo-design/assets/library/svg/noysi.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/npm-icon.svg b/.claude/skills/logo-design/assets/library/svg/npm-icon.svg deleted file mode 100644 index 3aeb1b5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/npm-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/npm.svg b/.claude/skills/logo-design/assets/library/svg/npm.svg deleted file mode 100644 index 458e97a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/npm.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nuclide.svg b/.claude/skills/logo-design/assets/library/svg/nuclide.svg deleted file mode 100644 index 789c400..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nuclide.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/numpy.svg b/.claude/skills/logo-design/assets/library/svg/numpy.svg deleted file mode 100644 index df927b8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/numpy.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nuxt-icon.svg b/.claude/skills/logo-design/assets/library/svg/nuxt-icon.svg deleted file mode 100644 index dba25e6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nuxt-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nuxt.svg b/.claude/skills/logo-design/assets/library/svg/nuxt.svg deleted file mode 100644 index 147e49a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nuxt.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/nx.svg b/.claude/skills/logo-design/assets/library/svg/nx.svg deleted file mode 100644 index dc60906..0000000 --- a/.claude/skills/logo-design/assets/library/svg/nx.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/oauth.svg b/.claude/skills/logo-design/assets/library/svg/oauth.svg deleted file mode 100644 index 815505a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/oauth.svg +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ocaml.svg b/.claude/skills/logo-design/assets/library/svg/ocaml.svg deleted file mode 100644 index d4db2fa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ocaml.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/octodns.svg b/.claude/skills/logo-design/assets/library/svg/octodns.svg deleted file mode 100644 index c623b2b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/octodns.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/octopus-deploy.svg b/.claude/skills/logo-design/assets/library/svg/octopus-deploy.svg deleted file mode 100644 index 1b076ea..0000000 --- a/.claude/skills/logo-design/assets/library/svg/octopus-deploy.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/olark.svg b/.claude/skills/logo-design/assets/library/svg/olark.svg deleted file mode 100644 index 1d835a7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/olark.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/onesignal.svg b/.claude/skills/logo-design/assets/library/svg/onesignal.svg deleted file mode 100644 index d8c4200..0000000 --- a/.claude/skills/logo-design/assets/library/svg/onesignal.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/open-graph.svg b/.claude/skills/logo-design/assets/library/svg/open-graph.svg deleted file mode 100644 index ba1e101..0000000 --- a/.claude/skills/logo-design/assets/library/svg/open-graph.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/open-zeppelin-icon.svg b/.claude/skills/logo-design/assets/library/svg/open-zeppelin-icon.svg deleted file mode 100644 index f8f4af2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/open-zeppelin-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/open-zeppelin.svg b/.claude/skills/logo-design/assets/library/svg/open-zeppelin.svg deleted file mode 100644 index d0ae452..0000000 --- a/.claude/skills/logo-design/assets/library/svg/open-zeppelin.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/openai-icon.svg b/.claude/skills/logo-design/assets/library/svg/openai-icon.svg deleted file mode 100644 index 7dbf89a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/openai-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/openai.svg b/.claude/skills/logo-design/assets/library/svg/openai.svg deleted file mode 100644 index afd1974..0000000 --- a/.claude/skills/logo-design/assets/library/svg/openai.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/opencart.svg b/.claude/skills/logo-design/assets/library/svg/opencart.svg deleted file mode 100644 index 7536b33..0000000 --- a/.claude/skills/logo-design/assets/library/svg/opencart.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/opencollective.svg b/.claude/skills/logo-design/assets/library/svg/opencollective.svg deleted file mode 100644 index 5cddb4d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/opencollective.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/opencv.svg b/.claude/skills/logo-design/assets/library/svg/opencv.svg deleted file mode 100644 index d5b93e1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/opencv.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/openframeworks.svg b/.claude/skills/logo-design/assets/library/svg/openframeworks.svg deleted file mode 100644 index a565945..0000000 --- a/.claude/skills/logo-design/assets/library/svg/openframeworks.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/opengl.svg b/.claude/skills/logo-design/assets/library/svg/opengl.svg deleted file mode 100644 index b2c1416..0000000 --- a/.claude/skills/logo-design/assets/library/svg/opengl.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/openjs-foundation-icon.svg b/.claude/skills/logo-design/assets/library/svg/openjs-foundation-icon.svg deleted file mode 100644 index 75285ab..0000000 --- a/.claude/skills/logo-design/assets/library/svg/openjs-foundation-icon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/openjs-foundation.svg b/.claude/skills/logo-design/assets/library/svg/openjs-foundation.svg deleted file mode 100644 index f485d00..0000000 --- a/.claude/skills/logo-design/assets/library/svg/openjs-foundation.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/openlayers.svg b/.claude/skills/logo-design/assets/library/svg/openlayers.svg deleted file mode 100644 index d04a49b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/openlayers.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/openshift.svg b/.claude/skills/logo-design/assets/library/svg/openshift.svg deleted file mode 100644 index 41783b6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/openshift.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/opensource.svg b/.claude/skills/logo-design/assets/library/svg/opensource.svg deleted file mode 100644 index 7617a92..0000000 --- a/.claude/skills/logo-design/assets/library/svg/opensource.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/openstack-icon.svg b/.claude/skills/logo-design/assets/library/svg/openstack-icon.svg deleted file mode 100644 index cb5b329..0000000 --- a/.claude/skills/logo-design/assets/library/svg/openstack-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/openstack.svg b/.claude/skills/logo-design/assets/library/svg/openstack.svg deleted file mode 100644 index e5d879c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/openstack.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/opentelemetry-icon.svg b/.claude/skills/logo-design/assets/library/svg/opentelemetry-icon.svg deleted file mode 100644 index 74c7958..0000000 --- a/.claude/skills/logo-design/assets/library/svg/opentelemetry-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/opentelemetry.svg b/.claude/skills/logo-design/assets/library/svg/opentelemetry.svg deleted file mode 100644 index 70d36e9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/opentelemetry.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/opera.svg b/.claude/skills/logo-design/assets/library/svg/opera.svg deleted file mode 100644 index 1cf2a0d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/opera.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/opsgenie.svg b/.claude/skills/logo-design/assets/library/svg/opsgenie.svg deleted file mode 100644 index 8dbf2b0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/opsgenie.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/optimizely.svg b/.claude/skills/logo-design/assets/library/svg/optimizely.svg deleted file mode 100644 index 5cd3f6f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/optimizely.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/oracle.svg b/.claude/skills/logo-design/assets/library/svg/oracle.svg deleted file mode 100644 index 043b588..0000000 --- a/.claude/skills/logo-design/assets/library/svg/oracle.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/oreilly.svg b/.claude/skills/logo-design/assets/library/svg/oreilly.svg deleted file mode 100644 index 6e62573..0000000 --- a/.claude/skills/logo-design/assets/library/svg/oreilly.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/origami.svg b/.claude/skills/logo-design/assets/library/svg/origami.svg deleted file mode 100644 index f16205f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/origami.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/origin.svg b/.claude/skills/logo-design/assets/library/svg/origin.svg deleted file mode 100644 index df6e0d8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/origin.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/oshw.svg b/.claude/skills/logo-design/assets/library/svg/oshw.svg deleted file mode 100644 index 98efb4d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/oshw.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/osquery.svg b/.claude/skills/logo-design/assets/library/svg/osquery.svg deleted file mode 100644 index 69849b2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/osquery.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/packer.svg b/.claude/skills/logo-design/assets/library/svg/packer.svg deleted file mode 100644 index 988997a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/packer.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pagekit.svg b/.claude/skills/logo-design/assets/library/svg/pagekit.svg deleted file mode 100644 index 28266a2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pagekit.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pagekite.svg b/.claude/skills/logo-design/assets/library/svg/pagekite.svg deleted file mode 100644 index 1de607c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pagekite.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pagerduty-icon.svg b/.claude/skills/logo-design/assets/library/svg/pagerduty-icon.svg deleted file mode 100644 index 36d946c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pagerduty-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pagerduty.svg b/.claude/skills/logo-design/assets/library/svg/pagerduty.svg deleted file mode 100644 index 05718a2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pagerduty.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/panda.svg b/.claude/skills/logo-design/assets/library/svg/panda.svg deleted file mode 100644 index c030f55..0000000 --- a/.claude/skills/logo-design/assets/library/svg/panda.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/parcel-icon.svg b/.claude/skills/logo-design/assets/library/svg/parcel-icon.svg deleted file mode 100644 index 074c097..0000000 --- a/.claude/skills/logo-design/assets/library/svg/parcel-icon.svg +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/parcel.svg b/.claude/skills/logo-design/assets/library/svg/parcel.svg deleted file mode 100644 index 6b5e5bb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/parcel.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/parse.svg b/.claude/skills/logo-design/assets/library/svg/parse.svg deleted file mode 100644 index 94cc2bb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/parse.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/parsehub.svg b/.claude/skills/logo-design/assets/library/svg/parsehub.svg deleted file mode 100644 index 2e5b39f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/parsehub.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/partytown-icon.svg b/.claude/skills/logo-design/assets/library/svg/partytown-icon.svg deleted file mode 100644 index 6ab2ff2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/partytown-icon.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/partytown.svg b/.claude/skills/logo-design/assets/library/svg/partytown.svg deleted file mode 100644 index 3505e6f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/partytown.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/passbolt-icon.svg b/.claude/skills/logo-design/assets/library/svg/passbolt-icon.svg deleted file mode 100644 index 98e4144..0000000 --- a/.claude/skills/logo-design/assets/library/svg/passbolt-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/passbolt.svg b/.claude/skills/logo-design/assets/library/svg/passbolt.svg deleted file mode 100644 index 47c0acf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/passbolt.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/passport.svg b/.claude/skills/logo-design/assets/library/svg/passport.svg deleted file mode 100644 index 14641ad..0000000 --- a/.claude/skills/logo-design/assets/library/svg/passport.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/patreon.svg b/.claude/skills/logo-design/assets/library/svg/patreon.svg deleted file mode 100644 index 63d06e5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/patreon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/paypal.svg b/.claude/skills/logo-design/assets/library/svg/paypal.svg deleted file mode 100644 index 538eb7d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/paypal.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/peer5.svg b/.claude/skills/logo-design/assets/library/svg/peer5.svg deleted file mode 100644 index e850e92..0000000 --- a/.claude/skills/logo-design/assets/library/svg/peer5.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pepperoni.svg b/.claude/skills/logo-design/assets/library/svg/pepperoni.svg deleted file mode 100644 index f8d764b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pepperoni.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/percona.svg b/.claude/skills/logo-design/assets/library/svg/percona.svg deleted file mode 100644 index b84d072..0000000 --- a/.claude/skills/logo-design/assets/library/svg/percona.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/percy-icon.svg b/.claude/skills/logo-design/assets/library/svg/percy-icon.svg deleted file mode 100644 index 52bebe1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/percy-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/percy.svg b/.claude/skills/logo-design/assets/library/svg/percy.svg deleted file mode 100644 index 548ff8a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/percy.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/perf-rocks.svg b/.claude/skills/logo-design/assets/library/svg/perf-rocks.svg deleted file mode 100644 index d239d9b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/perf-rocks.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/perl.svg b/.claude/skills/logo-design/assets/library/svg/perl.svg deleted file mode 100644 index 6e7cbae..0000000 --- a/.claude/skills/logo-design/assets/library/svg/perl.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/phalcon.svg b/.claude/skills/logo-design/assets/library/svg/phalcon.svg deleted file mode 100644 index bc9559b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/phalcon.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/phoenix.svg b/.claude/skills/logo-design/assets/library/svg/phoenix.svg deleted file mode 100644 index 2c39a1b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/phoenix.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/phonegap-bot.svg b/.claude/skills/logo-design/assets/library/svg/phonegap-bot.svg deleted file mode 100644 index 9f93785..0000000 --- a/.claude/skills/logo-design/assets/library/svg/phonegap-bot.svg +++ /dev/null @@ -1,261 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/phonegap.svg b/.claude/skills/logo-design/assets/library/svg/phonegap.svg deleted file mode 100644 index 661d718..0000000 --- a/.claude/skills/logo-design/assets/library/svg/phonegap.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/php-alt.svg b/.claude/skills/logo-design/assets/library/svg/php-alt.svg deleted file mode 100644 index acb913d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/php-alt.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/php.svg b/.claude/skills/logo-design/assets/library/svg/php.svg deleted file mode 100644 index 7b63025..0000000 --- a/.claude/skills/logo-design/assets/library/svg/php.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/phpstorm.svg b/.claude/skills/logo-design/assets/library/svg/phpstorm.svg deleted file mode 100644 index d1559b3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/phpstorm.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pinterest.svg b/.claude/skills/logo-design/assets/library/svg/pinterest.svg deleted file mode 100644 index 16b9cc7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pinterest.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pipedrive.svg b/.claude/skills/logo-design/assets/library/svg/pipedrive.svg deleted file mode 100644 index 9ec6c05..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pipedrive.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pipefy.svg b/.claude/skills/logo-design/assets/library/svg/pipefy.svg deleted file mode 100644 index 7690521..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pipefy.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pivotal_tracker.svg b/.claude/skills/logo-design/assets/library/svg/pivotal_tracker.svg deleted file mode 100644 index c2e51e4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pivotal_tracker.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pixijs.svg b/.claude/skills/logo-design/assets/library/svg/pixijs.svg deleted file mode 100644 index b027bc4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pixijs.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pkg.svg b/.claude/skills/logo-design/assets/library/svg/pkg.svg deleted file mode 100644 index 5b1d2d6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pkg.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/planless-icon.svg b/.claude/skills/logo-design/assets/library/svg/planless-icon.svg deleted file mode 100644 index 098f5f1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/planless-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/planless.svg b/.claude/skills/logo-design/assets/library/svg/planless.svg deleted file mode 100644 index ea88662..0000000 --- a/.claude/skills/logo-design/assets/library/svg/planless.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/plastic-scm.svg b/.claude/skills/logo-design/assets/library/svg/plastic-scm.svg deleted file mode 100644 index 36d467c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/plastic-scm.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/platformio.svg b/.claude/skills/logo-design/assets/library/svg/platformio.svg deleted file mode 100644 index c4406e7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/platformio.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/play.svg b/.claude/skills/logo-design/assets/library/svg/play.svg deleted file mode 100644 index 182125c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/play.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/playwright.svg b/.claude/skills/logo-design/assets/library/svg/playwright.svg deleted file mode 100644 index f3a60e6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/playwright.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pm2.svg b/.claude/skills/logo-design/assets/library/svg/pm2.svg deleted file mode 100644 index 647b5be..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pm2.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pnpm.svg b/.claude/skills/logo-design/assets/library/svg/pnpm.svg deleted file mode 100644 index e3860d6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pnpm.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/poeditor.svg b/.claude/skills/logo-design/assets/library/svg/poeditor.svg deleted file mode 100644 index 958ddb5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/poeditor.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/polymer.svg b/.claude/skills/logo-design/assets/library/svg/polymer.svg deleted file mode 100644 index 9a5ffe0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/polymer.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/postcss.svg b/.claude/skills/logo-design/assets/library/svg/postcss.svg deleted file mode 100644 index 5272b75..0000000 --- a/.claude/skills/logo-design/assets/library/svg/postcss.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/postgraphile.svg b/.claude/skills/logo-design/assets/library/svg/postgraphile.svg deleted file mode 100644 index 9af80d0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/postgraphile.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/postgresql.svg b/.claude/skills/logo-design/assets/library/svg/postgresql.svg deleted file mode 100644 index 4ee76c8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/postgresql.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/postman-icon.svg b/.claude/skills/logo-design/assets/library/svg/postman-icon.svg deleted file mode 100644 index fa49fbb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/postman-icon.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/postman.svg b/.claude/skills/logo-design/assets/library/svg/postman.svg deleted file mode 100644 index f6dc155..0000000 --- a/.claude/skills/logo-design/assets/library/svg/postman.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pouchdb.svg b/.claude/skills/logo-design/assets/library/svg/pouchdb.svg deleted file mode 100644 index e7aebcd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pouchdb.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/preact.svg b/.claude/skills/logo-design/assets/library/svg/preact.svg deleted file mode 100644 index a8d395e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/preact.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/precursor.svg b/.claude/skills/logo-design/assets/library/svg/precursor.svg deleted file mode 100644 index a1358f0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/precursor.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/prerender-icon.svg b/.claude/skills/logo-design/assets/library/svg/prerender-icon.svg deleted file mode 100644 index 31a5a55..0000000 --- a/.claude/skills/logo-design/assets/library/svg/prerender-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/prerender.svg b/.claude/skills/logo-design/assets/library/svg/prerender.svg deleted file mode 100644 index 166819c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/prerender.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/prestashop.svg b/.claude/skills/logo-design/assets/library/svg/prestashop.svg deleted file mode 100644 index 27a2deb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/prestashop.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/presto.svg b/.claude/skills/logo-design/assets/library/svg/presto.svg deleted file mode 100644 index 455e440..0000000 --- a/.claude/skills/logo-design/assets/library/svg/presto.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/prettier.svg b/.claude/skills/logo-design/assets/library/svg/prettier.svg deleted file mode 100644 index c0404eb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/prettier.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/prisma.svg b/.claude/skills/logo-design/assets/library/svg/prisma.svg deleted file mode 100644 index 1c84bb6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/prisma.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/prismic-icon.svg b/.claude/skills/logo-design/assets/library/svg/prismic-icon.svg deleted file mode 100644 index d1a1a16..0000000 --- a/.claude/skills/logo-design/assets/library/svg/prismic-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/prismic.svg b/.claude/skills/logo-design/assets/library/svg/prismic.svg deleted file mode 100644 index ac0b298..0000000 --- a/.claude/skills/logo-design/assets/library/svg/prismic.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/processwire.svg b/.claude/skills/logo-design/assets/library/svg/processwire.svg deleted file mode 100644 index bf94f7e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/processwire.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/productboard-icon.svg b/.claude/skills/logo-design/assets/library/svg/productboard-icon.svg deleted file mode 100644 index 8df3791..0000000 --- a/.claude/skills/logo-design/assets/library/svg/productboard-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/productboard.svg b/.claude/skills/logo-design/assets/library/svg/productboard.svg deleted file mode 100644 index 9a42e57..0000000 --- a/.claude/skills/logo-design/assets/library/svg/productboard.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/producthunt.svg b/.claude/skills/logo-design/assets/library/svg/producthunt.svg deleted file mode 100644 index 582f56f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/producthunt.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/progress.svg b/.claude/skills/logo-design/assets/library/svg/progress.svg deleted file mode 100644 index 6cde8ab..0000000 --- a/.claude/skills/logo-design/assets/library/svg/progress.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/prometheus.svg b/.claude/skills/logo-design/assets/library/svg/prometheus.svg deleted file mode 100644 index e4d54bf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/prometheus.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/promises.svg b/.claude/skills/logo-design/assets/library/svg/promises.svg deleted file mode 100644 index d60afcc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/promises.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/proofy.svg b/.claude/skills/logo-design/assets/library/svg/proofy.svg deleted file mode 100644 index 3ad1bdf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/proofy.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/prospect.svg b/.claude/skills/logo-design/assets/library/svg/prospect.svg deleted file mode 100644 index 02d0bf5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/prospect.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/protactor.svg b/.claude/skills/logo-design/assets/library/svg/protactor.svg deleted file mode 100644 index 37dad25..0000000 --- a/.claude/skills/logo-design/assets/library/svg/protactor.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/protoio.svg b/.claude/skills/logo-design/assets/library/svg/protoio.svg deleted file mode 100644 index c4ab360..0000000 --- a/.claude/skills/logo-design/assets/library/svg/protoio.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/protonet.svg b/.claude/skills/logo-design/assets/library/svg/protonet.svg deleted file mode 100644 index 49cd5e8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/protonet.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/prott.svg b/.claude/skills/logo-design/assets/library/svg/prott.svg deleted file mode 100644 index a657b56..0000000 --- a/.claude/skills/logo-design/assets/library/svg/prott.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pug.svg b/.claude/skills/logo-design/assets/library/svg/pug.svg deleted file mode 100644 index 6a778f2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pug.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pumpkindb.svg b/.claude/skills/logo-design/assets/library/svg/pumpkindb.svg deleted file mode 100644 index 2a7db9b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pumpkindb.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/puppet-icon.svg b/.claude/skills/logo-design/assets/library/svg/puppet-icon.svg deleted file mode 100644 index 3706558..0000000 --- a/.claude/skills/logo-design/assets/library/svg/puppet-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/puppet.svg b/.claude/skills/logo-design/assets/library/svg/puppet.svg deleted file mode 100644 index 81d512c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/puppet.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/puppeteer.svg b/.claude/skills/logo-design/assets/library/svg/puppeteer.svg deleted file mode 100644 index 6f5c0fc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/puppeteer.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/puppy-linux.svg b/.claude/skills/logo-design/assets/library/svg/puppy-linux.svg deleted file mode 100644 index 5817ebb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/puppy-linux.svg +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/purescript-icon.svg b/.claude/skills/logo-design/assets/library/svg/purescript-icon.svg deleted file mode 100644 index 479400e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/purescript-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/purescript.svg b/.claude/skills/logo-design/assets/library/svg/purescript.svg deleted file mode 100644 index 7b24e59..0000000 --- a/.claude/skills/logo-design/assets/library/svg/purescript.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pushbullet.svg b/.claude/skills/logo-design/assets/library/svg/pushbullet.svg deleted file mode 100644 index 390368c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pushbullet.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pusher-icon.svg b/.claude/skills/logo-design/assets/library/svg/pusher-icon.svg deleted file mode 100644 index d8c23b0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pusher-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pusher.svg b/.claude/skills/logo-design/assets/library/svg/pusher.svg deleted file mode 100644 index 69c0ce3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pusher.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pwa.svg b/.claude/skills/logo-design/assets/library/svg/pwa.svg deleted file mode 100644 index a3f8361..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pwa.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pycharm.svg b/.claude/skills/logo-design/assets/library/svg/pycharm.svg deleted file mode 100644 index a479393..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pycharm.svg +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/python.svg b/.claude/skills/logo-design/assets/library/svg/python.svg deleted file mode 100644 index 1655e14..0000000 --- a/.claude/skills/logo-design/assets/library/svg/python.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pytorch.svg b/.claude/skills/logo-design/assets/library/svg/pytorch.svg deleted file mode 100644 index efad5a4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pytorch.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/pyup.svg b/.claude/skills/logo-design/assets/library/svg/pyup.svg deleted file mode 100644 index 022d3fa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/pyup.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/q.svg b/.claude/skills/logo-design/assets/library/svg/q.svg deleted file mode 100644 index f3bfc36..0000000 --- a/.claude/skills/logo-design/assets/library/svg/q.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/qlik.svg b/.claude/skills/logo-design/assets/library/svg/qlik.svg deleted file mode 100644 index a17fdb5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/qlik.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/qt.svg b/.claude/skills/logo-design/assets/library/svg/qt.svg deleted file mode 100644 index 1d4b443..0000000 --- a/.claude/skills/logo-design/assets/library/svg/qt.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/quarkus-icon.svg b/.claude/skills/logo-design/assets/library/svg/quarkus-icon.svg deleted file mode 100644 index eda1040..0000000 --- a/.claude/skills/logo-design/assets/library/svg/quarkus-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/quarkus.svg b/.claude/skills/logo-design/assets/library/svg/quarkus.svg deleted file mode 100644 index f4db20a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/quarkus.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/quay.svg b/.claude/skills/logo-design/assets/library/svg/quay.svg deleted file mode 100644 index d872865..0000000 --- a/.claude/skills/logo-design/assets/library/svg/quay.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/quobyte.svg b/.claude/skills/logo-design/assets/library/svg/quobyte.svg deleted file mode 100644 index 4b778f7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/quobyte.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/quora.svg b/.claude/skills/logo-design/assets/library/svg/quora.svg deleted file mode 100644 index ad86868..0000000 --- a/.claude/skills/logo-design/assets/library/svg/quora.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/r-lang.svg b/.claude/skills/logo-design/assets/library/svg/r-lang.svg deleted file mode 100644 index b7d8f17..0000000 --- a/.claude/skills/logo-design/assets/library/svg/r-lang.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rabbitmq-icon.svg b/.claude/skills/logo-design/assets/library/svg/rabbitmq-icon.svg deleted file mode 100644 index a09ea52..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rabbitmq-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rabbitmq.svg b/.claude/skills/logo-design/assets/library/svg/rabbitmq.svg deleted file mode 100644 index 7c4e1c5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rabbitmq.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rackspace.svg b/.claude/skills/logo-design/assets/library/svg/rackspace.svg deleted file mode 100644 index 4ec036a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rackspace.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rails.svg b/.claude/skills/logo-design/assets/library/svg/rails.svg deleted file mode 100644 index 90db830..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rails.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ramda.svg b/.claude/skills/logo-design/assets/library/svg/ramda.svg deleted file mode 100644 index 7e2fd04..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ramda.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/raml.svg b/.claude/skills/logo-design/assets/library/svg/raml.svg deleted file mode 100644 index 3a3001c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/raml.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rancher-icon.svg b/.claude/skills/logo-design/assets/library/svg/rancher-icon.svg deleted file mode 100644 index 9da56e9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rancher-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rancher.svg b/.claude/skills/logo-design/assets/library/svg/rancher.svg deleted file mode 100644 index 8e19cd5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rancher.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/raphael.svg b/.claude/skills/logo-design/assets/library/svg/raphael.svg deleted file mode 100644 index 698f5d4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/raphael.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/raspberry-pi.svg b/.claude/skills/logo-design/assets/library/svg/raspberry-pi.svg deleted file mode 100644 index ba87700..0000000 --- a/.claude/skills/logo-design/assets/library/svg/raspberry-pi.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rax.svg b/.claude/skills/logo-design/assets/library/svg/rax.svg deleted file mode 100644 index b2ab20e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rax.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/react-query-icon.svg b/.claude/skills/logo-design/assets/library/svg/react-query-icon.svg deleted file mode 100644 index 8b3570c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/react-query-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/react-query.svg b/.claude/skills/logo-design/assets/library/svg/react-query.svg deleted file mode 100644 index e8a8ef3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/react-query.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/react-router.svg b/.claude/skills/logo-design/assets/library/svg/react-router.svg deleted file mode 100644 index a41865b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/react-router.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/react-spring.svg b/.claude/skills/logo-design/assets/library/svg/react-spring.svg deleted file mode 100644 index 75b96de..0000000 --- a/.claude/skills/logo-design/assets/library/svg/react-spring.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/react-styleguidist.svg b/.claude/skills/logo-design/assets/library/svg/react-styleguidist.svg deleted file mode 100644 index 5a82464..0000000 --- a/.claude/skills/logo-design/assets/library/svg/react-styleguidist.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/react.svg b/.claude/skills/logo-design/assets/library/svg/react.svg deleted file mode 100644 index 4c514e9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/react.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/reactivex.svg b/.claude/skills/logo-design/assets/library/svg/reactivex.svg deleted file mode 100644 index 87a44a7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/reactivex.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/realm.svg b/.claude/skills/logo-design/assets/library/svg/realm.svg deleted file mode 100644 index 39e417a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/realm.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/reapp.svg b/.claude/skills/logo-design/assets/library/svg/reapp.svg deleted file mode 100644 index 3db6ac9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/reapp.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/reasonml-icon.svg b/.claude/skills/logo-design/assets/library/svg/reasonml-icon.svg deleted file mode 100644 index ed23467..0000000 --- a/.claude/skills/logo-design/assets/library/svg/reasonml-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/reasonml.svg b/.claude/skills/logo-design/assets/library/svg/reasonml.svg deleted file mode 100644 index 509a4fb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/reasonml.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/reddit-icon.svg b/.claude/skills/logo-design/assets/library/svg/reddit-icon.svg deleted file mode 100644 index e5d92b7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/reddit-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/reddit.svg b/.claude/skills/logo-design/assets/library/svg/reddit.svg deleted file mode 100644 index 14b8c8d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/reddit.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/redhat-icon.svg b/.claude/skills/logo-design/assets/library/svg/redhat-icon.svg deleted file mode 100644 index 7483024..0000000 --- a/.claude/skills/logo-design/assets/library/svg/redhat-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/redhat.svg b/.claude/skills/logo-design/assets/library/svg/redhat.svg deleted file mode 100644 index 697c9f1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/redhat.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/redis.svg b/.claude/skills/logo-design/assets/library/svg/redis.svg deleted file mode 100644 index 7a56580..0000000 --- a/.claude/skills/logo-design/assets/library/svg/redis.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/redsmin.svg b/.claude/skills/logo-design/assets/library/svg/redsmin.svg deleted file mode 100644 index 6dcfea2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/redsmin.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/redux-observable.svg b/.claude/skills/logo-design/assets/library/svg/redux-observable.svg deleted file mode 100644 index 06abfd8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/redux-observable.svg +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/redux-saga.svg b/.claude/skills/logo-design/assets/library/svg/redux-saga.svg deleted file mode 100644 index aa59d95..0000000 --- a/.claude/skills/logo-design/assets/library/svg/redux-saga.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/redux.svg b/.claude/skills/logo-design/assets/library/svg/redux.svg deleted file mode 100644 index 35c9de5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/redux.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/redwoodjs.svg b/.claude/skills/logo-design/assets/library/svg/redwoodjs.svg deleted file mode 100644 index d5d8eb5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/redwoodjs.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/reindex.svg b/.claude/skills/logo-design/assets/library/svg/reindex.svg deleted file mode 100644 index f676e5d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/reindex.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/relay.svg b/.claude/skills/logo-design/assets/library/svg/relay.svg deleted file mode 100644 index ba756b5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/relay.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/release.svg b/.claude/skills/logo-design/assets/library/svg/release.svg deleted file mode 100644 index a4c41fe..0000000 --- a/.claude/skills/logo-design/assets/library/svg/release.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/remix-icon.svg b/.claude/skills/logo-design/assets/library/svg/remix-icon.svg deleted file mode 100644 index e41dd15..0000000 --- a/.claude/skills/logo-design/assets/library/svg/remix-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/remix.svg b/.claude/skills/logo-design/assets/library/svg/remix.svg deleted file mode 100644 index 31cf082..0000000 --- a/.claude/skills/logo-design/assets/library/svg/remix.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/require.svg b/.claude/skills/logo-design/assets/library/svg/require.svg deleted file mode 100644 index 6f2bde9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/require.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rescript-icon.svg b/.claude/skills/logo-design/assets/library/svg/rescript-icon.svg deleted file mode 100644 index bce2370..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rescript-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rescript.svg b/.claude/skills/logo-design/assets/library/svg/rescript.svg deleted file mode 100644 index fd3d357..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rescript.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rest-li.svg b/.claude/skills/logo-design/assets/library/svg/rest-li.svg deleted file mode 100644 index e5453fe..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rest-li.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rethinkdb.svg b/.claude/skills/logo-design/assets/library/svg/rethinkdb.svg deleted file mode 100644 index 6f0d331..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rethinkdb.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/retool-icon.svg b/.claude/skills/logo-design/assets/library/svg/retool-icon.svg deleted file mode 100644 index 6d9dfdb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/retool-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/retool.svg b/.claude/skills/logo-design/assets/library/svg/retool.svg deleted file mode 100644 index a1b7c03..0000000 --- a/.claude/skills/logo-design/assets/library/svg/retool.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/riak.svg b/.claude/skills/logo-design/assets/library/svg/riak.svg deleted file mode 100644 index ffc3011..0000000 --- a/.claude/skills/logo-design/assets/library/svg/riak.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/riot.svg b/.claude/skills/logo-design/assets/library/svg/riot.svg deleted file mode 100644 index b8a4f89..0000000 --- a/.claude/skills/logo-design/assets/library/svg/riot.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rocket-chat-icon.svg b/.claude/skills/logo-design/assets/library/svg/rocket-chat-icon.svg deleted file mode 100644 index e9da2e3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rocket-chat-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rocket-chat.svg b/.claude/skills/logo-design/assets/library/svg/rocket-chat.svg deleted file mode 100644 index e7262d8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rocket-chat.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rocksdb.svg b/.claude/skills/logo-design/assets/library/svg/rocksdb.svg deleted file mode 100644 index 60928b6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rocksdb.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rocky-linux-icon.svg b/.claude/skills/logo-design/assets/library/svg/rocky-linux-icon.svg deleted file mode 100644 index cade175..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rocky-linux-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rocky-linux.svg b/.claude/skills/logo-design/assets/library/svg/rocky-linux.svg deleted file mode 100644 index b192d88..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rocky-linux.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rollbar-icon.svg b/.claude/skills/logo-design/assets/library/svg/rollbar-icon.svg deleted file mode 100644 index f930a5f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rollbar-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rollbar.svg b/.claude/skills/logo-design/assets/library/svg/rollbar.svg deleted file mode 100644 index 32af20b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rollbar.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rollupjs.svg b/.claude/skills/logo-design/assets/library/svg/rollupjs.svg deleted file mode 100644 index c894d15..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rollupjs.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rome-icon.svg b/.claude/skills/logo-design/assets/library/svg/rome-icon.svg deleted file mode 100644 index 4e2d8b4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rome-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rome.svg b/.claude/skills/logo-design/assets/library/svg/rome.svg deleted file mode 100644 index 3fe8df0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rome.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rsa.svg b/.claude/skills/logo-design/assets/library/svg/rsa.svg deleted file mode 100644 index 854c108..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rsa.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rsmq.svg b/.claude/skills/logo-design/assets/library/svg/rsmq.svg deleted file mode 100644 index 3ebab4a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rsmq.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rubocop.svg b/.claude/skills/logo-design/assets/library/svg/rubocop.svg deleted file mode 100644 index 2f32e7f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rubocop.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ruby.svg b/.claude/skills/logo-design/assets/library/svg/ruby.svg deleted file mode 100644 index 5232aaa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ruby.svg +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rubygems.svg b/.claude/skills/logo-design/assets/library/svg/rubygems.svg deleted file mode 100644 index c76d3e6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rubygems.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rubymine.svg b/.claude/skills/logo-design/assets/library/svg/rubymine.svg deleted file mode 100644 index 29d69c2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rubymine.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rum.svg b/.claude/skills/logo-design/assets/library/svg/rum.svg deleted file mode 100644 index ce9bb72..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rum.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/runscope.svg b/.claude/skills/logo-design/assets/library/svg/runscope.svg deleted file mode 100644 index 785d97b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/runscope.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rust.svg b/.claude/skills/logo-design/assets/library/svg/rust.svg deleted file mode 100644 index 0b1411d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rust.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/rxdb.svg b/.claude/skills/logo-design/assets/library/svg/rxdb.svg deleted file mode 100644 index d71fa39..0000000 --- a/.claude/skills/logo-design/assets/library/svg/rxdb.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/safari.svg b/.claude/skills/logo-design/assets/library/svg/safari.svg deleted file mode 100644 index 1901de3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/safari.svg +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sagui.svg b/.claude/skills/logo-design/assets/library/svg/sagui.svg deleted file mode 100644 index 8814b6b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sagui.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sails.svg b/.claude/skills/logo-design/assets/library/svg/sails.svg deleted file mode 100644 index f4c183d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sails.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/salesforce.svg b/.claude/skills/logo-design/assets/library/svg/salesforce.svg deleted file mode 100644 index 540007d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/salesforce.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sameroom.svg b/.claude/skills/logo-design/assets/library/svg/sameroom.svg deleted file mode 100644 index 1c0c636..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sameroom.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/samsung.svg b/.claude/skills/logo-design/assets/library/svg/samsung.svg deleted file mode 100644 index 6547945..0000000 --- a/.claude/skills/logo-design/assets/library/svg/samsung.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sanity.svg b/.claude/skills/logo-design/assets/library/svg/sanity.svg deleted file mode 100644 index f09336f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sanity.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sass-doc.svg b/.claude/skills/logo-design/assets/library/svg/sass-doc.svg deleted file mode 100644 index bca8e42..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sass-doc.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sass.svg b/.claude/skills/logo-design/assets/library/svg/sass.svg deleted file mode 100644 index 97dc972..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sass.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/saucelabs.svg b/.claude/skills/logo-design/assets/library/svg/saucelabs.svg deleted file mode 100644 index 8fb4b6b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/saucelabs.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/scala.svg b/.claude/skills/logo-design/assets/library/svg/scala.svg deleted file mode 100644 index aab8f40..0000000 --- a/.claude/skills/logo-design/assets/library/svg/scala.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/scaledrone.svg b/.claude/skills/logo-design/assets/library/svg/scaledrone.svg deleted file mode 100644 index 2cba9d2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/scaledrone.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/scribd-icon.svg b/.claude/skills/logo-design/assets/library/svg/scribd-icon.svg deleted file mode 100644 index c37f592..0000000 --- a/.claude/skills/logo-design/assets/library/svg/scribd-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/scribd.svg b/.claude/skills/logo-design/assets/library/svg/scribd.svg deleted file mode 100644 index dae48ba..0000000 --- a/.claude/skills/logo-design/assets/library/svg/scribd.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/section-icon.svg b/.claude/skills/logo-design/assets/library/svg/section-icon.svg deleted file mode 100644 index 96e68ba..0000000 --- a/.claude/skills/logo-design/assets/library/svg/section-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/section.svg b/.claude/skills/logo-design/assets/library/svg/section.svg deleted file mode 100644 index 4ba4269..0000000 --- a/.claude/skills/logo-design/assets/library/svg/section.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/segment-icon.svg b/.claude/skills/logo-design/assets/library/svg/segment-icon.svg deleted file mode 100644 index 3e64fb3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/segment-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/segment.svg b/.claude/skills/logo-design/assets/library/svg/segment.svg deleted file mode 100644 index d0cfcf1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/segment.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/selenium.svg b/.claude/skills/logo-design/assets/library/svg/selenium.svg deleted file mode 100644 index 74d1207..0000000 --- a/.claude/skills/logo-design/assets/library/svg/selenium.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/semantic-release.svg b/.claude/skills/logo-design/assets/library/svg/semantic-release.svg deleted file mode 100644 index 23c9d13..0000000 --- a/.claude/skills/logo-design/assets/library/svg/semantic-release.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/semantic-ui.svg b/.claude/skills/logo-design/assets/library/svg/semantic-ui.svg deleted file mode 100644 index c8bae87..0000000 --- a/.claude/skills/logo-design/assets/library/svg/semantic-ui.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/semantic-web.svg b/.claude/skills/logo-design/assets/library/svg/semantic-web.svg deleted file mode 100644 index 1224c03..0000000 --- a/.claude/skills/logo-design/assets/library/svg/semantic-web.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/semaphoreci.svg b/.claude/skills/logo-design/assets/library/svg/semaphoreci.svg deleted file mode 100644 index c39faac..0000000 --- a/.claude/skills/logo-design/assets/library/svg/semaphoreci.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sencha.svg b/.claude/skills/logo-design/assets/library/svg/sencha.svg deleted file mode 100644 index 292d233..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sencha.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sendgrid-icon.svg b/.claude/skills/logo-design/assets/library/svg/sendgrid-icon.svg deleted file mode 100644 index ef31bc2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sendgrid-icon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sendgrid.svg b/.claude/skills/logo-design/assets/library/svg/sendgrid.svg deleted file mode 100644 index 8e5bb17..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sendgrid.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/seneca.svg b/.claude/skills/logo-design/assets/library/svg/seneca.svg deleted file mode 100644 index 30be6db..0000000 --- a/.claude/skills/logo-design/assets/library/svg/seneca.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sensu-icon.svg b/.claude/skills/logo-design/assets/library/svg/sensu-icon.svg deleted file mode 100644 index 425adb6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sensu-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sensu.svg b/.claude/skills/logo-design/assets/library/svg/sensu.svg deleted file mode 100644 index 8a9c104..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sensu.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sentry-icon.svg b/.claude/skills/logo-design/assets/library/svg/sentry-icon.svg deleted file mode 100644 index 4c2cc5d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sentry-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sentry.svg b/.claude/skills/logo-design/assets/library/svg/sentry.svg deleted file mode 100644 index 7c4028b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sentry.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sequelize.svg b/.claude/skills/logo-design/assets/library/svg/sequelize.svg deleted file mode 100644 index 3fd2a44..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sequelize.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/serverless.svg b/.claude/skills/logo-design/assets/library/svg/serverless.svg deleted file mode 100644 index 96845a5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/serverless.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sherlock-icon.svg b/.claude/skills/logo-design/assets/library/svg/sherlock-icon.svg deleted file mode 100644 index e0a8c3a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sherlock-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sherlock.svg b/.claude/skills/logo-design/assets/library/svg/sherlock.svg deleted file mode 100644 index 8b6297c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sherlock.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/shields.svg b/.claude/skills/logo-design/assets/library/svg/shields.svg deleted file mode 100644 index df46345..0000000 --- a/.claude/skills/logo-design/assets/library/svg/shields.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/shipit.svg b/.claude/skills/logo-design/assets/library/svg/shipit.svg deleted file mode 100644 index 961a244..0000000 --- a/.claude/skills/logo-design/assets/library/svg/shipit.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/shippable.svg b/.claude/skills/logo-design/assets/library/svg/shippable.svg deleted file mode 100644 index f5642a7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/shippable.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/shogun.svg b/.claude/skills/logo-design/assets/library/svg/shogun.svg deleted file mode 100644 index db50aa0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/shogun.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/shopify.svg b/.claude/skills/logo-design/assets/library/svg/shopify.svg deleted file mode 100644 index b431a49..0000000 --- a/.claude/skills/logo-design/assets/library/svg/shopify.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sidekick.svg b/.claude/skills/logo-design/assets/library/svg/sidekick.svg deleted file mode 100644 index c176680..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sidekick.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sidekiq-icon.svg b/.claude/skills/logo-design/assets/library/svg/sidekiq-icon.svg deleted file mode 100644 index 7c33d4b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sidekiq-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sidekiq.svg b/.claude/skills/logo-design/assets/library/svg/sidekiq.svg deleted file mode 100644 index 5252532..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sidekiq.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/signal.svg b/.claude/skills/logo-design/assets/library/svg/signal.svg deleted file mode 100644 index 1c3379b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/signal.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sinatra.svg b/.claude/skills/logo-design/assets/library/svg/sinatra.svg deleted file mode 100644 index 07c58e8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sinatra.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sitepoint.svg b/.claude/skills/logo-design/assets/library/svg/sitepoint.svg deleted file mode 100644 index c3c1657..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sitepoint.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/skaffolder.svg b/.claude/skills/logo-design/assets/library/svg/skaffolder.svg deleted file mode 100644 index dc33b58..0000000 --- a/.claude/skills/logo-design/assets/library/svg/skaffolder.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sketch.svg b/.claude/skills/logo-design/assets/library/svg/sketch.svg deleted file mode 100644 index d244fe0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sketch.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/skylight.svg b/.claude/skills/logo-design/assets/library/svg/skylight.svg deleted file mode 100644 index ddb7b82..0000000 --- a/.claude/skills/logo-design/assets/library/svg/skylight.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/skype.svg b/.claude/skills/logo-design/assets/library/svg/skype.svg deleted file mode 100644 index 292e20a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/skype.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/slack-icon.svg b/.claude/skills/logo-design/assets/library/svg/slack-icon.svg deleted file mode 100644 index 049ca59..0000000 --- a/.claude/skills/logo-design/assets/library/svg/slack-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/slack.svg b/.claude/skills/logo-design/assets/library/svg/slack.svg deleted file mode 100644 index 61776bc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/slack.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/slides.svg b/.claude/skills/logo-design/assets/library/svg/slides.svg deleted file mode 100644 index d6a988d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/slides.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/slim.svg b/.claude/skills/logo-design/assets/library/svg/slim.svg deleted file mode 100644 index 1312704..0000000 --- a/.claude/skills/logo-design/assets/library/svg/slim.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/smartling.svg b/.claude/skills/logo-design/assets/library/svg/smartling.svg deleted file mode 100644 index 7950ab1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/smartling.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/smashingmagazine.svg b/.claude/skills/logo-design/assets/library/svg/smashingmagazine.svg deleted file mode 100644 index 57f31b2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/smashingmagazine.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/snap-svg.svg b/.claude/skills/logo-design/assets/library/svg/snap-svg.svg deleted file mode 100644 index 4deb1a6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/snap-svg.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/snowflake-icon.svg b/.claude/skills/logo-design/assets/library/svg/snowflake-icon.svg deleted file mode 100644 index 695aad5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/snowflake-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/snowflake.svg b/.claude/skills/logo-design/assets/library/svg/snowflake.svg deleted file mode 100644 index 83d980d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/snowflake.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/snowpack.svg b/.claude/skills/logo-design/assets/library/svg/snowpack.svg deleted file mode 100644 index cbb81d1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/snowpack.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/snupps.svg b/.claude/skills/logo-design/assets/library/svg/snupps.svg deleted file mode 100644 index 5d91789..0000000 --- a/.claude/skills/logo-design/assets/library/svg/snupps.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/snyk.svg b/.claude/skills/logo-design/assets/library/svg/snyk.svg deleted file mode 100644 index cf04cdb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/snyk.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/socket.io.svg b/.claude/skills/logo-design/assets/library/svg/socket.io.svg deleted file mode 100644 index c7bbb6c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/socket.io.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/solarwinds.svg b/.claude/skills/logo-design/assets/library/svg/solarwinds.svg deleted file mode 100644 index 833f0e2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/solarwinds.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/solid.svg b/.claude/skills/logo-design/assets/library/svg/solid.svg deleted file mode 100644 index 4f18e1e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/solid.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/solidity.svg b/.claude/skills/logo-design/assets/library/svg/solidity.svg deleted file mode 100644 index b6331f8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/solidity.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/solidjs-icon.svg b/.claude/skills/logo-design/assets/library/svg/solidjs-icon.svg deleted file mode 100644 index 4d471f0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/solidjs-icon.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/solidjs.svg b/.claude/skills/logo-design/assets/library/svg/solidjs.svg deleted file mode 100644 index 25eb34e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/solidjs.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/solr.svg b/.claude/skills/logo-design/assets/library/svg/solr.svg deleted file mode 100644 index 3a300e1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/solr.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sonarqube.svg b/.claude/skills/logo-design/assets/library/svg/sonarqube.svg deleted file mode 100644 index acafc45..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sonarqube.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/soundcloud.svg b/.claude/skills/logo-design/assets/library/svg/soundcloud.svg deleted file mode 100644 index 66744f5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/soundcloud.svg +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sourcegraph.svg b/.claude/skills/logo-design/assets/library/svg/sourcegraph.svg deleted file mode 100644 index 815a2ab..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sourcegraph.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sourcetrail.svg b/.claude/skills/logo-design/assets/library/svg/sourcetrail.svg deleted file mode 100644 index d1d52ee..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sourcetrail.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sourcetree.svg b/.claude/skills/logo-design/assets/library/svg/sourcetree.svg deleted file mode 100644 index 098c521..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sourcetree.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/spark.svg b/.claude/skills/logo-design/assets/library/svg/spark.svg deleted file mode 100644 index 0fcfceb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/spark.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sparkcentral.svg b/.claude/skills/logo-design/assets/library/svg/sparkcentral.svg deleted file mode 100644 index c724013..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sparkcentral.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sparkpost.svg b/.claude/skills/logo-design/assets/library/svg/sparkpost.svg deleted file mode 100644 index 6e2ba3c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sparkpost.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/speakerdeck.svg b/.claude/skills/logo-design/assets/library/svg/speakerdeck.svg deleted file mode 100644 index fcb7e14..0000000 --- a/.claude/skills/logo-design/assets/library/svg/speakerdeck.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/speedcurve.svg b/.claude/skills/logo-design/assets/library/svg/speedcurve.svg deleted file mode 100644 index a4acdd0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/speedcurve.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/spidermonkey-icon.svg b/.claude/skills/logo-design/assets/library/svg/spidermonkey-icon.svg deleted file mode 100644 index 99f1868..0000000 --- a/.claude/skills/logo-design/assets/library/svg/spidermonkey-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/spidermonkey.svg b/.claude/skills/logo-design/assets/library/svg/spidermonkey.svg deleted file mode 100644 index 3d94602..0000000 --- a/.claude/skills/logo-design/assets/library/svg/spidermonkey.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/spinnaker.svg b/.claude/skills/logo-design/assets/library/svg/spinnaker.svg deleted file mode 100644 index 4f49b80..0000000 --- a/.claude/skills/logo-design/assets/library/svg/spinnaker.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/splunk.svg b/.claude/skills/logo-design/assets/library/svg/splunk.svg deleted file mode 100644 index 52a42ff..0000000 --- a/.claude/skills/logo-design/assets/library/svg/splunk.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/spotify-icon.svg b/.claude/skills/logo-design/assets/library/svg/spotify-icon.svg deleted file mode 100644 index 964645a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/spotify-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/spotify.svg b/.claude/skills/logo-design/assets/library/svg/spotify.svg deleted file mode 100644 index 7de9834..0000000 --- a/.claude/skills/logo-design/assets/library/svg/spotify.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/spree.svg b/.claude/skills/logo-design/assets/library/svg/spree.svg deleted file mode 100644 index a9928df..0000000 --- a/.claude/skills/logo-design/assets/library/svg/spree.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/spring-icon.svg b/.claude/skills/logo-design/assets/library/svg/spring-icon.svg deleted file mode 100644 index 61cfbbf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/spring-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/spring.svg b/.claude/skills/logo-design/assets/library/svg/spring.svg deleted file mode 100644 index d90c9d8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/spring.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sqlite.svg b/.claude/skills/logo-design/assets/library/svg/sqlite.svg deleted file mode 100644 index 618e225..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sqlite.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/square.svg b/.claude/skills/logo-design/assets/library/svg/square.svg deleted file mode 100644 index af672b6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/square.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/squarespace.svg b/.claude/skills/logo-design/assets/library/svg/squarespace.svg deleted file mode 100644 index 7ccaa15..0000000 --- a/.claude/skills/logo-design/assets/library/svg/squarespace.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stackbit-icon.svg b/.claude/skills/logo-design/assets/library/svg/stackbit-icon.svg deleted file mode 100644 index 043a4a9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stackbit-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stackbit.svg b/.claude/skills/logo-design/assets/library/svg/stackbit.svg deleted file mode 100644 index 5a5b74c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stackbit.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stackoverflow-icon.svg b/.claude/skills/logo-design/assets/library/svg/stackoverflow-icon.svg deleted file mode 100644 index b829388..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stackoverflow-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stackoverflow.svg b/.claude/skills/logo-design/assets/library/svg/stackoverflow.svg deleted file mode 100644 index b968e7c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stackoverflow.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stackshare.svg b/.claude/skills/logo-design/assets/library/svg/stackshare.svg deleted file mode 100644 index 16c9034..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stackshare.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/statuspage.svg b/.claude/skills/logo-design/assets/library/svg/statuspage.svg deleted file mode 100644 index 7bbb39f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/statuspage.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stdlib-icon.svg b/.claude/skills/logo-design/assets/library/svg/stdlib-icon.svg deleted file mode 100644 index d8d2817..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stdlib-icon.svg +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stdlib.svg b/.claude/skills/logo-design/assets/library/svg/stdlib.svg deleted file mode 100644 index c801bac..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stdlib.svg +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/steam.svg b/.claude/skills/logo-design/assets/library/svg/steam.svg deleted file mode 100644 index 03587f5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/steam.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stenciljs-icon.svg b/.claude/skills/logo-design/assets/library/svg/stenciljs-icon.svg deleted file mode 100644 index eb0b90d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stenciljs-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stenciljs.svg b/.claude/skills/logo-design/assets/library/svg/stenciljs.svg deleted file mode 100644 index fd28474..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stenciljs.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stetho.svg b/.claude/skills/logo-design/assets/library/svg/stetho.svg deleted file mode 100644 index 1efa8e7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stetho.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stickermule.svg b/.claude/skills/logo-design/assets/library/svg/stickermule.svg deleted file mode 100644 index 53b2c38..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stickermule.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stimulus.svg b/.claude/skills/logo-design/assets/library/svg/stimulus.svg deleted file mode 100644 index e4c3a2f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stimulus.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stitch.svg b/.claude/skills/logo-design/assets/library/svg/stitch.svg deleted file mode 100644 index 8cf2f4d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stitch.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stoplight.svg b/.claude/skills/logo-design/assets/library/svg/stoplight.svg deleted file mode 100644 index bb599de..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stoplight.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/storybook-icon.svg b/.claude/skills/logo-design/assets/library/svg/storybook-icon.svg deleted file mode 100644 index 6271795..0000000 --- a/.claude/skills/logo-design/assets/library/svg/storybook-icon.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/storybook.svg b/.claude/skills/logo-design/assets/library/svg/storybook.svg deleted file mode 100644 index 7d502a1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/storybook.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/strapi-icon.svg b/.claude/skills/logo-design/assets/library/svg/strapi-icon.svg deleted file mode 100644 index 41c5fca..0000000 --- a/.claude/skills/logo-design/assets/library/svg/strapi-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/strapi.svg b/.claude/skills/logo-design/assets/library/svg/strapi.svg deleted file mode 100644 index 5f46d0e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/strapi.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/strider.svg b/.claude/skills/logo-design/assets/library/svg/strider.svg deleted file mode 100644 index fd5e733..0000000 --- a/.claude/skills/logo-design/assets/library/svg/strider.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stripe.svg b/.claude/skills/logo-design/assets/library/svg/stripe.svg deleted file mode 100644 index 9b3cc9f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stripe.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/struts.svg b/.claude/skills/logo-design/assets/library/svg/struts.svg deleted file mode 100644 index 869a3ee..0000000 --- a/.claude/skills/logo-design/assets/library/svg/struts.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/styleci.svg b/.claude/skills/logo-design/assets/library/svg/styleci.svg deleted file mode 100644 index d33ce2c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/styleci.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stylefmt.svg b/.claude/skills/logo-design/assets/library/svg/stylefmt.svg deleted file mode 100644 index 9306a23..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stylefmt.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stylelint.svg b/.claude/skills/logo-design/assets/library/svg/stylelint.svg deleted file mode 100644 index 464e749..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stylelint.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stylis.svg b/.claude/skills/logo-design/assets/library/svg/stylis.svg deleted file mode 100644 index 5b29d95..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stylis.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/stylus.svg b/.claude/skills/logo-design/assets/library/svg/stylus.svg deleted file mode 100644 index 13727d4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/stylus.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sublimetext-icon.svg b/.claude/skills/logo-design/assets/library/svg/sublimetext-icon.svg deleted file mode 100644 index ce6db52..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sublimetext-icon.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sublimetext.svg b/.claude/skills/logo-design/assets/library/svg/sublimetext.svg deleted file mode 100644 index 85ab615..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sublimetext.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/subversion.svg b/.claude/skills/logo-design/assets/library/svg/subversion.svg deleted file mode 100644 index 2d521f7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/subversion.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sugarss.svg b/.claude/skills/logo-design/assets/library/svg/sugarss.svg deleted file mode 100644 index d09cff3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sugarss.svg +++ /dev/null @@ -1,571 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/supabase-icon.svg b/.claude/skills/logo-design/assets/library/svg/supabase-icon.svg deleted file mode 100644 index a3003f7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/supabase-icon.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/supabase.svg b/.claude/skills/logo-design/assets/library/svg/supabase.svg deleted file mode 100644 index 157e5d9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/supabase.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/surge.svg b/.claude/skills/logo-design/assets/library/svg/surge.svg deleted file mode 100644 index dcb7438..0000000 --- a/.claude/skills/logo-design/assets/library/svg/surge.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/survicate.svg b/.claude/skills/logo-design/assets/library/svg/survicate.svg deleted file mode 100644 index 11b5f56..0000000 --- a/.claude/skills/logo-design/assets/library/svg/survicate.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/suse.svg b/.claude/skills/logo-design/assets/library/svg/suse.svg deleted file mode 100644 index b17f82c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/suse.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/susy.svg b/.claude/skills/logo-design/assets/library/svg/susy.svg deleted file mode 100644 index 4acec37..0000000 --- a/.claude/skills/logo-design/assets/library/svg/susy.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/svelte-icon.svg b/.claude/skills/logo-design/assets/library/svg/svelte-icon.svg deleted file mode 100644 index b4c5a00..0000000 --- a/.claude/skills/logo-design/assets/library/svg/svelte-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/svelte.svg b/.claude/skills/logo-design/assets/library/svg/svelte.svg deleted file mode 100644 index cd4f06c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/svelte.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/svg.svg b/.claude/skills/logo-design/assets/library/svg/svg.svg deleted file mode 100644 index 3244650..0000000 --- a/.claude/skills/logo-design/assets/library/svg/svg.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/swagger.svg b/.claude/skills/logo-design/assets/library/svg/swagger.svg deleted file mode 100644 index b009ac3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/swagger.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/swift.svg b/.claude/skills/logo-design/assets/library/svg/swift.svg deleted file mode 100644 index 5dbaed7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/swift.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/swiftype.svg b/.claude/skills/logo-design/assets/library/svg/swiftype.svg deleted file mode 100644 index d780bea..0000000 --- a/.claude/skills/logo-design/assets/library/svg/swiftype.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/symfony.svg b/.claude/skills/logo-design/assets/library/svg/symfony.svg deleted file mode 100644 index 08ae93a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/symfony.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/sysdig-icon.svg b/.claude/skills/logo-design/assets/library/svg/sysdig-icon.svg deleted file mode 100644 index 3ea3dd5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/sysdig-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/t3.svg b/.claude/skills/logo-design/assets/library/svg/t3.svg deleted file mode 100644 index c2216fd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/t3.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tableau-icon.svg b/.claude/skills/logo-design/assets/library/svg/tableau-icon.svg deleted file mode 100644 index a305906..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tableau-icon.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tableau.svg b/.claude/skills/logo-design/assets/library/svg/tableau.svg deleted file mode 100644 index 795b0f1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tableau.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/taiga.svg b/.claude/skills/logo-design/assets/library/svg/taiga.svg deleted file mode 100644 index 859cf16..0000000 --- a/.claude/skills/logo-design/assets/library/svg/taiga.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tailwindcss-icon.svg b/.claude/skills/logo-design/assets/library/svg/tailwindcss-icon.svg deleted file mode 100644 index ddcc2fc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tailwindcss-icon.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tailwindcss.svg b/.claude/skills/logo-design/assets/library/svg/tailwindcss.svg deleted file mode 100644 index eff31b2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tailwindcss.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tapcart-icon.svg b/.claude/skills/logo-design/assets/library/svg/tapcart-icon.svg deleted file mode 100644 index 164965b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tapcart-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tapcart.svg b/.claude/skills/logo-design/assets/library/svg/tapcart.svg deleted file mode 100644 index 22ca29d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tapcart.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/targetprocess.svg b/.claude/skills/logo-design/assets/library/svg/targetprocess.svg deleted file mode 100644 index c2b7854..0000000 --- a/.claude/skills/logo-design/assets/library/svg/targetprocess.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/taskade-icon.svg b/.claude/skills/logo-design/assets/library/svg/taskade-icon.svg deleted file mode 100644 index 92463ac..0000000 --- a/.claude/skills/logo-design/assets/library/svg/taskade-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/taskade.svg b/.claude/skills/logo-design/assets/library/svg/taskade.svg deleted file mode 100644 index 507cad8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/taskade.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tastejs.svg b/.claude/skills/logo-design/assets/library/svg/tastejs.svg deleted file mode 100644 index 69d3a6b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tastejs.svg +++ /dev/null @@ -1,615 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tauri.svg b/.claude/skills/logo-design/assets/library/svg/tauri.svg deleted file mode 100644 index f21af36..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tauri.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tealium.svg b/.claude/skills/logo-design/assets/library/svg/tealium.svg deleted file mode 100644 index ceeda47..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tealium.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/teamgrid.svg b/.claude/skills/logo-design/assets/library/svg/teamgrid.svg deleted file mode 100644 index 5d3ffa9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/teamgrid.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/teamwork-icon.svg b/.claude/skills/logo-design/assets/library/svg/teamwork-icon.svg deleted file mode 100644 index e885ab4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/teamwork-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/teamwork.svg b/.claude/skills/logo-design/assets/library/svg/teamwork.svg deleted file mode 100644 index be538ee..0000000 --- a/.claude/skills/logo-design/assets/library/svg/teamwork.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/telegram.svg b/.claude/skills/logo-design/assets/library/svg/telegram.svg deleted file mode 100644 index 2965c00..0000000 --- a/.claude/skills/logo-design/assets/library/svg/telegram.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tensorflow.svg b/.claude/skills/logo-design/assets/library/svg/tensorflow.svg deleted file mode 100644 index 5475958..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tensorflow.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/terminal.svg b/.claude/skills/logo-design/assets/library/svg/terminal.svg deleted file mode 100644 index 4d01b7e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/terminal.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/terraform-icon.svg b/.claude/skills/logo-design/assets/library/svg/terraform-icon.svg deleted file mode 100644 index 5e067bd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/terraform-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/terraform.svg b/.claude/skills/logo-design/assets/library/svg/terraform.svg deleted file mode 100644 index 3ca53ff..0000000 --- a/.claude/skills/logo-design/assets/library/svg/terraform.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/terser-icon.svg b/.claude/skills/logo-design/assets/library/svg/terser-icon.svg deleted file mode 100644 index ea9e6d9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/terser-icon.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/terser.svg b/.claude/skills/logo-design/assets/library/svg/terser.svg deleted file mode 100644 index a991a1d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/terser.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/testing-library.svg b/.claude/skills/logo-design/assets/library/svg/testing-library.svg deleted file mode 100644 index d6f2edc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/testing-library.svg +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/testlodge.svg b/.claude/skills/logo-design/assets/library/svg/testlodge.svg deleted file mode 100644 index 5d0fbf1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/testlodge.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/threejs.svg b/.claude/skills/logo-design/assets/library/svg/threejs.svg deleted file mode 100644 index a5d80ad..0000000 --- a/.claude/skills/logo-design/assets/library/svg/threejs.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tidal-icon.svg b/.claude/skills/logo-design/assets/library/svg/tidal-icon.svg deleted file mode 100644 index 32fc4db..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tidal-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tidal.svg b/.claude/skills/logo-design/assets/library/svg/tidal.svg deleted file mode 100644 index f3398bb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tidal.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tiktok-icon.svg b/.claude/skills/logo-design/assets/library/svg/tiktok-icon.svg deleted file mode 100644 index 4defc5e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tiktok-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tiktok.svg b/.claude/skills/logo-design/assets/library/svg/tiktok.svg deleted file mode 100644 index d3b1500..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tiktok.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tnw.svg b/.claude/skills/logo-design/assets/library/svg/tnw.svg deleted file mode 100644 index 3b4cf6c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tnw.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/todoist-icon.svg b/.claude/skills/logo-design/assets/library/svg/todoist-icon.svg deleted file mode 100644 index ec39d40..0000000 --- a/.claude/skills/logo-design/assets/library/svg/todoist-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/todoist.svg b/.claude/skills/logo-design/assets/library/svg/todoist.svg deleted file mode 100644 index 9cb69ad..0000000 --- a/.claude/skills/logo-design/assets/library/svg/todoist.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/todomvc.svg b/.claude/skills/logo-design/assets/library/svg/todomvc.svg deleted file mode 100644 index b51e534..0000000 --- a/.claude/skills/logo-design/assets/library/svg/todomvc.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tomcat.svg b/.claude/skills/logo-design/assets/library/svg/tomcat.svg deleted file mode 100644 index c97d03e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tomcat.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/toml.svg b/.claude/skills/logo-design/assets/library/svg/toml.svg deleted file mode 100644 index 6322705..0000000 --- a/.claude/skills/logo-design/assets/library/svg/toml.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tor.svg b/.claude/skills/logo-design/assets/library/svg/tor.svg deleted file mode 100644 index 07d7ccc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tor.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/torus.svg b/.claude/skills/logo-design/assets/library/svg/torus.svg deleted file mode 100644 index 4586314..0000000 --- a/.claude/skills/logo-design/assets/library/svg/torus.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/traackr.svg b/.claude/skills/logo-design/assets/library/svg/traackr.svg deleted file mode 100644 index cdd84ad..0000000 --- a/.claude/skills/logo-design/assets/library/svg/traackr.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/trac.svg b/.claude/skills/logo-design/assets/library/svg/trac.svg deleted file mode 100644 index a4118d7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/trac.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/travis-ci-monochrome.svg b/.claude/skills/logo-design/assets/library/svg/travis-ci-monochrome.svg deleted file mode 100644 index f83d582..0000000 --- a/.claude/skills/logo-design/assets/library/svg/travis-ci-monochrome.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/travis-ci.svg b/.claude/skills/logo-design/assets/library/svg/travis-ci.svg deleted file mode 100644 index cb2518e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/travis-ci.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/treasuredata-icon.svg b/.claude/skills/logo-design/assets/library/svg/treasuredata-icon.svg deleted file mode 100644 index 8df7972..0000000 --- a/.claude/skills/logo-design/assets/library/svg/treasuredata-icon.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/treasuredata.svg b/.claude/skills/logo-design/assets/library/svg/treasuredata.svg deleted file mode 100644 index 746d669..0000000 --- a/.claude/skills/logo-design/assets/library/svg/treasuredata.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/treehouse.svg b/.claude/skills/logo-design/assets/library/svg/treehouse.svg deleted file mode 100644 index e5e55d4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/treehouse.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/trello.svg b/.claude/skills/logo-design/assets/library/svg/trello.svg deleted file mode 100644 index d8ae484..0000000 --- a/.claude/skills/logo-design/assets/library/svg/trello.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/truffle-icon.svg b/.claude/skills/logo-design/assets/library/svg/truffle-icon.svg deleted file mode 100644 index 39cfca3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/truffle-icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/truffle.svg b/.claude/skills/logo-design/assets/library/svg/truffle.svg deleted file mode 100644 index 2469847..0000000 --- a/.claude/skills/logo-design/assets/library/svg/truffle.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tsnode.svg b/.claude/skills/logo-design/assets/library/svg/tsnode.svg deleted file mode 100644 index 003fd86..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tsnode.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tsu.svg b/.claude/skills/logo-design/assets/library/svg/tsu.svg deleted file mode 100644 index 92c846c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tsu.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tsuru.svg b/.claude/skills/logo-design/assets/library/svg/tsuru.svg deleted file mode 100644 index 91c76ca..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tsuru.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tumblr-icon.svg b/.claude/skills/logo-design/assets/library/svg/tumblr-icon.svg deleted file mode 100644 index 1d686e4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tumblr-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tumblr.svg b/.claude/skills/logo-design/assets/library/svg/tumblr.svg deleted file mode 100644 index 2c3eda1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tumblr.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tunein.svg b/.claude/skills/logo-design/assets/library/svg/tunein.svg deleted file mode 100644 index 8814929..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tunein.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/tuple.svg b/.claude/skills/logo-design/assets/library/svg/tuple.svg deleted file mode 100644 index 50ac227..0000000 --- a/.claude/skills/logo-design/assets/library/svg/tuple.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/turborepo-icon.svg b/.claude/skills/logo-design/assets/library/svg/turborepo-icon.svg deleted file mode 100644 index 745b259..0000000 --- a/.claude/skills/logo-design/assets/library/svg/turborepo-icon.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/turborepo.svg b/.claude/skills/logo-design/assets/library/svg/turborepo.svg deleted file mode 100644 index 7e9bdb9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/turborepo.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/turret.svg b/.claude/skills/logo-design/assets/library/svg/turret.svg deleted file mode 100644 index c4a400c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/turret.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/twilio-icon.svg b/.claude/skills/logo-design/assets/library/svg/twilio-icon.svg deleted file mode 100644 index 844d2dc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/twilio-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/twilio.svg b/.claude/skills/logo-design/assets/library/svg/twilio.svg deleted file mode 100644 index cc96627..0000000 --- a/.claude/skills/logo-design/assets/library/svg/twilio.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/twitch.svg b/.claude/skills/logo-design/assets/library/svg/twitch.svg deleted file mode 100644 index 56ea968..0000000 --- a/.claude/skills/logo-design/assets/library/svg/twitch.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/twitter.svg b/.claude/skills/logo-design/assets/library/svg/twitter.svg deleted file mode 100644 index 5d45938..0000000 --- a/.claude/skills/logo-design/assets/library/svg/twitter.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/typeform-icon.svg b/.claude/skills/logo-design/assets/library/svg/typeform-icon.svg deleted file mode 100644 index 5000ae9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/typeform-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/typeform.svg b/.claude/skills/logo-design/assets/library/svg/typeform.svg deleted file mode 100644 index 7602aed..0000000 --- a/.claude/skills/logo-design/assets/library/svg/typeform.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/typescript-icon.svg b/.claude/skills/logo-design/assets/library/svg/typescript-icon.svg deleted file mode 100644 index 887e81e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/typescript-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/typescript.svg b/.claude/skills/logo-design/assets/library/svg/typescript.svg deleted file mode 100644 index 81a1bb7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/typescript.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/typo3-icon.svg b/.claude/skills/logo-design/assets/library/svg/typo3-icon.svg deleted file mode 100644 index 536b763..0000000 --- a/.claude/skills/logo-design/assets/library/svg/typo3-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/typo3.svg b/.claude/skills/logo-design/assets/library/svg/typo3.svg deleted file mode 100644 index 9f4a9a0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/typo3.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ubuntu.svg b/.claude/skills/logo-design/assets/library/svg/ubuntu.svg deleted file mode 100644 index a4a9fda..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ubuntu.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/udacity-icon.svg b/.claude/skills/logo-design/assets/library/svg/udacity-icon.svg deleted file mode 100644 index 4c29c43..0000000 --- a/.claude/skills/logo-design/assets/library/svg/udacity-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/udacity.svg b/.claude/skills/logo-design/assets/library/svg/udacity.svg deleted file mode 100644 index 18da276..0000000 --- a/.claude/skills/logo-design/assets/library/svg/udacity.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/udemy-icon.svg b/.claude/skills/logo-design/assets/library/svg/udemy-icon.svg deleted file mode 100644 index ad6a86e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/udemy-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/udemy.svg b/.claude/skills/logo-design/assets/library/svg/udemy.svg deleted file mode 100644 index 9cb1c31..0000000 --- a/.claude/skills/logo-design/assets/library/svg/udemy.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/uikit.svg b/.claude/skills/logo-design/assets/library/svg/uikit.svg deleted file mode 100644 index 92e2ba8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/uikit.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/umu.svg b/.claude/skills/logo-design/assets/library/svg/umu.svg deleted file mode 100644 index e55d1aa..0000000 --- a/.claude/skills/logo-design/assets/library/svg/umu.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/unbounce-icon.svg b/.claude/skills/logo-design/assets/library/svg/unbounce-icon.svg deleted file mode 100644 index 60e5cd3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/unbounce-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/unbounce.svg b/.claude/skills/logo-design/assets/library/svg/unbounce.svg deleted file mode 100644 index 4cfdaef..0000000 --- a/.claude/skills/logo-design/assets/library/svg/unbounce.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/undertow.svg b/.claude/skills/logo-design/assets/library/svg/undertow.svg deleted file mode 100644 index dab9829..0000000 --- a/.claude/skills/logo-design/assets/library/svg/undertow.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/unionpay.svg b/.claude/skills/logo-design/assets/library/svg/unionpay.svg deleted file mode 100644 index e3d437a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/unionpay.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/unitjs.svg b/.claude/skills/logo-design/assets/library/svg/unitjs.svg deleted file mode 100644 index d96b18f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/unitjs.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/unito-icon.svg b/.claude/skills/logo-design/assets/library/svg/unito-icon.svg deleted file mode 100644 index a7abab8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/unito-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/unito.svg b/.claude/skills/logo-design/assets/library/svg/unito.svg deleted file mode 100644 index ace907e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/unito.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/unity.svg b/.claude/skills/logo-design/assets/library/svg/unity.svg deleted file mode 100644 index 042b8d7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/unity.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/unocss.svg b/.claude/skills/logo-design/assets/library/svg/unocss.svg deleted file mode 100644 index bff436b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/unocss.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/unrealengine-icon.svg b/.claude/skills/logo-design/assets/library/svg/unrealengine-icon.svg deleted file mode 100644 index 5a6e077..0000000 --- a/.claude/skills/logo-design/assets/library/svg/unrealengine-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/unrealengine.svg b/.claude/skills/logo-design/assets/library/svg/unrealengine.svg deleted file mode 100644 index 8f85ce4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/unrealengine.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/upcase.svg b/.claude/skills/logo-design/assets/library/svg/upcase.svg deleted file mode 100644 index 626e68f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/upcase.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/upwork.svg b/.claude/skills/logo-design/assets/library/svg/upwork.svg deleted file mode 100644 index f5cae7d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/upwork.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/user-testing-icon.svg b/.claude/skills/logo-design/assets/library/svg/user-testing-icon.svg deleted file mode 100644 index 70e2f06..0000000 --- a/.claude/skills/logo-design/assets/library/svg/user-testing-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/user-testing.svg b/.claude/skills/logo-design/assets/library/svg/user-testing.svg deleted file mode 100644 index f0901d7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/user-testing.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/uservoice-icon.svg b/.claude/skills/logo-design/assets/library/svg/uservoice-icon.svg deleted file mode 100644 index cf6061e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/uservoice-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/uservoice.svg b/.claude/skills/logo-design/assets/library/svg/uservoice.svg deleted file mode 100644 index 257373d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/uservoice.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/uwsgi.svg b/.claude/skills/logo-design/assets/library/svg/uwsgi.svg deleted file mode 100644 index 0290552..0000000 --- a/.claude/skills/logo-design/assets/library/svg/uwsgi.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/v8-ignition.svg b/.claude/skills/logo-design/assets/library/svg/v8-ignition.svg deleted file mode 100644 index 4f0ed51..0000000 --- a/.claude/skills/logo-design/assets/library/svg/v8-ignition.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/v8-turbofan.svg b/.claude/skills/logo-design/assets/library/svg/v8-turbofan.svg deleted file mode 100644 index 90b074d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/v8-turbofan.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/v8.svg b/.claude/skills/logo-design/assets/library/svg/v8.svg deleted file mode 100644 index 9f8addf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/v8.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vaadin.svg b/.claude/skills/logo-design/assets/library/svg/vaadin.svg deleted file mode 100644 index 9457875..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vaadin.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vaddy.svg b/.claude/skills/logo-design/assets/library/svg/vaddy.svg deleted file mode 100644 index 90e1585..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vaddy.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vagrant-icon.svg b/.claude/skills/logo-design/assets/library/svg/vagrant-icon.svg deleted file mode 100644 index 2220a6c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vagrant-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vagrant.svg b/.claude/skills/logo-design/assets/library/svg/vagrant.svg deleted file mode 100644 index 37974dc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vagrant.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vault-icon.svg b/.claude/skills/logo-design/assets/library/svg/vault-icon.svg deleted file mode 100644 index bfa40e0..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vault-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vault.svg b/.claude/skills/logo-design/assets/library/svg/vault.svg deleted file mode 100644 index 23e6e42..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vault.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vector-timber.svg b/.claude/skills/logo-design/assets/library/svg/vector-timber.svg deleted file mode 100644 index 0458487..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vector-timber.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vercel-icon.svg b/.claude/skills/logo-design/assets/library/svg/vercel-icon.svg deleted file mode 100644 index a4a38d1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vercel-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vercel.svg b/.claude/skills/logo-design/assets/library/svg/vercel.svg deleted file mode 100644 index 7eb306e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vercel.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/verdaccio-icon.svg b/.claude/skills/logo-design/assets/library/svg/verdaccio-icon.svg deleted file mode 100644 index ea9faa4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/verdaccio-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/verdaccio.svg b/.claude/skills/logo-design/assets/library/svg/verdaccio.svg deleted file mode 100644 index 03c096e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/verdaccio.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vernemq.svg b/.claude/skills/logo-design/assets/library/svg/vernemq.svg deleted file mode 100644 index fba113f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vernemq.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vim.svg b/.claude/skills/logo-design/assets/library/svg/vim.svg deleted file mode 100644 index 38fc6cb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vim.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vimeo-icon.svg b/.claude/skills/logo-design/assets/library/svg/vimeo-icon.svg deleted file mode 100644 index 8b27d74..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vimeo-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vimeo.svg b/.claude/skills/logo-design/assets/library/svg/vimeo.svg deleted file mode 100644 index fe9f017..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vimeo.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/visa.svg b/.claude/skills/logo-design/assets/library/svg/visa.svg deleted file mode 100644 index d031bed..0000000 --- a/.claude/skills/logo-design/assets/library/svg/visa.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/visaelectron.svg b/.claude/skills/logo-design/assets/library/svg/visaelectron.svg deleted file mode 100644 index a5e23a4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/visaelectron.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/visual-studio-code.svg b/.claude/skills/logo-design/assets/library/svg/visual-studio-code.svg deleted file mode 100644 index f28370f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/visual-studio-code.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/visual-studio.svg b/.claude/skills/logo-design/assets/library/svg/visual-studio.svg deleted file mode 100644 index 7236a32..0000000 --- a/.claude/skills/logo-design/assets/library/svg/visual-studio.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vitejs.svg b/.claude/skills/logo-design/assets/library/svg/vitejs.svg deleted file mode 100644 index 2dddea3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vitejs.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vitest.svg b/.claude/skills/logo-design/assets/library/svg/vitest.svg deleted file mode 100644 index 6097bba..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vitest.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vivaldi-icon.svg b/.claude/skills/logo-design/assets/library/svg/vivaldi-icon.svg deleted file mode 100644 index 47d6080..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vivaldi-icon.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vivaldi.svg b/.claude/skills/logo-design/assets/library/svg/vivaldi.svg deleted file mode 100644 index f74563a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vivaldi.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vlang.svg b/.claude/skills/logo-design/assets/library/svg/vlang.svg deleted file mode 100644 index 3e358e4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vlang.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/void.svg b/.claude/skills/logo-design/assets/library/svg/void.svg deleted file mode 100644 index e17f99e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/void.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vue.svg b/.claude/skills/logo-design/assets/library/svg/vue.svg deleted file mode 100644 index 4cd8088..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vue.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vuetifyjs.svg b/.claude/skills/logo-design/assets/library/svg/vuetifyjs.svg deleted file mode 100644 index 0445b79..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vuetifyjs.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vueuse.svg b/.claude/skills/logo-design/assets/library/svg/vueuse.svg deleted file mode 100644 index 25f373e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vueuse.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vulkan.svg b/.claude/skills/logo-design/assets/library/svg/vulkan.svg deleted file mode 100644 index 8fbbea8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vulkan.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vultr.svg b/.claude/skills/logo-design/assets/library/svg/vultr.svg deleted file mode 100644 index 08a27b7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vultr.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/vwo.svg b/.claude/skills/logo-design/assets/library/svg/vwo.svg deleted file mode 100644 index 24d2abd..0000000 --- a/.claude/skills/logo-design/assets/library/svg/vwo.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/w3c.svg b/.claude/skills/logo-design/assets/library/svg/w3c.svg deleted file mode 100644 index 896dc74..0000000 --- a/.claude/skills/logo-design/assets/library/svg/w3c.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/waffle-icon.svg b/.claude/skills/logo-design/assets/library/svg/waffle-icon.svg deleted file mode 100644 index 88c2a1d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/waffle-icon.svg +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/waffle.svg b/.claude/skills/logo-design/assets/library/svg/waffle.svg deleted file mode 100644 index e95a2d1..0000000 --- a/.claude/skills/logo-design/assets/library/svg/waffle.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wagtail.svg b/.claude/skills/logo-design/assets/library/svg/wagtail.svg deleted file mode 100644 index c0b1d60..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wagtail.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wakatime.svg b/.claude/skills/logo-design/assets/library/svg/wakatime.svg deleted file mode 100644 index a223d48..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wakatime.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/watchman.svg b/.claude/skills/logo-design/assets/library/svg/watchman.svg deleted file mode 100644 index 4ede2af..0000000 --- a/.claude/skills/logo-design/assets/library/svg/watchman.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wearos.svg b/.claude/skills/logo-design/assets/library/svg/wearos.svg deleted file mode 100644 index 75892b4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wearos.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/weave.svg b/.claude/skills/logo-design/assets/library/svg/weave.svg deleted file mode 100644 index 0771dc2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/weave.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/web-fundamentals.svg b/.claude/skills/logo-design/assets/library/svg/web-fundamentals.svg deleted file mode 100644 index 0b1b15c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/web-fundamentals.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/web.dev-icon.svg b/.claude/skills/logo-design/assets/library/svg/web.dev-icon.svg deleted file mode 100644 index bf649ca..0000000 --- a/.claude/skills/logo-design/assets/library/svg/web.dev-icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/web.dev.svg b/.claude/skills/logo-design/assets/library/svg/web.dev.svg deleted file mode 100644 index 3cdeec6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/web.dev.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/web3js.svg b/.claude/skills/logo-design/assets/library/svg/web3js.svg deleted file mode 100644 index 254ce38..0000000 --- a/.claude/skills/logo-design/assets/library/svg/web3js.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webassembly.svg b/.claude/skills/logo-design/assets/library/svg/webassembly.svg deleted file mode 100644 index e359c06..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webassembly.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webcomponents.svg b/.claude/skills/logo-design/assets/library/svg/webcomponents.svg deleted file mode 100644 index f9bac2b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webcomponents.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webdriverio.svg b/.claude/skills/logo-design/assets/library/svg/webdriverio.svg deleted file mode 100644 index d6d4429..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webdriverio.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webflow.svg b/.claude/skills/logo-design/assets/library/svg/webflow.svg deleted file mode 100644 index 85bf64e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webflow.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webhint-icon.svg b/.claude/skills/logo-design/assets/library/svg/webhint-icon.svg deleted file mode 100644 index 598003b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webhint-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webhint.svg b/.claude/skills/logo-design/assets/library/svg/webhint.svg deleted file mode 100644 index 5125ae2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webhint.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webhooks.svg b/.claude/skills/logo-design/assets/library/svg/webhooks.svg deleted file mode 100644 index b275fc8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webhooks.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webix-icon.svg b/.claude/skills/logo-design/assets/library/svg/webix-icon.svg deleted file mode 100644 index f5b47ff..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webix-icon.svg +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webix.svg b/.claude/skills/logo-design/assets/library/svg/webix.svg deleted file mode 100644 index 1169240..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webix.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webmin.svg b/.claude/skills/logo-design/assets/library/svg/webmin.svg deleted file mode 100644 index 783ce22..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webmin.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webpack.svg b/.claude/skills/logo-design/assets/library/svg/webpack.svg deleted file mode 100644 index 3d8441d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webpack.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webplatform.svg b/.claude/skills/logo-design/assets/library/svg/webplatform.svg deleted file mode 100644 index b6a5300..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webplatform.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webrtc.svg b/.claude/skills/logo-design/assets/library/svg/webrtc.svg deleted file mode 100644 index b9c6bed..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webrtc.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/websocket.svg b/.claude/skills/logo-design/assets/library/svg/websocket.svg deleted file mode 100644 index e5f7629..0000000 --- a/.claude/skills/logo-design/assets/library/svg/websocket.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webstorm.svg b/.claude/skills/logo-design/assets/library/svg/webstorm.svg deleted file mode 100644 index d071deb..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webstorm.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webtask.svg b/.claude/skills/logo-design/assets/library/svg/webtask.svg deleted file mode 100644 index 1b46385..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webtask.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/webtorrent.svg b/.claude/skills/logo-design/assets/library/svg/webtorrent.svg deleted file mode 100644 index 4c84bbf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/webtorrent.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/weebly.svg b/.claude/skills/logo-design/assets/library/svg/weebly.svg deleted file mode 100644 index 2634cfc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/weebly.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/whalar.svg b/.claude/skills/logo-design/assets/library/svg/whalar.svg deleted file mode 100644 index c0f08d7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/whalar.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/whatsapp.svg b/.claude/skills/logo-design/assets/library/svg/whatsapp.svg deleted file mode 100644 index 0b43ed5..0000000 --- a/.claude/skills/logo-design/assets/library/svg/whatsapp.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/whatwg.svg b/.claude/skills/logo-design/assets/library/svg/whatwg.svg deleted file mode 100644 index 84b262e..0000000 --- a/.claude/skills/logo-design/assets/library/svg/whatwg.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wicket-icon.svg b/.claude/skills/logo-design/assets/library/svg/wicket-icon.svg deleted file mode 100644 index d0d365d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wicket-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wicket.svg b/.claude/skills/logo-design/assets/library/svg/wicket.svg deleted file mode 100644 index 51e8dae..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wicket.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wifi.svg b/.claude/skills/logo-design/assets/library/svg/wifi.svg deleted file mode 100644 index 7349c62..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wifi.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wildfly.svg b/.claude/skills/logo-design/assets/library/svg/wildfly.svg deleted file mode 100644 index 9ec1896..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wildfly.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wire.svg b/.claude/skills/logo-design/assets/library/svg/wire.svg deleted file mode 100644 index f1df309..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wire.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wix.svg b/.claude/skills/logo-design/assets/library/svg/wix.svg deleted file mode 100644 index 736a268..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wix.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wmr.svg b/.claude/skills/logo-design/assets/library/svg/wmr.svg deleted file mode 100644 index d5a05d7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wmr.svg +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/woocommerce-icon.svg b/.claude/skills/logo-design/assets/library/svg/woocommerce-icon.svg deleted file mode 100644 index fcb1333..0000000 --- a/.claude/skills/logo-design/assets/library/svg/woocommerce-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/woocommerce.svg b/.claude/skills/logo-design/assets/library/svg/woocommerce.svg deleted file mode 100644 index fc1b5cc..0000000 --- a/.claude/skills/logo-design/assets/library/svg/woocommerce.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/woopra.svg b/.claude/skills/logo-design/assets/library/svg/woopra.svg deleted file mode 100644 index 6a26f1b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/woopra.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wordpress-icon.svg b/.claude/skills/logo-design/assets/library/svg/wordpress-icon.svg deleted file mode 100644 index d880bea..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wordpress-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wordpress.svg b/.claude/skills/logo-design/assets/library/svg/wordpress.svg deleted file mode 100644 index 0db7e11..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wordpress.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/workboard.svg b/.claude/skills/logo-design/assets/library/svg/workboard.svg deleted file mode 100644 index 5b31146..0000000 --- a/.claude/skills/logo-design/assets/library/svg/workboard.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/workplace.svg b/.claude/skills/logo-design/assets/library/svg/workplace.svg deleted file mode 100644 index 327f857..0000000 --- a/.claude/skills/logo-design/assets/library/svg/workplace.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wpengine.svg b/.claude/skills/logo-design/assets/library/svg/wpengine.svg deleted file mode 100644 index fc48ab9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wpengine.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/wufoo.svg b/.claude/skills/logo-design/assets/library/svg/wufoo.svg deleted file mode 100644 index 13c0288..0000000 --- a/.claude/skills/logo-design/assets/library/svg/wufoo.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/xamarin.svg b/.claude/skills/logo-design/assets/library/svg/xamarin.svg deleted file mode 100644 index 90dd2e2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/xamarin.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/xampp.svg b/.claude/skills/logo-design/assets/library/svg/xampp.svg deleted file mode 100644 index ebcdf14..0000000 --- a/.claude/skills/logo-design/assets/library/svg/xampp.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/xcart.svg b/.claude/skills/logo-design/assets/library/svg/xcart.svg deleted file mode 100644 index 70c01cf..0000000 --- a/.claude/skills/logo-design/assets/library/svg/xcart.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/xero.svg b/.claude/skills/logo-design/assets/library/svg/xero.svg deleted file mode 100644 index f37c4ed..0000000 --- a/.claude/skills/logo-design/assets/library/svg/xero.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/xplenty.svg b/.claude/skills/logo-design/assets/library/svg/xplenty.svg deleted file mode 100644 index 75bb523..0000000 --- a/.claude/skills/logo-design/assets/library/svg/xplenty.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/xstate.svg b/.claude/skills/logo-design/assets/library/svg/xstate.svg deleted file mode 100644 index 8dc056f..0000000 --- a/.claude/skills/logo-design/assets/library/svg/xstate.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/xtend.svg b/.claude/skills/logo-design/assets/library/svg/xtend.svg deleted file mode 100644 index 7539069..0000000 --- a/.claude/skills/logo-design/assets/library/svg/xtend.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/xwiki-icon.svg b/.claude/skills/logo-design/assets/library/svg/xwiki-icon.svg deleted file mode 100644 index a449ff4..0000000 --- a/.claude/skills/logo-design/assets/library/svg/xwiki-icon.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/xwiki.svg b/.claude/skills/logo-design/assets/library/svg/xwiki.svg deleted file mode 100644 index 437b155..0000000 --- a/.claude/skills/logo-design/assets/library/svg/xwiki.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/yahoo.svg b/.claude/skills/logo-design/assets/library/svg/yahoo.svg deleted file mode 100644 index ec0f042..0000000 --- a/.claude/skills/logo-design/assets/library/svg/yahoo.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/yaml.svg b/.claude/skills/logo-design/assets/library/svg/yaml.svg deleted file mode 100644 index cf49df9..0000000 --- a/.claude/skills/logo-design/assets/library/svg/yaml.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/yammer.svg b/.claude/skills/logo-design/assets/library/svg/yammer.svg deleted file mode 100644 index 5d33243..0000000 --- a/.claude/skills/logo-design/assets/library/svg/yammer.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/yandex-ru.svg b/.claude/skills/logo-design/assets/library/svg/yandex-ru.svg deleted file mode 100644 index 0d4fa90..0000000 --- a/.claude/skills/logo-design/assets/library/svg/yandex-ru.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/yarn.svg b/.claude/skills/logo-design/assets/library/svg/yarn.svg deleted file mode 100644 index ab46e2d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/yarn.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/ycombinator.svg b/.claude/skills/logo-design/assets/library/svg/ycombinator.svg deleted file mode 100644 index 2c52df8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/ycombinator.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/yeoman.svg b/.claude/skills/logo-design/assets/library/svg/yeoman.svg deleted file mode 100644 index 90961c3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/yeoman.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/yii.svg b/.claude/skills/logo-design/assets/library/svg/yii.svg deleted file mode 100644 index b5d3a8c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/yii.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/youtrack.svg b/.claude/skills/logo-design/assets/library/svg/youtrack.svg deleted file mode 100644 index ce7d666..0000000 --- a/.claude/skills/logo-design/assets/library/svg/youtrack.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/youtube-icon.svg b/.claude/skills/logo-design/assets/library/svg/youtube-icon.svg deleted file mode 100644 index b0602b6..0000000 --- a/.claude/skills/logo-design/assets/library/svg/youtube-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/youtube.svg b/.claude/skills/logo-design/assets/library/svg/youtube.svg deleted file mode 100644 index b995211..0000000 --- a/.claude/skills/logo-design/assets/library/svg/youtube.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zapier-icon.svg b/.claude/skills/logo-design/assets/library/svg/zapier-icon.svg deleted file mode 100644 index 4f116a2..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zapier-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zapier.svg b/.claude/skills/logo-design/assets/library/svg/zapier.svg deleted file mode 100644 index 17f9f64..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zapier.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zend-framework.svg b/.claude/skills/logo-design/assets/library/svg/zend-framework.svg deleted file mode 100644 index 941c37d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zend-framework.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zendesk-icon.svg b/.claude/skills/logo-design/assets/library/svg/zendesk-icon.svg deleted file mode 100644 index 79eac75..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zendesk-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zendesk.svg b/.claude/skills/logo-design/assets/library/svg/zendesk.svg deleted file mode 100644 index ab7beb7..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zendesk.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zenhub-icon.svg b/.claude/skills/logo-design/assets/library/svg/zenhub-icon.svg deleted file mode 100644 index 4071a19..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zenhub-icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zenhub.svg b/.claude/skills/logo-design/assets/library/svg/zenhub.svg deleted file mode 100644 index 16211d3..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zenhub.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zeplin.svg b/.claude/skills/logo-design/assets/library/svg/zeplin.svg deleted file mode 100644 index 8362590..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zeplin.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zoho.svg b/.claude/skills/logo-design/assets/library/svg/zoho.svg deleted file mode 100644 index 5091c9a..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zoho.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zorin-os.svg b/.claude/skills/logo-design/assets/library/svg/zorin-os.svg deleted file mode 100644 index 2652b4c..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zorin-os.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zube.svg b/.claude/skills/logo-design/assets/library/svg/zube.svg deleted file mode 100644 index 090b80b..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zube.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zulip-icon.svg b/.claude/skills/logo-design/assets/library/svg/zulip-icon.svg deleted file mode 100644 index f63aa9d..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zulip-icon.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zulip.svg b/.claude/skills/logo-design/assets/library/svg/zulip.svg deleted file mode 100644 index 7083060..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zulip.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/assets/library/svg/zwave.svg b/.claude/skills/logo-design/assets/library/svg/zwave.svg deleted file mode 100644 index 951fbc8..0000000 --- a/.claude/skills/logo-design/assets/library/svg/zwave.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.claude/skills/logo-design/references/color.md b/.claude/skills/logo-design/references/color.md deleted file mode 100644 index 0f7a4a5..0000000 --- a/.claude/skills/logo-design/references/color.md +++ /dev/null @@ -1,142 +0,0 @@ -# Colour - -Colour is the second memory hook after shape, the most basic form of non-verbal communication, and one of -the few things a brand can truly *own*. But it is secondary to form: design in black first, add colour after -the concept is chosen. - -## Contents -1. Order of operations -2. Associations (and their limits) -3. Owning a colour -4. Harmony systems -5. How many colours? -6. Practical reproduction (RGB, CMYK, Pantone, HEX) -7. Accessibility and contrast -8. Library data -9. Palette specification template - ---- - -## 1. Order of operations - -1. **Design in black and white.** A mark that only works because of its colours is not yet a mark. Monochrome - exposes form problems and forces the concept to stand on shape. -2. **Present concepts in greyscale first** so reactions are about the idea, not about a colour someone dislikes. -3. **Choose colour after the direction is selected** — research competitor colours and deliberately avoid their - palette unless there is a strategic reason. -4. **Specify every version**: full colour, one colour, black, white/reversed, and on the primary brand colour. - -## 2. Associations (and their limits) - -Common Western associations — useful as a starting vocabulary, never as a rule: - -| Colour | Frequently associated with | Watch out for | -|---|---|---| -| Red | energy, passion, boldness, urgency, appetite, leadership | danger, debt/loss (finance), aggression | -| Orange | friendliness, enthusiasm, playfulness, affordability, confidence | cheapness if overused; low contrast on white | -| Yellow | optimism, warmth, attention, originality, cheer | illegible on white; caution/warning | -| Green | growth, health, nature, balance, renewal, money (US) | "eco" cliché; hard in process print when vivid | -| Blue | trust, stability, calm, integrity, technology, loyalty | the default of tech, finance and healthcare — hard to stand out | -| Purple | creativity, imagination, wisdom, luxury, individuality | can feel immature or mystical | -| Pink | care, playfulness, youth, sweetness, boldness (hot pinks) | gender stereotypes | -| Black / grey | authority, sophistication, neutrality, strength, mystery | can feel cold, heavy or generic | -| White | purity, simplicity, space | mourning in parts of East Asia | -| Brown / earth | craft, reliability, warmth, organic | dullness; "you can't build equity in beige" | - -- **Culture changes meaning.** White is purity in much of Europe and mourning in parts of East Asia; red is luck and - celebration in China, danger in signage, and taboo for losses in financial reporting; green has religious - significance in some regions. Check the audience's cultures. -- **Learned conventions**: red = stop, green = go, blue links on screens, yellow/black = hazard. Use knowingly. -- **Personal memory** attaches emotions to colours unpredictably — another reason to anchor decisions in strategy, - not taste. -- **Demographic tendencies** (e.g. children's brands trending colourful and saturated) are only tendencies; a brand - strategy can deliberately contradict them. - -## 3. Owning a colour - -- Owning a colour is one of the highest priorities of an identity — a signature colour, used consistently across - every touchpoint, becomes recognisable even without the mark. -- **Subverting category norms makes a colour proprietary.** When every competitor is blue, a red, orange or green - brand is instantly distinguishable. A colour swap experiment makes the point: put a competitor's colours on a - famous logo and it immediately feels like a different company. -- Keep existing colour equity during redesigns unless there is a strong reason to drop it — colour is often what the - public remembers most. -- Pair a signature colour with a neutral (black, white, a dark tone) to give it room. - -## 4. Harmony systems - -Use the colour wheel as a generator, then refine by eye: -- **Complementary** — opposites (red/green, blue/orange, yellow/purple). High contrast, energetic; familiar, can feel - obvious. Shift hues slightly off the exact complement for sophistication. -- **Split-complementary** — a base plus the two neighbours of its complement. Contrast with less tension. -- **Analogous** — neighbours on the wheel. Calm, cohesive; needs value contrast to stay legible. -- **Triadic / tetradic** — rotate a triangle or rectangle on the wheel; vivid, playful, good for multi-colour - systems. Balance by letting one colour dominate. -- **Monochromatic** — one hue in several tints/shades. Elegant; relies on value contrast. -- Think in **hue, saturation, value**: most palette problems are value problems (two colours of similar lightness - blur together, especially in greyscale or for colour-blind viewers). - -## 5. How many colours? - -- The fewer the colours, the stronger the recall and the easier the reproduction. One or two colours is the sweet - spot for most marks; three is common; beyond four, colours must be justified by concept (e.g. a multi-product or - "diversity" story) and the mark must still work in one colour. -- Multi-colour marks: give each colour a role (segments of an idea, a sequence, a hierarchy), keep saturation and - value families consistent, and provide a single-colour fallback. -- Secondary palette: 3–5 complementary colours for the wider identity, used sparingly (accents often ≈ 5–10 % of a - layout) so the primary stays dominant. - -## 6. Practical reproduction - -- **Specify all four systems** for every brand colour: HEX (web), RGB (screen), CMYK (process print), and a Pantone - / spot equivalent for premium print. Whole-number CMYK percentages are cleaner to hand to printers. -- **RGB ≠ print.** Neon, saturated greens, electric blues and bright oranges can fall outside the CMYK gamut and print - dull. Check the CMYK conversion early; choose a spot colour if the signature colour must be vivid on paper. -- **Gradients**: see `visual-techniques.md` — keep a flat master. -- **Materials**: embroidery thread, vinyl, enamel, neon, laser-etched metal each shift colour; one-colour and - two-colour versions keep production affordable (screen printing charges per colour). -- **Dark mode / dark backgrounds**: the brand colour may need a lighter tint to keep contrast on dark UI; specify it. - -## 7. Accessibility and contrast - -- Test colour pairs for contrast. For logos, WCAG does not strictly apply, but any text within the lockup (and taglines) - should aim for at least **3 : 1** against its background; body-size text needs 4.5 : 1. -- Don't encode meaning in colour alone (red vs green segments may be indistinguishable to ~8 % of men). Check a - greyscale version: segments should still separate by value. -- Yellow, light cyan and pale pastels on white fail contrast; give them a dark companion or a dark version. - -## 8. Library data (1,400+ real-world logos) - -The bundled library skews heavily to technology brands, so treat these as *category conventions to be aware of*, -not recommendations: - -- **Colour count** (counting black/white when used): 1 colour ≈ 33 %, 2 colours ≈ 25 %, 3 colours ≈ 17 % — - **≈ 75 % of logos use three colours or fewer**. Among standalone icons, **≈ 47 % are a single colour** and - **≈ 82 % use three or fewer**. -- **Gradients** appear in ≈ 19 % of files — a minority, and mostly in digital-native brands. -- **Dominant single hue** among single-hue marks: blue is by far the most common (≈ 22 % of all logos), then red - (≈ 13 %) and black/grey monochrome (≈ 13 %); green, orange, cyan and purple follow at 4–7 % each; yellow and pink - are rare (≈ 2 % and ≈ 1 %). ≈ 28 % of logos are multi-hued. -- **Implication**: in tech, blue is the camouflage colour. A non-blue signature colour is an easy win for - distinction; if blue is strategically necessary, differentiate by hue shift (ultramarine, teal, periwinkle), - pairing, or form. - -Explore by colour: `python3 scripts/search_library.py --color orange --type pictorial --format table`. - -## 9. Palette specification template - -```markdown -### Primary -| Name | HEX | RGB | CMYK | Pantone (approx.) | Use | -|---|---|---|---|---|---| -| Harbor Teal | #0F7C80 | 15 124 128 | 88 23 44 5 | 7714 C | Logo, key UI, headings | -| Ink | #14212B | 20 33 43 | 83 67 49 64 | Black 7 C | Type, one-colour logo | - -### Secondary (≈ 10–20 % of any layout) -| Sand | #F2E6D0 | … | Backgrounds | -| Signal Coral | #FF6B4A | … | Accents, calls to action (sparingly) | - -### Logo colour versions -Full colour on white · Reversed (white) on Harbor Teal / Ink · One-colour Ink · One-colour white -``` -(Pantone matches are approximations — verify against a physical guide before print production.) diff --git a/.claude/skills/logo-design/references/critique.md b/.claude/skills/logo-design/references/critique.md deleted file mode 100644 index b1f9f41..0000000 --- a/.claude/skills/logo-design/references/critique.md +++ /dev/null @@ -1,66 +0,0 @@ -# Critiquing a Logo - -Use when the user asks for feedback on a logo (theirs or anyone's), wants to compare options, or needs a diagnosis -before a redesign. Be specific, kind and useful: name what works, what doesn't, why, and exactly how to fix it. - -## Method - -1. **Understand the context first** — what the organisation does, for whom, what it should feel like. A logo can only - be judged against its purpose. If unknown, ask one question or state assumptions. -2. **First impression (2 seconds)** — what do you see, feel, and remember? What would a stranger call it? -3. **Technical pass** — if an SVG is available, run `scripts/svg_audit.py` and `scripts/preview_sheet.py`, then look at - the preview. For a raster image, reason visually about the same checks. -4. **Principles pass** — score each dimension below 1–5 with one-line evidence. -5. **Prioritise** — the 3 changes with the biggest impact, most important first. Make each actionable. -6. **Optionally demonstrate** — sketch the fix as an SVG revision when the user wants it. - -## Scorecard - -| Dimension | Question | Score (1–5) | Evidence | -|---|---|---|---| -| Idea | Is there one clear, relevant idea? Can it be said in a sentence? | | | -| Simplicity | Is anything unnecessary? Does it survive 16 px and a squint? | | | -| Distinction | Does it stand apart from competitors and famous marks? | | | -| Memorability | Is there one defining feature you'd recall tomorrow? | | | -| Relevance / tone | Does its character (shape, weight, colour, type) match the brand? | | | -| Craft | Clean geometry, optical corrections, consistent weights, good spacing/kerning? | | | -| Versatility | One colour, reversed, small, large, embroidery, app icon, lockups? | | | -| Longevity | Conceptual rather than trendy? Will it date soon? | | | -| Colour | Few, purposeful, ownable, accessible, reproducible? | | | -| Typography | Appropriate, customised, legible, well spaced, ≤ 2 families? | | | - -Total /50 is a rough guide only; one fatal flaw (illegible at small size, looks like a competitor, offensive reading) -outweighs a high total. - -## Common diagnoses and fixes - -| Symptom | Likely cause | Fix | -|---|---|---| -| Turns to mush at small sizes | Too many elements, thin lines, small gaps | Remove details, thicken strokes, open gaps; make a small-size version | -| Looks generic / like a template | Stock typeface, cliché symbol (globe, swoosh, lightbulb) | Customise letters, find an ownable twist, derive the idea from the name or promise | -| Looks dated | Effects (gradients, bevels, shadows), trendy fonts | Flatten, simplify, choose a more timeless type direction | -| Busy | Two or three ideas competing | Pick one idea; move the others into the identity system | -| Symbol and type feel unrelated | Different geometry/weight logic | Share radii, stroke weights, angles; rebalance sizes | -| Feels unstable | Accidental tilt, top-heavy mass | Widen the base, correct axes, check optical centre | -| Circle looks small next to letters | Missing overshoot | Enlarge round forms 1–3 % | -| Rounded rectangle looks pinched | Bone effect | Smooth curvature transitions | -| Reversed version looks bold | Irradiation | Thin the white version slightly | -| Fails on photos | No graphic device | Add an outline/container version | -| Hidden meaning nobody sees | Too subtle or too complex | Make it a bonus, not the point — or simplify until it reads | -| Unfortunate reading | Designer blindness after long exposure | Change the offending shape; test with fresh eyes | - -## Output format - -```markdown -## Logo critique — -**First impression:** <1–2 sentences> -**What works:** <2–3 bullets> -**Scorecard:**
    -**Top 3 changes (in priority order):** -1. — why, and how (specific: "open the counter of the e from 6 to 12 units") -2. … -3. … -**Optional next step:** -``` - -Tone: critique the work, never the person. Balance honesty with encouragement; the goal is a better mark. diff --git a/.claude/skills/logo-design/references/discovery-brief.md b/.claude/skills/logo-design/references/discovery-brief.md deleted file mode 100644 index 7450914..0000000 --- a/.claude/skills/logo-design/references/discovery-brief.md +++ /dev/null @@ -1,187 +0,0 @@ -# Discovery & the Design Brief - -Design is a strategic response to a business need, not decoration. Without clarity about the need, the work -lacks direction no matter how beautiful it is. This file covers how to gather that clarity quickly and turn it -into a brief that anchors every later decision. - -## Contents -1. Why discovery first -2. The fast path (when the user wants speed) -3. The full question bank -4. Research you do yourself -5. From answers to a brief (template) -6. Word mapping — turning language into symbols -7. Warning signs in a brief - ---- - -## 1. Why discovery first - -- Uncover and define the problem before attempting to solve it visually. Rushing into drawing raises the odds - of missing the mark, and a missed mark is expensive for everyone. -- The brief is a *contract of clarity*: a shared, written record of what success looks like. When - disagreements come (they will), return to the brief instead of arguing taste. That doesn't mean never - adjusting — it means adjustments are purposeful, not arbitrary. -- A strong brief doesn't constrain creativity; it channels it. -- The designer is hired as the expert who guides, creates and solves — not as a technician executing a - pre-drawn idea. If a client already has the exact design in mind, clarify the relationship early and honestly. - ---- - -## 2. The fast path (when the user wants speed) - -Ask **at most five** questions in one message, then proceed. If the user can't or won't answer, infer sensible -answers, **state your assumptions explicitly**, and continue — you can revise after they react to concepts. - -1. **Name & what you do** — exact spelling/casing of the name, one-line description, and any tagline. -2. **Audience** — who must notice and trust this (age, profession, mindset)? Where will they meet the logo? -3. **Three to five adjectives** the brand should feel like (e.g. calm, precise, rebellious, warm, premium). - Adjectives are the single most useful input for concepting. -4. **Competitors or look-alikes to avoid** — and any marks the user admires (and why). -5. **Constraints** — colours to keep/avoid, existing equity to preserve, where it must work (app icon, - embroidery, signage, favicon), deadline for decisions. - -Optional sixth when relevant: *Who makes the final decision?* (Always know who signs off.) - ---- - -## 3. The full question bank - -Use for substantial projects. Every business is different — adapt, don't recite. Allow time for answers; -off-topic remarks often open new avenues, but keep the conversation focused on outcomes. - -### The essential four -- Who are you? -- Who needs to know? -- How will they find out? -- Why should they care? - -### The business -- **Positioning** — compared with alternatives, where do you sit? What is your price point? How big is the - business and where is it heading (projected scale gives context for positioning)? -- **Purpose & mission** — beyond the economics, why is this worth doing? -- **Composition** — how is the organisation structured (parent/sub-brands, divisions, products)? -- **Culture** — what shared behaviours best express the mission? -- **Personality** — what style and manner? If the brand were a person, how would they speak and dress? -- **Goals** — five key goals over the next year / five years. -- **Growth** — where are the biggest opportunities for the business and its image? -- **Promises** — what does the organisation promise its audiences? (Promises synthesise what it stands for.) - -### The audience -- **Current audience** — who, where, when, why? -- **Desired audience** — a different or wider group? Demographics (age, gender, nationality, profession) - and psychographics (values, lifestyle). -- **Current perception** — how does the audience see the brand today? -- **Desired perception** — how should they see it? -- **Desired response** — what should they feel, think or do after encountering the brand? - -### The competition -- Who are the main competitors? How are you different? What visual cues, colours and typefaces dominate the - category? What marketing is gaining traction? - -### The project -- What are the goals for the new identity? What specific deliverables are needed? -- Why now? What's motivating the project and driving the timeline? -- Who is involved, with what roles? Any outside agencies or partners? -- What concerns or obstacles do you anticipate? Anything in the culture, structure or past experiences that - could make this easier or harder? -- Budget range? Are other designers being considered, and when will a decision be made? -- **Who makes the final decision?** Involve that person when presenting. -- Existing equity: current logo, colours, symbols people already recognise? What must survive a redesign? -- Applications: where will it appear first — and where might it appear in five years? Any production - constraints (embossing dies, embroidery, laser etching, signage regulations, single-colour printing)? -- Naming: is the name final? Is there a shorter name people already use? (A nickname the public already - uses can be a stronger communicative name than the legal one.) - -### After gathering answers, ask yourself -- What are the client's real concerns? -- What does the organisation want to emphasise? -- What is it *really* selling? (A tap sells convenience and kitchen pride; a gym sells confidence.) -- How does it want to be perceived in the market? Stylish identities win awards; relevant ones win market share. - ---- - -## 4. Research you do yourself - -- **The organisation's history**, its current identity, past identity efforts and how they shaped perception. - Previous logos often reveal useful patterns or pitfalls. -- **The competitive landscape**: collect competitor marks, note colours, shapes, type, and what they all share. - Map them (e.g. on axes like *traditional ↔ modern*, *playful ↔ serious*) to find open territory. -- **Category conventions** via the bundled library. Examples: - ```bash - python3 scripts/search_library.py --industry payments-fintech --format table - python3 scripts/search_library.py --subject shield --format table - python3 scripts/search_library.py --industry database-data --summary - ``` - `--summary` shows the dominant mark types, colours and techniques in a category — i.e. what to avoid - repeating and what cues signal "belonging". -- **Cultural checks**: meanings of candidate colours, symbols and gestures in the audience's cultures; - whether a symbol is sacred or owned by a community. -- **Name mechanics**: letter shapes (which letters have rich structure for a monogram — `a`, `s`, `w`, `g`, `k` - combine well; `i`, `l` offer little), ligature opportunities, symmetry, how the word sounds spoken. - ---- - -## 5. From answers to a brief (template) - -Write this before designing and show it to the user. Keep it short, jargon-free and specific — designers -must be editors too. - -```markdown -## Design brief — - -**Summary**: -**Audience**: -**Brand adjectives**: <3–5 words> **Avoid feeling**: <2–3 words> -**Promise / big idea**: -**Competitive landscape**: -**Mark type hypothesis**: (see mark-types.md) -**Must work on**: -**Constraints**: -**Success criteria**: -**Decision-maker**: **Deliverables**: -**Assumptions I made**: -``` - ---- - -## 6. Word mapping — turning language into symbols - -Good designers translate language into symbols. A word map bridges strategy and form. - -1. Write the core words: the name, the offering, the adjectives, the promise. -2. Branch from each word into **nouns** (things you can draw), then into associations, metaphors, opposites, - sounds, places, materials, processes, historical references. -3. Circle the intersections — where two branches meet is where distinctive ideas live (e.g. "trust" → shield; - name begins with T → a T that is also a shield; the name's meaning is a woodworking joint → precise fit). -4. Turn the best 6–10 intersections into one-sentence concept statements before drawing anything. - -Example (abridged): -``` -Brand: "Harbor" — a savings app. Adjectives: safe, calm, patient. - harbor → boat, anchor, lighthouse, breakwater, shelter, bay-shape, tide - safe → shield, lock, nest, roof, cupped hands, enclosure - calm → horizon line, still water, circle, slow wave - patient→ growth rings, stacking, tide rising, sunrise -Intersections: - • An "H" whose crossbar is a calm horizon/water line - • Stacked horizontal waves forming a rising bar chart (tide = growth) - • A bay-shaped enclosure (negative space) that shelters a coin -``` - -If neither the name nor the activity offers visual clues, use abstract keywords that do translate to form: -*connection, speed, unity, network, care, stability, balance, growth, openness, precision*. - ---- - -## 7. Warning signs in a brief - -- **"Total creative freedom."** Usually means the client has no vision and expects the designer to supply one - — which takes many more rounds. Ask for stylistic references (marks they like/dislike and why) to calibrate. -- **"It should show everything we do."** Explain *identify, don't explain*; offer a system (icons, imagery, - copy) to carry the detail instead of the mark. -- **"Make it pop / modern / clean."** Ask what those words mean to them; show references. -- **No decision-maker identified.** Presentations to the wrong person get re-litigated later. -- **The real problem isn't the logo.** If the product, service or message is broken, say so; a logo won't fix it. -- **Design by committee.** Plan to present to the smallest group that includes the decision-maker; many voices - produce an illusion of consensus and averaged, forgettable marks. See `presentation-delivery.md`. diff --git a/.claude/skills/logo-design/references/identity-system.md b/.claude/skills/logo-design/references/identity-system.md deleted file mode 100644 index 4179d3b..0000000 --- a/.claude/skills/logo-design/references/identity-system.md +++ /dev/null @@ -1,146 +0,0 @@ -# From Logo to Identity System - -A logo is the foundation; the identity system is the framing built on it. The audience never meets a logo in a -void — always on a card, a van, a screen, a building, next to photography and words. Read this when the user needs -more than a mark: a kit of parts, sub-brands, patterns, a dynamic identity, motion, or guidelines. - -## Contents -1. Principles of a system -2. The kit of parts (checklist) -3. Logo systems and sub-brands -4. Static vs. changeable (dynamic) identities -5. Patterns and graphic devices -6. Motion and sound -7. Standards manual / brand guidelines -8. Rollout and stewardship - ---- - -## 1. Principles of a system - -- **Consistency of concept** — every element (visual and verbal) identifies the organisation to its audiences. - Consistency is central to branding; it doesn't preclude creativity. A predictable, lifeless system fails; power, - clarity and freshness must accompany consistency. -- **Clarity of message** — every element supports the logo and the intended perception; nothing competes with it. -- **Derived, not duplicated** — the system grows *from* the mark (its angles, radii, colours, a fragment) but - complements rather than copies it. -- **Accommodate the user** — understand who will use the system (in-house designers, agencies, printers, franchisees, - developers) and how; make it customisable within constraints. -- **Flexibility** — other creatives will use it; plan enough variables to keep it fresh, and make it damage-proof so - imperfect use still looks on-brand. At some point the original designer must let go; good rules make that safe. - -## 2. The kit of parts (checklist) - -**Logo & variations** -- Primary mark/signature (symbol + wordmark) and variations: horizontal, stacked, symbol-only, wordmark-only. -- Size variants: a simplified small-size version; redrawn details for very large use if needed. -- Media variants: e.g. heavier line weights for broadcast/screen, single-colour for embroidery. -- Brand extensions and product logos; relationship with partner or trademark symbols. - -**Colour palettes** -- Primary colour(s) and acceptable alternatives; black/white usage; can it be reversed, or reversed only out of a - containing shape? Exact Pantone, CMYK, RGB, HEX values. Secondary/accent palette. - -**Typography** -- Primary and secondary families, weights, italics; web/app fallbacks; rules for headlines vs body. - -**Taglines and modifying copy** -- Primary and alternative taglines, typeface, size ratio to the logo, legal lines, ™/® usage. - -**Imagery** -- Photography/illustration style, when and how used, ratio and proximity to the logo, image library access. - -**Containing shapes / graphic devices** -- Is the logo ever placed in a shape? Always or only in some contexts? Does the shape change? Can it hold other - content? - -**Patterns, icons, textures** -- Brand pattern(s), icon set built on the logo's geometry, supporting graphic elements. - -**Motion and sound** (screen, broadcast, product) -- How the logo moves and resolves; how it interacts with other elements; sonic signature if relevant. - -**Voice** -- Editorial tone — part of the identity even though it isn't visual. - -## 3. Logo systems and sub-brands - -- **Branded house**: one master mark; sub-brands expressed by descriptor text, colour, or a consistent modifier. - Maximum equity transfer, least flexibility. -- **Endorsed brands**: each sub-brand has its own mark with a visible link to the parent ("by Parent"), or shares a - structural element (frame, typeface, icon grid). -- **House of brands**: independent marks; the parent is invisible to consumers. -- Decide on hierarchy deliberately: is association with the parent an advantage or a liability for the product? - If association would position the product badly, that's a strategy problem to solve before any design. -- Keep repeated elements truly consistent (same typeface, same symbol proportions, same spacing rules); vary one - dimension at a time (colour *or* icon *or* descriptor). - -## 4. Static vs. changeable (dynamic) identities - -- A logo must provide a cohesive voice, but it need not be immutable. Screen media expects logos to move, react and - sometimes change. Someone will make it spin — better that the designer defines how. -- Dynamic identity patterns: - - **Fixed frame, changing content** — a container or grid that holds changing images, colours or patterns. - - **Fixed type, changing symbol** — consistent letterforms and colour; the accompanying shape varies per - application. - - **Approved sets** — e.g. a square of colour from 12 approved colours with the name set in one of 12 approved - typefaces; users combine freely within the sets. - - **Generative** — a rule (data, date, location, user input) that produces variants. - - **Many logos, one voice** — several marks used discreetly for sophisticated audiences who are weary of loud - branding; recognition comes from consistent attitude rather than one symbol. -- Whatever changes, keep at least two anchors constant (e.g. name typography + colour, or frame + position). -- The action of the logo must reinforce the concept; motion for its own sake dilutes it. - -## 5. Patterns and graphic devices - -- A pattern is often the most important branding element after the logo. It must complement the mark without - duplicating it and work from a business card to an aircraft, in signage and interiors. -- Build from components of the mark when possible (a fragment, the construction grid, the key angle); if the mark - offers nothing, develop a new visual language on par with or deliberately contrasting the logo. -- Grid choice drives character: square (versatile, common), triangular, hexagonal, rotated; see - `visual-techniques.md` §13. -- Graphic devices (containers, outlines, bands, frames) solve visibility on busy backgrounds and create recognisable - layouts; keep their proportions in sync with the logo's. - -## 6. Motion and sound - -- Define: entrance (how it builds), resolve (final static state, which must equal the master), exit, loop; duration - (logo stings are typically 1–3 s); easing character matching the brand (snappy vs. gentle). -- Build motion from the logo's construction (strokes drawing on, modules assembling, a rotation that reveals a - negative shape). -- Sound signature for broadcast/apps: short, ownable, consistent; specify when it plays. - -## 7. Standards manual / brand guidelines - -Useful to the widest group of users (in-house designers, agencies, PR, marketing, printers, signage fabricators, -packaging, vehicle and uniform suppliers, purchasing). Written in plain language for non-designers. Prefer friendly -rules and more "do"s than "don't"s. - -**Suggested anatomy** (scale down for a start-up; a one-page sheet can be enough): -1. **Introduction** — a short letter from leadership (drives buy-in), the brand idea, how to use the manual. -2. **Logo** — the mark and its rationale; versions and lockups; construction; **clear space** (defined by an element - of the logo, e.g. the height of the symbol's dot or the cap height, so it scales — never a fixed distance); - **minimum sizes** (px and mm); placement; logo on backgrounds (black on white, white on black, colour, photo); - **misuse** examples (stretching, recolouring, rotating, adding effects, rearranging lockups, outlining, placing on - busy backgrounds without a device). -3. **Colour** — primary and secondary palettes with all colour codes; proportions; approved logo/background pairs. -4. **Typography** — families, hierarchy, spacing; kerning of the wordmark at large sizes if relevant. -5. **Imagery, iconography, patterns, graphic devices** — rules and examples. -6. **Grids and layouts** — margins and gutters chosen deliberately (square-ish modules are the most versatile). -7. **Applications** — stationery (business cards: clean front with name, title, contact; pattern or colour on the back; - letterhead: nothing printed on the back), digital (web, social avatars, email signatures), signage, vehicles, - uniforms, packaging, advertising, merchandise. -8. **Motion and sound** if relevant. -9. **Contacts and files** — who to ask, where the master files live. - -Template for a compact guideline: `templates/brand-guidelines-template.md`. - -## 8. Rollout and stewardship - -- **Rollout**: plan the order of applications (digital first is cheap; signage and vehicles are expensive), supervise - early production (printing, fabrication), and coordinate with in-house teams and outside agencies. -- **Asset management**: one source of truth for master files, named clearly, accessible to all users. -- **Audit periodically** (monthly → quarterly → yearly after launch): review materials for consistency, production - quality and supplier compliance; interview users about friction; adapt the system to new needs; track changes in - the competitive landscape; report findings and celebrate good applications. A system that is never reviewed - decays within a year. diff --git a/.claude/skills/logo-design/references/library-guide.md b/.claude/skills/logo-design/references/library-guide.md deleted file mode 100644 index 7789e34..0000000 --- a/.claude/skills/logo-design/references/library-guide.md +++ /dev/null @@ -1,164 +0,0 @@ -# The Reference Library — Guide & Insights - -The skill ships with **1,400+ real-world SVG logos** (≈1,200 brands; 233 brands include both a full lockup and a -standalone `-icon` symbol), each visually classified by mark type, technique, geometry, subject, typography, mood and -industry. Use it to learn *how* marks are built and to see what a category already looks like. - -> **The logos are trademarks of their respective owners.** They are included only as study material. -> Never copy, trace or lightly modify them for a client. If your concept resembles one, change it. - -## Contents -1. What's inside & where -2. How to use it well -3. Data-driven insights -4. Curated lessons by technique (with example files) -5. Catalog schema & extending the library - ---- - -## 1. What's inside & where - -``` -assets/library/ - svg/ 1,400+ logo files (brand.svg = full logo, brand-icon.svg = standalone symbol) - catalog.json one record per file: structure + colours + complexity + visual classification - classifications.json the visual labels (source of truth for mark_type, techniques, subject, …) - stats.json distributions used by svg_audit.py (anchors, colours, types …) - gallery.html filterable visual browser for humans — open locally in a browser -``` -The collection skews heavily to technology brands (developer tools 21 %, frameworks/libraries 17 %, cloud 7 %, -databases 6 %, testing/monitoring 6 %…). Keep that bias in mind: its conventions are *tech* conventions. -Categories such as food & drink, fashion, hospitality, health or public services are barely represented: for those, -use `--subject`/`--query` to find marks that share a subject or technique (cups, leaves, arches, letter K…), build -the shelf test from hand-picked files with `preview_sheet.py --refs …`, and rely on your own knowledge of the -category's conventions. - -## 2. How to use it well - -- **Study a technique before using it**: pull 5–8 exemplary files and *read the SVG* to see how the geometry is - built (how few anchors, which primitives, how negative space is cut): - `python3 scripts/search_library.py --technique negative-space --exemplary --format paths` -- **Map a category's conventions** before designing, then decide where to conform and where to depart: - `python3 scripts/search_library.py --industry security-identity --summary` -- **Check your idea isn't already taken**: `python3 scripts/search_library.py --subject "rocket"` -- **Shelf test your concept** against real marks: - `python3 scripts/preview_sheet.py concept.svg --refs-industry developer-tools -o shelf.html` -- **Calibrate complexity**: `svg_audit.py` compares your anchor count and colour count with the library. -- For inspiration by feel: `--mood friendly`, `--mood technical`, `--type-style serif`, `--case lowercase`. - -Useful filters: `--type`, `--symbol-type`, `--technique`, `--geometry`, `--industry`, `--color`, `--primary-color`, -`--max-colors`, `--aspect`, `--variant icon`, `--type-style`, `--case`, `--mood`, `--subject`, `--query`, -`--exemplary`, `--no-gradient`, `--summary`, `--list-values`. - -## 3. Data-driven insights - -**Mark types (per file)** — abstract 23.5 %, combination 20.6 %, pictorial 20.2 %, letterform 15.2 %, wordmark 9.9 %, -emblem 3.8 %, mascot 3.8 %, lettermark 3.0 %. (Standalone icon files inflate symbol types.) -Inside combination marks, the symbol is abstract 43 %, pictorial 33 %, letterform 17 %, mascot 5 %. - -**Proportions** — 55 % of files are near-square (0.8–1.25 : 1). Of brands with both files, ~9 in 10 lockups are wide -(> 2.5 : 1) and ~3 in 4 icons are near-square: symbol + horizontal lockup is the standard pair. - -**Colour** — median 2 colours; ≈ 75 % use ≤ 3; ≈ 47 % of standalone icons are single-colour. Gradients in ≈ 19 % of -files. Dominant hue: blue ≈ 22 %, red ≈ 13 %, monochrome ≈ 13 %, multi-hue ≈ 28 %; yellow and pink are rare. -→ In tech, blue is camouflage; warm or unusual hues are an easy distinction win. - -**Geometry** — circle is the most common base (26 %), then organic (14 %), square (14 %), freeform (13 %), -triangle (8 %), hexagon (8 %; 10 % among developer/cloud/data brands — a category cliché), rounded square (7 %). - -**Techniques** — containment 32 %, negative space 20 %, monoline 17 %, colour segments 14 %, dimensional shading 10 %, -geometric construction 9 %, modular repetition 7.5 %, overlap/transparency 7 %, hidden meaning 7 %, isometric 6 %, -radial symmetry 6 %, letter substitution 3 %. -→ Containing a symbol in a circle/square is the most common move — useful for app icons, but also generic. Negative -space and hidden meaning appear in most of the strongest (exemplary) marks. - -**Typography (541 files containing type)** — geometric sans 49 %, custom/display 19 %, grotesque 13 %, humanist 8 %, -script 5 %, serif 3 %, slab 1 %, rounded 1 %. Case: lowercase 36 %, uppercase 32 %, title 20 %, mixed 13 %. -→ Lowercase geometric sans is the tech default; a serif, slab, humanist or truly custom wordmark stands out. - -**Complexity** — square symbols have a median of ~53 anchor points (p75 ≈ 96, p90 ≈ 194). The exemplary marks cluster -at the low end: great marks are built from few, deliberate points. - -**Mood labels** most used — technical, friendly, bold, modern, playful. "Friendly" is almost always carried by rounded -geometry and lowercase; "technical" by monoline, grids, brackets, isometric forms. - -## 4. Curated lessons by technique (with example files) - -Every file below is in `assets/library/svg/`. Read them as SVG to study construction. - -**Negative space** — figure and ground both carry meaning. -- `auth0-icon.svg` star carved from a shield · `apache-camel.svg` camel cut from a circle · `doctrine.svg` arrow cut - from a teardrop · `esdoc.svg` owl face entirely from negative space · `houndci.svg` dog profile in a square · - `npm-icon.svg` letter carved from a solid square · `khan_academy-icon.svg` sprout that reads as a person. - -**Hidden meaning / double reading** — one form, two ideas. -- `airbnb.svg` one loop = pin + heart + A · `amplitude-icon.svg` A = sound wave · `astro.svg` A = rocket · - `gnome-icon.svg` footprint = G · `spidermonkey-icon.svg` monkey = S · `kissmetrics.svg` heart + bar chart · - `botanalytics.svg` speech-bubble edge = chart line · `twitch.svg` speech bubble with eyes. - -**Letter substitution & custom wordmarks** — make a name ownable. -- `hubspot.svg` sprocket as the "o" · `fastly.svg` stopwatch in a letter · `tor.svg` onion as "o" · `sparkpost.svg` - flame for "O" · `mozilla.svg` URL syntax in the name · `100tb.svg` double zero as infinity · `adyen.svg` fully - custom squared letters · `nextjs.svg` extended X stroke · `go.svg` italic + speed lines · `stripe.svg` tight custom - lowercase. - -**Letterform symbols** — one letter, one idea. -- `kotlin-icon.svg` K from one triangular cut · `patreon.svg` P = bar + circle · `pagekit.svg` P from a notched square · - `gatsby.svg` G from circle + diagonal · `pinterest.svg` P as a pin · `zendesk-icon.svg` Z from triangles and - semicircles · `mesos.svg` M from triangles · `metabase.svg` M from a dot grid · `mobx.svg` `]v[` reads as M. - -**Geometric construction** — primitives, consistent radii, clean angles. -- `elm.svg` tangram square · `framer.svg` squares and triangles · `google-photos.svg` four half-circles · - `circleci.svg` notched ring · `vercel-icon.svg` a single triangle · `twitter.svg` bird from circle arcs · - `buck.svg` monoline deer from strict geometry · `tsuru.svg` origami crane · `figma.svg` modular circles. - -**Modular repetition & radial symmetry** -- `slack-icon.svg` rotated modules forming a hash · `dropbox.svg` five rhombi · `openai-icon.svg` one module rotated - six times · `cardano-icon.svg` graduated dots · `centos-icon.svg` pinwheel · `ibm.svg` stripes unifying letters · - `tidal-icon.svg` four diamonds · `ubuntu.svg` three figures in a ring. - -**Dimension with flat means** — depth without realism. -- `ethereum.svg` faceted octahedron · `sketch.svg` faceted gem · `codesandbox.svg` cube from cuts · `unity.svg` cube - from negative space · `webpack.svg` cube in cube · `tensorflow.svg` one form reads T and F · `laravel.svg` monoline - isometric L. - -**Overlap & colour segments** -- `mastercard.svg` two overlapping circles · `dreamhost.svg` crescent from two circles · `chrome.svg` three segments + - core · `google-icon.svg` segmented G · `lit-icon.svg` faceted flame · `playwright.svg` two masks. - -**Pictorial reduction** — objects reduced to their most characteristic silhouette. -- `apple.svg` · `redhat-icon.svg` · `couchbase.svg` · `docker-icon.svg` · `swift.svg` · `snowpack.svg` · - `stackoverflow-icon.svg` · `trello.svg` · `youtube-icon.svg` · `whatsapp.svg` · `gitlab.svg` (faceted animal). - -**Mascots done simply** -- `android-icon.svg` built from rounded primitives · `discord-icon.svg` controller = face · `github-icon.svg` strong - silhouette in a circle · `giantswarm.svg` terminal glyphs as eyes. - -**Emblems & containers** -- `markdown.svg` M + arrow in a frame · `jupyter.svg` orbits framing the name · `lua.svg` moon orbiting a planet. - -**Combination systems** -- `soundcloud.svg` cloud built from sound bars · `tableau.svg` plus-sign cluster echoed in the name · `aws.svg` smile - arrow under plain type · `arduino.svg` infinity loop holding − and + · `microsoft.svg` four squares. - -Get more: `python3 scripts/search_library.py --exemplary --type ` (141 files are flagged exemplary). - -## 5. Catalog schema & extending the library - -Each record in `catalog.json`: - -| Field | Meaning | -|---|---| -| `file`, `brand`, `variant` (`main`/`icon`), `pair` | identity of the file and its counterpart | -| `width`, `height`, `aspect`, `aspect_class` | canvas proportions | -| `bytes`, `shapes`, `anchors` | size and complexity | -| `colors`, `n_colors`, `color_families`, `primary_family`, `gradients`, `has_mask`, `has_filter` | colour data | -| `mark_type`, `symbol_type` | wordmark · lettermark · letterform · pictorial · abstract · mascot · emblem · combination | -| `subject` | what it depicts, in a few words | -| `geometry`, `techniques` | construction vocabulary (see `--list-values`) | -| `type_style`, `case` | typography, when present | -| `mood`, `industry`, `exemplary`, `note` | tone, sector, teaching flag and why | - -To add logos: place SVGs in `assets/library/svg/`, append classification objects with the same keys to -`classifications.json`, run `python3 scripts/build_catalog.py` (and `--check` to verify coverage). Only add marks you -have the right to redistribute for reference. diff --git a/.claude/skills/logo-design/references/mark-types.md b/.claude/skills/logo-design/references/mark-types.md deleted file mode 100644 index 3b8b75c..0000000 --- a/.claude/skills/logo-design/references/mark-types.md +++ /dev/null @@ -1,186 +0,0 @@ -# Mark Types — What to Choose and When - -Choosing the type of mark is a strategic decision that comes before drawing. Each type has different -strengths, costs and failure modes. Library examples can be pulled with -`python3 scripts/search_library.py --type --exemplary --format paths`. - -## Contents -1. Overview table -2. Wordmark (logotype) -3. Lettermark / monogram -4. Letterform (single-letter symbol) -5. Pictorial mark -6. Abstract mark -7. Negative-space mark -8. Mascot / character -9. Emblem / badge -10. Combination mark & lockups -11. Pictograms, logo systems, dynamic marks, patterns -12. Decision guide - ---- - -## 1. Overview table - -| Type | What it is | Best when | Watch out for | -|---|---|---|---| -| Wordmark | Name set in distinctive type only | Name is short, distinctive, new (needs to be learned); limited media budget | Generic if type is stock; long names shrink badly | -| Lettermark / monogram | 2+ initials combined | Long or hard-to-say names; heritage/fashion/institutions | Woven initials carry little meaning; needs lots of exposure | -| Letterform | One initial as a symbol | App icons, tech, finance; need a compact avatar | Many brands share the same letter; needs a twist | -| Pictorial | Recognisable object/animal | Name or story has a vivid image; global/wordless recognition | Literalness; clichés; too much detail | -| Abstract | Non-representational form | Conceptual positioning (speed, connection); diversified companies | Meaningless without exposure/story | -| Negative space | Two silhouettes sharing an edge | A clever, conceptually linked pair exists | Hardest to do; forced results; ambiguity | -| Mascot | Character with personality | Family, food, games, community brands | Complexity, dating, poor small-size performance | -| Emblem | Type locked inside a badge/seal | Institutions, clubs, craft, heritage, sports | Illegible when small; inflexible | -| Combination | Symbol + wordmark lockup | Most new brands (symbol can later stand alone) | Two weak halves ≠ one strong mark | - -Library data point: of the 233 brands in the bundled library that ship both a full logo and a standalone -icon, about **9 in 10** full logos are wide horizontal lockups (aspect ratio above 2.5 : 1), while about -**3 in 4** icons are near-square (0.8–1.25 : 1). Designing the symbol and the lockup as a *pair* from day one -is the norm, not the exception. - ---- - -## 2. Wordmark (logotype) - -The brand name alone, in type with strong, defined character. - -- **Advantage**: sidesteps the recognition problem — the name is always visible, so there is no symbol to learn. -- **Disadvantage**: if not handled skilfully, it's generic and has little mnemonic value. -- **Make it ownable**: customise letterforms (cuts, joins, terminals, a distinctive `a`/`g`/`e`), build a ligature, - substitute one letter with a meaningful sign, hide a shape in the counters or between letters, adjust weight - contrast, or draw it from scratch. If using a neutral sans, some device (ligature, trick, hidden sign) is - necessary to make it memorable. -- **Extreme minimal wordmarks** — very clean, near-neutral type — can signal sophistication, useful in B2B and - premium sectors crowded by loud identities. -- **Case matters**: lowercase reads approachable and contemporary; uppercase reads stable, institutional, - monumental; title case reads conventional. Legibility depends on the typeface — test both. -- **Spoken sound**: letter rhythm should echo how the word sounds; a playful shift on the baseline can make - the viewer "hear" the word. -- **Length**: long names become thin, wide strips that shrink poorly — consider a stacked version or a - companion monogram/letterform for small sizes. - -## 3. Lettermark / monogram - -Two or more initials combined into one mark. - -- **Advantage**: solves long names and legibility in tight spaces (a quarter-page ad, an app icon). -- **Disadvantage**: generic initials treated in clever ways can look better on towels than on a business card; - woven initials have little inherent meaning and depend on large-scale exposure to be recognised. -- **Letter chemistry**: letters with rich structure (`a`, `s`, `w`, `g`, `k`, `R`, `M`, `W`) interlock in more - interesting ways; simple letters (`i`, `l`, `I`) offer little. Look for shared strokes, mirrored shapes, - and counters that can nest. -- **Numbers pair well** with letters when the name includes one (a `D` and a `4` share curves and diagonals). -- Traditionally strong in fashion, luxury, publishing, institutions — where a person's or house's name is the brand. - -## 4. Letterform (single-letter symbol) - -One initial treated as a symbol that conceptually, stylistically or metaphorically carries the brand. - -- Carries less information than pictorial marks, so it's more neutral and often more timeless. Favoured by - finance and technology. -- Many brands share the same initial — the concept must live in the *treatment*: a letter that is also an arrow, - a path, a fold, a spark, a bracket, a container, a person. -- Excellent as app icon / favicon / avatar; pair with a wordmark for the full lockup. - -## 5. Pictorial mark - -A meaningful, recognisable icon — object, animal, plant — as the primary identifier. - -- The most widespread and one of the most effective forms; ideally recognisable **without** the name. -- Can depict the brand directly (name = object) or metaphorically (an animal's qualities = brand's qualities). -- Because the image is visually dense and characterful, pair it with **neutral typography** to create contrast - and avoid overload. -- Work in silhouette first: an object's most characteristic view (front view of an apple, side view of a bird) - is the one that can't be mistaken for anything else. -- Reduce to geometry: a leaf is two quarter circles; a bird is a few arcs. Geometric reduction is what makes - pictorial marks feel designed rather than clip-art. - -## 6. Abstract mark - -A form that represents an idea in a suggestive, subjective way — a phenomenon rather than an object. - -- Useful when the business is diversified, the name gives no visual clue, or the brand wants a conceptual, - ownable shape. -- Some phenomena map naturally to form (connection → linking shapes; speed → tapering sweep; growth → - ascending/expanding forms; openness → broken circle). Others ("reliability", "quality") have no natural sign, - so meaning is assigned through story and repetition. -- An abstract mark is only meaningful after heavy exposure. It works for organisations with the reach to teach - it; it's risky for a small business with little media presence. -- Avoid unintended connotations (political, ethnic, religious, sexual) — broad institutions especially need - marks with no negative associations. - -## 7. Negative-space mark - -Uses the surrounding space as part of the concept: figure and ground both carry meaning. - -- The strongest versions merge **two strongly recognisable silhouettes that are conceptually related** — one - positive, one negative — so the whole becomes more than its parts (a Gestalt effect). -- They are rare and arguably the hardest marks to create; only simple elements with distinctive silhouettes - combine cleanly. -- Also usable at smaller scale: an arrow hidden between two letters, a shape formed inside a counter. -- Check readability both ways: some people see only one figure. The hidden figure should be a bonus, not a - requirement for understanding. -- In SVG, build with `fill-rule="evenodd"` or subtracted compound paths (see `svg-construction.md`). - -## 8. Mascot / character - -A character with a face and personality. - -- Creates warmth and story; strong for food, family, games, community and education brands. -- Risks: detail, dating, and poor performance at small sizes. Provide a simplified head/icon version. -- Keep the construction geometric and the expression clear at a distance; test at 24 px. - -## 9. Emblem / badge - -Text integrated inside a seal, crest, shield or enclosure — the parts cannot be separated. - -- Conveys tradition, authority, membership, craft. Common for universities, sports clubs, breweries, public bodies. -- Loses legibility quickly at small sizes; plan a simplified inner symbol for favicons and avatars. -- Containment also solves practical problems: a box behind a wordmark can give presence in cluttered - environments. - -## 10. Combination mark & lockups - -A symbol and a wordmark designed to work together and, eventually, apart. - -- The most common and flexible solution. Over time a well-exposed symbol can stand alone. -- The symbol and type should share DNA (stroke weight, corner radius, angles, x-height relationships) without - duplicating each other. Ornate symbol → plain type; bold symbol → lighter type; aim for complement, not contrast - for its own sake. -- Provide **multiple lockups**: horizontal (symbol left of name), stacked/vertical (symbol above name), - symbol-only, wordmark-only, and optionally with tagline. Lock the relative sizes and spacing once approved. -- Symbol-to-type size: optically, the symbol usually spans the cap height to about 1.5–2.5× the cap height in - horizontal lockups; verify by eye, not formula. - -## 11. Pictograms, logo systems, dynamic marks, patterns - -- **Pictograms**: pictures standing for a word or idea, understandable across languages. Built from the most - primary elements (line, circle, square, triangle). Useful as companion icon sets for an identity. -- **Logo systems / sub-brands**: a parent symbol as the primary identifier with sub-brands distinguished by colour, - naming, or a shared visual language. Consistency and repetition of key elements hold the family together. One of - the most complex tasks: requires problem-solving and a strong sense of balance. -- **Dynamic / changeable marks**: a consistent core (letterforms, grid, frame) with changing elements (colour, - pattern, inner image, typeface from an approved set). Keeps a system fresh and lets different users express - themselves while remaining recognisable. Define the rules as carefully as the mark. -- **Patterns**: complement the mark without duplicating it; derive from components of the mark where possible; - must scale from a business card to an aircraft. See `identity-system.md`. - ---- - -## 12. Decision guide - -Answer in order; the first strong "yes" usually wins. - -1. **Is the name short (≤ ~8 letters), distinctive, and not yet known?** → Wordmark or wordmark-led combination. -2. **Is the name long, multi-word, or hard to pronounce?** → Lettermark/monogram or letterform + wordmark. -3. **Does the name or story contain a vivid, ownable image?** → Pictorial (or pictorial combination). -4. **Is there a strong phenomenon/idea but no object?** → Abstract (only if exposure will be high). -5. **Will the mark mostly live as an app icon, favicon or avatar?** → Letterform or compact symbol first, - then the lockup. -6. **Heritage, membership, authority or craft positioning?** → Emblem, with a simplified inner symbol. -7. **Warmth, family, play?** → Mascot or friendly pictorial, with a simplified head version. -8. **Parent brand with many children?** → Logo system with a fixed core. - -When in doubt, explore **three different types** in the first round (e.g. a wordmark, a letterform, and a -pictorial/abstract symbol) so the choice is made by comparing real options. diff --git a/.claude/skills/logo-design/references/presentation-delivery.md b/.claude/skills/logo-design/references/presentation-delivery.md deleted file mode 100644 index 801a66d..0000000 --- a/.claude/skills/logo-design/references/presentation-delivery.md +++ /dev/null @@ -1,121 +0,0 @@ -# Presentation, Feedback & Delivery - -How to present concepts so they are judged on the right criteria, how to handle feedback and committees, and what -to deliver at the end. Also covers the working relationship (fees, spec work, rights) for users who are designers. - -## Contents -1. Presentation rounds -2. Structure of a concept presentation -3. Talking about concepts -4. Feedback, committees and decision-makers -5. Final deliverables -6. The working relationship (for designer users) - ---- - -## 1. Presentation rounds - -A typical project has three presentations: -1. **Concepts (the checkpoint)** — three distinct directions at ~80 % finish, **in greyscale**, each with a one-sentence - idea and a short rationale tied to the brief, shown as one overview image (`scripts/concept_sheet.py`). End by - offering the full kit and wait. Goal: choose a direction. Nothing else is produced before this answer. -2. **Refinement** — the chosen direction refined (optical corrections, type, lockups) with **colour** options, - researched against competitors' palettes, shown in context with mockups (`scripts/presentation_board.py`). -3. **Final kit** — the approved mark with the system (palette, typography, variants), key applications, the file set - and the usage guide. - -In a chat with an AI designer, rounds 2 and 3 are often merged: once the user approves a direction and asks for the -kit, deliver the refined mark, colour, lockups, board, exports and guidelines together. Never merge round 1 into the -others unless the user explicitly asked you not to check in. - -Why three concepts? Enough for a real choice, few enough to develop properly. Three well-developed concepts beat a -dozen half-developed ones, and showing too many signals a lack of conviction. Make the three genuinely different -(e.g. a custom wordmark, a letterform symbol, a pictorial/abstract symbol) rather than three variations of one idea. - -Why greyscale first? Colour triggers personal preferences ("I hate green") that derail the conversation about the idea. -Form must stand on its own. - -## 2. Structure of a concept presentation - -For the checkpoint, the concept overview image plus a short chat message is enough (see SKILL.md). For a fuller -client presentation (round 2, or when the user asks for one), use `scripts/presentation_board.py` to generate an HTML board — set `"industry"` (coffee, food, retail, fashion, software, saas, finance, consumer-app, services, event, education, health) or an explicit `"mockups"` list so every context fits the business (`--list-mockups` shows all) — or follow this outline in chat/slides: - -1. **Title** — client, project, date, designer(s). -2. **What we heard** — the brief in a few lines: audience, adjectives, the problem, success criteria. This reminds - everyone of the agreed criteria before they see anything. -3. **Per concept** (one at a time, not all at once): - - Name the concept and give the **one-sentence idea**. - - Show the mark large, alone, in black on white. - - Explain *how it answers the brief* (2–4 bullets). Mention the craft decisions briefly (geometry, custom letters). - - Show it small (favicon/app icon) and reversed. - - Show 5–6 **mockups relevant to the business**, in a consistent style (a coffee brand on cups and a storefront, - a SaaS on an app icon, website header and a conference badge). -4. **Comparison** — all three side by side at the same size. -5. **Recommendation** — which one you recommend and why (the designer is the expert; have a point of view). -6. **Next steps** — what happens after a choice; what feedback you need. - -Keep the logo's role in perspective: a logo cannot carry deep brand stories. The aim is to communicate something about -the brand quickly and simply; the rest is the job of the identity system and the brand's actions. - -## 3. Talking about concepts - -- Lead with the idea and the brief, not with how long it took or which tool was used. -- Tie every choice to criteria: "Rounded terminals because 'approachable' was your first adjective." -- Show the system potential: patterns, icons, motion a concept could generate. A minimal mark often looks too simple - alone — shown in use, its simplicity becomes an asset that gives the wider identity room to breathe. -- Anticipate objections (resemblance to X, legibility at small size) and address them before they're raised. -- If a client asks for something that conflicts with the brief, return to the brief; explain trade-offs without - condescension. - -## 4. Feedback, committees and decision-makers - -- **Know who decides** and involve them directly in presentations. Feedback relayed through intermediaries loses - context; decisions made without the decision-maker get reversed. -- **Committees**: many voices tend toward consensus on the least objectionable (weakest) option, and people conform to - the loudest opinion. Present to the smallest group that includes the decision-maker; collect individual written - feedback against the criteria rather than open debate; keep focus groups for comprehension checks, not taste votes. -- **Value all feedback** — even irritating feedback contains information. Clients usually know their business better - than the designer. Don't fall in love with your own work, and never demonise the client. -- **Translate feedback into problems**: "Make it bigger" may mean "it lacks presence"; "I don't like the colour" may mean - "it feels cold". Ask *why* before changing anything. -- **Underpromise and overdeliver**; meet deadlines — reliability builds the trust that lets bolder ideas through. -- **Be strong, not stubborn**: hold the strategic line, concede on details, and remember the designer is the catalyst - for change — some discomfort is normal. The job is an effective logo, not making everyone feel good. - -## 5. Final deliverables - -**Master artwork (vector)** — SVG (web/dev), PDF (print), and, when the user has the tools, AI/EPS for printers and -agencies. **Raster** — PNG with transparency (e.g. 512, 1024, 2048 px) and JPG on white for office use. - -**Variants** (generate with `scripts/export_variants.py`): -- Full colour, one-colour black, one-colour white (reversed), one-colour brand colour. -- Lockups: horizontal, stacked, symbol-only, wordmark-only (+ with tagline if any). -- Favicon (SVG + 32/48 PNG; ICO if requested), app icon (1024 px square, platform tile), social avatar (circle-safe). - -**File naming**: `brand-logo-horizontal-color.svg`, `brand-logo-stacked-white.png`, `brand-symbol-black.svg` … -Organise folders by use: `print/`, `digital/`, `social/`, `source/`. - -**Mini guidelines** (at minimum one page, see `templates/brand-guidelines-template.md`): clear space, minimum sizes, -colour codes, approved backgrounds, typefaces, misuse examples, which file to use where (many clients send the digital -RGB file to their printer — spell it out). - -**Handover notes**: design rationale (one paragraph per key decision), test results, open items (trademark search, -Pantone proofing, outlines for any remaining type or strokes), and licence notes for fonts used. - -Final checklist before sending: see `process.md` §7 and `testing-checklist.md`. - -## 6. The working relationship (for designer users) - -- **Talk money early**; fees depend on scope (number of concepts, rounds, deliverables, usage/rights, timeline, the - client's size). Hourly rates suit beginners; experienced designers usually price per project (quick insight is - the result of years). Raise rates as demand and experience grow. -- **Get paid upfront** (e.g. a deposit before work starts), set revision limits and timelines in writing, and handle - print costs separately. -- **Avoid spec work** (free pitching/crowdsourcing): it devalues expertise and skips the discovery that makes logos - good. Pro bono work for causes you believe in is different — choose it deliberately. -- **Rights and ownership**: clarify when rights transfer (usually on full payment), and whether the designer may show - the work in a portfolio. Unused concepts usually remain the designer's. -- **Originality**: never pass off a light modification of existing work as original. If an unintentional similarity is - discovered, be honest, fix it, and make it right with the original creator if needed. -- **Stay involved** after launch: offer periodic audits and art direction; it protects the work and brings repeat - business. diff --git a/.claude/skills/logo-design/references/principles.md b/.claude/skills/logo-design/references/principles.md deleted file mode 100644 index ef95acf..0000000 --- a/.claude/skills/logo-design/references/principles.md +++ /dev/null @@ -1,234 +0,0 @@ -# Logo Design Principles - -The foundational thinking behind every decision in this skill. Read this when you need to justify a -direction, resolve a disagreement, critique a mark, or when a design "feels off" and you need a lens. - -## Contents -1. What a logo is (and is not) -2. The twelve principles -3. The mnemonic model — how marks get remembered -4. Simplicity, properly understood -5. Relevance vs. literalness -6. Distinction and originality -7. Longevity vs. trend -8. Tensions to manage -9. Quick diagnostic questions - ---- - -## 1. What a logo is (and is not) - -- **A logo is an identifier, not an explanation.** People are known by a name, not by a paragraph - describing where they live and what they do. A logo is a signpost: it points to the organisation and - hints at its attitude. It does not need to show the product, the service, the city and the founding - story at once. -- **A logo is not an illustration.** An illustration explains text. A logo is a shortcut that must be - recognised in a glance and remembered afterwards. -- **Logo ≠ identity ≠ brand.** - - *Logo*: the mark itself (symbol, wordmark, or both). - - *Identity*: the logo plus its visual system — typefaces, colours, imagery, patterns, tone of voice. - - *Brand*: the perception people hold about the organisation. It is formed by the audience from every - touchpoint — products, service, behaviour, communication. A designer cannot "make" a brand; a designer - builds the foundation the brand is perceived through. -- **A logo is not a magic lantern.** It cannot rescue a bad product or a poorly run organisation. A well- - designed mark, repeated consistently, helps a good product reach its potential. The logo supplies - attitude and direction; the organisation supplies the meaning, over time. -- **Meaning accrues.** Most marks are nearly empty when new; they become loaded through association and - exposure. Simple geometric forms carry whatever the organisation pours into them — which also means a - mark's meaning can be damaged by association. Choose forms that can hold the intended meaning for decades. -- **What a logo is for:** claim ownership and origin; differentiate from competitors; give the - organisation an internal rallying point; let the audience form a relationship; lend credibility; bring - order to many communications; create merchandising and recognition opportunities. - ---- - -## 2. The twelve principles - -These are synthesised from the whole body of logo-design practice. Treat them as a checklist of forces, -not as rigid laws — great marks sometimes break one principle deliberately to serve a stronger one. - -### 1. Start with who, what, why -Before any form: *Who is the client (values, attitude, goals)? Who is the audience (demographic and -psychographic)? What is actually needed — is a logo even the answer, or is the problem a bad product, -message, or team?* Let the problem dictate the solution rather than imposing a favourite idea onto it. This -does not mean obeying every client whim, nor suppressing the designer's vision — it means gathering enough -information to set criteria, then creating through the designer's filter. Also ask what the organisation -wants to be in one, five and ten years; design for where it is going, not only where it is. - -### 2. Identify, don't explain -Resist the urge to depict every facet of the business. Describing too much produces a cluttered mark and a -restraining identity that breaks the moment the business expands. The clearest, most direct voice wins. - -### 3. Keep it simple -A simple form is recognised faster, remembered longer, reproduced more reliably, and survives abuse — -bad printing, embroidery, tiny favicons, careless in-house designers. Many logos fail from their own -cleverness or overproduction. Let something be what it is. (See §4: simple is not the same as plain.) - -### 4. Make it relevant -The mark must fit the organisation, its industry, its audience and its personality. A florist's mark should -not look at home on a car dealership. Relevance is about *tone and fit*, not literal depiction (see §5). - -### 5. Aim for distinction -Study what competitors look like. If every mark in the category runs together (all blue, all globes, all -swooshes), that is an opportunity. Bucking category conventions makes a brand stand out — but keep the -general perception in mind so the mark still reads as belonging to the right world. - -### 6. Build memorability (mnemonic value) -Memory is built from shape and colour first, then context, then learned associations, then emotion (see §3). -A strong, singular silhouette and an ownable colour are the most reliable memory hooks. - -### 7. Focus on one thing -One clear idea, executed well, beats three ideas fighting for attention. A mark with a single defining -feature is easier to recall and describe. If you cannot explain the idea in one sentence, it will not work. - -### 8. Think small (and large) -Design for an inch, or 16 px. Intricate, layered forms that look superb at 400 % on screen become a -jumbled mess on a favicon or embroidered chest logo. Conversely, bad curves and sloppy kerning are -exaggerated on a building-sized sign. Test both extremes (see `testing-checklist.md`). - -### 9. Design for longevity -Marks that date quickly come from concentrating on *formal* ideas (a trendy effect, the typeface of the -moment) rather than *conceptual* ones. Style and trend rarely carry lasting emotional resonance. Aim for a -mark that can convey its message for decades and adapt to cultural change. - -### 10. Make the logo the foundation of a system -The audience never sees a logo in a void. It lives on cards, screens, vehicles, buildings, packaging, -next to photography and copy. Design the mark with its visual system in mind; the system should complement -the mark, not copy it. Guidelines protect the mark from party hats, wrong colours and floor decals. - -### 11. Design for every medium -Assume the logo must work in one-colour print, on screen, as a 3D sign, embroidered, animated, and in media -not yet invented. Most clients only picture their current use; the designer's job is to plan for the -unplanned. - -### 12. Be seductive — and be strong -Aesthetics matter. People would rather be drawn in by a mark than repelled by one; the message is primary but -the form must invite the viewer in. Simple, dynamic, well-crafted forms seduce. And "strong" applies to the -designer too: understand your role and the client's, keep a clear vision tied to the agreed goals, and -distinguish confidence from stubbornness. The designer is a catalyst for change; not everyone will be happy, -and that is not a failure. - -**Two supporting principles worth naming separately:** -- **Pose a question (lightly).** A mark that lets the viewer complete a small puzzle — a hidden arrow, a - letter doubling as an object, a figure/ground reversal — is looked at longer and remembered better. But - there is a fine line: a mark that needs hours to decode or accompanying text will fail. -- **Respect tradition where it exists.** Existing equity (a colour, a shape, a heritage detail) and - culturally significant symbols deserve respect. Borrowing a culture's sacred symbol requires permission - from its custodians; honouring tradition can create powerful, unexpected connections. - ---- - -## 3. The mnemonic model — how marks get remembered - -People process a mark in roughly this order: - -1. **Shape and colour.** All visual recognition starts here. Is it round and red? Square and green? - Consistency of shape inside the mark (counters echoing the outer form, repeated angles) strengthens it. -2. **Historical continuity / context.** The viewer places the form in time and culture: contemporary, - Victorian, retro-futurist, corporate, handmade. Signifiers of an era can intentionally evoke an attitude. -3. **Learned response.** Taught associations: red means stop, a green cross means pharmacy, a shield means - protection. Use them knowingly; they differ by culture. -4. **Emotional resonance.** The "wild card": personal memories attached to colours and forms. Hard to predict, - but it is where lasting attachment lives. - -Design implication: get the silhouette and the colour decision right first; everything else is secondary. - ---- - -## 4. Simplicity, properly understood - -- **Less information, more memory.** The fewer words a phrase has, the easier it is to memorise; the fewer - visual elements a mark has, the clearer and more memorable it is. -- **Simple is not plain.** Some shapes are too simple to be interesting — a bare circle or generic initials - in a stock typeface carry nothing ownable. Simplicity charms only when it carries a certain amount of - thought and detail: a clever junction, a precise proportion, an unexpected cut, a subtle light source. -- **Sculpt by subtraction.** Treat the process like sculpting: chip away weaker ideas, add and strip - elements, then strip some more. Don't stop at the first acceptable result; the longer you stay with the - form, the more correct it becomes. -- **The modernist vocabulary is shared ground.** Waves, stripes, stars, arrows, cubes, overlapping primitives - with exclusions, half- and quarter-circles, spirals, repetition. Knowing this alphabet lets you compose on - a solid foundation — but the vocabulary is shared, so push past its obvious combinations. -- **Minimalism as positioning.** Extreme reduction can itself be a differentiator — useful when a brand wants - conceptual sophistication in a market of loud identities (common in B2B and premium sectors). - ---- - -## 5. Relevance vs. literalness - -- **Avoid direct illustration of the subject.** A dentist logo that is a tooth, a plumber logo that is a - wrench, a software logo that is a laptop — these are forgettable because every competitor could use them. -- **Clichés are recognisable for a reason.** An apple, a shield, a leaf, a speech bubble — they read instantly. - Don't discard them; present them in a fresh form so the familiar sign is seen anew. -- **Where to find the idea:** the name (a letter, a word meaning, a sound); the brand's adjectives (fast, - warm, precise, rebellious); its promise; its origin, place or founder; a process or material it uses; an - abstract phenomenon it creates (connection, growth, flow, balance). -- **Literal naming shortcuts.** When the name is itself an object (e.g. a company named after a fruit), - using that object makes recall instant — the viewer sees the mark and the name surfaces automatically. That - directness is a legitimate choice; add craft and a twist so it is still ownable. -- **Abstract marks need assigned meaning and exposure.** Some ideas ("connection", "speed") have strong visual - analogues; others ("reliability", "trust") do not, so an abstract form gets meaning assigned by story and - repetition. Abstract marks only become meaningful with a great deal of exposure — factor media budget into - the choice. - ---- - -## 6. Distinction and originality - -- **The familiarity test.** If a solution feels familiar in even the slightest way and you know it isn't - yours, it is someone else's. Discard it or change it significantly. Memory is sneaky: marks you saw years ago - can resurface as "your" idea. -- **Basic shapes are common property; combinations are not.** Everyone can use circles and triangles; the - specific arrangement is what must be new. -- **Search before you commit.** Check the category, trademark databases, and a reverse image search. Use the - bundled library (`scripts/search_library.py`) to see what is already common for a subject or technique. -- **Never copy library marks.** The reference library exists to learn patterns and craft, not to trace. - If an accidental near-copy is discovered after delivery, be honest, change it, and make it right. - ---- - -## 7. Longevity vs. trend - -- Every era leaves fingerprints (gradients, drop shadows, glossy bevels, ultra-thin type, lowercase - everything). A trained eye can date a mark to its decade. Some brands deliberately want a current look — that - is valid if chosen knowingly and budgeted for refresh. -- Two viable ownership strategies: - - **Constancy**: one mark kept almost unchanged for generations; recognition compounds. - - **Managed evolution**: periodic refreshes that keep the core recognisable (colour, shape, key element) - while updating details. -- Custom letterforms add ownership, but the further they depart from recognisable letter shapes, the faster - they date. -- Conceptual ideas outlive formal ones. Build the mark on an idea, not on an effect. - ---- - -## 8. Tensions to manage - -| Tension | Guidance | -|---|---| -| Simple ↔ interesting | Reduce until the idea is clear, then make sure one detail is ownable. | -| Relevant ↔ literal | Evoke the attitude; don't depict the product. | -| Distinct ↔ appropriate | Break category conventions where they blur together, keep the cues that signal the right world. | -| Clever ↔ clear | A small puzzle helps; a riddle hurts. One-sentence test. | -| Symmetry ↔ energy | Perfect symmetry is stable but can bore; a subtle asymmetry keeps the eye moving. | -| Consistency ↔ flexibility | A fixed core (shape, colour, type) with rules for variation keeps systems fresh without losing recognition. | -| Client taste ↔ strategy | Return to the brief and the agreed criteria, not to personal preference — yours or theirs. | -| Perfection ↔ progress | Keep refining details, but know that no logo pleases everyone; even a mark loved by 99 % will have critics. | - ---- - -## 9. Quick diagnostic questions - -Run these on any concept (yours or one you're critiquing): - -1. Can I describe the idea in one sentence? -2. Is it recognisable as a silhouette, in one flat colour? -3. Does it still read at 16 px? At 16 m? -4. Would it survive a fax, an embroidery machine, a laser engraver? -5. Does it look like any competitor, or any famous mark? -6. Does its tone (sharp/round, heavy/light, warm/cool) match the brand's adjectives? -7. Is there one defining feature someone could describe from memory? -8. Is anything there only because it was fun to draw? -9. Will it look dated in ten years? Why not? -10. Does it work as the foundation of a system — can a pattern, icon set or motion idea grow from it? -11. Are there unintended readings (rotated, mirrored, at a distance, by someone who hasn't seen the brief)? -12. Would the audience — not the designer — understand and like it? diff --git a/.claude/skills/logo-design/references/process.md b/.claude/skills/logo-design/references/process.md deleted file mode 100644 index 0476757..0000000 --- a/.claude/skills/logo-design/references/process.md +++ /dev/null @@ -1,131 +0,0 @@ -# The Design Process in Detail - -The stages from brief to final artwork, adapted for an AI designer that works in SVG code as well as for a -human designer with a sketchbook. SKILL.md gives the short version; read this for the details of each stage. - -## Contents -1. Stage map -2. Concepting -3. Mood boards and reference gathering -4. Exploration ("sketching") — three stages -5. Development in vector -6. Refinement and gridding -7. Final artwork checklist -8. Working habits - ---- - -## 1. Stage map - -| Stage | Output | Gate | -|---|---|---| -| Collaboration / discovery | Brief, criteria, schedule, decision-maker | Brief agreed | -| Concepting | Word map, 6–10 one-sentence concepts | Concepts are distinct and on-brief | -| Exploration | Many rough forms per concept | 2–4 directions worth developing | -| Development | Clean black vector versions of 3 concepts | Presentable at ~80 % finish | -| Presentation 1 (checkpoint) | 3 concepts in greyscale as one overview image + kit offer | User picks a direction and asks for the kit | -| Refinement | Optical corrections, gridding, colour, type, lockups | Approved final mark | -| System & applications | Palette, typefaces, variants, patterns, key applications | System approved | -| Production | Final files, specifications, guidelines | Delivered; audit plan | - -Integrate existing equity (colours, shapes, heritage details) during exploration if it's a redesign. - -## 2. Concepting - -- Begin with the name and a detailed brief — from the brand's big idea down to how it operates. -- The most useful clues are **adjectives** describing the brand; they give abstract visual cues that can become - symbols. Also mine: the name's letters and meaning, the promise, the audience's world, the product's process - and materials, place and origin. -- If the name contains a visual (a letter + number with strong shapes, a word that is an object), the concept may be - hiding in plain sight. -- Write each concept as **one sentence** ("A 'T' whose crossbar is a shield's top edge, for a logistics firm whose - promise is protection"). If it can't be said in a sentence, it won't be understood in a glance. -- Aim for concepts that are clever *and* visually pleasing — marks with a clever idea and sound visual appeal make the - strongest first impression. -- Consider the audience's demographics and culture (colourful/rounded for children; bold for some audiences; - cultural symbols where relevant) — but the brand strategy decides; a children's product can have an adult identity. - -## 3. Mood boards and reference gathering - -- Not just logos: include nature, architecture, painting, materials, typography, photography, product details. -- Compartmentalise by direction — classic, futuristic/high-tech, colourful, monochrome — and by mark type - (pictorial, letterform, monogram), each with relevant imagery. Clear boundaries make choices easier. -- Use the library for logo references by technique and subject (`scripts/search_library.py --technique - negative-space --exemplary`). References are for learning construction and tone — never to be traced. -- Mood boards can be shared with the client to align on style, or kept private; clients can't always foresee how a - direction will develop, so don't let an early mood preference lock the outcome. - -## 4. Exploration — three stages - -A human designer does this with pencil and tracing paper; as an AI, do the equivalent with quick descriptions and -rough SVG thumbnails. The logic is the same. - -### Stage A — Initial (quantity over quality) -- Pour out ideas with no judgement about clarity, spacing, form or silhouette. Rough strokes, imperfect shapes, - careless curves. The page should look like a battlefield of half-formed ideas. -- Quantity matters because it lets unexpected accidents happen. For an AI: list 15–30 micro-variations across - the 6–10 concepts (different letter treatments, crops, containers, negative-space pairings, angles). -- Rough SVG thumbnails at 64–128 px are ideal: small size forces silhouette thinking. - -### Stage B — Refinement (from ~30 % to ~60 %) -- Pick the most promising concept by gut feel; it may be only ~30 % of the final. The goal is to reach 50–60 %. -- Redraw it as a reference, then make many similar versions, each trying one new improvement: how elements - interact, balanced flow, outline, proportion. Compare each version with the previous; keep what works, cut what - doesn't. - -### Stage C — Fine-tuning (clean and precise) -- Trace over the best version repeatedly with small improvements until the form is clean and precise. At the end, - few formal changes should remain for the vector stage. - -Designers who stop at the first acceptable result leave quality on the table. Keep adding and stripping. - -## 5. Development in vector - -- **Copy, then change.** Before every significant change, duplicate the current version and place it next to the - previous. When something goes wrong, you can see exactly where. (In SVG work: save `concept-a-v1.svg`, `-v2.svg` - … and compare them in `scripts/preview_sheet.py --compare`.) -- **Few anchor points.** Anchors have great power; too many make curves lumpy and jagged. Periodically delete - unnecessary ones. Clean curves come from few, well-placed anchors with handles aligned to the curve's tangent - (horizontal/vertical handles at extrema). -- **Build with shapes.** Use circles, rectangles and consistent radii to construct and to check curves and corners. -- **Black first.** Develop in solid black on white. Colour comes after the concept is chosen. -- Present at about **80 % finish** — refined enough to judge the idea, not so polished that effort is wasted on a - direction that gets dropped. - -## 6. Refinement and gridding - -After a direction is approved: -1. **Alignment**: check that all horizontals and verticals are true (not 1–2° off). Snap near-standard angles to - standard ones (43° → 45°). -2. **Primitives**: circles perfectly circular, squares square, consistent radii where intended. -3. **Consistency**: stroke weights, gap widths, corner radii, terminal angles. -4. **Optical corrections**: overshoot, bone effect, irradiation (reversed version), horizontal-stroke thinning, - optical centre (see `visual-techniques.md`). -5. **Colour**: build palette; test on backgrounds (see `color.md`). -6. **Type & lockups**: finalise wordmark, spacing and all lockups (see `typography.md`). -7. **Scale tests**: see `testing-checklist.md`. - -Don't grid organic curves that don't decompose into circles; leave them. - -## 7. Final artwork checklist - -- [ ] No duplicate, stray or unnecessary anchor points; no open paths in filled shapes. -- [ ] Angles accurate, especially on the outer silhouette. -- [ ] All text converted to outlines; no live fonts, no raster images, no filters or effects in the master. -- [ ] Strokes expanded to fills (unless a deliberately stroke-based variant). -- [ ] Shapes merged/compounded where they should be one shape (no hairline gaps or overlaps that show as seams). -- [ ] Artboard/viewBox tight to the mark with consistent padding; mark centred optically. -- [ ] Colours are exact brand values; one-colour and reversed versions provided. -- [ ] File set matches the agreed deliverables (see `presentation-delivery.md`). -- [ ] Working files archived; versions named clearly. - -## 8. Working habits - -- Carry a sketchbook (or a notes file): ideas arrive at odd moments and slip away quickly. Photograph interesting - shapes, architecture, and the negative spaces in signage. -- Experiment outside the brief: work in the opposite of your usual style (colour if you work in black and white, - lines if you work in solids, messy if you work clean). Accidents — a slipped stroke, a mis-set layer — can be - exactly what a project was missing. -- Treat client feedback as valuable information, not an attack; clients usually know their business better than - you. Don't fall in love with your creations, and don't demonise clients. -- Keep your process, not your mood, in charge: rested eyes, side-by-side comparisons, and returning to the brief. diff --git a/.claude/skills/logo-design/references/redesign.md b/.claude/skills/logo-design/references/redesign.md deleted file mode 100644 index 062d55b..0000000 --- a/.claude/skills/logo-design/references/redesign.md +++ /dev/null @@ -1,72 +0,0 @@ -# Redesign, Refresh & Rebrand - -Changing an existing logo is riskier than creating a new one: people already know it, and recognition is an asset -built over years. Read this when the user asks to modernise, refresh, update or replace a logo. - -## 1. First: should it change at all? - -Good reasons: -- The business has changed (merger, new offering, new audience, new positioning — e.g. from discount to premium). -- The mark fails functionally: illegible small, unusable on screens, can't be embroidered, breaks in one colour. -- Many inconsistent versions are in circulation (the mark has been stretched, redrawn and recoloured by every vendor). -- It resembles a competitor or carries a harmful association. -- It looks dated in a way that contradicts the brand's promise (a tech firm looking decades old). - -Weak reasons: a new executive wants to leave a mark; boredom inside the company (the audience is rarely as bored as -the staff); chasing a trend. Remember the public may care deeply about a familiar mark — radical redesigns of loved -brands can trigger backlash and even be reversed. - -If the user is only *thinking* about change, that alone justifies exploring options — explore, then decide. - -## 2. Evolution vs. revolution - -| | Evolution (refresh) | Revolution (rebrand) | -|---|---|---| -| When | Equity is strong; problems are technical or stylistic | The business or its perception must change fundamentally | -| What changes | Proportions, weight, curves, spacing, colour tuning, simplification, cleaner digital version | Concept, name treatment, possibly colour and symbol | -| Risk | Low — recognition carries over | High — must rebuild recognition; plan launch & explanation | - -Most successful updates are evolutionary: cleaner, sleeker versions of the same idea. Even radical changes often keep -one anchor — usually the colour scheme (perhaps shifted in shade) or a signature shape. - -## 3. Equity audit - -List what the public recognises, in order of strength: colour, symbol shape, a distinctive letter, the name's -typography, a mascot, a slogan, a sound. Ask: -- What must survive? (Usually the strongest one or two.) -- What is incidental and can go? -- What causes problems (legibility, reproduction, negative associations)? -Two ownership strategies exist — constancy for decades, or managed evolution that keeps core elements while updating -details. Choose one explicitly. - -## 4. Refresh techniques - -- **Redraw** curves with fewer, cleaner anchors; fix the bone effect; add overshoot; unify stroke weights and radii. -- **Simplify**: remove bevels, shadows, gradients, outlines, tiny details; merge elements; reduce colours. -- **Retune typography**: re-space, redraw letters for legibility, customise so it can't be typed in a stock font, - or replace an overused typeface while keeping the character. -- **Soften or sharpen**: round terminals and lowercase letters feel friendlier; sharper forms and capitals feel more - authoritative. (A common modern move: from stark capitals to friendlier rounded forms.) -- **Colour**: keep the hue family, adjust saturation/value for screens and accessibility. -- **Add a container** when the old mark gets lost in cluttered environments. -- **Build the missing variants** (symbol-only, horizontal/stacked, favicon, reversed) — often the real problem. -- **Keep heritage elements as accents** (a classic ampersand, an old monogram) next to modern type to express - continuity and progress at once. - -## 5. Mergers and new structures - -Options: choose one existing mark; combine elements of both (rarely elegant); create a new mark that signals a new -entity; or a transitional endorsement ("X, a Y company"). Communicate tactfully — people identify with their old brand. -Find elements that both sides can recognise as theirs. - -## 6. Launch - -Explain the change: why, what stays, what it means. Show before/after side by side. Roll out consistently — mixing old -and new marks for long signals confusion. Update guidelines and asset libraries on day one, and audit usage after launch. - -## 7. Deliverable for a redesign proposal - -1. Diagnosis of the current mark (use the critique format in `critique.md`). -2. Equity audit (what stays, what goes). -3. 2–3 options along the evolution ↔ revolution spectrum, each with before/after at the same sizes. -4. Recommendation and rollout considerations (cost of signage/vehicles/packaging changes, timing). diff --git a/.claude/skills/logo-design/references/svg-construction.md b/.claude/skills/logo-design/references/svg-construction.md deleted file mode 100644 index 712124b..0000000 --- a/.claude/skills/logo-design/references/svg-construction.md +++ /dev/null @@ -1,193 +0,0 @@ -# Building Logos in SVG - -How to turn a concept into clean, production-grade SVG code by hand (as an AI writing markup) — geometric, -minimal, and easy for printers, developers and vector editors to use. - -## Contents -1. File conventions -2. Construction strategy: think in primitives -3. Paths: writing clean geometry -4. Negative space and compound shapes -5. Strokes vs fills -6. Type in SVG -7. Colour, gradients, variants -8. Common construction recipes -9. What to avoid in a master file -10. Outlines and boolean unions -11. Validation - ---- - -## 1. File conventions - -```svg - - Harbor logo - - -``` -- **viewBox first**: work on a clean integer canvas. 256 × 256 (or 512 × 512) for symbols; for lockups keep the - height 256 and let the width follow (e.g. `0 0 960 256`). The bundled library uses the same convention (width - 256 or 512 in ~99 % of files). -- **Padding**: leave consistent padding inside the viewBox (≈ 4–8 % of the size for symbols) or crop tight and let - the clear-space rule handle spacing — be consistent across the set. -- **Integer or 1–2 decimal coordinates**. Excess precision (`127.99999`) bloats files and hides misalignment. -- **Include ``** for accessibility; keep IDs meaningful (`symbol`, `wordmark`). -- **Group logically**: `<g id="symbol">`, `<g id="wordmark">` so lockups can be recomposed. -- One file per variant (see §7), named predictably: `brand-logo-horizontal-color.svg`, `brand-symbol-black.svg`. - -## 2. Construction strategy: think in primitives - -Before writing path data, describe the construction in words: -- *"Circle r=96 centred at (128,128); remove a 45° wedge from the upper right; a smaller circle r=28 sits in the - gap as a 'dot'."* -- *"Letter M from three 40-unit-wide bars on a 256 grid; the middle vertex rises to y=96; outer stems are extended - 4 units below the baseline for overshoot of the pointed vertex."* - -Then choose the simplest element that expresses each part: -- `<circle>`, `<ellipse>`, `<rect rx>` for primitives (easy to read and adjust). -- `<path>` for everything else, and for the final merged silhouette. -- `<polygon>` for straight-edged shapes. - -Pick a **unit** (e.g. 8 or 16 on a 256 canvas) and snap key dimensions to multiples of it; the mark will feel -systematic and gridding later is trivial. Keep a list of the radii and angles you use — reuse them. - -## 3. Paths: writing clean geometry - -- **Commands**: `M` move, `L`/`H`/`V` lines, `A` elliptical arc (perfect for circle segments), `C` cubic Bézier, - `Q` quadratic, `Z` close. Uppercase = absolute (prefer while designing), lowercase = relative. -- **Arcs for circular geometry**: `A r r 0 largeArc sweep x y`. Circle-based curves keep radii consistent and - are easy to verify. Example — a semicircle cap: `M 64 128 A 64 64 0 0 1 192 128`. -- **Béziers for organic curves**: place anchors at extrema (top, bottom, left, right of a curve) with handles - horizontal or vertical there; this gives smooth, predictable curves with few points. A quarter circle as a cubic - uses handle length ≈ 0.5523 × radius. -- **Few anchors**. Every extra point is a chance for a wobble. If a curve needs many points, split it into arcs. -- **Angles**: compute diagonal endpoints from exact angles. For 30°/60°: offsets use sin/cos (0.5, 0.866); - for 45°: equal x and y offsets. Avoid "almost" angles like 44° or 2° off vertical (the audit script flags them). -- **Smooth corners (anti bone effect)**: instead of a plain arc joining a straight side, extend the curve's handles - so curvature ramps gradually. A good squircle corner of size `s` starts ~1.3 × s before the corner, with handles - ~0.6 × s. -- **Closed shapes**: always end filled paths with `Z`. - -## 4. Negative space and compound shapes - -- Put outer contour and holes in **one path** and use `fill-rule="evenodd"` — holes appear where subpaths overlap - an odd number of times. Or wind holes in the opposite direction with the default `nonzero` rule. - ```svg - <path fill-rule="evenodd" d="M128 16 A112 112 0 1 1 127.9 16 Z M128 80 A48 48 0 1 0 128.1 80 Z"/> - ``` -- For a hidden figure between two shapes, design the **negative shape first** (the arrow, the letter), then build the - positive shapes around it; this guarantees the negative form is clean. -- Avoid `<mask>` and `<clipPath>` in the master unless essential — some tools and embroidery/cutting software handle - them poorly. Bake the geometry into paths for final files. (In exploration, masks are fine for speed.) -- Where two filled shapes of the same colour touch, merge them into one path so there is no hairline seam when - rendered or cut. - -## 5. Strokes vs fills - -- Explore with strokes (`stroke-width`, `stroke-linecap="round"`, `stroke-linejoin="round"`) — they're quick. -- In the master, **convert strokes to filled outlines** so the mark scales proportionally everywhere and survives - tools that ignore stroke settings. As an AI without an outline tool, either construct the outlined geometry - directly (offset curves by half the stroke width), or keep strokes but set `vector-effect` nowhere and verify that - scaling the whole SVG scales stroke width proportionally (it does when the stroke is inside the scaled viewBox). - Flag remaining strokes in the delivery notes so a vector editor can expand them. -- Monoline marks: pick stroke width relative to size (≥ 8 % of the mark's width if it must read at 24 px). - -## 6. Type in SVG - -- Final logos must not depend on installed fonts: `<text>` renders differently (or not at all) on other machines. -- Options, in order of preference: - 1. **Construct letterforms geometrically** as paths (ideal for short wordmarks, monograms, letterform symbols — - and it forces ownable, custom letters). - 2. If the user has a font file and a vector tool, set the word, customise, and **convert to outlines**; paste the - path data. - 3. For exploration/presentation only, use `<text>` with a clearly named font stack and a note that the wordmark - must be outlined before delivery. Never ship `<text>` as the final master. -- When drawing letters: consistent stem width, overshoot on round letters, thinner horizontals, optical spacing - (see `typography.md`). - -## 7. Colour, gradients, variants - -- Use exact HEX values from the palette; limit to the approved colours. -- Put colours directly on elements (`fill="#…"`) rather than in `<style>` blocks for maximum compatibility; optionally - use `currentColor` for a UI-friendly one-colour variant. -- Gradients: define in `<defs>` with `gradientUnits="userSpaceOnUse"` and explicit coordinates so they render - identically everywhere; always keep a flat-colour master alongside. -- **Variant set** to generate from the master (`scripts/export_variants.py` automates the colour swaps): - - `*-color.svg` (full colour), `*-black.svg`, `*-white.svg` (reversed; consider slightly thinner geometry), - `*-mono-<hex>.svg` (one brand colour). - - Lockups: `horizontal`, `stacked`, `symbol`, `wordmark`. - - App/favicon: symbol on a solid rounded-square or circle container, with the symbol optically sized - (typically 60–70 % of the container). - -## 8. Common construction recipes - -**Perfect circle with a notch (open ring)** -```svg -<path fill="none" stroke="#111" stroke-width="32" stroke-linecap="round" - d="M 201.5 54.5 A 104 104 0 1 0 232 128"/> <!-- exploration; expand for master --> -``` - -**Rounded square container (app icon), 22 % radius** -```svg -<rect x="0" y="0" width="256" height="256" rx="56" fill="#0F7C80"/> -``` - -**Equilateral triangle (side 203.2, height 176), centred on its bounding box** — its visual mass (centroid) -sits low, so nudge it up a few units if it looks bottom-heavy inside a container. -```svg -<polygon points="128,40 229.6,216 26.4,216" fill="#111"/> -``` - -**Letter "A" as a letterform symbol** — flat apex, every edge on the same 1 : 2 slope, and a constant -48-unit stroke (legs, crossbar and apex all measure 48) -```svg -<path fill="#111" fill-rule="evenodd" - d="M104 32 H152 L248 224 H200 L184 192 H72 L56 224 H8 Z M96 144 H160 L128 80 Z"/> -``` - -**Speech bubble from a circle + tail (merged)** -```svg -<path fill="#111" d="M128 24 A104 104 0 1 1 61.6 208 L28 236 L37.9 180 A104 104 0 0 1 128 24 Z"/> -``` - -These are starting points; refine proportions and add the concept's twist. - -## 9. What to avoid in a master file - -| Avoid | Why | Instead | -|---|---|---| -| `<text>` | font dependence | outlined paths | -| `<image>` / embedded PNG | not vector, blurry | vector paths | -| `filter` (blur, shadow, glow) | inconsistent rendering, not printable | flat shapes; simulate shadow with a darker shape | -| many `<mask>`/`clipPath` | tool compatibility | bake into paths | -| transforms nested deeply | hard to edit, rounding errors | apply transforms to coordinates (one wrapper `translate/scale`, as `export_variants.py` writes, is fine) | -| 20+ colours / many gradients | poor reproduction, weak recall | ≤ 3 flat colours; stepped gradients | -| micro-details < 1/64 of size | vanish when small | merge or remove | -| off-by-a-degree angles | look accidental | exact angles | -| editor metadata, huge precision | bloat | clean markup | - -## 10. Outlines and boolean unions (production) - -Without a vector editor you can't boolean-unite shapes, but you can get close: -- Overlapping sub-paths inside **one** `<path>` with the default `nonzero` rule (all wound the same way) render as a - seamless union on screen and in print — acceptable for web and most print masters. -- Cutters, vinyl plotters and embroidery software prefer truly merged outlines. If Inkscape is installed, it can - expand strokes and union everything from the command line: - ```bash - inkscape logo.svg --actions="select-all:all;object-stroke-to-path;path-union;export-plain-svg;export-filename:logo-outlined.svg;export-do" - ``` - Otherwise note in the handover that a designer should run *Outline Stroke* + *Unite* in a vector editor. - -## 11. Validation - -Run after every significant iteration: -```bash -python3 scripts/svg_audit.py path/to/logo.svg # structure, colours, complexity, angles, text/raster checks -python3 scripts/preview_sheet.py path/to/logo.svg -o preview.html # sizes, backgrounds, mono, blur, mirror, favicon -python3 scripts/render_png.py path/to/logo.svg --size 512 -o look.png # quick render to view -``` -Open the preview in a browser and look at it (use the available browser/screenshot tool if you are an agent). The -audit compares the file's complexity with the reference library's distribution so you can see if a mark is unusually -complex for a logo. diff --git a/.claude/skills/logo-design/references/testing-checklist.md b/.claude/skills/logo-design/references/testing-checklist.md deleted file mode 100644 index 5d90d07..0000000 --- a/.claude/skills/logo-design/references/testing-checklist.md +++ /dev/null @@ -1,75 +0,0 @@ -# Testing Checklist - -A logo is only finished when it has survived these tests. Most can be run with -`scripts/svg_audit.py` (structure and geometry) and `scripts/preview_sheet.py` (visual tests); the rest need -judgement. Run them on every concept before presenting and again on the final artwork. - -## 1. Scale -- [ ] **16 px favicon**: the core idea survives; no mush. If not, design a simplified small-size version - (fewer elements, thicker strokes, bigger gaps) — detailed marks may keep a reduced companion. -- [ ] **24–32 px** (app lists, social avatars): recognisable at a glance. -- [ ] **Very large** (billboard, building): curves are smooth, no lumpy anchors, kerning holds up; flaws - invisible at small sizes become glaring. -- [ ] **Minimum size**: shrink until the mark loses its identifying features; the size just above that is the - documented minimum (in px for screen and mm for print). - -## 2. Colour and value -- [ ] Works in **one-colour black** on white. -- [ ] Works in **one-colour white** on black — and doesn't look heavier than the black version (irradiation). If it - does, provide a slightly thinned reversed file. -- [ ] Works on the **brand colour**, on **photos** and on **patterns** (use a graphic device — outline or container — - if not). -- [ ] **Greyscale**: colour segments still separate by value; nothing relies on hue alone. -- [ ] Colours reproduce in **CMYK** and have spot/Pantone equivalents if vivid. - -## 3. Form -- [ ] **Squint/blur test**: the silhouette alone is distinctive. -- [ ] **Mirror test**: flipping reveals no proportion errors you'd adapted to. -- [ ] **Rotation / unintended readings**: view rotated 90° and 180°, tiny, and at a distance; show it to someone who - hasn't seen the brief. Check for accidental letters, body parts, offensive or sexual readings, political or - religious symbols, and resemblance to hazard signs. -- [ ] **Optical corrections** done: overshoot, bone effect, horizontal stroke thinning, optical centre. -- [ ] **Geometry clean**: no near-miss angles, perfect primitives, consistent radii and stroke widths - (`svg_audit.py` flags near-miss angles and tiny details). -- [ ] **Balance**: not accidentally tilted; weight distributed; proportions close to square for symbols. - -- [ ] **Letter test**: every customised letter still reads as the intended letter at first glance (ask: "what - letter is this?"). A K that reads as an h, or an N that reads as a lightning bolt, needs revising. -- [ ] **Junction check**: zoom in on every place strokes meet or overlap — no accidental notches, slivers, lumps, - hairline gaps or ink traps. -- [ ] **Peer test**: next to 3–4 exemplary library marks at the same size, yours looks equally resolved. - -## 4. Distinctiveness and originality -- [ ] **Shelf test**: placed among competitors (`preview_sheet.py --refs-industry <industry>`), it stands out - rather than blending in. -- [ ] **Familiarity test**: it doesn't remind you (or anyone you ask) of an existing mark. If it feels familiar and - it isn't yours, it's someone else's. -- [ ] **Library check**: search the bundled library for the same subject/technique - (`search_library.py --subject <thing>`); make sure yours is clearly different. -- [ ] **Trademark check** (recommend to the user): search the relevant trademark databases and do a reverse image - search before launch. You cannot give legal clearance — say so. - -## 5. Meaning and fit -- [ ] The idea can be explained in **one sentence**. -- [ ] Tone matches the brand adjectives (sharp/round, heavy/light, warm/cool, classic/modern). -- [ ] It identifies rather than explains; it will still fit if the business expands. -- [ ] Cultural meaning of colours and symbols checked for the audience's cultures. -- [ ] It works without the tagline and, for symbols, eventually without the name. - -## 6. Media and production -- [ ] One-colour printing, embroidery (no hairlines, gaps ≥ ~1 mm at chest-logo size), laser engraving, vinyl - cutting, signage, dark mode, animation. -- [ ] App icon: optically sized inside the platform's rounded tile; no fine text. -- [ ] Social avatars: survives circular crop. -- [ ] Master file: vector only, text outlined, strokes expanded, no filters/raster, clean viewBox - (`svg_audit.py` score ≥ ~90 with no FAIL). - -## 7. Context -- [ ] Shown in 5–6 **realistic mockups relevant to the business** (a café's cup, not a gym bag), in a consistent - style. Never judge a logo only in isolation on a white artboard. -- [ ] Lockups (horizontal, stacked, symbol-only) all tested at their intended sizes. - -## Recording results -Summarise test outcomes when presenting: what passed, what was adjusted (e.g. "thinned the reversed version by 3 %; -opened the counter gap from 6 to 10 units so it survives 16 px"), and what the user must still do (trademark search, -Pantone proofing). diff --git a/.claude/skills/logo-design/references/typography.md b/.claude/skills/logo-design/references/typography.md deleted file mode 100644 index d4e3086..0000000 --- a/.claude/skills/logo-design/references/typography.md +++ /dev/null @@ -1,135 +0,0 @@ -# Typography for Logos - -Typography is pictures of words. We decode letterforms the way we decode images: their shapes carry attitude, -history and culture before a single word is read. Read this when designing wordmarks, lettermarks, lockups, or -choosing brand typefaces. - -## Contents -1. Choosing a direction: type study -2. Classification and what each voice says -3. Custom vs. existing type -4. Letterform craft (spacing, kerning, optical fixes) -5. Lockups: symbol + type -6. Brand typefaces beyond the logo -7. Licensing and technical checks -8. Common mistakes - ---- - -## 1. Choosing a direction: type study - -1. Set the name in 20–40 candidate typefaces across categories, in lowercase, uppercase and title case. - Starting with type is a legitimate way to begin a logo — once the type is right, the rest can flow from it. -2. Judge by: the shape of the letters *in combination* (not individually), legibility, the rhythm of the word, - how the letters echo the way the word sounds, and how it reads at small size. -3. Shortlist 3–5 and look for **opportunities**: interesting letter pairs, shared strokes, counters that can hold a - shape, a letter that can become a sign, repeated letters that can create rhythm, a natural ligature. -4. Only then customise (see §3). - -Legibility varies with case: some typefaces read better in upper and lower case, others in capitals. Test. - -## 2. Classification and what each voice says - -| Class | Character | Typical voice | -|---|---|---| -| Humanist / Venetian serif | calligraphic stress, low contrast | literary, traditional, warm | -| Old-style serif | moderate contrast, diagonal stress | classic, trustworthy, bookish | -| Transitional serif | sharper, more vertical stress | refined, institutional | -| Modern / Didone | extreme thick–thin contrast, hairlines | fashion, luxury, drama (fragile when small) | -| Slab serif | heavy, block serifs | sturdy, industrial, confident, retro | -| Grotesque / neo-grotesque sans | even, rational | neutral, corporate, modern, "Swiss" | -| Geometric sans | built on circles/squares | modern, clean, tech, optimistic | -| Humanist sans | calligraphic proportions | friendly, readable, approachable | -| Rounded sans | soft terminals | playful, gentle, youthful | -| Script / handwritten | cursive, personal | personal, crafted, elegant or casual | -| Display / custom | idiosyncratic shapes | highly specific personality (dates fastest) | -| Monospace | fixed widths | technical, code, systematic | - -Tone rules of thumb: -- Heavier weights read strong/confident; lighter weights read elegant/quiet (but fragile at small sizes). -- Wide proportions feel stable and expansive; condensed feel efficient, urgent, editorial. -- Lowercase feels approachable; uppercase feels monumental. Title case is the neutral default. -- Serif ↔ sans pairing in one mark can express "heritage + modern" (e.g. a classic ampersand in a modern gothic name). - -## 3. Custom vs. existing type - -- Most viewers can't tell a custom face from a stock one, yet it's precisely the unique attributes of custom - letters that give the client ownership and protect against imitation. An unmodified stock font can be typed by - anyone — including competitors and counterfeiters. -- Levels of customisation, from light to heavy: - 1. Tight custom spacing and kerning of an existing face. - 2. Modify a few letters (a distinctive `a`, `g`, `e`, `R`, a cut terminal, a joined pair, a swapped dot). - 3. Redraw the whole word with a consistent logic (shared radius, stroke contrast, terminal angle). - 4. Draw from scratch on a system (e.g. built on a square grid, or with the symbol's curvature applied to the type). -- **Warning**: the further letterforms depart from familiar shapes, the more quickly they date and the harder they - are to read. -- Reflect the symbol in the type subtly (a corner radius, a cut angle, a stroke ending) — echo, don't duplicate. -- Redraw and re-space existing marks for legibility when refreshing an old logo; making it impossible to reproduce - by typing in any existing font is itself protective. - -## 4. Letterform craft - -- **Spacing is optical, not metric.** Equalise the *area* of space between letters, not the distance. Round letters - (`O`, `C`) sit closer to neighbours than straight ones (`H`, `I`); diagonals (`A`, `V`, `W`) need kerning. -- **Kern for the size of use.** Spacing that works in a book heading may look loose at logo scale or on a building. - Check key pairs (`AV`, `To`, `LT`, `r.`, `ye`). -- **Overshoot**: round letters must extend slightly above cap height/x-height and below the baseline to look equal - in height. -- **Horizontal strokes thinner** than verticals to look equal; thin strokes where they meet at junctions to avoid dark - spots. -- **Consistent stroke logic**: contrast axis, terminal angles, corner radii and aperture should follow one rule. -- **Tittles and dots** (on `i`, `j`) are tempting substitution points; use them only if the substitute reads at small - size and doesn't feel like a cliché. -- **Small-size fixes**: open apertures, larger counters, slightly heavier weight and looser spacing for a - small-use version (optical size) of the wordmark. -- In SVG, final logo type must be **outlined paths**, not `<text>` — see `svg-construction.md`. - -## 5. Lockups: symbol + type - -- A lockup fixes the positions and relative sizes of all elements (symbol, wordmark, tagline). Once locked, they are - never rearranged ad hoc. -- Create several lockups for different formats: **horizontal** (most common for headers/signage), **stacked / - vertical** (square formats, social), **symbol only** (app icon, favicon, avatar), **wordmark only**, **with - tagline**. Simplify complexity as size shrinks — a letterhead lockup may carry more than a mobile header. -- **Balance**: an ornate or detailed symbol pairs with plain, neutral type; a bold symbol pairs with a lighter type - weight. The goal is complement, not contrast for its own sake. -- **Alignment**: align the symbol optically — typically centred on the cap height or x-height band, or spanning - baseline to cap height/ascender. Check by eye; geometric centring often looks low. -- **Spacing**: the gap between symbol and wordmark is usually derived from an element of the mark (e.g. the width - of a stem, the height of the x-height, or a fraction of the symbol's width) so it scales consistently. -- **Tagline**: significantly smaller, a lighter or contrasting style, aligned to the wordmark; define the size ratio - and specify a version without it. Taglines rarely survive at small sizes — drop them there. -- Details like "bold vs slightly more bold" or a small kerning tweak aren't noticed consciously, but they are the - difference between good and great. - -## 6. Brand typefaces beyond the logo - -- Corporate typography is often a different entity from the logo's letterforms. -- **Body/text face**: simple, highly readable, ideally a neutral sans with many weights; consider system/web - availability and cost. -- **Display/headline face**: more freedom, providing contrast with the body text. -- **Limit to two families** in most identities (weights and italics within them are fine). More families dilute - the voice. -- Specify web fallbacks and which faces are licensed for which uses. - -## 7. Licensing and technical checks - -- Free fonts are frequently **personal-use only**. A logo is commercial use: confirm the licence allows logo / - trademark use (some licences restrict it or require a separate logo licence). Open-licence families (e.g. SIL Open - Font License) are generally safe for logos. -- Check glyph coverage: accented characters for all the brand's languages, punctuation, `@`, `&`, numerals, currency - symbols. Incomplete fonts silently substitute or show boxes. -- Prefer professional OpenType fonts with proper kerning tables. -- Once outlined in the logo file, the font is no longer needed to display the logo — but the brand typefaces still - need licences for everyday use. - -## 8. Common mistakes - -- Using the default weight and spacing of a popular geometric sans with no modification — instantly generic. -- Too many typefaces in one mark (a script + a serif + a sans). -- Tracking lowercase text very wide (lowercase is designed to be read tight). -- Effects on type (outlines, drop shadows, bevels, distortion via horizontal/vertical scaling). Never scale type - non-uniformly to fit — choose a condensed/extended width instead. -- Overused faces chosen because they are fashionable this year. -- Thin hairlines or tiny counters that close up at small sizes. -- Letters so customised the name becomes a puzzle. diff --git a/.claude/skills/logo-design/references/visual-techniques.md b/.claude/skills/logo-design/references/visual-techniques.md deleted file mode 100644 index 9dd2f45..0000000 --- a/.claude/skills/logo-design/references/visual-techniques.md +++ /dev/null @@ -1,226 +0,0 @@ -# Visual Techniques & Optical Corrections - -The craft layer: how forms are perceived, and the small corrections that separate a good mark from a -perfect one. Read during development and refinement (phases 4–5), and when critiquing. - -## Contents -1. Geometry, grids and the golden ratio -2. Balance (stability, proportion, composition, consistency, scalability) -3. Optical corrections: overshoot, bone effect, irradiation, same-size look -4. Composition dynamics between shapes -5. Symmetry vs. asymmetry -6. Solid vs. line -7. Sharp vs. round -8. Negative space & figure/ground -9. Visual paradoxes: impossible figures, ambiguity, motion -10. Gradients, light and shading -11. Dimension -12. Visibility devices (outline, container) -13. Patterns -14. Reviewing with fresh eyes - ---- - -## 1. Geometry, grids and the golden ratio - -- **See the world as simple geometry.** Train yourself to reduce objects to circles, squares, triangles and - their parts. Once you feel the structure behind things, composition becomes easier and the results feel - inevitable. -- **Construct from primitives.** Circles, arcs of consistent radii, straight lines at deliberate angles. - Curves built from circle segments are easy to grid and reproduce; free-drawn curves are harder to justify - and to fix. -- **Golden ratio (≈1.618) and Fibonacci proportions** (1, 2, 3, 5, 8, 13, 21 …) are useful as a standard of - organisation — e.g. circle radii in a construction following 1 : 1.618 or Fibonacci multiples. Use them where - they help; never let numbers overpower a form that already feels right. If a form feels right, the maths - should not get in the way. -- **Whole-number angles.** Aim for clean angles: 0°, 15°, 30°, 45°, 60°, 90°. An element at 43° should be 45°; - 33.46° should become 30° or 35°. Lines that are 1–2° off horizontal/vertical read as mistakes, and clean - angles show the elements were placed deliberately. (Colour values too: prefer whole-number CMYK percentages.) -- **Perfect primitives.** A circle must be a perfect circle and a square a perfect square — unless the deviation - is an intentional optical correction. -- **Gridding is for finishing, not for starting.** Apply construction grids after the concept is approved to find - and fix misalignments, uneven radii and stray angles. The changes are usually too small for viewers to notice - consciously — but they feel the difference. -- **Don't over-grid.** Complex organic curves may not decompose into circles; it's fine to leave them ungridded. - If something doesn't work within the grid, make it work outside the grid. A construction drawing cluttered with - dozens of meaningless circles is a presentation gimmick, not rigour. - -## 2. Balance - -1. **Stability** — the mark should not feel accidentally tilted. There should be a sense of gravity; where the - concept allows, a heavier or wider base feels grounded. -2. **Proportion** — aim for an overall footprint closer to a square than a long rectangle. Very tall or very wide - symbols are awkward to use and to lock up with type. (Library data: ~76 % of standalone icons are between - 0.8 : 1 and 1.25 : 1.) -3. **Composition** — distribute elements and gaps evenly. Clusters in one area and emptiness in another create - dissonance (unless tension is the intent). -4. **Consistency** — keep weights related. Very thick next to very thin reads as imbalance; in line marks, keep - stroke width consistent throughout. Repeat radii and angles. -5. **Scalability** — every decision must survive enlargement and reduction. - -## 3. Optical corrections - -### Overshoot -Round and pointed shapes look smaller than flat-edged shapes of the same measured height. A circle placed -between squares of equal height looks too small; an `O` beside an `H` looks short. Let curves and apexes extend -slightly past the baseline/cap line/edge — typically **1–3 % of the height** for curves and more for sharp points -(triangles/apexes can need 3–6 %). Do it in the final stage, with one or two anchor tweaks. This is the -difference between great and perfect. - -### Bone effect -Where a curve meets a straight line tangentially (a capsule: two semicircles joined by straight sides; rounded -rectangles; rounded triangles), the straight segment appears to pinch inward like a bone. Fixes, from quick to best: -1. Stretch the end curves into ellipses (softens but doesn't remove it). -2. Pull the curve handles so curvature ramps up gradually instead of jumping from zero to the full circle. -3. Use a smooth curvature transition (a "squircle"/superellipse-like corner): extra anchors that ease from straight - to curved; copy the tuned curve to the symmetrical corners. -Not every instance needs fixing — sometimes the bone effect is expressive (bulkiness in a figure). Fixing it often -frees up interior space and makes rounded marks crisper at small sizes. In SVG, prefer continuous-curvature -corners (cubic Béziers with handles ≈ 0.55–0.65 of the corner size, extended past the tangent point) over plain -`rx` arcs when the corner is prominent. - -### Irradiation: white on black looks bigger -A light shape on a dark background appears larger and bolder than the identical dark shape on a light background. -Consequences: -- A reversed (white-on-dark) logo looks heavier. Provide a **reversed version with slightly thinned strokes** - (roughly 2–5 % of stroke weight), or scale the reversed version down slightly. Achieve it by offsetting the path - inward (expand a thin stroke and subtract it from the shape). -- Test both versions side by side until they look equal; record which file to use in the guidelines. -- Thin white lines on dark grounds can visually "bloom" and fill in when printed; keep counters open. - -### Same-size look for mixed shapes -Circles, squares and triangles of the same bounding box do not look the same size. Equalise by eye: circles -slightly larger than squares; triangles larger still. Same for icons in a set. - -### Horizontal vs. vertical strokes -Horizontal strokes look heavier than vertical strokes of equal thickness. In lettering and geometric marks, make -horizontals slightly thinner (often 5–10 %) to look equal. Where strokes meet at acute angles, thin them near the -junction to avoid dark ink traps and blobs at small sizes. - -### Optical centre -The optical centre of an area sits slightly above the geometric centre. A mark centred mathematically in a -container often looks low; nudge it up a little. Asymmetric shapes (a triangle pointing right, a play button) need -to be shifted toward their visual mass, not their bounding box. - -## 4. Composition dynamics between shapes - -Shapes interacting create feelings. First define the goal — harmony, tension, dynamism, balance, dissonance, -entropy — then arrange. -- Circle resting on a square of the same width → harmony, stability. -- Square balanced on a circle → tension, instability. -- Circle beside the apex of a triangle → motion. -- Circle exactly on top of a triangle's apex → balanced tension. -- Diagonals and tapering forms → movement; horizontals → calm; verticals → aspiration, strength. -- Density increasing across a form (sparse → dense lines or dots) → implied motion. - -Years of playing with forms build the intuition; in the meantime, test variations side by side. - -## 5. Symmetry vs. asymmetry - -- Perfect mirror symmetry is stable and formal but often boring; repetition by mirroring can feel mechanical. -- A subtle asymmetry keeps the eye travelling: a change in colour on one side, a detail added or removed, an - offset element, a mirrored-then-shifted part. -- Especially useful when the overall silhouette is symmetrical — let one detail break it. -- Symmetry still has its place for institutions and marks that must feel absolute (seals, public bodies). - -## 6. Solid vs. line - -- **Solid marks** look stable and strong; silhouettes stay clear when small and from a distance; bold shapes reproduce - well across media. -- **Line (monoline/outline) marks** look light and elegant; good for passive or refined brands, UI iconography and - interior signage. Downsides: weak from a distance and at small sizes unless strokes are thick enough; they are - more vulnerable to bad reproduction. -- If a mark works both ways, choose one as **primary** and the other as secondary. -- In the final SVG, expand strokes into filled outlines (see `svg-construction.md`), so scaling does not change the - line-to-size ratio unpredictably. - -## 7. Sharp vs. round - -- Sharp, angular forms read as assertive, authoritative, technical, sometimes threatening — we instinctively treat - sharp objects with caution. -- Rounded forms read as friendly, inviting, soft, safe — we want to touch and hold them. -- Keep sharp elements out of the silhouette unless the brand needs edge (security, sport, performance, luxury - precision). Most brands want to feel approachable, so rounded corners are a sensible default — but a slightly - rounded corner (small radius) often reads more premium than fully pill-shaped forms. -- Mixing: a sharp exterior with soft interior details (or vice versa) can express duality ("secure but friendly"). - -## 8. Negative space & figure/ground - -- Every silhouette has surrounding space. Treat the negative shapes (counters, gaps, space between elements) with the - same care as the positive shapes — the inner shapes of letters echoing the outer form create coherence. -- Clever negative space (a hidden arrow, an animal between two shapes, a letter carved out of an object) creates a - moment of discovery. Keep it simple: two elements with distinct silhouettes, conceptually related. -- Gaps must be large enough to survive reduction; a 1 px gap at 32 px disappears. As a rule of thumb, make the - smallest gap ≥ 1/32 of the mark's width if it must read at favicon sizes. - -## 9. Visual paradoxes - -When something appears to be one thing and becomes another on closer inspection, the mind solves a small problem and -enjoys the solution. Three families: -1. **Impossible figures** — shapes that can't exist in 3D (reversed perspective, manipulated line connections, - misaligned layers). Study the concept, don't copy famous figures; transpose the principle (e.g. a letter whose - perspective switches direction halfway). -2. **Ambiguous forms** — one image that reads as two. Rare to succeed intentionally. The bigger risk is the - *unintended* reading: after hours of work a designer stops seeing what is obvious to others (including sexual or - offensive readings). Always ask fresh eyes, rotate the mark 90/180°, view it tiny and mirrored. -3. **Motion illusions** — tapering sweeps, speed lines, progressive repetition. For speed, run the form from thin to - thick in the reading direction (left to right in Latin-script cultures); consider right-to-left audiences. - -Other tools for turning a mundane shape into something memorable: layering, interlacing, overlapping with -transparency, juxtaposing flat and dimensional, and playing with colour at intersections. - -## 10. Gradients, light and shading - -- **Gradients are easy and therefore cliché.** They can soften a mark and add depth, but they reproduce poorly: - vivid RGB gradients lose vigour in CMYK print and blur at small sizes. Unless the logo is digital-only, keep a flat - version as the master and treat gradients as an optional enhancement. -- **Simplify gradation.** Replace a smooth gradient with a few distinct steps (3–5 flat bands of related hues). At - small sizes the steps read as seamless; at large sizes they look crafted rather than default. -- **Light and shading for plain marks.** Simple is not always attractive — some marks look plain because they lack - content. Introducing a light source (a fold, an overlap shadow, a highlight) can add depth and sophistication. If the - mark is interesting in its reduced state, don't add light. -- **Few tones.** Many shades of grey kill sharpness at small sizes. Use at most highlight, one mid-tone, shadow and - background ("light–dark" chiaroscuro reduction). For letterforms and abstract marks, one mid-tone applied to the - parts that fold under or overlap others is usually enough. -- **Structure of light on a sphere**: highlight, midtone, core shadow, reflected light, cast shadow, occlusion shadow. - Understand it to shade any form convincingly; then reduce to 2–3 tones. -- **Tapered strokes (engraving style)**: tonal gradation built from arrow-like strokes that thin toward the tip — a - versatile way to render volume on organic forms. Time-consuming; reserve for brands where craft is the message. - -## 11. Dimension - -- Realistic 3D renders carry too much detail for logos. -- Dimension achieved by the simplest means — two or three flat faces, an isometric fold, an overlap — can be striking - and widens the space of original solutions, since flat combinations of primitives are largely exhausted. -- Always keep a version that works flat and in one colour. - -## 12. Visibility devices - -A logo designed for light backgrounds may not invert well (a white swan inverted becomes a black swan — maybe desired, -maybe not). For busy, photographic or multicoloured backgrounds use a **graphic device**: -- An outline (a sufficiently thick light stroke around the silhouette), or -- A containing shape: circle for circular marks; square or rounded square for most others (the safest for rectangular - formats and app icons). A basic container may not be the most beautiful, but it is functional. -- The device's proportions should match the mark's (square mark → square device; wide mark → wide device); mismatches - create distracting empty space. - -## 13. Patterns - -- A grid is the heart of a pattern. Square grids are the most versatile but most common → sameness. Try triangles, - hexagons, rotated squares (diamonds), or grids derived from the mark's angles. -- Plain tessellations are straightforward but get boring; prefer grids that allow variation. -- Distribute colour evenly; too much contrast disrupts flow, too little makes it invisible. -- Derive components from the mark when possible so the pattern and logo feel related without duplicating. -- Test at multiple scales (card, wall, vehicle) and, for print, keep ink coverage reasonable. - -## 14. Reviewing with fresh eyes (the dialectical approach) - -- **Save every meaningful iteration** side by side instead of overwriting. Designers often favour a lesser variant - in the moment of excitement and lose the better one. -- **Compare pairs** directly and pick the stronger; then iterate from the winner. -- **Rest before deciding** — fatigue makes judgement less objective. -- **Mirror the mark.** Flipping horizontally reveals proportion problems the eye has adapted to (especially in - animals and figures). -- **Blur/squint and shrink.** If the silhouette is unclear when blurred, the idea is not strong enough. -- **Physical aids**: for complex figures, references and simple 3D mock-ups (paper, clay, wire) reveal better - viewpoints and inconsistencies. diff --git a/.claude/skills/logo-design/scripts/build_catalog.py b/.claude/skills/logo-design/scripts/build_catalog.py deleted file mode 100644 index bbaa1d5..0000000 --- a/.claude/skills/logo-design/scripts/build_catalog.py +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/env python3 -"""Rebuild the reference-library catalog from the SVG files + visual classifications. - -Maintainer tool. Produces, inside assets/library/: - catalog.json one record per SVG (structure, colours, complexity + visual classification) - stats.json distribution statistics used by svg_audit.py for comparisons - gallery.html a self-contained, filterable browser for humans (open it locally) - -Usage: - python3 scripts/build_catalog.py # rebuild everything - python3 scripts/build_catalog.py --check # verify every SVG has a classification - -To add logos: drop SVGs into assets/library/svg/, add matching objects to -assets/library/classifications.json (schema: see references/library-guide.md), then rerun. -""" -import argparse -import json -import os -import statistics -import sys -from collections import Counter - -sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -import svglib # noqa: E402 - -CLASS_PATH = os.path.join(svglib.LIBRARY_DIR, "classifications.json") -GALLERY_PATH = os.path.join(svglib.LIBRARY_DIR, "gallery.html") - - -def analyse(path, names): - fname = os.path.basename(path) - base = fname[:-4] - is_icon = base.endswith("-icon") - brand = base[:-5] if is_icon else base - raw, root = svglib.load_svg(path) - vb = svglib.view_box(root) - w, h = (vb[2], vb[3]) if vb else (None, None) - aspect = round(w / h, 3) if w and h else None - counts = svglib.element_counts(root) - geo = svglib.document_geometry(root) - colors = svglib.collect_colors(root) - fams = Counter(svglib.hue_family(c) for c in colors) - chroma = sorted({f for f in fams if f not in ("black", "white", "gray")}) - if len(chroma) == 1: - primary = chroma[0] - elif len(chroma) > 1: - primary = "multi" - else: - primary = "mono" - pair = None - if is_icon and brand in names: - pair = brand + ".svg" - elif not is_icon and (brand + "-icon") in names: - pair = brand + "-icon.svg" - return { - "file": fname, - "brand": brand, - "variant": "icon" if is_icon else "main", - "pair": pair, - "width": w, - "height": h, - "aspect": aspect, - "aspect_class": svglib.aspect_class(aspect), - "bytes": os.path.getsize(path), - "shapes": sum(counts.get(t, 0) for t in svglib.SHAPE_TAGS), - "anchors": geo["anchors"], - "colors": colors, - "n_colors": len(colors), - "color_families": sorted(fams), - "primary_family": primary, - "gradients": counts.get("linearGradient", 0) + counts.get("radialGradient", 0), - "has_mask": counts.get("mask", 0) > 0, - "has_filter": counts.get("filter", 0) > 0, - } - - -def pct(values, q): - values = sorted(values) - if not values: - return None - k = (len(values) - 1) * q - f, c = int(k), min(int(k) + 1, len(values) - 1) - return round(values[f] + (values[c] - values[f]) * (k - f), 2) - - -def build_stats(records): - def dist(vals): - return {"p10": pct(vals, .1), "p25": pct(vals, .25), "median": pct(vals, .5), - "p75": pct(vals, .75), "p90": pct(vals, .9), "p95": pct(vals, .95)} - icons = [r for r in records if r["aspect_class"] == "square"] - n = len(records) - return { - "count": n, - "anchors_all": dist([r["anchors"] for r in records]), - "anchors_square": dist([r["anchors"] for r in icons]), - "shapes_all": dist([r["shapes"] for r in records]), - "n_colors_all": dist([r["n_colors"] for r in records]), - "n_colors_square": dist([r["n_colors"] for r in icons]), - "gradient_share": round(sum(1 for r in records if r["gradients"]) / n, 3), - "mark_types": Counter(r.get("mark_type") for r in records).most_common(), - "primary_family": Counter(r["primary_family"] for r in records).most_common(), - "aspect_class": Counter(r["aspect_class"] for r in records).most_common(), - "techniques": Counter(t for r in records for t in r.get("techniques", [])).most_common(), - "geometry": Counter(g for r in records for g in r.get("geometry", [])).most_common(), - "industries": Counter(r.get("industry") for r in records).most_common(), - } - - -GALLERY_TEMPLATE = """<!doctype html> -<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"> -<title>Logo Reference Library - -

    Logo Reference Library — for studying patterns; all marks are trademarks of their owners. Never copy.

    -
    - - - - - - - - -
    -
    - -""" - - -def main(): - ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) - ap.add_argument("--check", action="store_true", help="only verify classification coverage") - args = ap.parse_args() - - files = sorted(f for f in os.listdir(svglib.LIBRARY_SVG_DIR) if f.lower().endswith(".svg")) - names = {f[:-4] for f in files} - classes = {} - if os.path.exists(CLASS_PATH): - with open(CLASS_PATH, encoding="utf-8") as fh: - classes = {c["file"]: c for c in json.load(fh)} - missing = [f for f in files if f not in classes] - if args.check: - print(f"{len(files)} SVGs, {len(classes)} classifications, {len(missing)} missing") - for f in missing: - print(" missing:", f) - return 1 if missing else 0 - - records = [] - for f in files: - try: - rec = analyse(os.path.join(svglib.LIBRARY_SVG_DIR, f), names) - except Exception as exc: # keep going; report broken files - print(" ! could not parse", f, exc, file=sys.stderr) - continue - c = classes.get(f, {}) - for key in ("mark_type", "symbol_type", "subject", "geometry", "techniques", "type_style", "case", - "mood", "industry", "exemplary", "note"): - rec[key] = c.get(key) - rec["techniques"] = rec["techniques"] or [] - rec["geometry"] = rec["geometry"] or [] - rec["mood"] = rec["mood"] or [] - rec["exemplary"] = bool(rec["exemplary"]) - records.append(rec) - - with open(svglib.CATALOG_PATH, "w", encoding="utf-8") as fh: - json.dump(records, fh, ensure_ascii=False, separators=(",", ":")) - stats = build_stats(records) - with open(svglib.STATS_PATH, "w", encoding="utf-8") as fh: - json.dump(stats, fh, ensure_ascii=False, indent=1) - slim = [{k: r[k] for k in ("file", "brand", "mark_type", "symbol_type", "subject", "techniques", "geometry", - "industry", "exemplary", "note", "n_colors", "primary_family", "aspect_class")} - for r in records] - with open(GALLERY_PATH, "w", encoding="utf-8") as fh: - fh.write(GALLERY_TEMPLATE.replace("__DATA__", json.dumps(slim, ensure_ascii=False))) - print(f"catalog: {len(records)} records -> {svglib.CATALOG_PATH}") - print(f"stats -> {svglib.STATS_PATH}") - print(f"gallery -> {GALLERY_PATH}") - if missing: - print(f"warning: {len(missing)} SVGs have no classification (run with --check)") - print("median anchors (square):", stats["anchors_square"]["median"], "| p90:", stats["anchors_square"]["p90"]) - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/.claude/skills/logo-design/scripts/concept_sheet.py b/.claude/skills/logo-design/scripts/concept_sheet.py deleted file mode 100644 index bac44cb..0000000 --- a/.claude/skills/logo-design/scripts/concept_sheet.py +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env python3 -"""Build a one-page concept overview (SVG + PNG) to show the user BEFORE any kit is produced. - -Each concept gets a card: the artwork large, the same mark at 64 / 32 / 16 px (so scale is judged honestly), -a letter + name, and a one-line idea. Optionally a secondary file per concept (e.g. the lockup) under the symbol. -The PNG is rendered with render_png.py's backends (cairosvg, rsvg-convert, Inkscape, Chrome, Quick Look); -the SVG is always written. - -Usage: - python3 scripts/concept_sheet.py a.svg b.svg c.svg --names "Next Block" "Ranked F" "Forward f" \\ - --notes "One block steps forward: the next move." "An F of ranked priority bars." "The i-dot steps ahead." \\ - --title "Fabbit — logo concepts" --recommend 1 -o concepts.png - python3 scripts/concept_sheet.py a.svg b.svg c.svg --lockups a-h.svg b-h.svg c-h.svg --greyscale -o round1.png - -Show the resulting PNG to the user (view it yourself first), then stop and ask how to proceed. -""" -import argparse -import html -import os -import re -import sys - -sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -import render_png # noqa: E402 -import svglib # noqa: E402 - - -def embed(path, key, x, y, w, h): - """Nested that fits the file into the box; ids are prefixed so several files can coexist.""" - raw = open(path, encoding="utf-8", errors="ignore").read() - raw = re.sub(r"<\?xml[^>]*\?>|]*>", "", raw, flags=re.I) - raw = re.sub(r'\bid="([^"]+)"', lambda m: f'id="{key}-{m.group(1)}"', raw) - raw = re.sub(r"url\(#([^)]+)\)", lambda m: f"url(#{key}-{m.group(1)})", raw) - raw = re.sub(r'(xlink:href|href)="#([^"]+)"', lambda m: f'{m.group(1)}="#{key}-{m.group(2)}"', raw) - m = re.search(r"]*>", raw) - tag = m.group(0) - root_vb = svglib.view_box(svglib.load_svg(path)[1]) - vb = f' viewBox="{root_vb[0]:g} {root_vb[1]:g} {root_vb[2]:g} {root_vb[3]:g}"' if root_vb else "" - new_tag = re.sub(r'\s(width|height|x|y|viewBox|preserveAspectRatio)\s*=\s*"[^"]*"', "", tag) - new_tag = new_tag[:-1].rstrip("/") + f'{vb} x="{x:g}" y="{y:g}" width="{w:g}" height="{h:g}" preserveAspectRatio="xMidYMid meet">' - return raw.replace(tag, new_tag, 1) - - -def wrap(text, limit): - words, lines, line = text.split(), [], "" - for w in words: - if len(line) + len(w) + 1 > limit and line: - lines.append(line) - line = "" - line += (" " if line else "") + w - if line: - lines.append(line) - return lines - - -def main(): - ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) - ap.add_argument("files", nargs="+", help="one SVG per concept (usually the symbol)") - ap.add_argument("--lockups", nargs="*", default=[], help="optional second file per concept (lockup/wordmark)") - ap.add_argument("--names", nargs="*", default=[]) - ap.add_argument("--notes", nargs="*", default=[], help="one-sentence idea per concept") - ap.add_argument("--title", default="Logo concepts") - ap.add_argument("--subtitle", default="Concepts for review — pick a direction (or tell me what you like in each).") - ap.add_argument("--recommend", type=int, help="1-based index of the recommended concept") - ap.add_argument("--greyscale", action="store_true", help="show everything in greyscale (first-round rule)") - ap.add_argument("--width", type=int, default=1600) - ap.add_argument("-o", "--out", default="concepts.png", help="output .png (an .svg is written next to it)") - a = ap.parse_args() - - n = len(a.files) - cols = min(n, 3) - rows = (n + cols - 1) // cols - W, pad, gap = a.width, 60, 28 - card_w = (W - 2 * pad - (cols - 1) * gap) / cols - has_lock = bool(a.lockups) - art_h = 300 - lock_h = 0 - if has_lock: - ratios = [] - for lp in a.lockups: - if lp: - vb = svglib.view_box(svglib.load_svg(lp)[1]) - if vb and vb[3]: - ratios.append(vb[2] / vb[3]) - # wide lockups fit a short slot; squarish ones (emblems, stacked lockups) need more height - lock_h = 120 if not ratios or min(ratios) >= 2.2 else (170 if min(ratios) >= 1.4 else 210) - card_h = 40 + art_h + (lock_h + 24 if has_lock else 0) + 90 + 150 + (30 if a.recommend else 0) + 20 - header = 150 - H = header + rows * card_h + (rows - 1) * gap + pad - parts = [] - filt = ('' if a.greyscale else "") - gattr = ' filter="url(#grey)"' if a.greyscale else "" - font = "font-family=\"system-ui,-apple-system,'Segoe UI',Helvetica,Arial,sans-serif\"" - parts.append(f'') - parts.append(f'{html.escape(a.title)}') - parts.append(f'{html.escape(a.subtitle)}') - for i, f in enumerate(a.files): - r, c = divmod(i, cols) - x = pad + c * (card_w + gap) - y = header + r * (card_h + gap) - rec = a.recommend == i + 1 - parts.append(f'') - inner_x, inner_w = x + 30, card_w - 60 - parts.append(f"" + embed(f, f"c{i}", inner_x, y + 40, inner_w, art_h) + "") - yy = y + 40 + art_h - if has_lock and i < len(a.lockups) and a.lockups[i]: - yy += 24 - parts.append(f"" + embed(a.lockups[i], f"l{i}", inner_x, yy, inner_w, lock_h) + "") - yy += lock_h - # small sizes: 64 / 32 / 16 px, as they would appear - sx = inner_x - yy += 26 - for s in (64, 32, 16): - parts.append(f"" + embed(f, f"s{i}{s}", sx, yy + (64 - s), s, s) + "") - parts.append(f'{s}px') - sx += s + 26 - yy += 120 - label = f"{chr(65 + i)} · {a.names[i] if i < len(a.names) else os.path.splitext(os.path.basename(f))[0]}" - parts.append(f'{html.escape(label)}') - if rec: - parts.append(f'RECOMMENDED') - yy += 28 - note = a.notes[i] if i < len(a.notes) else "" - for k, line in enumerate(wrap(note, int(inner_w / 9.6))[:3]): - parts.append(f'{html.escape(line)}') - doc = (f'{filt}{"".join(parts)}\n') - base = os.path.splitext(a.out)[0] - svg_path = base + ".svg" - with open(svg_path, "w", encoding="utf-8") as fh: - fh.write(doc) - print("wrote", svg_path) - png_path = base + ".png" - used = render_png.render(svg_path, png_path, W, int(round(H))) - if used: - print(f"wrote {png_path} via {used} — view it, show it to the user, then stop and ask") - else: - print("PNG skipped (no renderer; see render_png.py --which) — show the SVG instead") - - -if __name__ == "__main__": - main() diff --git a/.claude/skills/logo-design/scripts/export_variants.py b/.claude/skills/logo-design/scripts/export_variants.py deleted file mode 100644 index 897c909..0000000 --- a/.claude/skills/logo-design/scripts/export_variants.py +++ /dev/null @@ -1,233 +0,0 @@ -#!/usr/bin/env python3 -"""Export the standard delivery variants of a logo from one master SVG (no required dependencies). - -SVG variants (next to the master, or in --out-dir): - -black.svg one-colour black (all paint -> #000000; gradients flattened) - -white.svg one-colour white, for dark backgrounds - -mono-.svg one-colour in a brand colour (repeatable --mono) - -square.svg mark centred on a 256×256 canvas with padding (avatar / social master) - -favicon.svg tight square version for browser tabs (works as favicon.svg) - -app-icon.svg mark in white (or --icon-fg) on a rounded-square tile (--icon-bg) - -Raster (needs any backend of render_png.py: cairosvg, rsvg-convert, inkscape, Chrome/Chromium, or macOS Quick Look): - --png 32 512 1024 PNGs of every SVG variant written (transparent) - --web-icons favicon.ico (16/32/48), favicon-16/32/48.png, apple-touch-icon.png (180), - icon-192.png, icon-512.png, maskable-512.png, plus site.webmanifest and - head-snippet.html — the full web/PWA icon set - -Usage: - python3 scripts/export_variants.py brand-symbol.svg --mono "#0F7C80" --icon-bg "#0F7C80" --title "Brand" - python3 scripts/export_variants.py brand-horizontal.svg --only black white mono --mono "#0F7C80" - python3 scripts/export_variants.py brand-symbol.svg --web-icons --icon-bg "#0F7C80" --out-dir dist/web - python3 scripts/export_variants.py brand-symbol.svg --favicon-source brand-symbol-small.svg --web-icons - -Notes: -- One-colour conversion replaces every fill/stroke/stop colour. White shapes used as fake cut-outs become - blobs: fix the master with real holes (fill-rule="evenodd"), or use --keep-white. -- Reversed (white) marks look heavier (irradiation); for critical uses thin the white geometry by hand. -- Small sizes deserve a simplified drawing: pass it with --favicon-source (used for favicon/app icon/web icons). -- Optical centring: --optical-offset -0.02 nudges square/app-icon/favicon marks up by 2 % of the canvas. -""" -import argparse -import html -import json -import os -import re -import sys -import tempfile - -sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -import svglib # noqa: E402 -import render_png # noqa: E402 - -PAINT_ATTR = re.compile(r'\b(fill|stroke|stop-color)\s*=\s*"([^"]*)"') -PAINT_CSS = re.compile(r'\b(fill|stroke|stop-color)\s*:\s*([^;"}]+)') - - -def recolor(raw, color, keep_white=False): - def swap(value): - v = value.strip() - low = v.lower() - if low in ("none", "transparent") or low.startswith("url("): - return v - norm = svglib.normalize_color(v) or (low if low == "currentcolor" else None) - if norm is None: - return v - if keep_white and norm == "#ffffff": - return v - return color - - raw = PAINT_ATTR.sub(lambda m: f'{m.group(1)}="{swap(m.group(2))}"', raw) - raw = PAINT_CSS.sub(lambda m: f"{m.group(1)}:{swap(m.group(2))}", raw) - # Unpainted shapes default to black; give the root a fill so they follow the new colour. - raw = re.sub(r"]*\bfill=)", f'.*?", "", raw, flags=re.S) - return re.sub(r"(]*>)", lambda m: m.group(1) + f"{html.escape(title)}", raw, count=1) - - -def inner_markup(raw): - m = re.search(r"]*>(.*)", raw, re.S) - body = m.group(1) if m else raw - return re.sub(r".*?", "", body, flags=re.S) - - -def square_wrap(raw, root, padding=0.1, bg=None, radius=0.0, fg=None, symbol_scale=None, offset=0.0, title=None): - """Centre the artwork's real bounding box on a 256×256 canvas (optionally on a rounded tile).""" - vb = svglib.view_box(root) - geo = svglib.document_geometry(root) - bb = geo["bbox"] or (vb[0], vb[1], vb[0] + vb[2], vb[1] + vb[3]) - w, h = bb[2] - bb[0], bb[3] - bb[1] - side = max(w, h) - canvas = 256.0 - target = symbol_scale if symbol_scale else (1 - 2 * padding) - s = round(canvas * target / side, 3) - tx = round((canvas - w * s) / 2 - bb[0] * s, 2) - ty = round((canvas - h * s) / 2 - bb[1] * s + offset * canvas, 2) - src = recolor(raw, fg) if fg else raw - body = inner_markup(src) - root_tag = re.search(r"]*>", src) - carried = "" - if root_tag: - for attr in ("fill", "stroke", "fill-rule", "clip-rule", "stroke-width", "stroke-linecap", "stroke-linejoin", "style"): - m = re.search(r'\s%s\s*=\s*"([^"]*)"' % re.escape(attr), root_tag.group(0)) - if m: - carried += f' {attr}="{m.group(1)}"' - tile = f'' if bg else "" - t = f"{html.escape(title)}" if title else "" - return (f'{t}' - f'{tile}{body}') - - -def main(): - ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) - ap.add_argument("master") - ap.add_argument("--out-dir") - ap.add_argument("--name", help="base name for outputs (default: master file name)") - ap.add_argument("--title", help="accessible for every output, e.g. 'Harbor logo'") - ap.add_argument("--mono", action="append", default=[], help="extra one-colour version(s), e.g. '#0F7C80'") - ap.add_argument("--icon-bg", default="#111111", help="app-icon / apple-touch / maskable tile colour") - ap.add_argument("--icon-fg", default="#ffffff", help="mark colour on tiles ('keep' = original colours)") - ap.add_argument("--icon-scale", type=float, default=0.62, help="mark size on the app-icon tile (0.55–0.7 typical)") - ap.add_argument("--optical-offset", type=float, default=0.0, help="vertical nudge for square outputs (fraction; negative = up)") - ap.add_argument("--favicon-source", help="simplified small-size drawing used for favicon/app-icon/web icons") - ap.add_argument("--keep-white", action="store_true", help="leave pure-white paint untouched in one-colour versions") - ap.add_argument("--only", nargs="*", help="subset: black white mono square favicon app-icon") - ap.add_argument("--png", nargs="*", type=int, default=[], help="PNG sizes for every SVG variant written") - ap.add_argument("--web-icons", action="store_true", help="favicon.ico + PNG icon set + webmanifest + head snippet") - a = ap.parse_args() - - raw, root = svglib.load_svg(a.master) - small_raw, small_root = svglib.load_svg(a.favicon_source) if a.favicon_source else (raw, root) - out_dir = a.out_dir or os.path.dirname(os.path.abspath(a.master)) - os.makedirs(out_dir, exist_ok=True) - base = a.name or os.path.splitext(os.path.basename(a.master))[0] - want = set(a.only) if a.only else {"black", "white", "mono", "square", "favicon", "app-icon"} - fg = None if a.icon_fg == "keep" else a.icon_fg - written = [] - - def write(suffix, content): - p = os.path.join(out_dir, f"{base}-{suffix}.svg") - with open(p, "w", encoding="utf-8") as fh: - fh.write(content) - written.append(p) - return p - - if "black" in want: - write("black", set_title(recolor(raw, "#000000", a.keep_white), a.title)) - if "white" in want: - write("white", set_title(recolor(raw, "#ffffff"), a.title)) - if "mono" in want: - for c in a.mono: - hx = svglib.normalize_color(c) - if not hx: - print("skip invalid colour", c) - continue - write(f"mono-{hx[1:]}", set_title(recolor(raw, hx, a.keep_white), a.title)) - if "square" in want: - write("square", square_wrap(raw, root, padding=0.08, offset=a.optical_offset, title=a.title)) - if "favicon" in want: - write("favicon", square_wrap(small_raw, small_root, padding=0.02, offset=a.optical_offset, title=a.title)) - if "app-icon" in want: - write("app-icon", square_wrap(small_raw, small_root, bg=a.icon_bg, radius=0.225, fg=fg, - symbol_scale=a.icon_scale, offset=a.optical_offset, title=a.title)) - - colors = svglib.collect_colors(root) - if any(svglib.lightness(c) > 0.97 for c in colors) and len(colors) > 1: - print("note: master contains white paint — check the one-colour files for blobs (fake cut-outs).") - - raster = [] - if a.png: - for p in list(written): - for size in a.png: - txt = open(p, encoding="utf-8").read() - vb = re.search(r'viewBox\s*=\s*"[\d.\-]+[ ,]+[\d.\-]+[ ,]+([\d.]+)[ ,]+([\d.]+)"', txt) - ratio = float(vb.group(1)) / float(vb.group(2)) if vb else 1.0 - w, h = (size, max(1, round(size / ratio))) if ratio >= 1 else (max(1, round(size * ratio)), size) - png = p[:-4] + f"-{size}.png" - if render_png.render(p, png, w, h): - raster.append(png) - else: - print("PNG export skipped: no rendering backend (see: python3 scripts/render_png.py --which)") - break - - if a.web_icons: - with tempfile.TemporaryDirectory() as tmp: - fav_svg = os.path.join(tmp, "fav.svg") - with open(fav_svg, "w", encoding="utf-8") as fh: - fh.write(square_wrap(small_raw, small_root, padding=0.02, offset=a.optical_offset, title=a.title)) - tile_svg = os.path.join(tmp, "tile.svg") - with open(tile_svg, "w", encoding="utf-8") as fh: - fh.write(square_wrap(small_raw, small_root, bg=a.icon_bg, radius=0.0, fg=fg, - symbol_scale=a.icon_scale, offset=a.optical_offset)) - mask_svg = os.path.join(tmp, "mask.svg") # maskable: keep the mark inside the 80 % safe zone - with open(mask_svg, "w", encoding="utf-8") as fh: - fh.write(square_wrap(small_raw, small_root, bg=a.icon_bg, radius=0.0, fg=fg, - symbol_scale=min(a.icon_scale, 0.5), offset=a.optical_offset)) - jobs = [(fav_svg, "favicon-16.png", 16), (fav_svg, "favicon-32.png", 32), (fav_svg, "favicon-48.png", 48), - (tile_svg, "apple-touch-icon.png", 180), (tile_svg, "icon-192.png", 192), - (tile_svg, "icon-512.png", 512), (mask_svg, "maskable-512.png", 512)] - ok = True - for src, fname, size in jobs: - dst = os.path.join(out_dir, fname) - if render_png.render(src, dst, size, size): - raster.append(dst) - else: - ok = False - print(f"web icons skipped: could not render {fname} (see: python3 scripts/render_png.py --which)") - break - if ok: - ico = os.path.join(out_dir, "favicon.ico") - render_png.write_ico([os.path.join(out_dir, f"favicon-{s}.png") for s in (16, 32, 48)], ico) - raster.append(ico) - fav_copy = os.path.join(out_dir, "favicon.svg") - with open(fav_svg, encoding="utf-8") as src, open(fav_copy, "w", encoding="utf-8") as dst: - dst.write(src.read()) - raster.append(fav_copy) - manifest = {"name": a.title or base, "icons": [ - {"src": "/icon-192.png", "sizes": "192x192", "type": "image/png"}, - {"src": "/icon-512.png", "sizes": "512x512", "type": "image/png"}, - {"src": "/maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable"}], - "theme_color": a.icon_bg, "background_color": a.icon_bg, "display": "standalone"} - with open(os.path.join(out_dir, "site.webmanifest"), "w", encoding="utf-8") as fh: - json.dump(manifest, fh, indent=2) - with open(os.path.join(out_dir, "head-snippet.html"), "w", encoding="utf-8") as fh: - fh.write('\n' - '\n' - '\n' - '\n' - f'\n') - raster += [os.path.join(out_dir, "site.webmanifest"), os.path.join(out_dir, "head-snippet.html")] - - for p in written + raster: - print("wrote", p) - - -if __name__ == "__main__": - main() diff --git a/.claude/skills/logo-design/scripts/presentation_board.py b/.claude/skills/logo-design/scripts/presentation_board.py deleted file mode 100644 index 5a40195..0000000 --- a/.claude/skills/logo-design/scripts/presentation_board.py +++ /dev/null @@ -1,409 +0,0 @@ -#!/usr/bin/env python3 -"""Build a client-ready concept presentation (single HTML file, no dependencies). - -Follows references/presentation-delivery.md: title, "what we heard", then each concept with its -one-sentence idea, rationale, the mark large / small / reversed, and six mockups chosen for the client's -industry, followed by a side-by-side comparison and a recommendation. Greyscale by default for a first -round; set "greyscale": false for colour, and "final": true for a single final-design board. - -Usage: - python3 scripts/presentation_board.py spec.json -o presentation.html - python3 scripts/presentation_board.py spec.json -o board.html --png-dir slides # + one PNG per slide - python3 scripts/presentation_board.py --list-mockups - -spec.json (paths relative to the spec file; see templates/presentation-spec.example.json): -{ - "brand": "Kiln", "tagline": "Small-batch roasters", "brief": "…", "adjectives": ["warm", "crafted"], - "industry": "coffee", # picks relevant mockups (see --list-mockups) - "mockups": ["cup", "bag", "social"], # optional explicit list (overrides industry preset) - "nav": ["Shop", "Cafés", "Story"], # optional website menu items - "brand_color": "#B5532F", "greyscale": true, "final": false, "round": 1, - "concepts": [ - {"name": "Kiln K", "symbol": "b-symbol.svg", "lockup": "b-horizontal.svg", "stacked": "b-stacked.svg", "avatar": "b-avatar.svg", - "idea": "One sentence.", "rationale": ["…", "…"]} - ], - "recommendation": "…" -} -Each concept needs at least one of symbol / lockup / avatar; "stacked" (optional) is used on bags, signs and badges. -Optional colour artwork (otherwise the mark is forced to white on those surfaces): - "symbol_on_tile" / "stacked_on_tile" (or "lockup_on_tile") — for brand-colour tiles (cards, app icon, cup, shirt, bag); - "symbol_on_dark" / "lockup_on_dark" / "stacked_on_dark" — for the near-black signage, README, terminal and reversed strip. -Top-level "tile_color" overrides brand_color for the tiles (e.g. a dark ink so a bright second colour can show). -Missing ones fall back sensibly -(a wordmark-only concept can provide just "lockup" plus an "avatar" for small uses). -""" -import argparse -import datetime -import html -import json -import os -import re -import sys -import unicodedata - -sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -import svglib # noqa: E402 - -PRESETS = { - "software": ["readme", "app-icon", "website", "terminal", "sticker", "social"], - "consumer-app": ["app-icon", "website", "social", "favicon-tab", "sticker", "business-card"], - "coffee": ["cup", "bag", "signage", "business-card", "social", "tote"], - "food": ["bag", "cup", "signage", "box", "social", "business-card"], - "retail": ["shopping-bag", "signage", "website", "box", "social", "tote"], - "fashion": ["shopping-bag", "tshirt", "signage", "social", "business-card", "tote"], - "services": ["business-card", "website", "signage", "social", "badge", "app-icon"], - "event": ["badge", "tshirt", "website", "social", "sticker", "signage"], - "education": ["website", "badge", "tshirt", "social", "business-card", "app-icon"], - "health": ["website", "app-icon", "signage", "business-card", "social", "box"], - "finance": ["payment-card", "app-icon", "website", "social", "business-card", "favicon-tab"], - "saas": ["website", "favicon-tab", "app-icon", "social", "sticker", "business-card"], -} -ALIASES = { - "fintech": "finance", "bank": "finance", "banking": "finance", "payments": "finance", "insurance": "finance", - "accounting": "finance", "b2b-saas": "saas", "startup": "saas", - "developer": "software", "developer-tools": "software", "devtool": "software", "tech": "software", - "open-source": "software", "ai": "software", "app": "consumer-app", "mobile": "consumer-app", "cafe": "coffee", - "café": "coffee", "roaster": "coffee", "restaurant": "food", "bakery": "food", "beverage": "food", "drink": "food", - "ecommerce": "retail", "shop": "retail", "store": "retail", "agency": "services", "consulting": "services", - "legal": "services", "conference": "event", "festival": "event", "school": "education", - "university": "education", "clinic": "health", "wellness": "health", -} -DEFAULT_NAV = {"software": ["Docs", "Pricing", "GitHub"], "coffee": ["Shop", "Cafés", "Story"], - "food": ["Menu", "Order", "About"], "retail": ["Shop", "New in", "Stores"]} - -CSS = """ -:root{--ink:#161616;--muted:#6b6b6b;--line:#e6e6e2;--paper:#f7f7f4} -*{box-sizing:border-box}body{margin:0;background:#dcdcd6;font:15px/1.5 system-ui,-apple-system,Segoe UI,sans-serif;color:var(--ink)} -.slide{width:1280px;min-height:720px;margin:28px auto;background:#fff;box-shadow:0 8px 30px rgba(0,0,0,.12);padding:56px 64px 70px;position:relative;overflow:hidden} -.slide h1{font-size:44px;margin:0 0 8px;letter-spacing:-.02em}.slide h2{font-size:30px;margin:0 0 6px;letter-spacing:-.01em} -.kicker{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);margin-bottom:14px} -.idea{font-size:22px;max-width:900px;margin:6px 0 18px}.muted{color:var(--muted)} -.foot{position:absolute;left:64px;right:64px;bottom:24px;display:flex;justify-content:space-between;font-size:12px;color:var(--muted)} -.hero{display:grid;grid-template-columns:1.3fr 1fr;gap:40px;align-items:center} -.stage{height:420px;background:var(--paper);border-radius:14px;display:flex;align-items:center;justify-content:center} -.stage img{max-width:70%;max-height:62%} -ul.rat{padding-left:18px;margin:0}ul.rat li{margin:6px 0} -.sizes{display:flex;gap:18px;align-items:flex-end;margin-top:18px}.sizes div{display:flex;flex-direction:column;align-items:center;gap:4px;font-size:11px;color:var(--muted)} -.rev{background:#161616;border-radius:10px;padding:18px 22px;display:inline-flex;margin-top:14px} -.mock{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:10px} -.m{height:270px;border-radius:12px;overflow:hidden;position:relative;display:flex;align-items:center;justify-content:center} -.m .lbl{position:absolute;left:12px;bottom:10px;font-size:11px;color:rgba(0,0,0,.6);background:rgba(255,255,255,.75);padding:2px 8px;border-radius:20px} -.bc{width:250px;height:143px;background:#fff;border-radius:5px;box-shadow:0 10px 26px rgba(0,0,0,.22);padding:16px;display:flex;flex-direction:column;justify-content:space-between;transform:translate(-50px,-38px) rotate(-4deg)} -.bc2{position:absolute;width:250px;height:143px;border-radius:5px;transform:translate(70px,52px) rotate(6deg);box-shadow:0 10px 26px rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center} -.bc .t{font-size:9px;line-height:1.5;color:#333} -.phone{width:150px;height:224px;margin-bottom:14px;border-radius:24px;background:#10151c;padding:9px;box-shadow:0 10px 30px rgba(0,0,0,.3)} -.screen{width:100%;height:100%;border-radius:16px;background:linear-gradient(170deg,#e9edf1,#cfd7df);display:grid;grid-template-columns:repeat(3,1fr);gap:9px;padding:16px 10px;align-content:start} -.ai{width:32px;height:32px;border-radius:8px;background:rgba(0,0,0,.08);justify-self:center} -.bigapp{display:flex;flex-direction:column;align-items:center;gap:10px;font-size:12px;font-weight:600;color:#333;margin-left:30px} -.bigapp .bi{width:108px;height:108px;border-radius:25px;display:flex;align-items:center;justify-content:center;box-shadow:0 12px 26px rgba(0,0,0,.2)} -.web{width:340px;height:210px;background:#fff;border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.15);overflow:hidden} -.web .bar{height:22px;background:#eceff2;display:flex;gap:5px;align-items:center;padding:0 8px}.web .bar i{width:7px;height:7px;border-radius:50%;background:#c9ced4} -.web .nav{height:44px;display:flex;align-items:center;padding:0 16px;gap:14px;font-size:9px;color:#666;border-bottom:1px solid #eee} -.web .hero2{padding:18px 16px}.web .hero2 b{display:block;font-size:17px;line-height:1.2;margin-bottom:8px}.web .hero2 span{display:block;height:6px;background:#eee;border-radius:3px;margin:5px 0;width:80%} -.sign{width:300px;height:190px;background:linear-gradient(#8c8f93,#6f7276);display:flex;flex-direction:column;align-items:center;padding-top:18px} -.sign .board{width:230px;height:74px;border-radius:6px;display:flex;align-items:center;justify-content:center;box-shadow:0 6px 16px rgba(0,0,0,.3)} -.sign .door{width:80px;height:80px;margin-top:18px;background:#3d4146;border-radius:3px 3px 0 0} -.tote{width:180px;height:210px;background:#efe7d8;border-radius:4px 4px 10px 10px;position:relative;display:flex;align-items:center;justify-content:center;box-shadow:0 8px 20px rgba(0,0,0,.15);margin-top:40px} -.tote:before{content:"";position:absolute;top:-46px;left:50%;transform:translateX(-50%);width:84px;height:70px;border:9px solid #e3d8c3;border-bottom:none;border-radius:50px 50px 0 0} -.social{width:300px;background:#fff;border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.14);overflow:hidden} -.social .cover{height:70px}.social .av{width:74px;height:74px;border-radius:50%;background:#fff;border:4px solid #fff;margin:-38px 0 0 16px;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 8px rgba(0,0,0,.12);overflow:hidden} -.social .meta{padding:8px 16px 16px;font-size:11px;color:#555}.social .meta b{font-size:14px;color:#111;display:block} -.cup{position:relative;width:150px;height:200px;margin-top:30px} -.cup .body{position:absolute;inset:0;background:#f4f1ea;clip-path:polygon(0 0,100% 0,86% 100%,14% 100%);display:flex;align-items:center;justify-content:center;box-shadow:inset -18px 0 24px rgba(0,0,0,.06)} -.cup .lid{position:absolute;left:-8px;right:-8px;top:-22px;height:24px;border-radius:8px 8px 3px 3px;background:#2b2b2b} -.cup .sleeve{position:absolute;left:6%;right:6%;top:36%;height:34%;clip-path:polygon(0 0,100% 0,96% 100%,4% 100%);display:flex;align-items:center;justify-content:center} -.bag{position:relative;width:170px;height:230px;background:#e9e2d6;border-radius:6px 6px 10px 10px;box-shadow:0 12px 26px rgba(0,0,0,.2);display:flex;flex-direction:column;align-items:center;padding-top:38px;gap:14px} -.bag:before{content:"";position:absolute;top:0;left:0;right:0;height:22px;background:repeating-linear-gradient(90deg,rgba(0,0,0,.08) 0 4px,transparent 4px 8px);border-radius:6px 6px 0 0} -.bag .label{width:118px;height:118px;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center} -.bag .t{font-size:8px;letter-spacing:.14em;color:#555;text-transform:uppercase;padding:0 12px;text-align:center;line-height:1.4} -.sbag{position:relative;width:180px;height:210px;box-shadow:0 12px 26px rgba(0,0,0,.2);display:flex;align-items:center;justify-content:center;margin-top:30px} -.sbag:before{content:"";position:absolute;top:-40px;left:50%;transform:translateX(-50%);width:70px;height:56px;border:5px solid #333;border-bottom:none;border-radius:40px 40px 0 0} -.box{width:220px;height:150px;background:#f3efe6;box-shadow:14px 14px 0 rgba(0,0,0,.08),0 12px 26px rgba(0,0,0,.18);display:flex;align-items:center;justify-content:center;border-top:14px solid rgba(0,0,0,.06)} -.readme{width:360px;background:#0d1117;border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.25);padding:18px 20px;color:#c9d1d9;font-size:10px} -.readme .rh{display:flex;align-items:center;gap:10px;border-bottom:1px solid #30363d;padding-bottom:12px;margin-bottom:10px} -.readme .badges{display:flex;gap:6px;margin:8px 0}.readme .badges i{display:block;width:54px;height:12px;border-radius:3px;background:#238636}.readme .badges i:nth-child(2){background:#1f6feb}.readme .badges i:nth-child(3){background:#6e7681} -.readme .ln{height:6px;background:#21262d;border-radius:3px;margin:6px 0} -.term{width:360px;background:#1e1e1e;border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.3);overflow:hidden;font:10px/1.6 ui-monospace,Menlo,monospace;color:#d4d4d4} -.term .tb{height:22px;background:#2d2d2d;display:flex;gap:5px;align-items:center;padding:0 8px}.term .tb i{width:8px;height:8px;border-radius:50%;background:#555} -.term .tbody{padding:14px 16px;display:flex;gap:14px;align-items:center} -.sticker{width:250px;height:170px;background:linear-gradient(135deg,#9aa0a6,#6b7177);border-radius:12px;display:flex;align-items:center;justify-content:center;box-shadow:0 10px 24px rgba(0,0,0,.25)} -.sticker .s{width:100px;height:100px;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px rgba(0,0,0,.25)} -.shirt{width:210px;height:220px;display:flex;align-items:center;justify-content:center;position:relative} -.shirt svg{position:absolute;inset:0} -.badge{width:170px;height:235px;background:#fff;border-radius:10px;box-shadow:0 10px 24px rgba(0,0,0,.2);display:flex;flex-direction:column;align-items:center;padding:20px 14px;gap:14px;position:relative;margin-top:30px} -.badge:before{content:"";position:absolute;top:-60px;left:50%;width:22px;height:62px;transform:translateX(-50%)} -.badge .hole{width:40px;height:8px;border-radius:4px;background:#ddd}.badge .nm{font-size:15px;font-weight:600}.badge .rl{font-size:10px;color:#777} -.pcard{position:relative;width:300px;height:189px;border-radius:14px;box-shadow:0 14px 30px rgba(0,0,0,.28);font:600 12px ui-monospace,Menlo,monospace} -.pcard .chip{position:absolute;left:22px;top:76px;width:40px;height:30px;border-radius:6px;background:linear-gradient(135deg,#e9d8a6,#c9a95c)} -.pcard .num{position:absolute;left:22px;top:122px;letter-spacing:.12em;font-size:14px} -.pcard .holder{position:absolute;left:22px;bottom:18px;font-size:10px;letter-spacing:.14em;opacity:.85} -.pcard .brandline{position:absolute;right:20px;bottom:16px;font:700 13px system-ui,sans-serif;opacity:.9} -.tabbar{width:340px;background:#dfe1e5;border-radius:10px;padding:8px 8px 0} -.tab{width:230px;height:36px;background:#fff;border-radius:10px 10px 0 0;display:flex;align-items:center;gap:8px;padding:0 12px;font-size:11px;color:#333} -.addr{height:40px;background:#fff;display:flex;align-items:center;padding:0 12px;font-size:10px;color:#777;border-top:1px solid #eee} -.cmp{display:grid;gap:22px;margin-top:20px}.cmp .c{background:var(--paper);border-radius:12px;padding:22px;display:flex;flex-direction:column;align-items:center;gap:12px} -.cmp img{max-height:120px;max-width:80%} -img.g{filter:grayscale(1)}img.w{filter:brightness(0) invert(1)}img.k{filter:brightness(0)} -.adj span{display:inline-block;border:1px solid var(--line);border-radius:20px;padding:4px 14px;margin:0 8px 8px 0;font-size:14px} -""" - - -def uri(path, base): - p = path if os.path.isabs(path) else os.path.join(base, path) - return svglib.svg_data_uri(p) - - -def text_on(bg): - """White text while it keeps 3:1 on the background, near-black below that (white if the colour can't be parsed).""" - h = (bg or "").strip().lstrip("#") - if len(h) == 3: - h = "".join(ch * 2 for ch in h) - try: - rgb = [int(h[i:i + 2], 16) / 255 for i in (0, 2, 4)] - except ValueError: - return "#fff" - lin = [v / 12.92 if v <= 0.04045 else ((v + 0.055) / 1.055) ** 2.4 for v in rgb] - lum = 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2] - return "#fff" if 1.05 / (lum + 0.05) >= 3 else "#161616" - - -def mock_html(kind, c): - """c: dict with sym, lock, avatar, color, cls, name, tag, nav.""" - sym, lock, av, cls, name, tag = c["sym"], c["lock"], c["avatar"], c["cls"], c["name"], c["tag"] - stack = c.get("stacked") or lock # stacked lockup for tall/boxy surfaces (bags, signs, badges) when provided - # Artwork on brand-colour tiles ("on_tile") and on the fixed near-black surfaces ("on_dark"): use the dedicated - # colour files when given (keeps multi-colour marks), otherwise force the mark to white. - avt, wat = (c["avatar_tile"], "") if c.get("avatar_tile") else (av, "w") - avd, wav = (c["avatar_dark"], "") if c.get("avatar_dark") else (av, "w") - skt, wst = (c["stack_tile"], "") if c.get("stack_tile") else (stack, "w") - lkd, wlk = (c["lock_dark"], "") if c.get("lock_dark") else (lock, "w") - skd, wsk = ((c.get("stack_dark") or c["lock_dark"]), "") if (c.get("stack_dark") or c.get("lock_dark")) else (stack, "w") - tile = c["tile"] - # e-mail / social handle / domain: plain ASCII letters and digits ("Marlow & Finch" -> "marlowfinch") - handle = re.sub(r"[^a-z0-9]", "", unicodedata.normalize("NFKD", name).encode("ascii", "ignore").decode().lower()) - n = html.escape(name) - if kind == "business-card": - return (f'
    ' - f'
    Alex Morgan
    Founder
    alex@{handle}.com
    ' - f'
    Business cards
    ') - if kind == "app-icon": - cells = "".join('
    ' for _ in range(4)) - icon = (f'
    ' - f'
    ') - # the home screen shows the icon among others; the large tile beside it shows it at store size - big = (f'
    {n}
    ') - return (f'
    {cells}{icon}' - + "".join('
    ' for _ in range(7)) + f'
    {big}App icon
    ') - if kind == "website": - nav = "".join(f"{html.escape(x)}" for x in c["nav"]) - return (f'
    ' - f'' - f'
    {html.escape(tag) or n}
    Website
    ') - if kind == "signage": - return (f'
    ' - f'
    Storefront / signage
    ') - if kind == "tote": - return (f'
    ' - 'Tote bag
    ') - if kind == "social": - return (f'
    Social profile
    ') - if kind == "cup": - return (f'
    ' - f'
    ' - 'Paper cup
    ') - if kind == "bag": - return (f'
    ' - f'
    {html.escape(tag)[:40]}
    ' - 'Packaging bag
    ') - if kind == "shopping-bag": - return (f'
    ' - 'Shopping bag
    ') - if kind == "box": - return (f'
    ' - 'Packaging
    ') - if kind == "readme": - return (f'
    ' - f'
    {html.escape(tag) or n}
    ' - '
    GitHub README
    ') - if kind == "terminal": - return (f'
    ' - f'
    $ {handle} --version
    ' - f'{n} 1.0.0
    $ {handle} search "error"
    Terminal
    ') - if kind == "sticker": - return (f'
    ' - 'Laptop sticker
    ') - if kind == "tshirt": - shirt = ('') - return (f'
    {shirt}
    ' - 'T-shirt
    ') - if kind == "badge": - return (f'
    ' - '
    Alex Morgan
    Speaker
    Event badge
    ') - if kind == "payment-card": - return (f'
    ' - f'' - f'
    •••• •••• •••• 4821
    ' - f'
    ALEX MORGAN
    {n}
    ' - 'Payment card
    ') - if kind == "favicon-tab": - return (f'
    ' - f'{n} — Home✕
    https://{handle}.com
    Browser tab
    ') - raise KeyError(kind) - - -ALL_MOCKUPS = ["payment-card", "business-card", "app-icon", "website", "signage", "tote", "social", "cup", "bag", "shopping-bag", "box", - "readme", "terminal", "sticker", "tshirt", "badge", "favicon-tab"] - - -def pick_mockups(spec): - if spec.get("mockups"): - chosen = [m for m in spec["mockups"] if m in ALL_MOCKUPS] - else: - ind = str(spec.get("industry", "")).lower() - key = ind if ind in PRESETS else ALIASES.get(ind, ind) # a real preset name always wins over an alias - chosen = PRESETS.get(key, PRESETS["services"]) - return chosen[:6] if len(chosen) >= 6 else (chosen + [m for m in PRESETS["services"] if m not in chosen])[:6] - - -def main(): - ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) - ap.add_argument("spec", nargs="?") - ap.add_argument("-o", "--out", default="presentation.html") - ap.add_argument("--list-mockups", action="store_true") - ap.add_argument("--png-dir", help="also export every slide as slide-NN.png (needs Chrome/Chromium)") - a = ap.parse_args() - if a.list_mockups: - print("mockups:", ", ".join(ALL_MOCKUPS)) - for k, v in PRESETS.items(): - print(f" industry '{k}': {', '.join(v)}") - print(" aliases:", ", ".join(f"{k}→{v}" for k, v in ALIASES.items())) - return - if not a.spec: - ap.error("spec.json required") - with open(a.spec, encoding="utf-8") as fh: - spec = json.load(fh) - base = os.path.dirname(os.path.abspath(a.spec)) - brand = spec.get("brand", "Brand") - color = spec.get("brand_color", "#161616") - grey = spec.get("greyscale", True) - final = spec.get("final", False) - cls = "g" if grey else "" - tile = "#161616" if grey else (spec.get("tile_color") or color) - date = spec.get("date") or datetime.date.today().isoformat() - designer = spec.get("designer", "") - concepts = spec.get("concepts", []) - ind = str(spec.get("industry", "")).lower() - nav = spec.get("nav") or DEFAULT_NAV.get(ALIASES.get(ind, ind), ["Products", "About", "Contact"]) - mockups = pick_mockups(spec) - deck_title = spec.get("deck_title", "final identity" if final else "identity concepts") - - def foot(i): - return f'
    {html.escape(brand)} — {html.escape(deck_title)}{i}
    ' - - slides = [] - custom_title = spec.get("deck_title") - cover_mark = "" - if final and concepts: - c0 = concepts[0] - first = c0.get("lockup") or c0.get("symbol") or c0.get("avatar") - if first: - cover_mark = (f'
    ' - f'
    ') - kicker = (custom_title.capitalize() if (final and custom_title) else "Final identity") if final \ - else f"Logo design · round {spec.get('round', 1)}" - note = ("Concepts are shown in greyscale so the conversation stays on form and idea; colour follows once a " - "direction is chosen." if grey and not final else "") - slides.append(f"""
    {kicker}
    -

    {html.escape(brand)}

    {html.escape(deck_title.capitalize())}{(' · ' + html.escape(designer)) if designer else ''} · {date}

    -{cover_mark}

    {note}

    {foot(1)}
    """) - adj = "".join(f"{html.escape(x)}" for x in spec.get("adjectives", [])) - crit = spec.get("criteria", "Success: distinctive in its category, recognisable at 16 px, works in one colour, " - "and feels like the words above.") - slides.append(f"""
    What we heard

    The brief

    -

    {html.escape(spec.get('brief', ''))}

    {adj}
    -

    {html.escape(crit)}

    {foot(2)}
    """) - items = [] - for i, c in enumerate(concepts): - paths = [c.get("symbol"), c.get("lockup"), c.get("avatar")] - if not any(paths): - print(f"skip concept {i}: needs symbol, lockup or avatar") - continue - sym = uri(c.get("symbol") or c.get("avatar") or c.get("lockup"), base) - lock = uri(c.get("lockup") or c.get("symbol") or c.get("avatar"), base) - av = uri(c.get("avatar") or c.get("symbol") or c.get("lockup"), base) - stacked = uri(c["stacked"], base) if c.get("stacked") else None - dark = {} - if not grey: - pick = lambda *keys: next((c[k] for k in keys if c.get(k)), None) - if c.get("symbol_on_dark") and not c.get("symbol_on_tile"): - print(f"note: concept {chr(65 + i)} has no symbol_on_tile; symbol_on_dark is used on the {tile} tiles " - "(app icon, cards) — check its contrast there, or pass a dedicated tile file") - for k, src in (("avatar_tile", pick("symbol_on_tile", "symbol_on_dark")), - ("stack_tile", pick("stacked_on_tile", "lockup_on_tile")), - ("avatar_dark", pick("symbol_on_dark")), ("lock_dark", pick("lockup_on_dark")), - ("stack_dark", pick("stacked_on_dark"))): - if src: - dark[k] = uri(src, base) - items.append((c, sym, lock)) - label = spec.get("label") or ((custom_title.capitalize() if custom_title else "Final design") if final - else f"Concept {chr(65 + i)}") - rat = "".join(f"
  • {html.escape(r)}
  • " for r in c.get("rationale", [])) - sizes = "".join(f'
    {s}px
    ' for s in (16, 24, 32, 64)) - slides.append(f"""
    {label}

    {html.escape(c.get('name', ''))}

    -

    {html.escape(c.get('idea', ''))}

    -
    -
      {rat}
    {sizes}
    -{foot(len(slides) + 1)}
    """) - ctx = {"sym": sym, "lock": lock, "avatar": av, "cls": cls, "name": brand, "tag": spec.get("tagline", ""), - "tile": tile, "nav": nav, "stacked": stacked, **dark} - cells = "".join(mock_html(k, ctx) for k in mockups) - slides.append(f"""
    {label} · in use

    {html.escape(c.get('name', ''))}

    -
    {cells}
    {foot(len(slides) + 1)}
    """) - if len(items) > 1: - cells = "".join(f'
    ' - f'{chr(65 + i)} · {html.escape(c.get("name", ""))}{html.escape(c.get("idea", ""))}
    ' - for i, (c, sym, lock) in enumerate(items)) - slides.append(f"""
    Side by side

    {len(items)} directions

    -
    {cells}
    {foot(len(slides) + 1)}
    """) - if spec.get("recommendation"): - steps = spec.get("next_steps") or ([] if final else ["Choose a direction (or name what you like in each).", - "We refine it: geometry, optical corrections, lockups.", - "Colour and typography options for the chosen direction.", - "Final artwork, variants and mini guidelines."]) - title = "Notes" if final else "Our recommendation" - slides.append(f"""
    {'Next steps' if final else 'Recommendation & next steps'}

    {title}

    -

    {html.escape(spec['recommendation'])}

    -
      {''.join(f'
    • {html.escape(s)}
    • ' for s in steps)}
    {foot(len(slides) + 1)}
    """) - doc = (f"{html.escape(brand)} — {html.escape(deck_title)}" - f"{''.join(slides)}") - with open(a.out, "w", encoding="utf-8") as fh: - fh.write(doc) - print(f"wrote {a.out} ({len(slides)} slides; mockups: {', '.join(mockups)})") - if a.png_dir: - import tempfile - import render_png - os.makedirs(a.png_dir, exist_ok=True) - solo_css = CSS + "body{background:#fff}.slide{margin:0;box-shadow:none;min-height:800px}" - for i, sl in enumerate(slides, 1): - with tempfile.NamedTemporaryFile("w", suffix=".html", delete=False, encoding="utf-8") as fh: - fh.write(f"{sl}") - tmp_html = fh.name - out = os.path.join(a.png_dir, f"slide-{i:02d}.png") - try: - render_png.screenshot_html(tmp_html, out, 1280, 800) - print("wrote", out) - except Exception as exc: - print(f"slide PNG export failed ({exc}); open the HTML instead") - break - finally: - os.unlink(tmp_html) - - -if __name__ == "__main__": - main() diff --git a/.claude/skills/logo-design/scripts/preview_sheet.py b/.claude/skills/logo-design/scripts/preview_sheet.py deleted file mode 100644 index ead60d5..0000000 --- a/.claude/skills/logo-design/scripts/preview_sheet.py +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/env python3 -"""Generate an HTML test sheet for one or more logo SVGs (no dependencies). - -Shows every concept at a ladder of sizes (16 px upward), a pixel-level favicon test, on light / dark / -brand-colour / photographic / patterned backgrounds, in treatments that expose weaknesses (greyscale, -one-colour black and white, squint blur, mirror, 180° rotation), in real contexts (browser tab, app icon, -avatar crop, website header, business card), side by side with other concepts, and on a "shelf" next to -reference logos (competitors or library examples) to judge distinctiveness. - -Usage: - python3 scripts/preview_sheet.py concept-a.svg concept-b.svg -o preview.html - python3 scripts/preview_sheet.py logo.svg --brand-color "#0F7C80" --name "Harbor" -o preview.html - python3 scripts/preview_sheet.py logo.svg --refs-industry payments-fintech -o shelf.html - python3 scripts/preview_sheet.py logo.svg --refs a.svg b.svg c.svg -o shelf.html - python3 scripts/preview_sheet.py v1.svg v2.svg v3.svg --compare-only -o compare.html - -Open the HTML in a browser (agents: use the browser/screenshot tool) and actually look at it. -""" -import argparse -import html -import json -import os -import random -import sys - -sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -import svglib # noqa: E402 - -SIZES = [16, 20, 24, 32, 48, 64, 96, 128, 256] - -CSS = """ -:root{--ink:#1b1b1b;--muted:#6d6d6d;--line:#e4e4e0;--paper:#fafaf8} -*{box-sizing:border-box}body{margin:0;font:14px/1.45 system-ui,-apple-system,Segoe UI,sans-serif;color:var(--ink);background:var(--paper)} -header{padding:20px 24px;border-bottom:1px solid var(--line);background:#fff}h1{margin:0 0 4px;font-size:20px} -h2{font-size:17px;margin:28px 0 10px}h3{font-size:13px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin:18px 0 8px} -.wrap{padding:0 24px 40px;max-width:1400px}.row{display:flex;flex-wrap:wrap;gap:14px;align-items:flex-end}.row>.cell{flex:0 0 auto;max-width:100%} -.cell{display:flex;flex-direction:column;align-items:center;gap:6px}.cap{font-size:11px;color:var(--muted);text-align:center} -.tile{display:flex;align-items:center;justify-content:center;border-radius:10px;border:1px solid var(--line);overflow:hidden} -.checklist{background:#fff;border:1px solid var(--line);border-radius:10px;padding:12px 16px;margin-top:14px;columns:2;font-size:13px} -.checklist li{margin:2px 0} -.concept{border-top:2px solid var(--ink);margin-top:34px} -.pix canvas{image-rendering:pixelated;image-rendering:crisp-edges;border:1px solid var(--line);background:#fff} -.tab{width:260px;height:38px;background:#dfe1e5;border-radius:10px 10px 0 0;display:flex;align-items:center;gap:8px;padding:0 12px;font-size:12px;color:#333} -.tab img{width:16px;height:16px;object-fit:contain} -.phone{width:250px;padding:18px;border-radius:28px;background:linear-gradient(160deg,#3a4a5e,#1d2733);display:grid;grid-template-columns:repeat(4,1fr);gap:14px} -.app{display:flex;flex-direction:column;align-items:center;gap:4px;font-size:9px;color:#fff} -.app .ico{width:46px;height:46px;border-radius:11px;background:rgba(255,255,255,.18)} -.nav{width:520px;max-width:100%;height:64px;background:#fff;border:1px solid var(--line);border-radius:8px;display:flex;align-items:center;padding:0 18px;gap:26px;font-size:13px;color:#444} -.nav .sp{flex:1}.nav .btn{background:#1b1b1b;color:#fff;padding:7px 12px;border-radius:6px} -.card{width:336px;height:192px;border-radius:6px;box-shadow:0 6px 24px rgba(0,0,0,.15);background:#fff;padding:22px;display:flex;flex-direction:column;justify-content:space-between} -.card .t{font-size:11px;color:#444;line-height:1.5} -.avatar{width:96px;height:96px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;border:1px solid var(--line)} -.shelf{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px} -.shelf .cell{align-items:stretch}.shelf .tile{height:110px;width:100%;background:#fff}.shelf .me{outline:3px solid #e8505b;outline-offset:2px} -.grey img{filter:grayscale(1)} -img.mono-black{filter:brightness(0)}img.mono-white{filter:brightness(0) invert(1)} -""" - -CHECKLIST = """
      -
    • Is the idea still clear at 16–24 px? Which details disappear first?
    • -
    • Does the silhouette survive the squint (blur) test?
    • -
    • Does the one-colour black version still carry the concept?
    • -
    • Does the reversed (white on dark) version look heavier? (irradiation → thin it)
    • -
    • Any unintended readings when mirrored or rotated 180°?
    • -
    • Does it hold up on the brand colour, a photo and a pattern?
    • -
    • In the favicon/app-icon tests, is the symbol optically sized and centred?
    • -
    • On the shelf: does it stand out from the references, or blend in?
    • -
    • Greyscale: do colour segments still separate by value?
    • -
    • Would you recognise it again tomorrow from memory?
    """ - -PIX_JS = """ -document.querySelectorAll('canvas[data-src]').forEach(c=>{ - const img=new Image(); const n=+c.dataset.n, k=+c.dataset.k; c.width=n*k; c.height=n*k; - img.onload=()=>{const t=document.createElement('canvas'); t.width=n; t.height=n; const x=t.getContext('2d'); - x.fillStyle=c.dataset.bg; x.fillRect(0,0,n,n); - const r=Math.min(n/img.width,n/img.height)*0.9, w=img.width*r, h=img.height*r; x.drawImage(img,(n-w)/2,(n-h)/2,w,h); - const g=c.getContext('2d'); g.imageSmoothingEnabled=false; g.drawImage(t,0,0,n*k,n*k);}; - img.src=c.dataset.src;}); -""" - - -def img(uri, h=None, w=None, cls="", style=""): - dims = "" - if h: - dims += f"height:{h}px;" - if w: - dims += f"max-width:{w}px;" - return f'' - - -def tile(inner, w, h, bg, extra=""): - return f'
    {inner}
    ' - - -def concept_block(name, uri, aspect, brand, idx): - square = aspect is None or aspect <= 1.35 - out = [f'

    {html.escape(name)}

    '] - # scale ladder - out.append("

    Scale ladder (height in px)

    ") - for s in SIZES: - out.append(f"
    {tile(img(uri, h=s), max(40, int(s * (aspect or 1)) + 16), s + 16, '#fff')}" - f"
    {s}px
    ") - out.append("
    ") - # pixel test - out.append("

    Pixel test — rendered at 16 / 32 / 48 px, enlarged

    ") - for n, k in ((16, 8), (32, 4), (48, 3)): - for bg in ("#ffffff", "#111111"): - out.append(f"
    " - f"
    {n}px on {bg}
    ") - out.append("
    ") - # backgrounds - photo = "radial-gradient(circle at 30% 30%,#e7b889,#8a5a3c 45%,#2d3b2f 80%)" - pattern = "repeating-linear-gradient(45deg,#e9e4da 0 10px,#d4cbbd 10px 20px)" - bgs = [("#ffffff", "white", ""), ("#f1f1ee", "light grey", ""), ("#111111", "black", "mono-white"), - ("#111111", "black (original colours)", ""), (brand, f"brand {brand}", ""), (brand, "brand (white)", "mono-white"), - (photo, "photo-like", ""), (pattern, "pattern", "")] - out.append("

    Backgrounds

    ") - for bg, cap, cls in bgs: - out.append(f"
    {tile(img(uri, h=72, w=200, cls=cls), 220, 120, bg)}
    {cap}
    ") - out.append("
    ") - # treatments - treats = [("original", "", ""), ("greyscale", "", "filter:grayscale(1)"), ("one-colour black", "mono-black", ""), - ("one-colour white", "mono-white", ""), ("squint (blur 2px)", "", "filter:blur(2px)"), - ("squint small (blur 1px @48)", "", "filter:blur(1px)"), ("mirrored", "", "transform:scaleX(-1)"), - ("rotated 180°", "", "transform:rotate(180deg)")] - out.append("

    Treatments

    ") - for cap, cls, st in treats: - bg = "#111" if cls == "mono-white" else "#fff" - h = 48 if "@48" in cap else 96 - out.append(f"
    {tile(img(uri, h=h, w=200, cls=cls, style=st), 220, 140, bg)}
    {cap}
    ") - out.append("
    ") - # contexts - out.append("

    Contexts

    ") - out.append(f"
    {img(uri)}{html.escape(name)} — Home" - f"✕
    browser tab (16 px favicon)
    ") - icon = (f"
    " - f"{img(uri, h=28, w=30, cls='mono-white')}
    ") - apps = "".join("
    app
    " for _ in range(6)) - out.append(f"
    {apps}
    {icon}{html.escape(name[:10])}
    {apps[:0]}" - + "".join("
    app
    " for _ in range(5)) - + "
    app icon (white symbol on brand colour)
    ") - out.append(f"
    {img(uri, h=58, w=70)}
    " - f"
    avatar circle crop
    ") - out.append(f"
    " - f"
    website header
    ") - out.append(f"
    {img(uri, h=40, w=160)}
    Alex Morgan
    Founder
    " - f"alex@example.com · +00 000 000 000
    business card (3.5 × 2 in)
    ") - out.append("
    ") - return "\n".join(out) - - -def compare_block(items): - out = ["

    Side by side

    "] - for h, cls, bg, cap in ((96, "", "#fff", "96 px"), (32, "", "#fff", "32 px"), (64, "mono-black", "#fff", "one-colour"), - (64, "mono-white", "#111", "reversed")): - out.append(f"

    {cap}

    ") - for name, uri, aspect in items: - w = max(60, int(h * (aspect or 1)) + 30) - out.append(f"
    {tile(img(uri, h=h, cls=cls), w, h + 30, bg)}
    {html.escape(name)}
    ") - out.append("
    ") - out.append("
    ") - return "\n".join(out) - - -def shelf_block(items, refs): - cells = [] - for name, uri, _ in items: - cells.append((name, uri, True)) - for p in refs: - cells.append((os.path.basename(p), svglib.svg_data_uri(p), False)) - random.Random(7).shuffle(cells) - out = ["

    Shelf test

    Your concept(s) outlined in red among " - "reference logos at equal height. Squint: does it stand out, or blend in? Second row repeats in greyscale.

    "] - for grey in (False, True): - out.append(f"
    ") - for name, uri, me in cells: - out.append(f"
    {img(uri, h=56, w=130)}
    " - f"
    {html.escape(name)}
    ") - out.append("
    ") - out.append("
    ") - return "\n".join(out) - - -def refs_for_industry(industry, n): - with open(svglib.CATALOG_PATH, encoding="utf-8") as fh: - cat = json.load(fh) - rows = [r for r in cat if r.get("industry") == industry and r.get("variant") == "main"] - rows.sort(key=lambda r: (not r.get("exemplary"), r["file"])) - return [os.path.join(svglib.LIBRARY_SVG_DIR, r["file"]) for r in rows[:n]] - - -def main(): - ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) - ap.add_argument("files", nargs="+", help="logo SVG(s) to test") - ap.add_argument("-o", "--out", default="logo-preview.html") - ap.add_argument("--name", help="brand name (used in mock contexts)") - ap.add_argument("--names", nargs="*", help="labels per file (default: file names)") - ap.add_argument("--brand-color", help="brand colour for background/app-icon tests (default: most saturated colour in the first logo, else dark grey)") - ap.add_argument("--refs", nargs="*", default=[], help="reference SVGs for the shelf test") - ap.add_argument("--refs-industry", help="pull shelf references from the library by industry") - ap.add_argument("--refs-count", type=int, default=11) - ap.add_argument("--compare-only", action="store_true", help="only the side-by-side section") - a = ap.parse_args() - - items = [] - for i, p in enumerate(a.files): - _, root = svglib.load_svg(p) - vb = svglib.view_box(root) - aspect = (vb[2] / vb[3]) if vb and vb[3] else None - label = (a.names[i] if a.names and i < len(a.names) else os.path.splitext(os.path.basename(p))[0]) - items.append((label, svglib.svg_data_uri(p), aspect)) - brand_name = a.name or items[0][0] - color_note = "given" - if not a.brand_color: - _, r0 = svglib.load_svg(a.files[0]) - cols = [c for c in svglib.collect_colors(r0) if 0.12 < svglib.lightness(c) < 0.9] - if cols: - import colorsys - a.brand_color = max(cols, key=lambda c: colorsys.rgb_to_hls(*[v / 255 for v in svglib.hex_to_rgb(c)])[2]) - color_note = "taken from the logo" - else: - a.brand_color, color_note = "#3a3a3a", "none given — neutral grey; pass --brand-color" - refs = list(a.refs) - if a.refs_industry: - refs += refs_for_industry(a.refs_industry, a.refs_count) - - body = [f"

    Logo test sheet — {html.escape(brand_name)}

    " - f"
    {len(items)} file(s) · brand colour {a.brand_color} ({color_note}). " - f"Look critically; fix what fails, then re-run.
    {CHECKLIST}
    "] - if len(items) > 1 or a.compare_only: - body.append(compare_block(items)) - if not a.compare_only: - for i, (label, uri, aspect) in enumerate(items): - body.append(concept_block(label, uri, aspect, a.brand_color, i)) - if refs: - body.append(shelf_block(items, refs)) - body.append("
    ") - doc = (f"Logo test — {html.escape(brand_name)}" - f"" - f"{''.join(body)}") - with open(a.out, "w", encoding="utf-8") as fh: - fh.write(doc) - print(f"wrote {a.out} ({len(items)} logo(s), {len(refs)} reference(s)) — open it in a browser") - - -if __name__ == "__main__": - main() diff --git a/.claude/skills/logo-design/scripts/render_png.py b/.claude/skills/logo-design/scripts/render_png.py deleted file mode 100644 index e0d3eb0..0000000 --- a/.claude/skills/logo-design/scripts/render_png.py +++ /dev/null @@ -1,381 +0,0 @@ -#!/usr/bin/env python3 -"""Render SVG logos to PNG (transparent by default) and build favicon.ico files — no required dependencies. - -Use it to *look* at your work (render, then view the PNG) and to produce raster deliverables. -The SVG is fitted ("contain") into an exact WIDTH×HEIGHT box with optional padding and background. - -Backends are tried in order until one works: - 1. cairosvg (python package) 2. rsvg-convert 3. inkscape - 4. headless Chrome / Chromium / Edge / Brave 5. macOS Quick Look (qlmanage) — last resort -Quick Look renders on opaque white; transparency is recovered by rendering on white and black -("difference matting") when Pillow is installed, otherwise the PNG stays opaque white. - -Usage: - python3 scripts/render_png.py logo.svg -o logo.png --size 512 - python3 scripts/render_png.py lockup.svg -o lockup.png --width 1200 --height 400 --padding 0.05 - python3 scripts/render_png.py symbol.svg -o preview.png --size 256 --bg "#ffffff" - python3 scripts/render_png.py a.svg b.svg c.svg --out-dir renders --size 400 # batch, for viewing - python3 scripts/render_png.py favicon.svg --ico favicon.ico --ico-sizes 16 32 48 - python3 scripts/render_png.py preview.html -o preview.png --width 1400 --height 3000 # screenshot an HTML page (Chrome) - python3 scripts/render_png.py --which # show available backends -""" -import argparse -import base64 -import contextlib -import os -import re -import shutil -import struct -import subprocess -import sys -import tempfile -import time - -sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -import svglib # noqa: E402,F401 (sets UTF-8 console output) - -CHROME_CANDIDATES = [ - "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", - "/Applications/Chromium.app/Contents/MacOS/Chromium", - "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge", - "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser", - "google-chrome", "google-chrome-stable", "chromium", "chromium-browser", "microsoft-edge", "brave-browser", - r"C:\Program Files\Google\Chrome\Application\chrome.exe", - r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe", -] - - -# ----------------------------------------------------------------------------- helpers - -def png_size(path): - with open(path, "rb") as fh: - head = fh.read(24) - if head[:8] != b"\x89PNG\r\n\x1a\n": - return None - return struct.unpack(">II", head[16:24]) - - -def wrap_svg(svg_path, width, height, padding=0.0, bg=None): - """Return SVG markup that fits the source into an exact width×height canvas (contain + padding).""" - with open(svg_path, encoding="utf-8", errors="ignore") as fh: - raw = fh.read() - raw = re.sub(r"<\?xml[^>]*\?>", "", raw) - raw = re.sub(r"]*>", "", raw, flags=re.I) - m = re.search(r"]*>", raw) - if not m: - raise ValueError(f"not an SVG: {svg_path}") - tag = m.group(0) - vb = re.search(r'viewBox\s*=\s*"([^"]+)"', tag) - if not vb: - w = re.search(r'\swidth\s*=\s*"([\d.]+)', tag) - h = re.search(r'\sheight\s*=\s*"([\d.]+)', tag) - if w and h: - tag2 = tag[:-1] + f' viewBox="0 0 {w.group(1)} {h.group(1)}">' - raw = raw.replace(tag, tag2, 1) - tag = tag2 - pw, ph = width * padding, height * padding - new_tag = re.sub(r'\s(width|height|x|y|preserveAspectRatio)\s*=\s*"[^"]*"', "", tag) - new_tag = new_tag[:-1].rstrip("/") + (f' x="{pw:g}" y="{ph:g}" width="{width - 2 * pw:g}" height="{height - 2 * ph:g}"' - ' preserveAspectRatio="xMidYMid meet">') - raw = raw.replace(tag, new_tag, 1) - bg_rect = f'' if bg else "" - return (f'{bg_rect}{raw}') - - -def find_chrome(): - for c in CHROME_CANDIDATES: - if os.path.isabs(c) and os.path.exists(c): - return c - if not os.path.isabs(c) and shutil.which(c): - return shutil.which(c) - return None - - -def available_backends(): - out = [] - try: - import cairosvg # noqa: F401 - out.append("cairosvg") - except Exception: - pass - if shutil.which("rsvg-convert"): - out.append("rsvg-convert") - if shutil.which("inkscape"): - out.append("inkscape") - if find_chrome(): - out.append("chrome") - if shutil.which("qlmanage"): - out.append("qlmanage") - return out - - -# ----------------------------------------------------------------------------- backends - -def _cairosvg(svg_file, png, w, h): - import cairosvg # type: ignore - cairosvg.svg2png(url=svg_file, write_to=png, output_width=w, output_height=h) - - -def _rsvg(svg_file, png, w, h): - subprocess.run(["rsvg-convert", "-w", str(w), "-h", str(h), "-o", png, svg_file], check=True, - stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - - -def _inkscape(svg_file, png, w, h): - subprocess.run(["inkscape", svg_file, "--export-type=png", f"--export-filename={png}", "-w", str(w), "-h", str(h)], - check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - - -@contextlib.contextmanager -def _tempdir(): - """Like tempfile.TemporaryDirectory, but cleanup never raises (Windows can keep Chrome's files locked).""" - path = tempfile.mkdtemp() - try: - yield path - finally: - for _ in range(10): - shutil.rmtree(path, ignore_errors=True) - if not os.path.exists(path): - break - time.sleep(0.3) - - -def _stop(proc): - """Stop a browser process and its children (Chrome keeps helper processes alive on Windows).""" - if proc.poll() is not None: - return - if os.name == "nt": - subprocess.run(["taskkill", "/PID", str(proc.pid), "/T", "/F"], stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL) - else: - proc.terminate() - try: - proc.wait(timeout=5) - except subprocess.TimeoutExpired: - proc.kill() - - -def _chrome(svg_file, png, w, h): - with open(svg_file, "rb") as fh: - data = base64.b64encode(fh.read()).decode("ascii") - page = (f"" - f"") - with _tempdir() as tmp: - html_path = os.path.join(tmp, "render.html") - with open(html_path, "w", encoding="utf-8") as fh: - fh.write(page) - screenshot_html(html_path, png, w, h) - - -def screenshot_html(html_path, png, w, h): - """Screenshot an HTML page (viewport w×h, transparent where the page is) with headless Chrome/Chromium.""" - chrome = find_chrome() - if not chrome: - raise RuntimeError("no Chromium-based browser found for HTML screenshots") - html_path = os.path.abspath(html_path) - with _tempdir() as tmp: - shot = os.path.join(tmp, "shot.png") # never poll the destination: an older file may already exist there - cmd = [chrome, "--headless=new", "--disable-gpu", "--hide-scrollbars", "--no-first-run", - "--no-default-browser-check", "--use-mock-keychain", "--password-store=basic", "--disable-extensions", - "--default-background-color=00000000", f"--window-size={w},{h}", f"--screenshot={shot}", - f"--user-data-dir={os.path.join(tmp, 'profile')}", "file://" + html_path] - proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - deadline = time.time() + 45 - last = -1 - while time.time() < deadline: - if os.path.exists(shot): - size = os.path.getsize(shot) - if size > 0 and size == last: - break - last = size - if proc.poll() is not None and os.path.exists(shot): - break - time.sleep(0.25) - try: - proc.wait(timeout=0.5) # it may exit by itself after --screenshot; otherwise stop the whole tree - except subprocess.TimeoutExpired: - pass - _stop(proc) - if not os.path.exists(shot): - raise RuntimeError("chrome produced no file") - shutil.move(shot, png) - - -def _qlmanage_once(svg_markup, w, h, tmp, name): - side = max(w, h) - p = os.path.join(tmp, name + ".svg") - with open(p, "w", encoding="utf-8") as fh: - fh.write(svg_markup) - subprocess.run(["qlmanage", "-t", "-s", str(side), "-o", tmp, p], check=True, - stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=60) - out = p + ".png" - if not os.path.exists(out): - raise RuntimeError("qlmanage produced no file") - return out - - -def _qlmanage(svg_file, png, w, h, want_alpha=True): - # Quick Look crops non-square canvases and ignores transparency: render a square canvas, crop after. - side = max(w, h) - with open(svg_file, encoding="utf-8") as fh: - markup = fh.read() - ox, oy = (side - w) / 2, (side - h) / 2 - square = re.sub(r"^]*>", f'', markup, count=1) - with tempfile.TemporaryDirectory() as tmp: - white = _qlmanage_once(square, w, h, tmp, "white") - try: - from PIL import Image # type: ignore - except Exception: - shutil.copy(white, png) - print(" note: Quick Look output is opaque white (install Pillow for transparency).", file=sys.stderr) - return - black_markup = re.sub(r"(]*>)", r'\1', - square, count=1) - black = _qlmanage_once(black_markup, w, h, tmp, "black") - iw = Image.open(white).convert("RGB") - ib = Image.open(black).convert("RGB").resize(iw.size) - if want_alpha: - flat = lambda im: list(im.get_flattened_data() if hasattr(im, "get_flattened_data") else im.getdata()) - wd, bd = flat(iw), flat(ib) - px = [] - for (wr, wg, wb), (br, bg_, bb) in zip(wd, bd): - a = 255 - max(wr - br, wg - bg_, wb - bb) - if a >= 255: - px.append((br, bg_, bb, 255)) - elif a <= 0: - px.append((0, 0, 0, 0)) - else: - px.append((min(255, br * 255 // a), min(255, bg_ * 255 // a), min(255, bb * 255 // a), a)) - out = Image.new("RGBA", iw.size) - out.putdata(px) - else: - out = iw - s = out.size[0] / side - box = (round(ox * s), round(oy * s), round((ox + w) * s), round((oy + h) * s)) - out.crop(box).resize((w, h)).save(png) - - -BACKENDS = {"cairosvg": _cairosvg, "rsvg-convert": _rsvg, "inkscape": _inkscape, "chrome": _chrome, "qlmanage": _qlmanage} - - -def render(svg_path, png_path, width, height, padding=0.0, bg=None, backend=None): - """Render svg_path into png_path at exactly width×height. Returns the backend used, or None.""" - markup = wrap_svg(svg_path, width, height, padding, bg) - order = [backend] if backend else available_backends() - with _tempdir() as tmp: - wrapped = os.path.join(tmp, "wrapped.svg") - with open(wrapped, "w", encoding="utf-8") as fh: - fh.write(markup) - for name in order: - for _attempt in range(2 if name == "chrome" else 1): # a browser can fail once on a busy machine - try: - BACKENDS[name](wrapped, png_path, width, height) - if os.path.exists(png_path): - return name - except Exception: # retry, then try the next backend - continue - return None - - -def write_ico(png_paths, ico_path): - """Write a .ico that embeds PNG images (supported by all modern browsers and Windows Vista+).""" - entries, blobs = [], [] - for p in png_paths: - with open(p, "rb") as fh: - blobs.append(fh.read()) - w, h = png_size(p) - entries.append((w, h)) - offset = 6 + 16 * len(blobs) - header = struct.pack(" a.max_colors: - return False - if a.min_colors is not None and r.get("n_colors", 0) < a.min_colors: - return False - if a.aspect and r.get("aspect_class") != a.aspect: - return False - if a.variant and r.get("variant") != a.variant: - return False - if a.type_style and r.get("type_style") != a.type_style: - return False - if a.case and r.get("case") != a.case: - return False - if a.mood and a.mood.lower() not in [m.lower() for m in r.get("mood", [])]: - return False - if a.exemplary and not r.get("exemplary"): - return False - if a.no_gradient and r.get("gradients"): - return False - if a.subject and a.subject.lower() not in (r.get("subject") or "").lower(): - return False - if a.query: - hay = " ".join([r.get("file", ""), r.get("subject") or "", r.get("note") or "", " ".join(r.get("mood", []))]).lower() - if not all(w in hay for w in a.query.lower().split()): - return False - return True - - -def summary(rows, total): - n = len(rows) - print(f"{n} logos match (of {total}).\n") - if not n: - return - - def block(title, counter, k=10): - print(title) - for key, cnt in counter.most_common(k): - print(f" {str(key):24s} {cnt:4d} {cnt / n * 100:5.1f}%") - print() - block("Mark types", Counter(r.get("mark_type") for r in rows)) - block("Symbol type (combination marks)", Counter(r.get("symbol_type") for r in rows if r.get("symbol_type"))) - block("Primary colour family", Counter(r.get("primary_family") for r in rows)) - block("Techniques", Counter(t for r in rows for t in r.get("techniques", [])), 12) - block("Geometry", Counter(g for r in rows for g in r.get("geometry", []))) - block("Type style (when type present)", Counter(r.get("type_style") for r in rows if r.get("type_style"))) - cols = Counter(r.get("n_colors") for r in rows) - few = sum(v for k, v in cols.items() if k is not None and k <= 2) - print(f"Colour count: {few / n * 100:.0f}% use 1-2 colours; gradients in " - f"{sum(1 for r in rows if r.get('gradients')) / n * 100:.0f}%.") - ex = [r["file"] for r in rows if r.get("exemplary")][:12] - if ex: - print("Exemplary examples:", ", ".join(ex)) - print("\nReading: the most frequent types/colours/techniques are the category's conventions. " - "Repeating them signals belonging; departing from them creates distinction.") - - -def main(): - ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) - ap.add_argument("--type", help="mark type: wordmark|lettermark|letterform|pictorial|abstract|mascot|emblem|combination") - ap.add_argument("--symbol-type", help="symbol type inside combination marks") - ap.add_argument("--technique", help="e.g. negative-space, geometric-construction, letter-substitution (comma = AND)") - ap.add_argument("--geometry", help="e.g. circle, hexagon, triangle, organic (comma = AND)") - ap.add_argument("--industry", help="e.g. developer-tools, payments-fintech, database-data") - ap.add_argument("--color", help="colour family present anywhere: red|orange|yellow|green|cyan|blue|purple|pink|black|white|gray") - ap.add_argument("--primary-color", help="dominant family: a hue, 'multi' or 'mono'") - ap.add_argument("--max-colors", type=int) - ap.add_argument("--min-colors", type=int) - ap.add_argument("--aspect", help="square|wide|horizontal|extra-wide|tall") - ap.add_argument("--variant", help="main|icon (icon = standalone symbol of a brand that also has a lockup)") - ap.add_argument("--type-style", help="geometric-sans|grotesque-sans|humanist-sans|rounded-sans|serif|slab|script|display-custom|monospace") - ap.add_argument("--case", help="lowercase|uppercase|titlecase|mixed") - ap.add_argument("--mood", help="single mood adjective, e.g. friendly, technical, playful") - ap.add_argument("--subject", help="substring of the visual subject, e.g. bird, shield, cloud, letter a") - ap.add_argument("--query", help="free-text words matched against file name, subject, note, mood") - ap.add_argument("--exemplary", action="store_true", help="only strong teaching examples") - ap.add_argument("--no-gradient", action="store_true") - ap.add_argument("--limit", type=int, default=25) - ap.add_argument("--format", choices=("table", "paths", "json"), default="table") - ap.add_argument("--summary", action="store_true", help="aggregate view: conventions of the matching set") - ap.add_argument("--list-values", action="store_true", help="print allowed values for every filter") - a = ap.parse_args() - - cat = load_catalog() - if a.list_values: - for key in ("mark_type", "symbol_type", "industry", "primary_family", "aspect_class", "type_style", "case"): - print(f"{key}: {', '.join(sorted({str(r.get(key)) for r in cat if r.get(key)}))}") - for key in ("techniques", "geometry"): - vals = Counter(v for r in cat for v in r.get(key, [])) - print(f"{key}: {', '.join(f'{k}({c})' for k, c in vals.most_common())}") - moods = Counter(m.lower() for r in cat for m in r.get("mood", [])) - print("mood (top 40):", ", ".join(k for k, _ in moods.most_common(40))) - return - - # forgive near-miss filter values: "security" -> "security-identity", "fintech" -> "payments-fintech" - for attr, field in (("industry", "industry"), ("type", "mark_type"), ("symbol_type", "symbol_type"), - ("type_style", "type_style"), ("aspect", "aspect_class"), ("primary_color", "primary_family")): - val = getattr(a, attr) - if not val: - continue - known = sorted({str(r.get(field)) for r in cat if r.get(field)}) - if val in known: - continue - close = [k for k in known if val.lower() in k.lower() or k.lower() in val.lower()] - if len(close) == 1: - print(f"(--{attr.replace('_', '-')} '{val}' → using '{close[0]}')") - setattr(a, attr, close[0]) - else: - hint = ", ".join(close) if close else ", ".join(known) - sys.exit(f"unknown --{attr.replace('_', '-')} '{val}'. Did you mean: {hint}") - for attr, field in (("technique", "techniques"), ("geometry", "geometry")): - val = getattr(a, attr) - if not val: - continue - known = sorted({v for r in cat for v in r.get(field, [])}) - fixed = [] - for part in val.split(","): - if part in known: - fixed.append(part) - continue - close = [k for k in known if part.lower() in k.lower()] - if len(close) == 1: - print(f"(--{attr} '{part}' → using '{close[0]}')") - fixed.append(close[0]) - else: - sys.exit(f"unknown --{attr} '{part}'. Did you mean: {', '.join(close) if close else ', '.join(known)}") - setattr(a, attr, ",".join(fixed)) - - rows = [r for r in cat if matches(r, a)] - rows.sort(key=lambda r: (not r.get("exemplary"), r.get("anchors", 0))) - if a.summary: - summary(rows, len(cat)) - return - shown = rows[: a.limit] - if a.format == "json": - print(json.dumps(shown, ensure_ascii=False, indent=1)) - elif a.format == "paths": - for r in shown: - print(os.path.join(svglib.LIBRARY_SVG_DIR, r["file"])) - else: - print(f"{len(rows)} match, showing {len(shown)} (★ = exemplary; files in {svglib.LIBRARY_SVG_DIR})") - for r in shown: - star = "★" if r.get("exemplary") else " " - kind = r.get("mark_type") or "?" - if r.get("symbol_type"): - kind += "/" + r["symbol_type"] - print(f"{star} {r['file']:34s} {kind:22s} {r.get('n_colors', 0):2d}c {(r.get('subject') or '')[:48]}") - if r.get("note") and r.get("exemplary"): - print(f" ↳ {r['note']}") - - -if __name__ == "__main__": - main() diff --git a/.claude/skills/logo-design/scripts/svg_audit.py b/.claude/skills/logo-design/scripts/svg_audit.py deleted file mode 100644 index 676d6ff..0000000 --- a/.claude/skills/logo-design/scripts/svg_audit.py +++ /dev/null @@ -1,261 +0,0 @@ -#!/usr/bin/env python3 -"""Audit a logo SVG against logo-design principles and production rules. - -Checks structure (viewBox, title, text/raster/filters), colour discipline, complexity versus the -reference library, near-miss angles (lines 0.3–3° off a clean angle), tiny details that vanish when small, -padding/centring inside the viewBox, strokes that should be expanded, and white "fake knockouts". - -Usage: - python3 scripts/svg_audit.py logo.svg [more.svg ...] - python3 scripts/svg_audit.py logo.svg --json # machine-readable - python3 scripts/svg_audit.py logo.svg --bg "#0F7C80" # also report contrast of colours on a background - -Exit code is 0 unless a file cannot be parsed. Findings are advice, not law: a deliberate choice can -override a warning — but you should be able to say why. -""" -import argparse -import json -import math -import os -import re -import sys - -sys.dont_write_bytecode = True # keep the skill folder clean (no __pycache__) -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -import svglib # noqa: E402 - -CLEAN_ANGLES = [0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180] - - -def load_stats(): - try: - with open(svglib.STATS_PATH, encoding="utf-8") as fh: - return json.load(fh) - except OSError: - return None - - -def audit(path, bg=None): - findings = [] # (level, code, message) - - def add(level, code, msg): - findings.append({"level": level, "code": code, "message": msg}) - - raw, root = svglib.load_svg(path) - counts = svglib.element_counts(root) - vb = svglib.view_box(root) - info = {"file": os.path.basename(path), "bytes": os.path.getsize(path)} - - # --- structure ------------------------------------------------------------------------- - if not root.get("viewBox"): - add("WARN", "no-viewbox", "No viewBox: the logo will not scale predictably. Add viewBox=\"0 0 W H\".") - if vb: - info["viewBox"] = vb - w, h = vb[2], vb[3] - info["aspect"] = round(w / h, 3) if h else None - info["aspect_class"] = svglib.aspect_class(info["aspect"]) - if any(abs(v - round(v)) > 1e-6 for v in vb): - add("INFO", "fractional-viewbox", "viewBox has fractional values; integer canvases are easier to grid.") - if counts.get("text", 0) or counts.get("tspan", 0): - add("FAIL", "live-text", "Contains : final logos must use outlined paths (fonts differ per machine).") - if counts.get("image", 0): - add("FAIL", "raster-image", "Contains (embedded raster). A logo master must be pure vector.") - if counts.get("filter", 0): - add("WARN", "filter", "Uses filters (blur/shadow/glow). They render inconsistently and cannot be printed; use flat shapes.") - if counts.get("mask", 0): - add("INFO", "mask", "Uses . Fine for exploration; bake into paths for production (cutters/embroidery).") - if counts.get("foreignObject", 0): - add("FAIL", "foreign-object", "Contains (HTML inside SVG). Not portable.") - if counts.get("style", 0): - add("INFO", "style-block", "Uses a