From 4634e0d7d94efcbe2ba15be0c1726583a12d605a Mon Sep 17 00:00:00 2001 From: handlecusion Date: Sun, 24 May 2026 18:33:49 +0900 Subject: [PATCH] feat(docs): redesign GitHub Pages landing --- design/landing-style-reference.md | 316 ++++ docs/favicon.png | Bin 0 -> 1743 bytes docs/index.html | 310 ++- docs/styles.css | 799 ++++++++ docs/tokcat-landing-motion.mp4 | Bin 0 -> 602346 bytes docs/tokcat-landing-poster.png | Bin 0 -> 168652 bytes package-lock.json | 2901 +++++++++++++++++++++++++++-- package.json | 3 + public/remotion/dashboard-3d.png | Bin 0 -> 98721 bytes public/remotion/menubar-cat2.gif | Bin 0 -> 19281 bytes remotion/Root.tsx | 15 + remotion/TokcatLandingMotion.tsx | 296 +++ remotion/index.ts | 4 + 13 files changed, 4428 insertions(+), 216 deletions(-) create mode 100644 design/landing-style-reference.md create mode 100644 docs/favicon.png create mode 100644 docs/styles.css create mode 100644 docs/tokcat-landing-motion.mp4 create mode 100644 docs/tokcat-landing-poster.png create mode 100644 public/remotion/dashboard-3d.png create mode 100644 public/remotion/menubar-cat2.gif create mode 100644 remotion/Root.tsx create mode 100644 remotion/TokcatLandingMotion.tsx create mode 100644 remotion/index.ts diff --git a/design/landing-style-reference.md b/design/landing-style-reference.md new file mode 100644 index 0000000..80cc23d --- /dev/null +++ b/design/landing-style-reference.md @@ -0,0 +1,316 @@ +# Scale — Style Reference +> Midnight Command Center: An expanse of polished dark surfaces, illuminated by precise white text and the occasional shimmer of an iridescent, almost holographic, light. + +**Theme:** dark + +This design system evokes a sense of deep, sophisticated technology within a secure, high-contrast environment. The dominant ultra-dark palette, punctuated by crisp white text and a subtle, iridescent gradient, creates an atmosphere of serious innovation. Minimal use of vibrant colors ensures that any color interaction is highly deliberate, like an indicator light on a complex machine. Typography features whisper-light headlines, conveying authority through understated elegance against the stark backdrop. + +## Tokens — Colors + +| Name | Value | Token | Role | +|------|-------|-------|------| +| Deep Space | `#000000` | `--color-deep-space` | Primary page background, card backgrounds, creating a high-contrast canvas. | +| Ghost White | `#ffffff` | `--color-ghost-white` | Primary text color for headlines and body text, accentuating information against the dark background. Also used for borders on interactive elements. | +| Iron Slate | `#a1a1a1` | `--color-iron-slate` | Secondary text for less prominent information, active navigation links, and subtle borders. | +| Halo Pale | `#f4f0ff` | `--color-halo-pale` | Subtle, near-white text for secondary links and body text in less prominent sections. This provides a very soft contrast against black. | +| Shadow Tint | `#020202` | `--color-shadow-tint` | Subtle shadows and background for elements that need a touch more depth than pure black. | +| Subtle Gray | `#e5e5e5` | `--color-subtle-gray` | Text and icon color, for details that require slightly less prominence than Ghost White. | +| Iridescent Glow | `#bbdef2` | `--color-iridescent-glow` | Backgrounds of geometric abstract shapes, providing a luminous, futuristic visual accent. | +| Spectrum Flare | `#d1aad7` | `--color-spectrum-flare` | Used for the lighter parts of the iridescent gradient, giving it a soft, ethereal quality. | +| Vivid Crimson | `#ff6467` | `--color-vivid-crimson` | Indicator or accent background, used sparingly to draw attention. | +| Goldenrod | `#ffd600` | `--color-goldenrod` | Indicator or accent background, used sparingly for specific highlight. | +| Emerald Green | `#72ce7b` | `--color-emerald-green` | Indicator or accent background, used sparingly for specific highlight. | +| Dark Rainbow Gradient | `linear-gradient(to right bottom in oklab, rgb(154, 154, 154) 0%, rgb(26, 26, 26) 50%, rgb(106, 106, 106) 100%)` | `--color-dark-rainbow-gradient` | Used for highly stylized, abstract background elements, providing a subtle shimmer that hints at dimension and data flow. | + +## Tokens — Typography + +### Inter — Standard body text, navigation elements, buttons, and various UI labels. Its wide range of sizes and normal weight support the bulk of content, ensuring readability without distracting from the main brand typography. · `--font-inter` +- **Substitute:** system-ui, sans-serif +- **Weights:** 400, 500 +- **Sizes:** 12px, 14px, 16px, 18px, 20px +- **Line height:** 1.33, 1.43, 1.50, 1.56, 1.60, 1.65, 1.71 +- **Letter spacing:** 0.10em at 12px, 0.286em at 14px, 0.333em at 16px +- **Role:** Standard body text, navigation elements, buttons, and various UI labels. Its wide range of sizes and normal weight support the bulk of content, ensuring readability without distracting from the main brand typography. + +### aeonik — Primary display font for headlines and sub-headlines. The signature weight 300 for large sizes creates a whisper-quiet yet authoritative tone, prioritizing understatement over visual shouting, which is distinctive for a high-tech brand. · `--font-aeonik` +- **Substitute:** Montserrat, sans-serif +- **Weights:** 300, 400 +- **Sizes:** 24px, 26px, 36px, 48px, 72px, 89px +- **Line height:** 1.00, 1.11, 1.13, 1.23, 1.25, 1.33, 1.67 +- **Letter spacing:** -0.01em +- **Role:** Primary display font for headlines and sub-headlines. The signature weight 300 for large sizes creates a whisper-quiet yet authoritative tone, prioritizing understatement over visual shouting, which is distinctive for a high-tech brand. + +### geist — Used for small, descriptive text, often for labels or details that require a slightly technical or precise feel. The wider letter-spacing at smaller sizes improves legibility. · `--font-geist` +- **Substitute:** Source Code Pro, monospace +- **Weights:** 400 +- **Sizes:** 12px, 14px +- **Line height:** 1.43, 1.50, 2.00 +- **Letter spacing:** 0.071em at 14px, 0.083em at 12px +- **Role:** Used for small, descriptive text, often for labels or details that require a slightly technical or precise feel. The wider letter-spacing at smaller sizes improves legibility. + +## Tokens — Spacing & Shapes + +**Base unit:** 8px + +**Density:** comfortable + +### Spacing Scale + +| Name | Value | Token | +|------|-------|-------| +| 8 | 8px | `--spacing-8` | +| 16 | 16px | `--spacing-16` | +| 24 | 24px | `--spacing-24` | +| 32 | 32px | `--spacing-32` | +| 40 | 40px | `--spacing-40` | +| 48 | 48px | `--spacing-48` | +| 64 | 64px | `--spacing-64` | +| 72 | 72px | `--spacing-72` | +| 80 | 80px | `--spacing-80` | +| 192 | 192px | `--spacing-192` | +| 224 | 224px | `--spacing-224` | + +### Border Radius + +| Element | Value | +|---------|-------| +| links | 16px | +| lists | 4px | +| default | 8px | + +### Shadows + +| Name | Value | Token | +|------|-------|-------| +| subtle | `rgba(255, 255, 255, 0.1) 0px 1px 1px 0px inset` | `--shadow-subtle` | + +### Layout + +- **Section gap:** 32px +- **Card padding:** 24px +- **Element gap:** 8px + +## Components + +### Navigation Link +**Role:** Primary navigation item + +White text (Ghost White #ffffff) on a transparent background, 4px vertical padding and 0px horizontal padding. Underlines appear on hover/active states, with no distinct border radius. Font is Inter 16px weight 400. + +### Secondary Hero Button (Text Link) +**Role:** Secondary call to action + +Ghost White #ffffff text on a transparent background, with an arrow icon. Font is Inter 16px weight 400. Padding of 17px horizontal and 12px vertical. No explicit border or radius. + +### Feature Card +**Role:** Content container for features + +Implicitly dark background (likely Deep Space #000000 or Shadow Tint #020202) with rounded corners (8px). Text is typically Ghost White #ffffff for headings and Halo Pale #f4f0ff or Iron Slate #a1a1a1 for body copy. Contains abstract image elements. + +## Do's and Don'ts + +### Do +- Prioritize Deep Space (#000000) for backgrounds and Ghost White (#ffffff) for primary text to maintain high contrast and sophistication. +- Use aeonik font with weight 300 for all large headlines (48px and above) to achieve an understated, authoritative tone. +- Apply Iron Slate (#a1a1a1) for secondary text and active navigation items to provide subtle differentiation without losing readability. +- Employ the Iridescent Glow (#bbdef2) and Spectrum Flare (#d1aad7) gradient only for abstract geometric elements or distinctive brand accents, not for interactive components. +- Maintain generous vertical spacing between sections, using multiples of 32px to provide breathing room on the dark canvas. +- Use 8px border radius as the default for most containers and images, with 16px for larger interactive links, and 4px for smaller list items. + +### Don't +- Do not introduce highly saturated colors for general UI elements; reserve them for specific accent indicators if truly necessary. +- Avoid heavy drop shadows; the design relies on subtle background variations and text contrast for depth, with minimal inset shadows. +- Do not use aeonik font for body text; reserve it for headlines and maintain its distinctive impact. +- Avoid excessive use of Halo Pale (#f4f0ff) for primary content; its low contrast is intended for secondary or subtle elements. +- Do not use generic system borders; interactive elements should feature white or subtle gray borders for consistency. +- Avoid dense information blocks; use ample White Space, especially on dark backgrounds, to enhance clarity and visual weight. + +## Imagery + +The visual language is characterized by abstract, geometric 3D renders with iridescent, gradient-filled surfaces (Iridescent Glow #bbdef2, Spectrum Flare #d1aad7). These graphics are contained and serve as decorative visual anchors in the dark space, emphasizing a futuristic, AI-driven aesthetic. Photography is minimal, if present, and product screenshots are likely stylized to fit the dark theme. Icons are typically white or subtle gray, outlined, reinforcing the clean, high-tech identity. The imagery acts primarily as atmospheric branding and conceptual illustration, occupying significant visual space relative to text in some hero sections, but is not dense or overwhelming. + +## Layout + +The page primarily uses a max-width contained layout, centered on the screen, though the hero section spans full-bleed with its striking dark background and large, centered typography. The hero features a simple, prominent headline over a dark void, balanced by abstract 3D graphics on one side. Subsequent sections predominantly follow a vertical stacking pattern with consistent Deep Space (#000000) backgrounds, occasionally introducing subtly different dark shades for content blocks. Content is often presented in centered stacks or simple two-column arrangements (text alongside an image/graphic). Navigation is a sticky top bar with minimal links and clear call-to-action buttons. Vertical spacing between sections is generous (32px and above), creating a spacious and unhurried rhythm. + +## Agent Prompt Guide + +### Quick Color Reference +- Text (Primary): #ffffff (Ghost White) +- Background (Primary): #000000 (Deep Space) +- CTA Button Background: transparent +- CTA Button Border: #ffffff (Ghost White) +- Accent Graphic: #bbdef2 (Iridescent Glow) + +### Example Component Prompts +1. Create a Hero Section: Full-width Deep Space #000000 background. Centered headline 'Breakthrough AI from Data to Deployment' using aeonik 89px weight 300, Ghost White #ffffff, letter-spacing -0.01em. Subtext 'Scale delivers proven data...' using Inter 20px weight 400, Halo Pale #f4f0ff, line-height 1.6. Two buttons: 'Book a Demo' with Ghost White #ffffff text, transparent background, 1px Ghost White #ffffff border, 17px horizontal, 12px vertical padding; and 'Build AI' with Ghost White #ffffff text, transparent background, no border, 17px horizontal, 12px vertical padding. Include an abstract geometric graphic using Iridescent Glow #bbdef2 and Spectrum Flare #d1aad7 colors on the right side. +2. Design a Navigation Bar: Deep Space #000000 background, 59-147px height. Logo 'Scale' using Inter 24px weight 500, Ghost White #ffffff. Navigation links 'Products', 'Research', 'Enterprise', 'Government', 'Resources' using Inter 16px weight 400, Ghost White #ffffff, white on hover, 4px vertical padding, 0px horizontal padding. Right-aligned buttons 'Book a Demo' (Ghost White #ffffff text, 1px Ghost White #ffffff border, transparent background) and 'Log In' (Ghost White #ffffff text, transparent background, no border). +3. Create a Testimonial Block: Deep Space #000000 background. Headline 'We have changed the game...' using aeonik 48px weight 300, Ghost White #ffffff, letter-spacing -0.01em. A testimonial card: 8px border-radius, transparent background with inset shadow rgba(255, 255, 255, 0.1) 0px 1px 1px 0px inset. Quote text '"We partnered with Scale AI..."' using Inter 20px weight 400, Ghost White #ffffff. Attribution 'Mark Zuckerberg' using Inter 16px weight 500, Halo Pale #f4f0ff. + +## Similar Brands + +- **OpenAI** — Shares a sophisticated, dark-mode focused UI with strong typography and minimal, controlled use of color, conveying high-tech and serious intent. +- **Databricks** — Employs an enterprise-grade dark theme, often featuring abstract geometric visuals and a clear hierarchy emphasized by text weight and color contrast. +- **Palantir** — Utilizes a dark, high-contrast interface with an emphasis on data visualization and a controlled, almost austere aesthetic, communicating complex capabilities. +- **Anthropic** — Features a clean, minimalist dark aesthetic with a focus on core information, using typography and subtle grays to establish hierarchy. + +## Quick Start + +### CSS Custom Properties + +```css +:root { + /* Colors */ + --color-deep-space: #000000; + --color-ghost-white: #ffffff; + --color-iron-slate: #a1a1a1; + --color-halo-pale: #f4f0ff; + --color-shadow-tint: #020202; + --color-subtle-gray: #e5e5e5; + --color-iridescent-glow: #bbdef2; + --color-spectrum-flare: #d1aad7; + --color-vivid-crimson: #ff6467; + --color-goldenrod: #ffd600; + --color-emerald-green: #72ce7b; + --color-dark-rainbow-gradient: #9a9a9a; + --gradient-dark-rainbow-gradient: linear-gradient(to right bottom in oklab, rgb(154, 154, 154) 0%, rgb(26, 26, 26) 50%, rgb(106, 106, 106) 100%); + + /* Typography — Font Families */ + --font-inter: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + --font-aeonik: 'aeonik', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + --font-geist: 'geist', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + + /* Typography — Scale */ + --text-xs: 12px; + --leading-xs: 2; + --text-sm: 14px; + --leading-sm: 1.43; + --text-base: 16px; + --leading-base: 1.5; + --text-lg: 18px; + --leading-lg: 1.65; + --text-xl: 20px; + --leading-xl: 1.6; + --text-2xl: 24px; + --leading-2xl: 1.67; + --text-2xl-2: 26px; + --leading-2xl-2: 1.23; + --text-4xl: 36px; + --leading-4xl: 1.25; + --text-5xl: 48px; + --leading-5xl: 1.25; + --text-5xl-2: 72px; + --leading-5xl-2: 1.11; + --text-5xl-3: 89px; + --leading-5xl-3: 1; + + /* Typography — Weights */ + --font-weight-light: 300; + --font-weight-regular: 400; + --font-weight-medium: 500; + + /* Spacing */ + --spacing-unit: 8px; + --spacing-8: 8px; + --spacing-16: 16px; + --spacing-24: 24px; + --spacing-32: 32px; + --spacing-40: 40px; + --spacing-48: 48px; + --spacing-64: 64px; + --spacing-72: 72px; + --spacing-80: 80px; + --spacing-192: 192px; + --spacing-224: 224px; + + /* Layout */ + --section-gap: 32px; + --card-padding: 24px; + --element-gap: 8px; + + /* Border Radius */ + --radius-md: 4px; + --radius-lg: 8px; + --radius-xl: 12px; + --radius-2xl: 16px; + + /* Named Radii */ + --radius-links: 16px; + --radius-lists: 4px; + --radius-default: 8px; + + /* Shadows */ + --shadow-subtle: rgba(255, 255, 255, 0.1) 0px 1px 1px 0px inset; +} +``` + +### Tailwind v4 + +```css +@theme { + /* Colors */ + --color-deep-space: #000000; + --color-ghost-white: #ffffff; + --color-iron-slate: #a1a1a1; + --color-halo-pale: #f4f0ff; + --color-shadow-tint: #020202; + --color-subtle-gray: #e5e5e5; + --color-iridescent-glow: #bbdef2; + --color-spectrum-flare: #d1aad7; + --color-vivid-crimson: #ff6467; + --color-goldenrod: #ffd600; + --color-emerald-green: #72ce7b; + --color-dark-rainbow-gradient: #9a9a9a; + + /* Typography */ + --font-inter: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + --font-aeonik: 'aeonik', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + --font-geist: 'geist', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + + /* Typography — Scale */ + --text-xs: 12px; + --leading-xs: 2; + --text-sm: 14px; + --leading-sm: 1.43; + --text-base: 16px; + --leading-base: 1.5; + --text-lg: 18px; + --leading-lg: 1.65; + --text-xl: 20px; + --leading-xl: 1.6; + --text-2xl: 24px; + --leading-2xl: 1.67; + --text-2xl-2: 26px; + --leading-2xl-2: 1.23; + --text-4xl: 36px; + --leading-4xl: 1.25; + --text-5xl: 48px; + --leading-5xl: 1.25; + --text-5xl-2: 72px; + --leading-5xl-2: 1.11; + --text-5xl-3: 89px; + --leading-5xl-3: 1; + + /* Spacing */ + --spacing-8: 8px; + --spacing-16: 16px; + --spacing-24: 24px; + --spacing-32: 32px; + --spacing-40: 40px; + --spacing-48: 48px; + --spacing-64: 64px; + --spacing-72: 72px; + --spacing-80: 80px; + --spacing-192: 192px; + --spacing-224: 224px; + + /* Border Radius */ + --radius-md: 4px; + --radius-lg: 8px; + --radius-xl: 12px; + --radius-2xl: 16px; + + /* Shadows */ + --shadow-subtle: rgba(255, 255, 255, 0.1) 0px 1px 1px 0px inset; +} +``` diff --git a/docs/favicon.png b/docs/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..fb10530a62144e176006a24b622bb830cbb4c672 GIT binary patch literal 1743 zcmV;=1~B=FP)z%v2-bz!_yd8|RkN_G>_tq)SV0kt z&~)R*ov!La+}MbML}QXhYyN-D%)EKG=R5b__miedExpX;zBljPd%kndcYa>d_kBfX zD5Xg8Z6cYV|6_QbN3QFV<2b>8NqfOSD3M^nF42n@FX-jVL7JVNlTETg;im+o1uOq3 zy;s2V#C3Eg`OI`h1=ZKrQ$s_8+3WL}ZV12%fA{Vk^FdugZ^`-;Y?qn%e@vb65cYG$8(;EmBicLrDgnD9;>z zS-pP!nmRf3w& zGtGgap&=&RELB!k%E8v`c39TJ_pm`!kmV3eypn_%+3d1d0%wTEyiQI{(eTJHZQQs~ z1Ay>cE*qH37@jD=;AqA}TVn+~bL_4>3s0p|0YNPfrl+SV!!E_ZwN)gS%hCM&yhN32 z<5NuLY4&2~<=PX|d0t*0DndgIpGH7YJH7NM3y z;zE;tlGe9Ys5O%vU@Ac1KpX<60tjBoVTzIJC*+kXRn@jK;XOVV_92tl2b^rkI*{@22`~+ayFWpzX6~&*L&CShp@Zdq}@9(FF4}YU$$BxmZOPAPXHDM~}8Ct;8 z2}HtVa)OQ?{Z@nn6kfEMapjQb28`v*g9i`9JpjEJ53*@2CX38?k z44wb}d?4hXgv&G64O29Oso=r`t!*Aa5dwEEUc4wFYU-}$AS>&J8O|5;&dtrzA@+ND zx?GA#RKUju7;ZrzJi#dlK_pzi{xg-8mx(Ja2o-gKu58*wyLRo0Wx#(k1cWWcTw_K? zM(A+MVS2yxo=QqeOfIoONTCIEC>D5AA_z6-6B`czcTK%7Eh(i8yVS9zTv@m`OsB zNQk>Y1smSH8KdLJkJH#6W6~pFBM5~UM^s=cBfzHcl@q|R=hm%ToKubp8H-pU+s3JA zCX8~x<3mwU;D-HQ?WY4@AE2E(cS=65tE-c)rmUP*zYh-&)7`swrTfif zYUM1+KPqf&aW4SGH@4$3$Y5TW5SxJ-rh{owP!<+OrHj&if*){W<*2Ag3uwFthAWLg zESKQ3ai7FS#3}lB+wItx)tM6nbaZSp5O5@wDheCc7^T8I5cZ6IB=;);j5FX8$%Kei z0-N1UcR@Y_~3frVxgf4l6i@aFsAb>lb{ULo2ofGMIdtnU7H?UglO!!D`i; lu;}Ora>Wt|ZQFNZ`~~vgTMDXVbhZEh002ovPDHLkV1hpxQ5XOK literal 0 HcmV?d00001 diff --git a/docs/index.html b/docs/index.html index 0f98860..5e41716 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,7 +3,7 @@ - Tokcat — AI Token Usage Monitor for the macOS Menu Bar + Tokcat - AI Token Usage Monitor for the macOS Menu Bar @@ -12,16 +12,18 @@ - + - + - - - + + + + + @@ -66,7 +68,7 @@ "Animated menu-bar cat icon reflecting token velocity", "macOS NSVisualEffectView vibrancy and light/dark adaptation", "Signed in-app updater with 30-minute check interval", - "Local-only data — no telemetry, no account", + "Local-only data with no telemetry and no account", "Launch at login via Tauri autostart" ], "offers": { @@ -112,7 +114,7 @@ "name": "How much does Tokcat cost?", "acceptedAnswer": { "@type": "Answer", - "text": "Tokcat is free and open-source under the MIT licence. There is no subscription, no paid tier, and no telemetry. Install with brew tap handlecusion/tokcat && brew install --cask tokcat." + "text": "Tokcat is free and open-source under the MIT license. There is no subscription, no paid tier, and no telemetry. Install with brew install --cask handlecusion/tokcat/tokcat." } }, { @@ -160,86 +162,232 @@ ] } - - -

Tokcat

-

AI token usage monitor for the macOS menu bar.

-

- macOS 11+ - Apple Silicon - Tauri 2 - MIT - No telemetry -

+ + +
+
+ + + +
+

Local command center for AI spend

+

Tokcat

+

+ AI token usage monitor and LLM cost tracker for Claude Code usage, Codex usage, Cursor usage, + Copilot, Gemini, OpenCode, Amp, Droid, and Hermes. Local logs in, clear spend out. +

+ +
+
+
Runtime
+
macOS 11+ arm64
+
+
+
Data path
+
Local-only logs
+
+
+
Surface
+
2D and 3D graph
+
+
+
+ No telemetry + Signed updater + Local only +
+
+
+ +
+
+
+

Quick start

+

Install, launch, click the menu-bar cat.

+

+ Tokcat reads supported AI coding session logs directly on your Mac. No separate token-usage CLI, + cloud account, or telemetry pipeline is required. +

+
+
+ +
brew install --cask handlecusion/tokcat/tokcat
+
+
+
+ +
+
+
+

Operational surfaces

+

See the menubar workflow before you install.

+

+ Real Tokcat screenshots show the daily cost view, the 2D and 3D contribution graphs, + and the settings panel used to tune the menubar behavior. +

+
-

- Tokcat is an AI token usage monitor and LLM cost tracker for the macOS menu bar, - built with Tauri 2 (Rust + React/Vite). It tracks Claude Code usage, OpenAI Codex usage, Cursor usage, - OpenCode, Google Gemini, GitHub Copilot, Amp, Droid, and Hermes as a 2D or 3D GitHub-style - contribution graph. The animated cat icon shows today's tokens or USD cost; clicking opens a - frosted-glass popover with per-client filters, streak summaries, and a settings panel. Tokcat - reads local usage logs on-device, checks for signed updates every 30 minutes, ships zero - telemetry, and requires no account. -

+
+
+ Tokcat 3D contribution graph dashboard +
+

3D contribution graph

+

Interactive tile terrain with cost and token totals visible at a glance.

+
+
+
+ Tokcat 2D heatmap dashboard +
+

2D heatmap

+

GitHub-style daily activity for long-term AI coding agent usage.

+
+
+
+ Tokcat settings panel +
+

System-style settings

+

Menu-bar title, launch at login, animation style, and updater checks.

+
+
+
+
+
-

Install

-
brew tap handlecusion/tokcat
-brew install --cask tokcat
-

Or grab the latest signed DMG from - GitHub Releases.

+
+
+
+

Supported sources

+

One local dashboard for the AI tools that leave usage trails.

+

+ Each source is normalized into the same contribution timeline, so token-heavy days and + high-cost clients stand out without leaving the menu bar. +

+
+
    +
  • Claude Code
  • +
  • OpenAI Codex
  • +
  • Cursor
  • +
  • GitHub Copilot
  • +
  • Gemini
  • +
  • OpenCode
  • +
  • Amp
  • +
  • Droid
  • +
  • Hermes
  • +
+
+
-

Links

- +
+
+
+

Why it exists

+

Token spend is easier to manage when it is always visible.

+
+
+
+

Glanceable

+

The animated menu-bar title can show today's tokens, today's cost, total tokens, total cost, or icon-only mode.

+
+
+

Native

+

Tauri 2, Rust, React, macOS vibrancy, light and dark adaptation, and a chromeless popover window.

+
+
+

Multi-client

+

Filter by Claude Code, Codex, Cursor, Copilot, Gemini, OpenCode, Amp, Droid, Hermes, and compatible logs.

+
+
+

Actionable

+

Streaks, daily average, best day, per-client totals, and model-aware cost estimates make usage patterns obvious.

+
+
+
+
-

FAQ

-
What is Tokcat? -

Tokcat is a free, open-source native macOS menu-bar app that visualizes your AI coding token usage as a 2D or 3D GitHub-style contribution graph. Its Tauri 2 backend reads local sessions from Claude Code, Codex, Cursor, OpenCode, Gemini, Copilot, Amp, Droid, and Hermes in one glanceable place. The app runs entirely on-device, makes zero analytics requests, and requires no account.

-
-
How much does Tokcat cost? -

Tokcat is free and open-source under the MIT licence. There is no subscription, no paid tier, and no telemetry. Install with brew tap handlecusion/tokcat && brew install --cask tokcat.

-
-
Which AI coding tools does Tokcat track? -

Tokcat tracks Claude Code, OpenAI Codex, Cursor, OpenCode, Google Gemini, GitHub Copilot, Amp, Droid, Hermes, and compatible local logs. New client formats are added in Tokcat's Rust usage reader.

-
-
Does Tokcat send my data anywhere? -

No. Tokcat's only network request is a check against the GitHub Releases updater manifest. There is no telemetry, no analytics, no cloud sync, no account, and no third-party server. All token data is read locally from session logs.

-
-
How is Tokcat different from CLI token-usage tools? -

Tokcat is a native macOS GUI and background local-log reader — an animated menu-bar cat, a click-to-open frosted-glass dashboard with a 2D heatmap and an interactive 3D tile graph, per-client filters, streaks, and a settings panel. It does not require a separate token-usage CLI at runtime.

-
-
Does Tokcat run on Intel Macs or Windows? -

Tokcat ships only for Apple Silicon (arm64) on macOS 11+. There is no Intel x86_64 build and no Windows or Linux build.

-
+
+
+
+

Privacy model

+

No telemetry. No account. No cloud sync.

+
+

+ Tokcat's only network traffic is the signed updater manifest from GitHub Releases. Usage data is read + from local session logs and rendered in the menubar dashboard on-device. +

+
+
-

Privacy

-

- No telemetry. No cloud sync. No account. Tokcat's only network traffic is the updater - manifest fetched from github.com/handlecusion/tokcat/releases/latest/download/latest.json - every 30 minutes. All token-usage data is read locally from session logs. -

+
+
+
+

FAQ

+

Common install and usage questions.

+
+
+
+ What is Tokcat? +

Tokcat is a free, open-source native macOS menu-bar app that visualizes AI coding token usage as a 2D or 3D contribution graph.

+
+
+ How much does Tokcat cost? +

Tokcat is free and open-source under the MIT license. There is no subscription, paid tier, telemetry, or account.

+
+
+ Which AI coding tools does Tokcat track? +

Tokcat tracks Claude Code, OpenAI Codex, Cursor, OpenCode, Google Gemini, GitHub Copilot, Amp, Droid, Hermes, and compatible local logs.

+
+
+ Does Tokcat send my data anywhere? +

No. Token usage stays local. The app checks GitHub Releases for updater metadata and does not run analytics.

+
+
+ Does Tokcat run on Intel Macs or Windows? +

Tokcat ships for Apple Silicon Macs on macOS 11 or newer. There is no Intel, Windows, or Linux build.

+
+
+
+
+
-

- © Tokcat contributors · MIT licence · - github.com/handlecusion/tokcat -

+ diff --git a/docs/styles.css b/docs/styles.css new file mode 100644 index 0000000..e3ac742 --- /dev/null +++ b/docs/styles.css @@ -0,0 +1,799 @@ +:root { + color-scheme: dark; + --color-deep-space: #000000; + --color-ghost-white: #ffffff; + --color-iron-slate: #a1a1a1; + --color-halo-pale: #f4f0ff; + --color-shadow-tint: #020202; + --color-subtle-gray: #e5e5e5; + --color-iridescent-glow: #bbdef2; + --color-spectrum-flare: #d1aad7; + --color-vivid-crimson: #ff6467; + --color-goldenrod: #ffd600; + --color-emerald-green: #72ce7b; + --gradient-dark-rainbow-gradient: linear-gradient(to right bottom in oklab, rgb(154, 154, 154) 0%, rgb(26, 26, 26) 50%, rgb(106, 106, 106) 100%); + --font-inter: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --font-aeonik: aeonik, Montserrat, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --font-geist: geist, "SFMono-Regular", "Source Code Pro", Menlo, Consolas, monospace; + --line: rgba(255, 255, 255, 0.16); + --line-soft: rgba(255, 255, 255, 0.08); + --panel: rgba(255, 255, 255, 0.035); + --panel-strong: rgba(255, 255, 255, 0.07); + --shadow-subtle: rgba(255, 255, 255, 0.1) 0 1px 1px 0 inset; + --radius: 8px; + --max: 1160px; +} + +* { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; + background: var(--color-deep-space); +} + +body { + margin: 0; + min-width: 320px; + background: + radial-gradient(circle at 74% 9%, rgba(187, 222, 242, 0.18), transparent 28rem), + radial-gradient(circle at 12% 45%, rgba(209, 170, 215, 0.11), transparent 30rem), + var(--color-deep-space); + color: var(--color-ghost-white); + font-family: var(--font-inter); + font-size: 16px; + line-height: 1.56; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} + +body::before { + content: ""; + position: fixed; + inset: 0; + z-index: -2; + pointer-events: none; + background-image: + linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px), + linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px); + background-size: 64px 64px; + mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.9), transparent 82%); +} + +a { + color: inherit; + text-decoration: none; +} + +a:hover { + text-decoration: underline; + text-underline-offset: 5px; +} + +img, +video { + display: block; + max-width: 100%; +} + +h1, +h2, +h3, +p { + margin-top: 0; +} + +h1, +h2, +h3 { + font-family: var(--font-aeonik); + font-weight: 300; + letter-spacing: -0.01em; +} + +.site-header { + position: sticky; + top: 0; + z-index: 20; + height: 72px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 32px; + padding: 0 40px; + background: rgba(0, 0, 0, 0.78); + border-bottom: 1px solid var(--line-soft); + backdrop-filter: blur(22px); + -webkit-backdrop-filter: blur(22px); +} + +.brand { + display: inline-flex; + align-items: center; + gap: 12px; + min-width: 0; + color: var(--color-ghost-white); + font-size: 18px; + font-weight: 500; +} + +.brand img { + width: 32px; + height: 32px; + border-radius: 8px; + box-shadow: var(--shadow-subtle); +} + +.nav-links { + display: flex; + align-items: center; + gap: 24px; + color: var(--color-halo-pale); + font-size: 15px; + font-weight: 400; +} + +.hero { + position: relative; + min-height: 680px; + height: calc(84svh - 72px); + max-height: 800px; + overflow: hidden; + isolation: isolate; + border-bottom: 1px solid var(--line-soft); + background: var(--color-deep-space); +} + +.hero-grid { + position: absolute; + inset: 0; + z-index: -4; + background: + linear-gradient(115deg, rgba(255, 255, 255, 0.08), transparent 18%), + repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.06) 0 1px, transparent 1px 96px); + opacity: 0.48; +} + +.hero-video { + position: absolute; + top: 160px; + right: max(32px, calc((100vw - var(--max)) / 2 - 76px)); + left: auto; + bottom: auto; + z-index: -1; + width: min(560px, 43vw); + height: min(350px, 38vw); + object-fit: cover; + object-position: center; + opacity: 1; + border: 1px solid var(--line-soft); + border-radius: var(--radius); + background: var(--color-shadow-tint); + box-shadow: var(--shadow-subtle); +} + +.hero-shade { + position: absolute; + inset: 0; + z-index: -2; + background: + linear-gradient(90deg, rgba(0, 0, 0, 0.98) 0%, rgba(0, 0, 0, 0.92) 48%, rgba(0, 0, 0, 0.5) 72%, rgba(0, 0, 0, 0.9) 100%), + linear-gradient(180deg, rgba(0, 0, 0, 0.28) 0%, rgba(0, 0, 0, 0.98) 100%); +} + +.hero-content { + width: min(760px, calc(100% - 48px)); + padding: 88px 0 64px; + margin-left: max(32px, calc((100vw - var(--max)) / 2)); +} + +.eyebrow, +.section-kicker { + margin-bottom: 32px; + color: var(--color-iridescent-glow); + font-family: var(--font-geist); + font-size: 12px; + line-height: 2; + font-weight: 400; + text-transform: uppercase; + letter-spacing: 0.083em; +} + +.hero h1 { + margin-bottom: 24px; + color: var(--color-ghost-white); + font-size: clamp(72px, 9vw, 128px); + line-height: 0.9; +} + +.hero-copy { + max-width: 660px; + margin-bottom: 32px; + color: var(--color-halo-pale); + font-size: 20px; + line-height: 1.6; +} + +.hero-actions { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-bottom: 40px; +} + +.button { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 48px; + padding: 12px 18px; + border-radius: 16px; + border: 1px solid transparent; + color: var(--color-ghost-white); + font-size: 16px; + font-weight: 400; + white-space: nowrap; +} + +.button.primary { + background: transparent; + border-color: var(--color-ghost-white); + box-shadow: var(--shadow-subtle); +} + +.button.secondary { + position: relative; + color: var(--color-ghost-white); + background: transparent; +} + +.button.secondary::after { + content: "->"; + margin-left: 10px; + color: var(--color-iridescent-glow); +} + +.hero-stats { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 8px; + width: min(680px, 100%); + margin: 0 0 16px; +} + +.hero-stats div { + min-width: 0; + padding: 16px; + border: 1px solid var(--line-soft); + border-radius: var(--radius); + background: rgba(2, 2, 2, 0.74); + box-shadow: var(--shadow-subtle); +} + +.hero-stats dt { + margin-bottom: 8px; + color: var(--color-iron-slate); + font-family: var(--font-geist); + font-size: 12px; + line-height: 1.5; + font-weight: 400; + text-transform: uppercase; + letter-spacing: 0.083em; +} + +.hero-stats dd { + margin: 0; + overflow-wrap: anywhere; + color: var(--color-ghost-white); + font-size: 16px; + font-weight: 500; +} + +.signal-rail { + display: flex; + flex-wrap: wrap; + gap: 8px; + color: var(--color-subtle-gray); + font-family: var(--font-geist); + font-size: 12px; + letter-spacing: 0.071em; + text-transform: uppercase; +} + +.signal-rail span { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 8px 10px; + border: 1px solid var(--line-soft); + border-radius: 4px; + background: rgba(255, 255, 255, 0.03); +} + +.signal { + width: 7px; + height: 7px; + border-radius: 999px; + display: inline-block; +} + +.signal.green { background: var(--color-emerald-green); } +.signal.white { background: var(--color-ghost-white); } +.signal.crimson { background: var(--color-vivid-crimson); } + +.section, +.install-band, +.privacy-band { + position: relative; + padding: 104px 0; + background: var(--color-deep-space); +} + +.section::before, +.install-band::before, +.privacy-band::before { + content: ""; + position: absolute; + inset: 0; + pointer-events: none; + background: linear-gradient(180deg, rgba(255, 255, 255, 0.035), transparent 30%); +} + +.section-inner { + position: relative; + width: min(var(--max), calc(100% - 48px)); + margin: 0 auto; +} + +.install-band { + border-top: 1px solid var(--line-soft); + border-bottom: 1px solid var(--line-soft); +} + +.install-grid, +.privacy-grid, +.tools-grid { + display: grid; + grid-template-columns: minmax(0, 0.82fr) minmax(360px, 1fr); + gap: 64px; + align-items: center; +} + +.install-band h2, +.privacy-band h2 { + margin-bottom: 18px; + color: var(--color-ghost-white); + font-size: clamp(42px, 5vw, 72px); + font-weight: 300; + line-height: 1.04; +} + +.install-band p, +.privacy-band p, +.tools-copy { + margin-bottom: 0; + color: var(--color-iron-slate); + font-size: 18px; + line-height: 1.65; +} + +.terminal { + overflow: hidden; + border: 1px solid var(--line); + border-radius: var(--radius); + background: + linear-gradient(135deg, rgba(187, 222, 242, 0.08), transparent 32%), + #020202; + box-shadow: var(--shadow-subtle); +} + +.terminal-top { + height: 40px; + display: flex; + align-items: center; + gap: 8px; + padding: 0 16px; + border-bottom: 1px solid var(--line-soft); +} + +.terminal-top span { + width: 8px; + height: 8px; + border-radius: 50%; +} + +.terminal-top span:nth-child(1) { background: var(--color-vivid-crimson); } +.terminal-top span:nth-child(2) { background: var(--color-goldenrod); } +.terminal-top span:nth-child(3) { background: var(--color-emerald-green); } + +pre { + margin: 0; + padding: 32px; + overflow: auto; +} + +code { + color: var(--color-halo-pale); + font-family: var(--font-geist); + font-size: 16px; + line-height: 1.5; +} + +.section-heading { + max-width: 820px; + margin-bottom: 48px; +} + +.section-heading h2, +.tools-grid h2 { + margin-bottom: 18px; + color: var(--color-ghost-white); + font-size: clamp(40px, 5vw, 72px); + font-weight: 300; + line-height: 1.05; +} + +.section-heading p { + margin-bottom: 0; + color: var(--color-iron-slate); + font-size: 18px; + line-height: 1.65; +} + +.showcase-grid { + display: grid; + grid-template-columns: 1.12fr 0.88fr; + grid-auto-rows: minmax(280px, auto); + gap: 16px; +} + +.showcase-card { + display: grid; + grid-template-rows: auto 1fr; + overflow: hidden; + border: 1px solid var(--line-soft); + border-radius: var(--radius); + background: var(--color-shadow-tint); + box-shadow: var(--shadow-subtle); +} + +.showcase-card.large { + grid-row: span 2; +} + +.showcase-card img { + width: 100%; + aspect-ratio: 640 / 527; + object-fit: cover; + border-bottom: 1px solid var(--line-soft); + background: #050505; + filter: saturate(0.86) contrast(1.1); +} + +.showcase-card div { + padding: 24px; +} + +.showcase-card h3, +.feature-card h3 { + margin-bottom: 10px; + color: var(--color-ghost-white); + font-size: 24px; + line-height: 1.23; +} + +.showcase-card p, +.feature-card p { + margin-bottom: 0; + color: var(--color-iron-slate); +} + +.tools-section { + border-top: 1px solid var(--line-soft); + border-bottom: 1px solid var(--line-soft); + background: + linear-gradient(90deg, rgba(187, 222, 242, 0.07), transparent 42%), + var(--color-deep-space); +} + +.tools-copy { + max-width: 470px; +} + +.tool-list { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 8px; + padding: 0; + margin: 0; + list-style: none; +} + +.tool-list li { + min-height: 48px; + display: flex; + align-items: center; + padding: 0 14px; + border: 1px solid var(--line-soft); + border-radius: 4px; + background: rgba(255, 255, 255, 0.025); + color: var(--color-subtle-gray); + font-size: 14px; + font-weight: 500; + box-shadow: var(--shadow-subtle); +} + +.tool-list li:nth-child(4n + 1) { border-color: rgba(187, 222, 242, 0.26); } +.tool-list li:nth-child(4n + 2) { border-color: rgba(209, 170, 215, 0.22); } +.tool-list li:nth-child(4n + 3) { border-color: rgba(255, 255, 255, 0.18); } +.tool-list li:nth-child(4n) { border-color: rgba(114, 206, 123, 0.18); } + +.feature-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 16px; +} + +.feature-card { + min-height: 230px; + padding: 24px; + border: 1px solid var(--line-soft); + border-radius: var(--radius); + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.055), rgba(255, 255, 255, 0.015)), + var(--color-shadow-tint); + box-shadow: var(--shadow-subtle); +} + +.feature-card::before { + content: ""; + display: block; + width: 48px; + height: 3px; + margin-bottom: 24px; + border-radius: 4px; + background: var(--gradient-dark-rainbow-gradient); +} + +.feature-card:nth-child(1)::before { background: linear-gradient(90deg, var(--color-iridescent-glow), transparent); } +.feature-card:nth-child(2)::before { background: linear-gradient(90deg, var(--color-spectrum-flare), transparent); } +.feature-card:nth-child(3)::before { background: linear-gradient(90deg, var(--color-emerald-green), transparent); } +.feature-card:nth-child(4)::before { background: linear-gradient(90deg, var(--color-goldenrod), transparent); } + +.privacy-band { + border-top: 1px solid var(--line-soft); + border-bottom: 1px solid var(--line-soft); + background: + radial-gradient(circle at 82% 38%, rgba(209, 170, 215, 0.13), transparent 28rem), + var(--color-deep-space); +} + +.privacy-grid { + grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr); +} + +.faq-section { + padding-bottom: 88px; +} + +.faq-list { + display: grid; + gap: 8px; +} + +details { + border: 1px solid var(--line-soft); + border-radius: var(--radius); + background: var(--color-shadow-tint); + box-shadow: var(--shadow-subtle); +} + +summary { + cursor: pointer; + padding: 18px 20px; + color: var(--color-ghost-white); + font-weight: 500; +} + +details p { + margin: 0; + padding: 0 20px 22px; + color: var(--color-iron-slate); +} + +.site-footer { + padding: 32px 0; + border-top: 1px solid var(--line-soft); + color: var(--color-iron-slate); + background: var(--color-deep-space); + font-size: 14px; +} + +.footer-grid { + display: flex; + justify-content: space-between; + gap: 24px; +} + +.footer-grid nav { + display: flex; + flex-wrap: wrap; + gap: 16px; +} + +@media (max-width: 980px) { + .hero { + min-height: 700px; + height: auto; + } + + .hero-content { + padding-top: 88px; + } + + .install-grid, + .privacy-grid, + .tools-grid { + grid-template-columns: 1fr; + gap: 40px; + } + + .showcase-grid, + .feature-grid { + grid-template-columns: 1fr 1fr; + } + + .showcase-card.large { + grid-row: span 1; + grid-column: span 2; + } + + .tool-list { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 720px) { + .site-header { + height: auto; + min-height: 64px; + padding: 14px 16px; + align-items: flex-start; + gap: 16px; + } + + .brand { + font-size: 15px; + } + + .brand img { + width: 26px; + height: 26px; + } + + .nav-links { + justify-content: flex-end; + flex-wrap: wrap; + gap: 8px 12px; + font-size: 12px; + } + + .hero { + min-height: 0; + } + + .hero-video { + display: none; + } + + .hero-shade { + background: + linear-gradient(180deg, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.84) 58%, rgba(0, 0, 0, 0.98) 100%); + } + + .hero-content { + width: min(calc(100% - 32px), 620px); + margin: 0 auto; + padding: 46px 0 40px; + } + + .hero h1 { + font-size: 58px; + } + + .eyebrow, + .section-kicker { + margin-bottom: 24px; + } + + .hero-copy, + .section-heading p, + .install-band p, + .privacy-band p, + .tools-copy { + font-size: 16px; + } + + .hero-stats { + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 8px; + } + + .hero-stats div { + padding: 10px; + } + + .hero-stats dt { + margin-bottom: 5px; + font-size: 10px; + } + + .hero-stats dd { + font-size: 12px; + line-height: 1.35; + } + + .button { + width: 100%; + white-space: normal; + text-align: center; + } + + .signal-rail { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 6px; + font-size: 10px; + } + + .signal-rail span { + padding: 6px 8px; + min-width: 0; + white-space: nowrap; + overflow: hidden; + } + + .section, + .install-band, + .privacy-band { + padding: 72px 0; + } + + .section-inner { + width: min(calc(100% - 32px), 640px); + } + + .install-band h2, + .privacy-band h2, + .section-heading h2, + .tools-grid h2 { + font-size: 42px; + } + + .showcase-grid, + .feature-grid, + .tool-list { + grid-template-columns: 1fr; + } + + .showcase-card.large { + grid-column: span 1; + } + + .feature-card { + min-height: 0; + } + + pre { + padding: 20px; + } + + code { + font-size: 13px; + } + + .footer-grid { + flex-direction: column; + } +} diff --git a/docs/tokcat-landing-motion.mp4 b/docs/tokcat-landing-motion.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..ba945c5827e231963190dc6745bcbaa61dd7f618 GIT binary patch literal 602346 zcmeFZcUTn7*63TzFo7sYPJ&93oJ2u#&N+!7l5@@(1SLsQ38El5DguHi85JaF5ipP> zh#<)Th;Rzu{kmuGd%pAB`|NY>bN={R*VL+Ct*Tnp)!kLIrWF9dV&@a+;ppw|3IGBe zrBH+{{j3FDJwyZnU>$UIclQGTxVZW`*uWI$KrREokPh&`(cga_|B`|D-|{m5wEUlG zNC3#5_;^`5!$LD3=ihxo_UHIVYYZlT$luDp_47aL7nKVDGWvG~R$Ch%Z>TZax_JBi zCciyBYL~|2uexM>t~QRAu#Cmk=HJGSXORL3?rj*p{9TjR!N$ewA8i0XM;qI}^`q1X z=G|2+-E3TJk8F-jx;nbqL50%K^>?GVZnN6_RmN!JWqV|EbR3lv`+B*s{G}he7}hFApzwI1s$9qbBhM0C08l@zPV4V==jC%7U4Jj{d_{OKWeBBb)!? zfL7nf|FRwB{V#0(SD3)Y*4r8yY(Qc4f}KO3D4|Yi|Ci2rq+9)^OC0I`J|6I@z|%R> zy$tl^p?-9-Iqh+DD;(Y0!|TZY2DFiIb@4sw>*zQd9kH#Op*~EpP#A$X&;!aq?r8il z4-fZz0M37dCo$!p%<2vR_16HPo%$zZ&4m{aymp@q{*(RloOoDzS^jPgAATb2;5pwa z0f6Kp02D(25MKIS20#7_-&kM~BlOE1{;>xxz!tCoRp17!0Uy+afB+B#qR@uS!}9k$ z;X(aKD6M>s#tjdY59e=zPJ8?OzO#<#k8%re*H)7{NH{Z{HOl?e>hLS&nG8b3#@-XseeDqf3FAdTKt{DXT#s?1JVrI z1^vVBD1mEQ04F{JaQX)Tn2%6S0Kj4a%iIA#Lpu~)_n4g^4~KdU z6d3@R>S5UfxEm3IYc3%ykAyr9x&hZ*!~k5TV1051xYY5(_CGOm4rGB)ABE{46xa{GCroFdFQ;Jp$DytS?V_M4!2VUCEgI_3CpnE3!}=VMo58*;p}_M; z5)EzPo`Nh1mhHnbMJRA@LIzX(amb!PX@KKA2GfU7rr~5L(pN6;q1^NhG0%$nD2s>Do z0wn_GpU!!klxpO6PKIKO!CS~#jpyaDT8fqD)U z12|@Ai>CqiM|d!O0|m|t(PfyzHc6htlmgnoy2Nnq@Kj)XaBqZn#mo2kYo~`&hff zK8_A}{#oJtWx}@VVZW1&01saqx)%xXm?Qw6%qM`S{SDxmbpSkDH-MMm3ok`EfR~>N zyJ7}-gWdpd(iPx+gtlvQ06|s*5R7jC;#4a@@SFh%d8l7X0thctIJKz&k;wuO*~tJ= zOa~B8RRQ8TDL}jmg}2UUfOy{qr}`K`tQNvs&lw>0-vT6J2Ox=F10?kvKr$T%NbVtk zgx^k)k`w?by8w`?9RR6s4v=Pt0BNfQkd9vf(#Ibl15E)kk_sTNc>`o>D?nyl1<3ni z09nEakgc$8mpefA>jUJt5I`_;GvyKdBwyXRHAHico<6WCP$ge+Bqmu-^0!fWNo}@HgE63OocTq6&EXivkqG z7C`Zm0Fxwod)Qq z0s!6A1JEN50R1Krpr@?>deaP`zx@Ij_K^