Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions packages/app/cypress/component/mode-toggle.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ describe('ModeToggle', () => {
<ThemeProvider
attribute="class"
defaultTheme="light"
themes={['light', 'dark', 'minecraft']}
themes={['light', 'dark', 'minecraft', 'rick-morty']}
disableTransitionOnChange
>
<ModeToggle />
Expand All @@ -28,13 +28,22 @@ describe('ModeToggle', () => {
cy.get('html').should('have.class', 'minecraft');
});

it('clicking toggle three times returns to light mode', () => {
it('clicking toggle three times cycles light → dark → minecraft → rick-morty', () => {
cy.get('[data-testid="theme-toggle"]').click();
cy.get('html').should('have.class', 'dark');
cy.get('[data-testid="theme-toggle"]').click();
cy.get('html').should('have.class', 'minecraft');
cy.get('[data-testid="theme-toggle"]').click();
cy.get('html').should('have.class', 'rick-morty');
});

it('clicking toggle four times returns to light mode', () => {
cy.get('[data-testid="theme-toggle"]').click();
cy.get('[data-testid="theme-toggle"]').click();
cy.get('[data-testid="theme-toggle"]').click();
cy.get('[data-testid="theme-toggle"]').click();
cy.get('html').should('not.have.class', 'dark');
cy.get('html').should('not.have.class', 'minecraft');
cy.get('html').should('not.have.class', 'rick-morty');
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
110 changes: 109 additions & 1 deletion packages/app/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
@import 'tw-animate-css';
@plugin '@tailwindcss/typography';

@custom-variant dark (&:is(.dark *, .minecraft *));
@custom-variant dark (&:is(.dark *, .minecraft *, .rick-morty *));
@custom-variant minecraft (&:is(.minecraft *));
@custom-variant rick-morty (&:is(.rick-morty *));

/* Allow hash navigation to clear the fixed navbar */
.blog-prose h2[id],
Expand Down Expand Up @@ -240,6 +241,70 @@
--overlay-run-7: oklch(0.78 0.18 60);
}

/* Rick and Morty theme — portal-green / Morty-yellow on deep space dark.
* Anchor colors are pulled from the canonical R&M palette: portal green
* #97ce4c, Morty yellow #f0e14a, Rick lab-coat blue #0bb4e4, Summer pink
* #e89ac7, with Beth purple / Birdperson red rounding out the 8 overlay
* slots. References:
* - color-hex.com/color-palette/9134
* - colorswall.com/palette/243091 (schwifty greens)
* - colorswall.com/palette/242810 (Rick blue)
*/
.rick-morty {
--background: #0d1525;
--foreground: #dceea0;
--card: #131c33;
--card-foreground: #f5fbe1;
--popover: #1a2440;
--popover-foreground: #f5fbe1;
--primary: #97ce4c;
--primary-foreground: #0d1525;
--secondary: #f0e14a;
--secondary-foreground: #0d1525;
--brand: var(--primary);
--muted: #1f2a47;
--muted-foreground: rgba(220, 238, 160, 0.65);
--accent: #0bb4e4;
--accent-foreground: #0d1525;
--destructive: #e63946;
--border: #2f4a3e;
--border-alt: #1d2a4b;
--input: rgba(151, 206, 76, 0.18);
--ring: #97ce4c;

/* Sidebar */
--sidebar: #0a1020;
--sidebar-foreground: #dceea0;
--sidebar-primary: #97ce4c;
--sidebar-primary-foreground: #0d1525;
--sidebar-accent: #1a2440;
--sidebar-accent-foreground: #f5fbe1;
--sidebar-border: #2f4a3e;
--sidebar-ring: #97ce4c;

/* Overlay-run palette: main R&M characters / iconic colors, tuned for
* legibility on the deep-space dark background. */
--overlay-run-0: #97ce4c; /* portal green */
--overlay-run-1: #f0e14a; /* Morty yellow */
--overlay-run-2: #0bb4e4; /* Rick lab coat blue */
--overlay-run-3: #e89ac7; /* Summer pink */
--overlay-run-4: #c1f762; /* schwifty bright green */
--overlay-run-5: #ffb78c; /* Jerry skin */
--overlay-run-6: #b388eb; /* Beth purple */
--overlay-run-7: #ff6e54; /* Birdperson red */
}

/* Subtle portal-green glow on rick-morty headings + the brand name so the
* theme has visual identity beyond the palette swap. */
.rick-morty h1,
.rick-morty h2,
.rick-morty h3,
.rick-morty .brand-name {
text-shadow:
0 0 6px rgba(151, 206, 76, 0.45),
0 0 14px rgba(151, 206, 76, 0.18);
}

/* Force pixel font on everything in minecraft mode */
.minecraft,
.minecraft * {
Expand Down Expand Up @@ -319,6 +384,49 @@
display: none;
}

/* Rick-morty: keep the circuit background, but shift its tone toward portal
* green so it sits on the deep-space dark surface coherently. */
.rick-morty .circuit-bg {
filter: hue-rotate(60deg) saturate(1.4) brightness(0.85);
}

/* Jerry-falling — one-shot top→bottom fall on rick-morty theme activation,
* triggered from rick-morty-decorations.tsx. Mirrors the minecraft Ender
* Dragon fly-across pattern but oriented vertically. Plays once and lands
* Jerry off-screen below so the GIF stops being rendered. The drift +
* rotation give the fall a flailing-arms cartoon feel. */
@keyframes rm-jerry-fall {
0% {
transform: translate(0, -30vh) rotate(-6deg);
opacity: 0;
}
10% {
opacity: 0.95;
}
50% {
transform: translate(3vw, 40vh) rotate(10deg);
}
90% {
opacity: 0.95;
}
100% {
transform: translate(-2vw, 130vh) rotate(-4deg);
opacity: 0;
}
}

.rm-jerry-fall {
animation: rm-jerry-fall 7s cubic-bezier(0.4, 0, 0.6, 1) 1 forwards;
will-change: transform, opacity;
}

@media (prefers-reduced-motion: reduce) {
.rm-jerry-fall {
animation: none;
display: none;
}
}

/* Splash text — yellow bouncing rotated text (Minecraft title screen style) */
@keyframes splash-bounce {
0%,
Expand Down
6 changes: 5 additions & 1 deletion packages/app/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { Footer } from '@/components/footer/footer';
import { Header } from '@/components/header/header';
import { CircuitBackground } from '@/components/circuit-background';
import { MinecraftBackgroundLazy } from '@/components/minecraft/minecraft-background-lazy';
import { RickMortyAudioLazy } from '@/components/rick-morty/rick-morty-audio-lazy';
import { RickMortyDecorations } from '@/components/rick-morty/rick-morty-decorations';
import { ThemeProvider } from '@/components/ui/theme-provider';
import {
AUTHOR_HANDLE,
Expand Down Expand Up @@ -178,13 +180,15 @@ export default async function RootLayout({
<body className={`${dm_sans.variable} antialiased relative min-h-screen flex flex-col`}>
<CircuitBackground />
<MinecraftBackgroundLazy />
<RickMortyDecorations />
<RickMortyAudioLazy />
<PostHogProvider>
<script type="application/ld+json">{JSON.stringify(jsonLd)}</script>
<QueryProvider>
<ThemeProvider
attribute="class"
defaultTheme="dark"
themes={['light', 'dark', 'minecraft']}
themes={['light', 'dark', 'minecraft', 'rick-morty']}
enableSystem
disableTransitionOnChange
>
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/components/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { track } from '@/lib/analytics';

import { ModeToggle } from '@/components/ui/mode-toggle';
import { MinecraftToggles } from '@/components/minecraft/minecraft-toggles';
import { RickMortyToggles } from '@/components/rick-morty/rick-morty-toggles';
import { navigateInApp } from '@/lib/client-navigation';
import { cn } from '@/lib/utils';

Expand Down Expand Up @@ -134,6 +135,7 @@ export const Header = ({ starCount }: { starCount?: number | null }) => {
<div className="ml-auto flex items-center gap-2">
<GitHubStars owner="SemiAnalysisAI" repo="InferenceX" starCount={starCount} />
<MinecraftToggles />
<RickMortyToggles />
<ModeToggle />

{/* Mobile hamburger */}
Expand Down
5 changes: 4 additions & 1 deletion packages/app/src/components/inference/ui/GPUGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ const GPUGraph = React.memo(
const gpuDateColorMap = useMemo(() => {
const { dates, sortedGPUs } = gpuDatePairs;
if (sortedGPUs.length === 0 || dates.length === 0) return {};
const theme = resolvedTheme === 'dark' || resolvedTheme === 'minecraft' ? 'dark' : 'light';
const theme =
resolvedTheme === 'dark' || resolvedTheme === 'minecraft' || resolvedTheme === 'rick-morty'
? 'dark'
: 'light';
return generateGpuDateColors(sortedGPUs, dates.length, theme);
}, [gpuDatePairs, resolvedTheme]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2004,7 +2004,7 @@ export default function ModelArchitectureDiagram({
renderDiagram(
svgRef.current,
arch,
resolvedTheme === 'dark' || resolvedTheme === 'minecraft',
resolvedTheme === 'dark' || resolvedTheme === 'minecraft' || resolvedTheme === 'rick-morty',
expandedBlocks,
toggleBlock,
);
Expand All @@ -2019,7 +2019,9 @@ export default function ModelArchitectureDiagram({
renderDiagram(
svgRef.current,
arch,
resolvedTheme === 'dark' || resolvedTheme === 'minecraft',
resolvedTheme === 'dark' ||
resolvedTheme === 'minecraft' ||
resolvedTheme === 'rick-morty',
expandedBlocks,
toggleBlock,
);
Expand Down
12 changes: 12 additions & 0 deletions packages/app/src/components/rick-morty/rick-morty-audio-lazy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use client';

import dynamic from 'next/dynamic';

const RickMortyAudio = dynamic(
() => import('./rick-morty-audio').then((mod) => mod.RickMortyAudio),
{ ssr: false },
);

export function RickMortyAudioLazy() {
return <RickMortyAudio />;
}
Loading
Loading