diff --git a/.github/workflows/deploy-app-walrus.yml b/.github/workflows/deploy-app-walrus.yml index 0c3a46bb0..b75c0ad63 100644 --- a/.github/workflows/deploy-app-walrus.yml +++ b/.github/workflows/deploy-app-walrus.yml @@ -77,6 +77,9 @@ jobs: VITE_ENOKI_API_KEY: ${{ vars.VITE_ENOKI_API_KEY }} VITE_GOOGLE_CLIENT_ID: ${{ vars.VITE_GOOGLE_CLIENT_ID }} VITE_DOCS_URL: ${{ vars.VITE_DOCS_URL }} + VITE_CONSOLE_URL: ${{ vars.VITE_CONSOLE_URL }} + VITE_PRIVACY_POLICY_URL: ${{ vars.VITE_PRIVACY_POLICY_URL }} + VITE_TERMS_OF_SERVICE_URL: ${{ vars.VITE_TERMS_OF_SERVICE_URL }} VITE_DEMO_URLS: ${{ vars.VITE_DEMO_URLS }} VITE_GA_MEASUREMENT_ID: ${{ vars.VITE_GA_MEASUREMENT_ID }} VITE_GTM_CONTAINER_ID: ${{ vars.VITE_GTM_CONTAINER_ID }} diff --git a/apps/app/.env.example b/apps/app/.env.example index 2e103d5f2..7d964102c 100644 --- a/apps/app/.env.example +++ b/apps/app/.env.example @@ -21,6 +21,9 @@ VITE_SECURITY_DELETE_ENABLED=false # Migration date shown in the pre-migration cleanup card. VITE_MIGRATION_COMPLETED_DATE=July 30, 2026 +# Dashboard Walrus Console button and "View your memories" card. Off unless true. +VITE_WALRUS_CONSOLE_ENABLED=false + # Keep pre-migration account/blob lookups on the V1 contract and SEAL # committee while the current package points at the migrated contract. VITE_LEGACY_MEMWAL_PACKAGE_ID= @@ -42,7 +45,7 @@ VITE_GA_MEASUREMENT_ID= # Google Tag Manager Container ID. Set to GTM-KPDDH5DX in production. VITE_GTM_CONTAINER_ID= -# Analytics only sends on these production hosts. Applies to GTM, GA4, and PostHog. +# Analytics only sends on these production hosts. Applies to GTM, GA4, PostHog, and Statsig. # Use * for local analytics testing. VITE_ANALYTICS_ALLOWED_HOSTS=walrus.xyz,www.walrus.xyz @@ -51,6 +54,9 @@ VITE_POSTHOG_PROJECT_API_KEY= VITE_POSTHOG_HOST=https://t.walrus.xyz VITE_POSTHOG_UI_HOST=https://us.posthog.com +# Statsig client SDK key. Leave blank to disable. Safe to ship in the browser bundle. +VITE_STATSIG_CLIENT_KEY= + # ══════════════════════════════════════════════════════════════ # ▷ INACTIVE: MAINNET (uncomment below, comment out TESTNET above) # ══════════════════════════════════════════════════════════════ @@ -60,8 +66,11 @@ VITE_POSTHOG_UI_HOST=https://us.posthog.com # VITE_SUI_RPC_URL=https://rpc-mainnet.suiscan.xyz # Sui RPC v2 gRPC-Web endpoint used by the security-delete subsystem. # VITE_SUI_GRPC_URL=https://fullnode.mainnet.sui.io:443 -# VITE_MEMWAL_PACKAGE_ID=0xcee7a6fd8de52ce645c38332bde23d4a30fd9426bc4681409733dd50958a24c6 -# VITE_MEMWAL_REGISTRY_ID=0x0da982cefa26864ae834a8a0504b904233d49e20fcc17c373c8bed99c75a7edd +# VITE_MEMWAL_PACKAGE_ID=0xe7c16fbea0560e7057e2bf7422feaa4fb313749fc69c9e9092fac7a33b81d7f5 +# VITE_MEMWAL_REGISTRY_ID=0x8bf82c9e09e36b8d1c38298f68b7cb68e7b8762887e7592add9986d5e9cf199f +# Pre-cutover mainnet deployment. Seal decryption of those blobs stays on these ids. +# VITE_LEGACY_MEMWAL_PACKAGE_ID=0xcee7a6fd8de52ce645c38332bde23d4a30fd9426bc4681409733dd50958a24c6 +# VITE_LEGACY_MEMWAL_REGISTRY_ID=0x0da982cefa26864ae834a8a0504b904233d49e20fcc17c373c8bed99c75a7edd # Console's Memory tab URL for THIS network — like PACKAGE_ID/REGISTRY_ID # above, set per network block, not shared across testnet/mainnet. # Include the Memory tab path: WM only appends `from=wm`, and Console runs @@ -73,10 +82,12 @@ VITE_POSTHOG_UI_HOST=https://us.posthog.com # ══════════════════════════════════════════════════════════════ VITE_SUI_NETWORK=testnet VITE_SUI_GRPC_URL=https://fullnode.testnet.sui.io:443 -VITE_MEMWAL_PACKAGE_ID=0xcf6ad755a1cdff7217865c796778fabe5aa399cb0cf2eba986f4b582047229c6 -VITE_MEMWAL_REGISTRY_ID=0xe80f2feec1c139616a86c9f71210152e2a7ca552b20841f2e192f99f75864437 -# e.g. https://testnet.console.walrus.xyz/buckets?tab=memory (local: http://localhost:3000/buckets?tab=memory) -VITE_CONSOLE_URL= +VITE_MEMWAL_PACKAGE_ID=0x0a625e2db2af6f591a4c80a3d8551ddf11656089cc3a20c5e9e7f8fb75b9265c +VITE_MEMWAL_REGISTRY_ID=0x736aef9906798fca4460490ccdf8e8502ef170122dc26ecae32111b78c6b42dd +# Include the Memory tab path: WM only appends `from=wm`, and Console runs +# its return flow only on the Memory tab, so a bare host lands on Assets. +# Local Console: http://localhost:3000/buckets?tab=memory +VITE_CONSOLE_URL=https://testnet.console.walrus.xyz/buckets?tab=memory # ══════════════════════════════════════════════════════════════ # ▷ CUTOVER: legacy deployment ids for the security-delete surface. diff --git a/apps/app/Dockerfile b/apps/app/Dockerfile index 0f866fa85..0a11df4f1 100644 --- a/apps/app/Dockerfile +++ b/apps/app/Dockerfile @@ -29,8 +29,10 @@ COPY apps/app/ ./apps/app/ # Vite env vars must be injected at build time ARG VITE_MEMWAL_SERVER_URL -ARG VITE_MEMWAL_PACKAGE_ID=0xcee7a6fd8de52ce645c38332bde23d4a30fd9426bc4681409733dd50958a24c6 -ARG VITE_MEMWAL_REGISTRY_ID=0x0da982cefa26864ae834a8a0504b904233d49e20fcc17c373c8bed99c75a7edd +# Current mainnet deployment. Used only when a build omits the arg. +# The previous ids are the legacy package Railway production still sets. +ARG VITE_MEMWAL_PACKAGE_ID=0xe7c16fbea0560e7057e2bf7422feaa4fb313749fc69c9e9092fac7a33b81d7f5 +ARG VITE_MEMWAL_REGISTRY_ID=0x8bf82c9e09e36b8d1c38298f68b7cb68e7b8762887e7592add9986d5e9cf199f ARG VITE_LEGACY_MEMWAL_PACKAGE_ID ARG VITE_LEGACY_MEMWAL_REGISTRY_ID ARG VITE_SUI_NETWORK=mainnet @@ -46,6 +48,9 @@ ARG VITE_MIGRATION_COMPLETED_DATE ARG VITE_ENOKI_API_KEY ARG VITE_GOOGLE_CLIENT_ID ARG VITE_DOCS_URL +ARG VITE_CONSOLE_URL +ARG VITE_PRIVACY_POLICY_URL +ARG VITE_TERMS_OF_SERVICE_URL ARG VITE_DEMO_URLS ARG VITE_GA_MEASUREMENT_ID ARG VITE_GTM_CONTAINER_ID @@ -54,10 +59,12 @@ ARG VITE_POSTHOG_PROJECT_API_KEY ARG VITE_POSTHOG_KEY ARG VITE_POSTHOG_HOST ARG VITE_POSTHOG_UI_HOST +ARG VITE_STATSIG_CLIENT_KEY # Flag baked at build time; without this ARG the Railway # service variable can never reach the bundle and the delete UI stays off. ARG VITE_ENABLE_MEMORY_DELETION ARG VITE_SECURITY_DELETE_ENABLED +ARG VITE_WALRUS_CONSOLE_ENABLED ENV VITE_MEMWAL_SERVER_URL=$VITE_MEMWAL_SERVER_URL ENV VITE_MEMWAL_PACKAGE_ID=$VITE_MEMWAL_PACKAGE_ID @@ -77,6 +84,9 @@ ENV VITE_MIGRATION_COMPLETED_DATE=$VITE_MIGRATION_COMPLETED_DATE ENV VITE_ENOKI_API_KEY=$VITE_ENOKI_API_KEY ENV VITE_GOOGLE_CLIENT_ID=$VITE_GOOGLE_CLIENT_ID ENV VITE_DOCS_URL=$VITE_DOCS_URL +ENV VITE_CONSOLE_URL=$VITE_CONSOLE_URL +ENV VITE_PRIVACY_POLICY_URL=$VITE_PRIVACY_POLICY_URL +ENV VITE_TERMS_OF_SERVICE_URL=$VITE_TERMS_OF_SERVICE_URL ENV VITE_DEMO_URLS=$VITE_DEMO_URLS ENV VITE_GA_MEASUREMENT_ID=$VITE_GA_MEASUREMENT_ID ENV VITE_GTM_CONTAINER_ID=$VITE_GTM_CONTAINER_ID @@ -85,8 +95,10 @@ ENV VITE_POSTHOG_PROJECT_API_KEY=$VITE_POSTHOG_PROJECT_API_KEY ENV VITE_POSTHOG_KEY=$VITE_POSTHOG_KEY ENV VITE_POSTHOG_HOST=$VITE_POSTHOG_HOST ENV VITE_POSTHOG_UI_HOST=$VITE_POSTHOG_UI_HOST +ENV VITE_STATSIG_CLIENT_KEY=$VITE_STATSIG_CLIENT_KEY ENV VITE_ENABLE_MEMORY_DELETION=$VITE_ENABLE_MEMORY_DELETION ENV VITE_SECURITY_DELETE_ENABLED=$VITE_SECURITY_DELETE_ENABLED +ENV VITE_WALRUS_CONSOLE_ENABLED=$VITE_WALRUS_CONSOLE_ENABLED RUN pnpm --filter @memwal/app build diff --git a/apps/app/index.html b/apps/app/index.html index a02c2a3cf..42d972e8f 100644 --- a/apps/app/index.html +++ b/apps/app/index.html @@ -5,37 +5,37 @@ - + + content="Connect Walrus Memory to your agent or app. Follow guided plugin or SDK setup and use portable memory across sessions and tools." /> - - - + + + - - - - + + + + - - - + + + - - - - + + + + - Portable AI Agent Memory | Walrus Memory Dashboard + Portable AI Agent Memory | Connect Walrus Memory diff --git a/apps/app/public/sept2026/antigravity.png b/apps/app/public/sept2026/antigravity.png new file mode 100644 index 000000000..0851f9283 Binary files /dev/null and b/apps/app/public/sept2026/antigravity.png differ diff --git a/apps/app/public/sept2026/claude.png b/apps/app/public/sept2026/claude.png new file mode 100644 index 000000000..34569c9a7 Binary files /dev/null and b/apps/app/public/sept2026/claude.png differ diff --git a/apps/app/public/sept2026/codex.png b/apps/app/public/sept2026/codex.png new file mode 100644 index 000000000..8ff09dfee Binary files /dev/null and b/apps/app/public/sept2026/codex.png differ diff --git a/apps/app/public/sept2026/discord.svg b/apps/app/public/sept2026/discord.svg new file mode 100644 index 000000000..6ec0c4c8e --- /dev/null +++ b/apps/app/public/sept2026/discord.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/app/public/sept2026/docs.svg b/apps/app/public/sept2026/docs.svg new file mode 100644 index 000000000..938727cca --- /dev/null +++ b/apps/app/public/sept2026/docs.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/app/public/sept2026/github.svg b/apps/app/public/sept2026/github.svg new file mode 100644 index 000000000..9dbb9ce46 --- /dev/null +++ b/apps/app/public/sept2026/github.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/apps/app/public/sept2026/javascript.png b/apps/app/public/sept2026/javascript.png new file mode 100644 index 000000000..70202173e Binary files /dev/null and b/apps/app/public/sept2026/javascript.png differ diff --git a/apps/app/public/sept2026/memories-card.png b/apps/app/public/sept2026/memories-card.png new file mode 100644 index 000000000..576dcac9e Binary files /dev/null and b/apps/app/public/sept2026/memories-card.png differ diff --git a/apps/app/public/sept2026/python.svg b/apps/app/public/sept2026/python.svg new file mode 100644 index 000000000..05155f370 --- /dev/null +++ b/apps/app/public/sept2026/python.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/app/public/signin/glow-desktop.png b/apps/app/public/signin/glow-desktop.png new file mode 100644 index 000000000..272fbb1e8 Binary files /dev/null and b/apps/app/public/signin/glow-desktop.png differ diff --git a/apps/app/public/signin/glow-mobile.png b/apps/app/public/signin/glow-mobile.png new file mode 100644 index 000000000..601fb7726 Binary files /dev/null and b/apps/app/public/signin/glow-mobile.png differ diff --git a/apps/app/public/signin/logo-allium.png b/apps/app/public/signin/logo-allium.png new file mode 100644 index 000000000..2a8dae858 Binary files /dev/null and b/apps/app/public/signin/logo-allium.png differ diff --git a/apps/app/public/signin/logo-inflectiv.svg b/apps/app/public/signin/logo-inflectiv.svg new file mode 100644 index 000000000..d1dbe215b --- /dev/null +++ b/apps/app/public/signin/logo-inflectiv.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/app/public/signin/logo-talus.svg b/apps/app/public/signin/logo-talus.svg new file mode 100644 index 000000000..820b677ef --- /dev/null +++ b/apps/app/public/signin/logo-talus.svg @@ -0,0 +1,5 @@ + + + diff --git a/apps/app/public/signin/logo-tatum.svg b/apps/app/public/signin/logo-tatum.svg new file mode 100644 index 000000000..765057f44 --- /dev/null +++ b/apps/app/public/signin/logo-tatum.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/app/public/signin/logo-wordmark.svg b/apps/app/public/signin/logo-wordmark.svg new file mode 100644 index 000000000..b78e043e9 --- /dev/null +++ b/apps/app/public/signin/logo-wordmark.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/apps/app/public/signin/screen.png b/apps/app/public/signin/screen.png new file mode 100644 index 000000000..ba371ec3a Binary files /dev/null and b/apps/app/public/signin/screen.png differ diff --git a/apps/app/public/signin/tile-back.png b/apps/app/public/signin/tile-back.png new file mode 100644 index 000000000..d6944a6e3 Binary files /dev/null and b/apps/app/public/signin/tile-back.png differ diff --git a/apps/app/public/signin/tile-left-mobile.png b/apps/app/public/signin/tile-left-mobile.png new file mode 100644 index 000000000..2cd032a75 Binary files /dev/null and b/apps/app/public/signin/tile-left-mobile.png differ diff --git a/apps/app/public/signin/tile-left.png b/apps/app/public/signin/tile-left.png new file mode 100644 index 000000000..b87b920ce Binary files /dev/null and b/apps/app/public/signin/tile-left.png differ diff --git a/apps/app/public/signin/tile-right-mobile.png b/apps/app/public/signin/tile-right-mobile.png new file mode 100644 index 000000000..7f083a6d5 Binary files /dev/null and b/apps/app/public/signin/tile-right-mobile.png differ diff --git a/apps/app/public/signin/tile-right.png b/apps/app/public/signin/tile-right.png new file mode 100644 index 000000000..552bf59a5 Binary files /dev/null and b/apps/app/public/signin/tile-right.png differ diff --git a/apps/app/public/walrus-memory-logo.svg b/apps/app/public/walrus-memory-logo.svg index 8bfb84e10..c5ca37a2a 100644 --- a/apps/app/public/walrus-memory-logo.svg +++ b/apps/app/public/walrus-memory-logo.svg @@ -5,42 +5,42 @@ - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + diff --git a/apps/app/public/walrus-memory-og.jpg b/apps/app/public/walrus-memory-og.jpg new file mode 100644 index 000000000..c9e8291f8 Binary files /dev/null and b/apps/app/public/walrus-memory-og.jpg differ diff --git a/apps/app/public/walrus-memory-social-preview.jpg b/apps/app/public/walrus-memory-social-preview.jpg index 2df8f93f5..c9e8291f8 100644 Binary files a/apps/app/public/walrus-memory-social-preview.jpg and b/apps/app/public/walrus-memory-social-preview.jpg differ diff --git a/apps/app/scripts/verify-static-server.mjs b/apps/app/scripts/verify-static-server.mjs index c1828d938..203a60a2a 100644 --- a/apps/app/scripts/verify-static-server.mjs +++ b/apps/app/scripts/verify-static-server.mjs @@ -83,6 +83,7 @@ try { await expectContentType('/walrus-signin-bg.png', 'image/png') await expectContentType('/walrus-memory-logo.svg', 'image/svg+xml') await expectContentType('/og-image.jpg', 'image/jpeg') + await expectContentType('/walrus-memory-og.jpg', 'image/jpeg') await expectContentType('/walrus-memory-social-preview.jpg', 'image/jpeg') await expectContentType('/fonts/Ratch-Variable.ttf', 'font/ttf') await expectHead('/', 200, 'text/html') diff --git a/apps/app/src/App.tsx b/apps/app/src/App.tsx index 64203c266..2894a1026 100644 --- a/apps/app/src/App.tsx +++ b/apps/app/src/App.tsx @@ -414,7 +414,6 @@ function RequireAccountForSetup() { function AppContent() { const currentAccount = useCurrentAccount() const autoConnectStatus = useAutoConnectWallet() - const { delegateKey } = useDelegateKey() const authPending = autoConnectStatus === 'idle' const requireAccount = (element: React.ReactNode) => { @@ -429,10 +428,10 @@ function AppContent() { currentAccount ? : } /> )} /> + {/* dev (#1003): owns the has-key redirect and the fromConsoleSetup signal. */} } /> - : - )} /> + {/* #1006: the playground only needs a signed-in account. */} + )} /> } /> } /> } /> diff --git a/apps/app/src/components/AdminActivity.tsx b/apps/app/src/components/AdminActivity.tsx new file mode 100644 index 000000000..04bd7b552 --- /dev/null +++ b/apps/app/src/components/AdminActivity.tsx @@ -0,0 +1,465 @@ +import { useEffect, useState } from 'react' +import { useQuery } from '@tanstack/react-query' +import { Card } from './Card' +import { CopyableText } from './CopyableText' +import { + fetchAdminActivity, + formatTokenAmount, + spendPace, + type ActivityTokenWindow, + type AdminActivity, + type SpendPace, +} from '../utils/admin-api' + +interface AdminActivityProps { + adminKey: string + onInvalidKey: () => void + /** Local-only sample, so the spend layout can be reviewed without the API. */ + preview?: boolean +} + +const WINDOWS = [ + { hours: 24, label: '24 hours' }, + { hours: 168, label: '7 days' }, + { hours: 720, label: '30 days' }, +] as const + +function abbreviateAddress(address: string): string { + if (address.length <= 22) return address + return `${address.slice(0, 6)}...${address.slice(-4)}` +} + +function formatInterval(seconds: number): string { + if (seconds % 3600 === 0) return `${seconds / 3600} hour${seconds === 3600 ? '' : 's'}` + if (seconds % 60 === 0) return `${seconds / 60} minutes` + return `${seconds} seconds` +} + +function formatSigned(raw: bigint, symbol: string): string { + const sign = raw > 0n ? '+' : '' + return `${sign}${formatTokenAmount(raw)} ${symbol}` +} + +function paceLabel(pace: SpendPace): string { + if (pace === 'faster') return 'Faster than the previous window' + if (pace === 'slower') return 'Slower than the previous window' + if (pace === 'same') return 'Same as the previous window' + return 'Not enough history' +} + +function chartHeights(points: ActivityTokenWindow['series']): number[] { + if (points.length === 0) return [] + const values = points.map((point) => point.balance) + const min = values.reduce((left, right) => (left < right ? left : right)) + const max = values.reduce((left, right) => (left > right ? left : right)) + const span = max - min + if (span === 0n) return values.map(() => 0) + return values.map((value) => Number(((value - min) * 1000n) / span)) +} + +function BalanceSparkline({ + points, + label, +}: { + points: ActivityTokenWindow['series'] + label: string +}) { + const heights = chartHeights(points) + if (heights.length < 2) return null + const width = 320 + const height = 64 + const coords = heights + .map((value, index) => { + const x = (index / (heights.length - 1)) * width + const y = height - 2 - (value / 1000) * (height - 4) + return `${x},${y}` + }) + .join(' ') + return ( + + + + ) +} + +function BurnColumn({ + title, + symbol, + token, +}: { + title: string + symbol: string + token: ActivityTokenWindow +}) { + const pace = spendPace(token.comparable, token.outflow, token.priorOutflow) + return ( +
+
{title}
+
{formatTokenAmount(token.outflow)} {symbol}
+
+ Previous window {formatTokenAmount(token.priorOutflow)} {symbol} +
+
Net {formatSigned(token.net, symbol)}
+ {paceLabel(pace)} + {token.latest != null && token.latestAt ? ( +
+ Latest {formatTokenAmount(token.latest)} {symbol} at {new Date(token.latestAt).toLocaleString()} +
+ ) : ( +
No balance sample yet
+ )} + +
+ ) +} + +function formatChartDay(day: string): string { + const [year, month, date] = day.split('-').map(Number) + if (!year || !month || !date) return day + return new Date(year, month - 1, date).toLocaleDateString(undefined, { + month: 'numeric', + day: 'numeric', + }) +} + +type MemoryBucket = { key: string; label: string; detail: string; count: number } + +// `YYYY-MM-DDTHH:00` is already on the viewer's clock, so no Date parsing. +function formatChartHour(hour: string): string { + const [day, time] = hour.split('T') + if (!day || !time) return hour + // A 24h window spans two dates, and "00:00" at both ends reads the same. + // Name the date at midnight instead. + return time === '00:00' ? formatChartDay(day) : time +} + +function describeChartHour(hour: string): string { + const [day, time] = hour.split('T') + return day && time ? `${formatChartDay(day)} ${time}` : hour +} + +function MemoryChart({ + days, + hours, +}: { + days: { day: string; count: number }[] + hours: { hour: string; count: number }[] | null +}) { + const hourly = hours != null && hours.length > 0 + const buckets: MemoryBucket[] = hourly + ? hours.map((h) => ({ + key: h.hour, + label: formatChartHour(h.hour), + detail: describeChartHour(h.hour), + count: h.count, + })) + : days.map((d) => { + const label = formatChartDay(d.day) + return { key: d.day, label, detail: label, count: d.count } + }) + if (buckets.length === 0) { + return

No memories written in this window

+ } + const unit = hourly ? 'hour' : 'day' + const total = buckets.reduce((sum, b) => sum + b.count, 0) + const peak = buckets.reduce((best, b) => (b.count > best.count ? b : best), buckets[0]) + const max = Math.max(1, ...buckets.map((b) => b.count)) + const labelStep = hourly ? 3 : buckets.length > 16 ? 5 : buckets.length > 8 ? 2 : 1 + const summary = + total === 0 + ? 'No memories written in this window' + : `${total} ${total === 1 ? 'memory' : 'memories'} · busiest ${unit} ${peak.detail} with ${peak.count}` + return ( +
+

{summary}

+
+ {buckets.map((b, index) => ( +
+
+ {b.count > 0 && !hourly && {b.count}} +
+
+ ))} +
+ +
+ ) +} + +function countLine(label: string, count: number, prior: number | null) { + return ( +
+ {label} + + {count} + {prior == null ? '' : ` · previous ${prior}`} + +
+ ) +} + +const PREVIEW_ACTIVITY: AdminActivity = { + generatedAt: '2026-09-24T12:00:00.000Z', + windowHours: 24, + balanceMonitorIntervalSecs: 300, + uploaderWal: { + samples: 8, + comparable: true, + latest: 1_240_000_000_000n, + latestAt: '2026-09-24T11:55:00.000Z', + outflow: 86_500_000_000n, + priorOutflow: 41_200_000_000n, + net: -62_000_000_000n, + series: [1400, 1360, 1310, 1288, 1264, 1251, 1244, 1240].map((whole, index) => ({ + at: new Date(Date.UTC(2026, 8, 24, index * 3)).toISOString(), + balance: BigInt(whole) * 1_000_000_000n, + })), + }, + uploaderSui: { + samples: 8, + comparable: true, + latest: 42_800_000_000n, + latestAt: '2026-09-24T11:55:00.000Z', + outflow: 3_400_000_000n, + priorOutflow: 6_100_000_000n, + net: -1_200_000_000n, + series: [48, 47, 46, 45.5, 44.8, 44.1, 43.4, 42.8].map((whole, index) => ({ + at: new Date(Date.UTC(2026, 8, 24, index * 3)).toISOString(), + balance: BigInt(Math.round(whole * 1000)) * 1_000_000n, + })), + }, + sponsorSui: { + samples: 8, + comparable: true, + latest: 18_600_000_000n, + latestAt: '2026-09-24T11:55:00.000Z', + outflow: 900_000_000n, + priorOutflow: 900_000_000n, + net: -900_000_000n, + series: [19.5, 19.3, 19.2, 19.1, 19, 18.9, 18.8, 18.6].map((whole, index) => ({ + at: new Date(Date.UTC(2026, 8, 24, index * 3)).toISOString(), + balance: BigInt(Math.round(whole * 1000)) * 1_000_000n, + })), + }, + actions: { + uploadsCompleted: 128, + uploadsCompletedPrior: 96, + uploadsFailed: 4, + uploadsFailedPrior: 7, + uploadsInFlight: 2, + memoryDeletes: 11, + memoryDeletesPrior: 3, + securityDeleteBatches: 1, + securityDeleteBatchesPrior: 0, + securityDeleteBlobs: 40, + securityDeleteBlobsPrior: 0, + sponsored: [ + { kind: 'create_account', count: 6, priorCount: 2 }, + { kind: 'add_delegate_key', count: 9, priorCount: 9 }, + { kind: 'remove_delegate_key', count: 1, priorCount: 0 }, + ], + topOwners: [ + { owner: '0x8c4e91ab23f04d11a0c8e21b77aa9012cd34ef56', uploadsCompleted: 41 }, + { owner: '0x11aa90bb33445566778899aabbccddeeff001122', uploadsCompleted: 27 }, + { owner: '0xabcdef0123456789abcdef0123456789abcdef01', uploadsCompleted: 14 }, + ], + memoriesByDay: [2, 0, 5, 4, 9, 3, 8, 6].map((count, index) => ({ + day: new Date(Date.UTC(2026, 8, 17 + index)).toISOString().slice(0, 10), + count, + })), + memoriesByHour: null, + }, +} + +function ActivityBody({ data, hours, onHours }: { + data: AdminActivity + hours: number + onHours: (hours: number) => void +}) { + const { actions } = data + return ( +
+ + {WINDOWS.map((choice) => ( + + ))} +
+ } + > +
+ + + +
+

+ Samples are recorded about every {formatInterval(data.balanceMonitorIntervalSecs)} and + kept for 60 days. Comparing a window with the one before it needs samples in both, so a + 30-day comparison stays incomplete until the monitor has been running about 60 days. +

+ + + + + + + +
+ {countLine('Uploads completed', actions.uploadsCompleted, actions.uploadsCompletedPrior)} + {countLine('Uploads failed', actions.uploadsFailed, actions.uploadsFailedPrior)} + {countLine('Uploads in flight now', actions.uploadsInFlight, null)} + {countLine('Memory deletes', actions.memoryDeletes, actions.memoryDeletesPrior)} + {actions.securityDeleteBatches == null ? ( +
+ Security delete + Not configured +
+ ) : ( + <> + {countLine( + 'Security-delete batches', + actions.securityDeleteBatches, + actions.securityDeleteBatchesPrior, + )} + {countLine( + 'Security-delete blobs', + actions.securityDeleteBlobs ?? 0, + actions.securityDeleteBlobsPrior, + )} + + )} + {actions.sponsored.map((row) => + countLine( + `Sponsored ${row.kind.replace(/_/g, ' ')}`, + row.count, + row.priorCount, + ), + )} +
+

+ Sponsored rows count account create and delegate-key transactions that executed after + this version deployed, and are kept for 60 days. Upload rows are remember jobs. +

+
+ + + + + + + + + {actions.topOwners.length === 0 ? ( + + + + ) : ( + actions.topOwners.map((owner) => ( + + + + + )) + )} + +
Top ownersCompleted uploads
+ No completed uploads in this window +
+ + + {owner.uploadsCompleted} +
+
+
+ + ) +} + +export function AdminActivityPanel({ adminKey, onInvalidKey, preview = false }: AdminActivityProps) { + const [hours, setHours] = useState(24) + const { data, isLoading, error } = useQuery({ + queryKey: ['admin', 'activity', hours], + queryFn: () => fetchAdminActivity(adminKey, hours), + enabled: !preview, + refetchInterval: preview ? false : 60_000, + retry: (failureCount, error) => { + const err = error as Error + return err.message !== 'INVALID_KEY' && failureCount < 3 + }, + }) + + const isInvalidKey = !preview && error instanceof Error && error.message === 'INVALID_KEY' + + useEffect(() => { + if (isInvalidKey) onInvalidKey() + }, [isInvalidKey, onInvalidKey]) + + if (preview) { + return + } + + if (isLoading) { + return ( + +
Loading spend and activity...
+
+ ) + } + + if (error || !data) { + return ( + +
+ {isInvalidKey ? 'Invalid API key — signing out...' : 'Failed to load spend and activity'} +
+
+ ) + } + + return +} diff --git a/apps/app/src/components/AdminConfig.tsx b/apps/app/src/components/AdminConfig.tsx index 68a34d66a..10ebdd3a8 100644 --- a/apps/app/src/components/AdminConfig.tsx +++ b/apps/app/src/components/AdminConfig.tsx @@ -26,7 +26,7 @@ export function AdminConfig({ adminKey, onInvalidKey }: AdminConfigProps) { if (isLoading) { return ( - +
Loading configuration...
) @@ -34,7 +34,7 @@ export function AdminConfig({ adminKey, onInvalidKey }: AdminConfigProps) { if (error) { return ( - +
{isInvalidKey ? 'Invalid API key — signing out...' : 'Failed to load configuration'}
@@ -44,14 +44,14 @@ export function AdminConfig({ adminKey, onInvalidKey }: AdminConfigProps) { if (!data) { return ( - +
No configuration available
) } return ( - +
Balance Monitor Interval diff --git a/apps/app/src/components/AdminKeyEntry.tsx b/apps/app/src/components/AdminKeyEntry.tsx index 8af9f3c72..9fff9861f 100644 --- a/apps/app/src/components/AdminKeyEntry.tsx +++ b/apps/app/src/components/AdminKeyEntry.tsx @@ -44,7 +44,7 @@ export function AdminKeyEntry({ return (
diff --git a/apps/app/src/components/AdminUploadErrors.tsx b/apps/app/src/components/AdminUploadErrors.tsx index ec5b600e1..81f4db979 100644 --- a/apps/app/src/components/AdminUploadErrors.tsx +++ b/apps/app/src/components/AdminUploadErrors.tsx @@ -1,24 +1,62 @@ -import { useState, useEffect } from 'react' +import { useState, useEffect, type ReactNode } from 'react' import { useQuery } from '@tanstack/react-query' -import { Copy, ChevronLeft, ChevronRight } from 'lucide-react' +import { ChevronLeft, ChevronRight, ExternalLink } from 'lucide-react' import { Card } from './Card' -import { fetchAdminErrors } from '../utils/admin-api' +import { CopyButton } from './CopyButton' +import { CopyableText } from './CopyableText' +import { + fetchAdminErrors, + shortAddress, + suiExplorerAccountUrl, + type UploadError, +} from '../utils/admin-api' interface AdminUploadErrorsProps { adminKey: string onInvalidKey: () => void } -interface ExpandedError { - timestamp: string - fullMessage: string +/** "4m 12s" between two ISO times; null when either is unreadable. */ +function describeDuration(fromIso: string, toIso: string): string | null { + const ms = Date.parse(toIso) - Date.parse(fromIso) + if (!Number.isFinite(ms) || ms < 0) return null + const seconds = Math.round(ms / 1000) + if (seconds < 60) return `${seconds}s` + const minutes = Math.floor(seconds / 60) + if (minutes < 60) return `${minutes}m ${seconds % 60}s` + return `${Math.floor(minutes / 60)}h ${minutes % 60}m` +} + +/** Everything about one failed job, for pasting into a ticket or chat. */ +function errorDetailsText(error: UploadError): string { + return JSON.stringify( + { + job_id: error.id, + owner: error.owner, + namespace: error.namespace, + status: error.status, + created_at: error.createdAt, + failed_at: error.timestamp, + error_message: error.rawErrorMessage, + }, + null, + 2, + ) +} + +function DetailRow({ label, children }: { label: string; children: ReactNode }) { + return ( +
+
{label}
+
{children}
+
+ ) } export function AdminUploadErrors({ adminKey, onInvalidKey }: AdminUploadErrorsProps) { const [limit, setLimit] = useState(20) const [offset, setOffset] = useState(0) - const [expanded, setExpanded] = useState(null) - const [copied, setCopied] = useState(false) + const [expanded, setExpanded] = useState(null) const { data, isLoading, error } = useQuery({ queryKey: ['admin', 'errors', limit, offset], @@ -44,18 +82,8 @@ export function AdminUploadErrors({ adminKey, onInvalidKey }: AdminUploadErrorsP return () => document.removeEventListener('keydown', handleKeyDown) }, [expanded]) - const handleCopy = async (text: string) => { - try { - await navigator.clipboard.writeText(text) - setCopied(true) - setTimeout(() => setCopied(false), 2000) - } catch (err) { - console.error('Failed to copy:', err) - } - } - - const openError = (timestamp: string, message: string) => { - setExpanded({ timestamp, fullMessage: message }) + const openError = (error: UploadError) => { + setExpanded(error) } const closeError = () => { @@ -76,7 +104,7 @@ export function AdminUploadErrors({ adminKey, onInvalidKey }: AdminUploadErrorsP if (isLoading) { return ( - +
Loading error data...
) @@ -84,7 +112,7 @@ export function AdminUploadErrors({ adminKey, onInvalidKey }: AdminUploadErrorsP if (error) { return ( - +
{isInvalidKey ? 'Invalid API key — signing out...' : 'Failed to load errors'}
@@ -94,7 +122,7 @@ export function AdminUploadErrors({ adminKey, onInvalidKey }: AdminUploadErrorsP if (!data) { return ( - +
No data available
) @@ -105,7 +133,7 @@ export function AdminUploadErrors({ adminKey, onInvalidKey }: AdminUploadErrorsP return ( <> - +
-

- {new Date(expanded.timestamp).toLocaleString()} -

-
{expanded.fullMessage}
+
+ + + + + + + + + + + + + + + {expanded.status} + + + + {new Date(expanded.createdAt).toLocaleString()} + + + {new Date(expanded.timestamp).toLocaleString()} + {describeDuration(expanded.createdAt, expanded.timestamp) && ( + + {' '} + · after {describeDuration(expanded.createdAt, expanded.timestamp)} + + )} + +
+ +
+ Error message + {expanded.rawErrorMessage && ( + + )} +
+ {expanded.rawErrorMessage ? ( +
{expanded.rawErrorMessage}
+ ) : ( +

+ The server recorded no error message for this job. Use the job ID to look it up + in the relayer logs. +

+ )}
- + Copy all details +
diff --git a/apps/app/src/components/AdminWalletBalances.tsx b/apps/app/src/components/AdminWalletBalances.tsx index f324463d8..834db1342 100644 --- a/apps/app/src/components/AdminWalletBalances.tsx +++ b/apps/app/src/components/AdminWalletBalances.tsx @@ -2,6 +2,7 @@ import { useEffect } from 'react' import { useQuery } from '@tanstack/react-query' import { RefreshCw } from 'lucide-react' import { Card } from './Card' +import { CopyableText } from './CopyableText' import { fetchAdminWallets, formatTokenAmount, type AdminWalletsResponse } from '../utils/admin-api' interface AdminWalletBalancesProps { @@ -37,7 +38,7 @@ export function AdminWalletBalances({ adminKey, onInvalidKey }: AdminWalletBalan if (isLoading) { return ( - +
Loading wallet data...
) @@ -45,7 +46,7 @@ export function AdminWalletBalances({ adminKey, onInvalidKey }: AdminWalletBalan if (error) { return ( - +
{isInvalidKey ? 'Invalid API key — signing out...' : 'Failed to load wallets'}
@@ -59,7 +60,7 @@ export function AdminWalletBalances({ adminKey, onInvalidKey }: AdminWalletBalan
} @@ -93,8 +94,12 @@ export function AdminWalletBalances({ adminKey, onInvalidKey }: AdminWalletBalan ) : response.uploaderPoolWallets.map((wallet) => ( - - {abbreviateAddress(wallet.address)} + +
- +
Address - - {abbreviateAddress(response.sponsorWallet.address)} - + + {response.sponsorWallet.address.startsWith('0x') ? ( + + ) : ( + response.sponsorWallet.address + )} +
diff --git a/apps/app/src/components/CopyButton.tsx b/apps/app/src/components/CopyButton.tsx new file mode 100644 index 000000000..bef8fa7b8 --- /dev/null +++ b/apps/app/src/components/CopyButton.tsx @@ -0,0 +1,96 @@ +import { useEffect, useRef, useState, type ReactNode } from 'react' +import { Check, CircleX, Copy } from 'lucide-react' + +type CopyStatus = 'idle' | 'done' | 'error' + +interface CopyButtonProps { + /** Text to copy, or a function that returns it at click time. */ + text: string | (() => string) + /** Optional label beside the icon. Without it the button is icon-only. */ + children?: ReactNode + /** Accessible name; also the hover title while idle. */ + ariaLabel?: string + className?: string + size?: 'icon' | 'sm' + onCopySuccess?: (text: string) => void + onCopyError?: (error: Error) => void +} + +/** How long the done or error state stays before returning to idle. */ +const RESET_MS = 1600 + +export async function writeClipboard(text: string): Promise { + if (navigator.clipboard?.writeText) { + await navigator.clipboard.writeText(text) + return + } + // Clipboard API is unavailable on plain-HTTP origins other than localhost. + const area = document.createElement('textarea') + area.value = text + area.setAttribute('readonly', '') + area.style.position = 'fixed' + area.style.opacity = '0' + document.body.appendChild(area) + area.select() + const ok = document.execCommand('copy') + area.remove() + if (!ok) throw new Error('Copy command was rejected') +} + +/** + * Copies text and shows what happened: the icon swaps to a check (or a cross) + * with a short pop, the label reads "Copied", and screen readers hear it. + */ +export function CopyButton({ + text, + children, + ariaLabel = 'Copy', + className = '', + size = 'icon', + onCopySuccess, + onCopyError, +}: CopyButtonProps) { + const [status, setStatus] = useState('idle') + const timer = useRef(undefined) + + useEffect(() => () => window.clearTimeout(timer.current), []) + + const handleClick = async (event: React.MouseEvent) => { + // Rows and modals often have their own click handlers. + event.stopPropagation() + const value = typeof text === 'function' ? text() : text + window.clearTimeout(timer.current) + try { + await writeClipboard(value) + setStatus('done') + onCopySuccess?.(value) + } catch (err) { + setStatus('error') + onCopyError?.(err instanceof Error ? err : new Error(String(err))) + } + timer.current = window.setTimeout(() => setStatus('idle'), RESET_MS) + } + + const icon = + status === 'done' ? : status === 'error' ? : + const statusText = status === 'done' ? 'Copied' : status === 'error' ? 'Copy failed' : '' + + return ( + + ) +} diff --git a/apps/app/src/components/CopyStatus.tsx b/apps/app/src/components/CopyStatus.tsx new file mode 100644 index 000000000..2d547f832 --- /dev/null +++ b/apps/app/src/components/CopyStatus.tsx @@ -0,0 +1,74 @@ +import type { CSSProperties } from 'react' +import type { CopyStatus } from '../hooks/useCopyFeedback' + +const SVG_PROPS = { + viewBox: '0 0 14 14', + fill: 'none', + stroke: 'currentColor', + strokeWidth: 1.5, + strokeLinecap: 'round', + strokeLinejoin: 'round', +} as const + +/** + * Copy, check, and cross icons stacked in one cell. The active one fades and + * scales in, the check draws its stroke, and screen readers hear the result. + * Motion lives in index.css (`.copy-status-icon`) and honors reduced motion. + */ +export function CopyStatusIcon({ status, size = 14 }: { status: CopyStatus; size?: number }) { + return ( + <> + + + {status === 'copied' ? 'Copied' : status === 'error' ? 'Copy failed' : ''} + + + ) +} + +/** + * Button text that blurs between its idle, copied, and error wording. All three + * share one grid cell, so the button keeps the width of the longest one. + */ +export function CopyStatusLabel({ + status, + idle, + copied = 'Copied', + error = 'Copy failed', +}: { + status: CopyStatus + idle: string + copied?: string + error?: string +}) { + const labels: Array<[CopyStatus, string]> = [ + ['idle', idle], + ['copied', copied], + ['error', error], + ] + return ( + + ) +} diff --git a/apps/app/src/components/CopyableText.tsx b/apps/app/src/components/CopyableText.tsx new file mode 100644 index 000000000..a26a5b024 --- /dev/null +++ b/apps/app/src/components/CopyableText.tsx @@ -0,0 +1,69 @@ +import { useEffect, useRef, useState } from 'react' +import { Check, CircleX, Copy } from 'lucide-react' + +import { writeClipboard } from './CopyButton' + +type CopyStatus = 'idle' | 'done' | 'error' + +interface CopyableTextProps { + /** The full value that goes on the clipboard. */ + value: string + /** What is shown; defaults to the value itself. */ + display?: string + /** Accessible name, e.g. "Copy owner address". */ + label: string + /** Let long values (a full address) wrap instead of overflowing. */ + wrap?: boolean + className?: string +} + +const RESET_MS = 1600 + +/** + * A value you click to copy. No box around it: the text itself is the button. + * A small copy icon shows on hover or focus; after a click the text turns + * green, the icon pops to a check, and a "Copied" chip floats up and fades. + */ +export function CopyableText({ value, display, label, wrap = false, className = '' }: CopyableTextProps) { + const [status, setStatus] = useState('idle') + const timer = useRef(undefined) + + useEffect(() => () => window.clearTimeout(timer.current), []) + + const handleClick = async (event: React.MouseEvent) => { + event.stopPropagation() + window.clearTimeout(timer.current) + try { + await writeClipboard(value) + setStatus('done') + } catch { + setStatus('error') + } + timer.current = window.setTimeout(() => setStatus('idle'), RESET_MS) + } + + const statusText = status === 'done' ? 'Copied' : status === 'error' ? 'Copy failed' : '' + + return ( + + ) +} diff --git a/apps/app/src/components/SecurityDeleteSection.test.tsx b/apps/app/src/components/SecurityDeleteSection.test.tsx index 792a34dbe..addc46b24 100644 --- a/apps/app/src/components/SecurityDeleteSection.test.tsx +++ b/apps/app/src/components/SecurityDeleteSection.test.tsx @@ -51,7 +51,7 @@ beforeEach(() => { it('shows the migration notice and cleanup guide in the delete module', () => { render() - expect(screen.getByText('Delete Pre-Migration Memories')).toBeInTheDocument() + expect(screen.getByText('Delete pre-migration memories')).toBeInTheDocument() expect(screen.getByText('Applies only to memories written before July 30, 2026')).toBeInTheDocument() expect(screen.getByText(/On July 30, 2026 all existing memories were migrated/)).toBeInTheDocument() expect(screen.getByRole('link', { name: 'here' })).toHaveAttribute( diff --git a/apps/app/src/components/SecurityDeleteSection.tsx b/apps/app/src/components/SecurityDeleteSection.tsx index 7af78a378..4db126bdf 100644 --- a/apps/app/src/components/SecurityDeleteSection.tsx +++ b/apps/app/src/components/SecurityDeleteSection.tsx @@ -229,7 +229,7 @@ export default function SecurityDeleteSection({ accountObjectId }: { accountObje }, [accountObjectId, address, preview, signer, suiClient]) if (!config.securityDeleteEnabled || !address) return null - return Refresh }>
diff --git a/apps/app/src/config.ts b/apps/app/src/config.ts index 61b0674d6..7e8bbe1d9 100644 --- a/apps/app/src/config.ts +++ b/apps/app/src/config.ts @@ -11,9 +11,9 @@ function parseCsv(value: string | undefined, fallback = '') { } const memwalPackageId = import.meta.env.VITE_MEMWAL_PACKAGE_ID as string || - '0xcf6ad755a1cdff7217865c796778fabe5aa399cb0cf2eba986f4b582047229c6' + '0x0a625e2db2af6f591a4c80a3d8551ddf11656089cc3a20c5e9e7f8fb75b9265c' const memwalRegistryId = import.meta.env.VITE_MEMWAL_REGISTRY_ID as string || - '0xe80f2feec1c139616a86c9f71210152e2a7ca552b20841f2e192f99f75864437' + '0x736aef9906798fca4460490ccdf8e8502ef170122dc26ecae32111b78c6b42dd' const sealKeyServers = parseCsv(import.meta.env.VITE_SEAL_KEY_SERVERS as string) const legacySealKeyServers = parseCsv(import.meta.env.VITE_LEGACY_SEAL_KEY_SERVERS as string) const localE2eJsonRpc = import.meta.env.DEV && @@ -83,15 +83,20 @@ export const config = { walrusSystemObjectId: import.meta.env.VITE_WALRUS_SYSTEM_OBJECT_ID as string || '', walrusStakingPoolId: import.meta.env.VITE_WALRUS_STAKING_POOL_ID as string || '', sidecarUrl: import.meta.env.VITE_SIDECAR_URL as string || 'http://localhost:9000', - docsUrl: import.meta.env.VITE_DOCS_URL as string || '', + docsUrl: import.meta.env.VITE_DOCS_URL as string || + 'https://docs.wal.app/walrus-memory/', termsOfServiceUrl: import.meta.env.VITE_TERMS_OF_SERVICE_URL as string || 'https://docs.wal.app/docs/legal/walrus_general_tos', privacyPolicyUrl: import.meta.env.VITE_PRIVACY_POLICY_URL as string || 'https://docs.wal.app/docs/legal/privacy', - // "Back to Console" target on /keys (WALM-675). Per-deployment like the - // package/registry ids above — never read from a URL query param, since - // that's exactly the trust model WALM-288 broke. Empty hides the link. - consoleUrl: import.meta.env.VITE_CONSOLE_URL as string || '', + // "Back to Console" target (WALM-675). Never read from a URL query param, + // since that's the trust model WALM-288 broke. A set VITE_CONSOLE_URL + // wins; otherwise this is the Memory tab for the active network. + // WM only appends from=wm, and Console's return flow runs on that tab. + consoleUrl: import.meta.env.VITE_CONSOLE_URL as string || + ((import.meta.env.VITE_SUI_NETWORK as string || 'testnet') === 'mainnet' + ? 'https://console.walrus.xyz/buckets?tab=memory' + : 'https://testnet.console.walrus.xyz/buckets?tab=memory'), gtmContainerId: import.meta.env.VITE_GTM_CONTAINER_ID as string || '', gaMeasurementId: import.meta.env.VITE_GA_MEASUREMENT_ID as string || '', posthogProjectApiKey: ( @@ -101,10 +106,15 @@ export const config = { ), posthogHost: import.meta.env.VITE_POSTHOG_HOST as string || 'https://t.walrus.xyz', posthogUiHost: import.meta.env.VITE_POSTHOG_UI_HOST as string || 'https://us.posthog.com', + // Client SDK key. Blank disables Statsig. This is not a server secret. + statsigClientKey: import.meta.env.VITE_STATSIG_CLIENT_KEY as string || '', analyticsAllowedHosts: parseCsv( import.meta.env.VITE_ANALYTICS_ALLOWED_HOSTS as string | undefined, DEFAULT_ANALYTICS_ALLOWED_HOSTS, ), + // Dashboard Walrus Console button and "View your memories" card. + // Off unless explicitly enabled. + walrusConsoleEnabled: (import.meta.env.VITE_WALRUS_CONSOLE_ENABLED as string || '') === 'true', // Permanent V1 memory deletion UI. Off by default so nothing // is user-visible until the feature is tested and rollout is agreed. // Must be enabled together with the relayer's ENABLE_MEMORY_DELETION. diff --git a/apps/app/src/hooks/useCopyFeedback.ts b/apps/app/src/hooks/useCopyFeedback.ts new file mode 100644 index 000000000..ab491364e --- /dev/null +++ b/apps/app/src/hooks/useCopyFeedback.ts @@ -0,0 +1,46 @@ +import { useCallback, useEffect, useRef, useState } from 'react' +import { writeClipboard } from '../components/CopyButton' + +export type CopyStatus = 'idle' | 'copied' | 'error' + +type CopyResult = { item: string; status: Exclude } + +/** + * Copy feedback for a group of copy buttons that share one page. + * Only the most recently clicked item shows "copied" or "error"; a new + * click restarts the timer, so an older click cannot cut it short. + */ +export function useCopyFeedback(timeout = 2000) { + const [result, setResult] = useState(null) + const timer = useRef(undefined) + const mounted = useRef(false) + + useEffect(() => { + mounted.current = true + return () => { + mounted.current = false + window.clearTimeout(timer.current) + } + }, []) + + const copy = useCallback(async (text: string, item: string) => { + let ok = true + try { + await writeClipboard(text) + } catch { + ok = false + } + if (!mounted.current) return ok + window.clearTimeout(timer.current) + setResult({ item, status: ok ? 'copied' : 'error' }) + timer.current = window.setTimeout(() => setResult(null), timeout) + return ok + }, [timeout]) + + const statusOf = useCallback( + (item: string): CopyStatus => (result?.item === item ? result.status : 'idle'), + [result], + ) + + return { copy, statusOf } +} diff --git a/apps/app/src/index.css b/apps/app/src/index.css index acef37945..f26280567 100644 --- a/apps/app/src/index.css +++ b/apps/app/src/index.css @@ -1,4 +1,4 @@ -@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Google+Sans+Code:wght@300;400&family=Google+Sans+Flex:opsz,wght@6..144,400;6..144,500;6..144,600&family=JetBrains+Mono:wght@400;500&display=swap'); @font-face { font-family: 'Ratch'; @@ -6125,7 +6125,7 @@ h1, h2, h3 { background: rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.16); color: var(--dash-text); - transition: background 0.12s ease, border-color 0.12s ease; + transition: background 0.12s ease, border-color 0.12s ease, translate 0.16s var(--copy-status-ease); } .dash-page .key-display .btn-secondary:hover:not(:disabled) { @@ -7093,1868 +7093,1798 @@ h1, h2, h3 { color: #8f9294; } -.playground-dashboard select.input option { - background: #050505; - color: #faf8f5; +.dash-page { + background: + radial-gradient(ellipse 70% 520px at 50% -40px, rgba(92, 54, 168, 0.55), transparent 68%), + #000000; } -.playground-dashboard .demo-code-block { - border: 1px solid #54575a; - background: #050505 !important; - color: #faf8f5 !important; - box-shadow: none; +.connect-wm { + width: min(720px, 100%); + margin: 36px auto 64px; + display: flex; + flex-direction: column; + align-items: stretch; + gap: 28px; } -/* NOTE: removed `.playground-dashboard .demo-code-block span { color: inherit !important }`. - That rule forced every syntax token to the base off-white via !important, - overriding react-syntax-highlighter's inline token colors and making the - playground snippets fully monochrome. Without it, walrusCodeTheme's token - colors (purple keywords, lime strings/keys, gray comments) render. */ - -.playground-dashboard .demo-info-panel, -.playground-dashboard .demo-phase-indicator { - border: 1px solid var(--playground-accent-border); - background: var(--playground-accent-soft); - color: #c7c5c1; +.connect-wm-hero { + text-align: center; } -.playground-dashboard .demo-info-label, -.playground-dashboard summary { - color: #8f9294; +.connect-wm-hero h2 { + margin: 0; + color: #faf8f5; + font-family: Ratch, sans-serif; + font-size: 72px; + font-weight: 425; + line-height: 0.95; + letter-spacing: 0; } -.playground-dashboard .demo-ai-panel { - border: 1px solid #54575a; - background: #050505; - box-shadow: none; +.connect-wm-hero p { + margin: 14px 0 0; + color: #c7c5c1; + font-family: Ratch, sans-serif; + font-size: 18px; + font-weight: 400; + line-height: 1.3; } -.playground-dashboard .demo-result-panel { - border: 1px solid rgba(34, 197, 94, 0.35); - background: rgba(34, 197, 94, 0.08); - box-shadow: none; +.connect-wm-paths { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; } -.playground-dashboard .demo-error-panel { - border: 1px solid rgba(248, 113, 113, 0.35); - background: rgba(248, 113, 113, 0.08); - box-shadow: none; +.connect-wm-path { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + min-height: 104px; + padding: 20px 22px; + border-radius: 18px; + border: 1px solid rgba(250, 248, 245, 0.18); + background: rgba(0, 0, 0, 0.35); + color: #faf8f5; + text-align: left; + cursor: pointer; } -.playground-dashboard .demo-memory-item span:last-child, -.playground-dashboard .demo-result-pre { - color: #c7c5c1; +.connect-wm-path--active { + border-color: rgba(250, 248, 245, 0.72); } -@media (max-width: 640px) { - .playground-nav .walrus-memory-wordmark { - font-size: 1.2rem; - } +.connect-wm-path-top, +.connect-wm-path-title { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + width: 100%; + font-size: 1rem; + font-weight: 600; } -/* ========== Dashboard density alignment ========== */ - -.dashboard-nav { - position: sticky; - top: 0; - z-index: 80; - border-bottom: 1px solid rgba(250, 248, 245, 0.1); +.connect-wm-path-copy, +.connect-wm-timeline p, +.connect-wm-memories-copy p { + margin: 0; + color: #a7a8ae; + font-size: 0.86rem; + line-height: 1.4; + font-weight: 450; } -.dashboard-nav .nav-inner { - max-width: 1280px; +.connect-wm-marks { + display: inline-flex; + gap: 4px; } -.dashboard-nav .lp-nav-cta { - min-height: 0; - padding: 10px 22px; - border: 1px solid #faf8f5; - border-radius: 999px; - background: #faf8f5; - color: #000000; - box-shadow: none; - font-size: 0.92rem; - font-weight: 700; - text-transform: lowercase; +.connect-wm-mark, +.connect-wm-tab-mark { + width: 16px; + height: 16px; + display: inline-grid; + place-items: center; } -.dashboard-nav .lp-nav-cta:hover:not(:disabled) { - background: var(--playground-accent, #e8ff75); - border-color: var(--playground-accent, #e8ff75); - transform: translateY(-1px); - box-shadow: none; +.connect-wm-mark svg, +.connect-wm-tab-mark svg, +.connect-wm-client-badge svg { + width: 16px; + height: 16px; + display: block; } -.dash-page .dash-shell { - width: min(1100px, calc(100% - 64px)); - max-width: 1100px; - padding: 34px 0 68px; +.connect-wm-client-badge { + width: 32px; + height: 32px; + display: grid; + place-items: center; } -.dash-page .dashboard-header { - margin-bottom: 20px; +.connect-wm-client-badge svg { + width: 32px; + height: 32px; } -.dash-page .dashboard-header--compact { - margin-bottom: 18px; +.connect-wm-tabs { + align-self: center; + display: inline-flex; + flex-wrap: wrap; + gap: 2px; + padding: 4px; + border: 1px solid rgba(250, 248, 245, 0.22); + border-radius: 999px; } -.dash-page .dashboard-header h2 { - margin: 0 0 8px; - font-size: 1.54rem; - font-weight: 800; - line-height: 1.05; +.connect-wm-tab { + display: inline-flex; + align-items: center; + gap: 6px; + border: 0; + background: transparent; + color: #d7d7dc; + border-radius: 999px; + padding: 6px 10px; + font-size: 11px; + letter-spacing: 0.06em; + text-transform: uppercase; + cursor: pointer; } -.dash-page .dashboard-header p { - max-width: 680px; - margin-top: 0; - font-size: 0.92rem; - line-height: 1.45; +.connect-wm-tab--active { + background: #f4f4f5; + border-color: #f4f4f5; + color: #161616; } -.dash-page .dash-alert { - min-height: 48px; - margin-bottom: 18px !important; - padding: 11px 16px 11px 48px; +.connect-wm-client { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + gap: 12px; } -.dash-alert-icon { - left: 18px; - width: 22px; - height: 20px; +.connect-wm-client-badge { + width: 36px; + height: 36px; + font-size: 16px; } -.dash-alert-icon::before { - left: 10px; - top: 5px; - width: 2px; - height: 8px; +.connect-wm-client h3, +.connect-wm-timeline h3, +.connect-wm-memories-copy h3 { + margin: 0; + color: #faf8f5; + font-family: Ratch, sans-serif; + font-size: 32px; + font-weight: 500; + line-height: 1.05; + letter-spacing: 0; } -.dash-alert-icon::after { - left: 10px; - top: 15px; - width: 2px; - height: 2px; +.connect-wm-timeline { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 26px; } -.dash-page .dash-alert p { - font-size: 0.88rem; - line-height: 1.28; +.connect-wm-timeline li { + display: grid; + grid-template-columns: 32px minmax(0, 1fr); + gap: 16px; + position: relative; } -.dash-page .dashboard-cta-row { - gap: 14px; - margin-bottom: 20px; +.connect-wm-timeline li:not(:last-child)::before { + content: ""; + position: absolute; + left: 13px; + top: 36px; + bottom: -26px; + width: 1px; + background: rgba(250, 248, 245, 0.16); } -.dash-page .dashboard-cta { - min-height: 76px; - height: auto; - gap: 14px; - padding: 15px 18px; - border-radius: 12px; +.connect-wm-num { + width: 28px; + height: 28px; + margin-top: 4px; + display: grid; + place-items: center; + border-radius: 50%; + border: 1px solid rgba(250, 248, 245, 0.35); + background: #000; + color: #faf8f5; + font-size: 11px; + font-weight: 500; + letter-spacing: 0.02em; + position: relative; + z-index: 1; } -.dash-page .dashboard-cta-icon-wrap { - width: 24px; - height: 28px; - margin-top: 1px; +.connect-wm-timeline h3 { + font-size: 28px; + font-weight: 500; + margin-bottom: 8px; } -.dash-page .dashboard-cta-icon { - width: 24px; - height: 28px; +.connect-wm-timeline p { + font-size: 16px; + line-height: 1.45; + color: #a7a6a2; } -.dash-page .dashboard-cta-title { - font-size: 1.02rem; - font-weight: 800; - line-height: 1.18; +.connect-wm-timeline code { + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + color: #faf8f5; } -.dash-page .dashboard-cta-subtitle { - margin-top: 4px; - font-size: 0.82rem; - line-height: 1.35; +.connect-wm-or { + margin-top: 22px !important; } -.dash-page .dashboard-cta-arrow { - width: 16px; - height: 16px; +.connect-wm-code { + position: relative; + margin-top: 10px; + border-radius: 14px; + border: 1px solid rgba(250, 248, 245, 0.14); + background: #070709; } -.dash-page .card { - margin-bottom: 20px !important; - padding: 20px; - border-radius: 12px; +.connect-wm-code pre { + margin: 0; + padding: 16px 44px 16px 18px; + overflow-x: auto; + color: #f4f4f5; + font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 13px; + font-weight: 400; + line-height: 1.55; } -.dash-page .dashboard-keys-card, -.dash-page .dashboard-quickstart-card, -.dash-page .dashboard-install-card { - min-height: 0; - margin-bottom: 20px !important; -} - -.dash-page .card-header { - margin-bottom: 14px; - gap: 16px; +.connect-wm-copy { + position: absolute; + top: 10px; + right: 10px; + width: 28px; + height: 28px; + display: grid; + place-items: center; + border: 0; + border-radius: 8px; + background: transparent; + color: #c8c8ce; + cursor: pointer; } -.dash-page .card-title, -.dash-page .dashboard-keys-card .card-title { - font-size: 1.08rem; - font-weight: 800; - line-height: 1.15; +.connect-wm-inline { + display: inline-block; + margin-top: 10px; + color: #faf8f5; + text-underline-offset: 3px; } -.dash-page .card-subtitle { +.connect-wm-console { + align-self: center; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; margin-top: 4px; - font-size: 0.82rem; - line-height: 1.35; + padding: 12px 22px; + border: 1px solid rgba(250, 248, 245, 0.55); + border-radius: 999px; + color: #faf8f5; + text-decoration: none; + text-transform: uppercase; + letter-spacing: 0.08em; + font-size: 12px; + white-space: nowrap; } -.dash-page .card-header-actions { - gap: 10px; +.connect-wm-memories { + display: grid; + grid-template-columns: 1fr 1.15fr; + gap: 18px; + align-items: center; + padding: 28px 28px 24px; + border-radius: 22px; + background: linear-gradient(180deg, #f3efff 0%, #e7e4fb 100%); + color: #16161d; } -.dash-page .card-header-actions .btn-secondary, -.dash-page .dashboard-keys-refresh, -.dash-page .dashboard-keys-add { - /* Figma node 2325-6980: 52px pills, radius 26, px-30, 18px label, - tracking 0.72px. Both buttons equal. */ - min-height: 52px; - height: 52px; - padding: 10px 30px; - border-radius: 26px; - font-size: 1.125rem; - letter-spacing: 0.72px; +.connect-wm-memories-copy h3 { + color: #16161d; + font-size: 2rem; + line-height: 1.05; } -.dash-page .key-display, -.dash-page .key-display--white { - padding: 13px 15px; - border-radius: 10px; +.connect-wm-memories-copy p { + margin-top: 10px; + color: #3d3d48; + font-size: 0.95rem; } -.dash-page .key-display .key-label { - font-size: 0.68rem; +.connect-wm-memories-copy a { + display: inline-block; + margin-top: 18px; + color: #16161d; + font-size: 0.78rem; + letter-spacing: 0.08em; + text-transform: uppercase; + text-underline-offset: 4px; } -.dash-page .key-display .key-value { - font-size: 0.78rem; - line-height: 1.5; +.connect-wm-preview { + position: relative; + border-radius: 16px; + background: + radial-gradient(circle at 0 40%, rgba(168, 120, 255, 0.35), transparent 42%), + #f7f7fb; + box-shadow: 0 16px 40px rgba(40, 30, 80, 0.12); + padding: 14px 16px 16px; + color: #1c1c22; + overflow: hidden; } -.dash-page .warning-box { - padding: 13px 15px; - border-radius: 10px; +.connect-wm-preview::before { + content: ""; + position: absolute; + inset: 8px auto auto 0; + width: 70px; + height: 120px; + background: + repeating-linear-gradient(115deg, transparent 0 6px, rgba(150, 90, 255, 0.35) 6px 7px); + pointer-events: none; } -.dash-page .dashboard-quickstart-card .card-header { - margin-bottom: 16px; +.connect-wm-preview-bar { + display: flex; + align-items: center; + gap: 10px; + font-size: 0.75rem; } -.dash-page .dashboard-quickstart-card pre, -.dash-page .dashboard-quickstart-card .demo-code-block { - min-height: 0; - padding: 18px 20px !important; - border-radius: 12px; - font-size: 12.5px; - line-height: 1.42; +.connect-wm-dots { + display: inline-flex; + gap: 4px; } -.dash-page .dashboard-quickstart-copy { - top: 12px; - right: 12px; - width: 34px; - height: 34px; +.connect-wm-dots i { + width: 6px; + height: 6px; + border-radius: 50%; + background: #d7d7e0; } -.dash-page .install-tabs { - gap: 8px; - margin-bottom: 14px; +.connect-wm-preview-kicker { + display: flex; + gap: 14px; + margin: 16px 0 0; + font-size: 12px; + color: #8a8a96; } -.dash-page .install-tab, -.dash-page .install-tab:last-child { - width: 64px; - height: 28px; - font-size: 0.78rem; +.connect-wm-preview-kicker .is-active { + color: #1c1c22; + text-decoration: underline; + text-underline-offset: 4px; } -.dash-page .install-command, -.dash-page .install-tabs + .demo-code-block { - padding: 10px 0 !important; - font-size: 0.82rem; +.connect-wm-preview-bar em { + font-style: normal; + color: #6d6d78; } -.dash-page .dashboard-install-codewrap { - position: relative; - display: inline-flex; - align-items: center; - gap: 24px; - width: 100%; - max-width: 100%; +.connect-wm-preview-bar em.is-active { + color: #1c1c22; + text-decoration: underline; + text-underline-offset: 4px; } -.dash-page .dashboard-install-codewrap .install-command { - display: inline-block; - width: auto; - max-width: calc(100% - 40px); - padding: 10px 0 !important; - white-space: pre; - overflow-x: auto; +.connect-wm-preview-stat { + margin: 18px 0 8px; + font-size: 1.7rem; + font-weight: 620; } -.dash-page .dashboard-install-copy { - position: static; - z-index: 2; - width: 24px; - height: 24px; - padding: 0; - border: 0; - border-radius: 0; - background: transparent; - color: #54575a; - display: grid; - place-items: center; - box-shadow: none; - cursor: pointer; - transform: none; - flex: 0 0 24px; +.connect-wm-preview-meter { + height: 6px; + border-radius: 999px; + background: linear-gradient(90deg, #5b6cff 0 38%, #3dce7a 38% 62%, #e6e6ee 62%); } -.dash-page .dashboard-install-copy:hover:not(:disabled) { - background: transparent; - color: #8f9294; - box-shadow: none; +.connect-wm-preview-agents { + margin: 10px 0 0; + font-size: 0.75rem; + color: #555560; } -.dash-page .dashboard-install-copy svg { - width: 18px; - height: 18px; - display: block; +.connect-wm-preview-agents i, +.connect-wm-preview-agents b { + display: inline-block; + width: 7px; + height: 7px; + margin-right: 4px; + border-radius: 50%; + background: #5b6cff; } -.dash-page .install-command-text { - font-family: var(--font-mono); - color: #faf8f5; - background: transparent; - border: 0; - box-shadow: none; - font-weight: 700; +.connect-wm-preview-agents b { + margin-left: 10px; + background: #3dce7a; } -.dash-page .dashboard-keys-add { - height: 52px; - min-height: 52px; - padding: 10px 30px; - gap: 10px; - justify-content: center; - border: 1px solid #faf8f5; - border-radius: 26px; - background: #faf8f5; - color: #000000; - font-size: 18px; - font-weight: 500; - line-height: 0.84; - letter-spacing: 0.72px; - white-space: nowrap; - box-shadow: none; +@media (max-width: 900px) { + .connect-wm-hero h2 { + font-size: 44px; + } + + .connect-wm-paths, + .connect-wm-memories { + grid-template-columns: 1fr; + } } -.dash-page .dashboard-keys-add svg { - width: 12.15px; - height: 12.15px; - stroke-width: 1.8; +.playground-dashboard select.input option { + background: #050505; + color: #faf8f5; } -/* ── Refresh: transparent + white outline; hover LIGHTENS the fill ── */ -.dash-page .dashboard-keys-refresh, -.dash-page .dashboard-keys-refresh:focus, -.dash-page .dashboard-keys-refresh:focus-visible, -.dash-page .dashboard-keys-refresh:disabled { - background: transparent; - border-color: #faf8f5; +.playground-dashboard .demo-code-block { + border: 1px solid #54575a; + background: #050505 !important; color: #faf8f5 !important; - -webkit-text-fill-color: #faf8f5; - opacity: 1; - transform: none; box-shadow: none; - transition: background 0.14s ease; } -.dash-page .dashboard-keys-refresh:hover:not(:disabled), -.dash-page .dashboard-keys-refresh:active:not(:disabled) { - background: rgba(250, 248, 245, 0.16); - border-color: #faf8f5; - color: #faf8f5 !important; - -webkit-text-fill-color: #faf8f5; - transform: none; - box-shadow: none; +/* NOTE: removed `.playground-dashboard .demo-code-block span { color: inherit !important }`. + That rule forced every syntax token to the base off-white via !important, + overriding react-syntax-highlighter's inline token colors and making the + playground snippets fully monochrome. Without it, walrusCodeTheme's token + colors (purple keywords, lime strings/keys, gray comments) render. */ + +.playground-dashboard .demo-info-panel, +.playground-dashboard .demo-phase-indicator { + border: 1px solid var(--playground-accent-border); + background: var(--playground-accent-soft); + color: #c7c5c1; } -/* ── Add key: white fill; hover BRIGHTENS to the lime accent ── */ -.dash-page .dashboard-keys-add, -.dash-page .dashboard-keys-add:focus, -.dash-page .dashboard-keys-add:focus-visible, -.dash-page .dashboard-keys-add:disabled { - background: #faf8f5; - border-color: #faf8f5; - color: #000000 !important; - -webkit-text-fill-color: #000000; - opacity: 1; - transform: none; +.playground-dashboard .demo-info-label, +.playground-dashboard summary { + color: #8f9294; +} + +.playground-dashboard .demo-ai-panel { + border: 1px solid #54575a; + background: #050505; box-shadow: none; - transition: background 0.14s ease, border-color 0.14s ease; } -.dash-page .dashboard-keys-add:hover:not(:disabled), -.dash-page .dashboard-keys-add:active:not(:disabled) { - background: #e8ff75; - border-color: #e8ff75; - color: #000000 !important; - -webkit-text-fill-color: #000000; - transform: none; +.playground-dashboard .demo-result-panel { + border: 1px solid rgba(34, 197, 94, 0.35); + background: rgba(34, 197, 94, 0.08); box-shadow: none; } -.dash-page .dashboard-keys-add svg { - width: 12.15px; - height: 12.15px; - stroke-width: 1.8; +.playground-dashboard .demo-error-panel { + border: 1px solid rgba(248, 113, 113, 0.35); + background: rgba(248, 113, 113, 0.08); + box-shadow: none; } -.dash-page .install-tabs { - gap: 10px; - margin-bottom: 22px; +.playground-dashboard .demo-memory-item span:last-child, +.playground-dashboard .demo-result-pre { + color: #c7c5c1; } -.dash-page .install-tab, -.dash-page .install-tab:last-child { - width: 72px; - height: 28px; - min-height: 28px; - padding: 8px 12px; - border: 0; - outline: 0; - border-radius: 4px; - background: #1d2227; - color: #8f9294; - box-shadow: none; - font-size: 14px; - font-weight: 500; - line-height: 0.84; - letter-spacing: 0.14px; - text-transform: lowercase; - transition: background 0.12s ease, color 0.12s ease; +@media (max-width: 640px) { + .playground-nav .walrus-memory-wordmark { + font-size: 1.2rem; + } } -/* Inactive tab: hover BRIGHTENS the text (matches the TS/PY toggle behavior) */ -.dash-page .install-tab:hover:not(.install-tab--active), -.dash-page .install-tab:focus-visible:not(.install-tab--active) { - outline: 0; - background: #262b30; - color: #faf8f5; - box-shadow: none; +/* ========== Dashboard density alignment ========== */ + +.dashboard-nav { + position: sticky; + top: 0; + z-index: 80; + border-bottom: 1px solid rgba(250, 248, 245, 0.1); } -.dash-page .install-tab--active, -.dash-page .install-tab--active:hover, -.dash-page .install-tab--active:focus, -.dash-page .install-tab--active:focus-visible, -.dash-page .install-tab--active:active { - outline: 0; +.dashboard-nav .nav-inner { + max-width: 1280px; +} + +.dashboard-nav .lp-nav-cta { + min-height: 0; + padding: 10px 22px; + border: 1px solid #faf8f5; + border-radius: 999px; background: #faf8f5; - color: #000000 !important; + color: #000000; box-shadow: none; + font-size: 0.92rem; + font-weight: 700; + text-transform: lowercase; } -.dash-page .dashboard-empty-message--account { - width: 100%; - min-height: 86px; - padding: 29px 0 !important; - color: #54575a !important; - font-size: 21px !important; - font-weight: 400; - line-height: 1.3; - text-align: center; +.dashboard-nav .lp-nav-cta:hover:not(:disabled) { + background: var(--playground-accent, #e8ff75); + border-color: var(--playground-accent, #e8ff75); + transform: translateY(-1px); + box-shadow: none; } -.dash-page .dashboard-empty-message--account .dashboard-empty-message-link { - display: inline; - padding: 0; - border: none; - background: none; - font: inherit; - color: #faf8f5; - cursor: pointer; - text-decoration-line: underline; - text-decoration-thickness: from-font; - text-underline-position: from-font; +.dash-page .dash-shell { + width: min(1100px, calc(100% - 64px)); + max-width: 1100px; + padding: 34px 0 68px; } -.dash-page .dashboard-empty-message--account .dashboard-empty-message-link:hover { - opacity: 0.8; +.dash-page .dashboard-header { + margin-bottom: 20px; } -@media (max-width: 860px) { - .dashboard-nav .nav-inner { - max-width: none; - } - - .dash-page .dash-shell { - width: calc(100% - 32px); - padding: 32px 0 56px; - } +.dash-page .dashboard-header--compact { + margin-bottom: 18px; +} - .dash-page .dashboard-header h2 { - font-size: 1.55rem; - } +.dash-page .dashboard-header h2 { + margin: 0 0 8px; + font-size: 1.54rem; + font-weight: 800; + line-height: 1.05; +} - .dash-page .dashboard-cta { - min-height: 82px; - padding: 16px 18px; - } +.dash-page .dashboard-header p { + max-width: 680px; + margin-top: 0; + font-size: 0.92rem; + line-height: 1.45; +} - .dash-page .card { - padding: 20px; - } +.dash-page .dash-alert { + min-height: 48px; + margin-bottom: 18px !important; + padding: 11px 16px 11px 48px; } -/* ========== Walrus Memory app flow system pass ========== */ +.dash-alert-icon { + left: 18px; + width: 22px; + height: 20px; +} -.setup-classic-nav, -.playground-nav, -.dashboard-nav { - height: 128px; - padding: 0 50px 0 49px; - background: #000000; - border-bottom: 0; - align-items: flex-start; +.dash-alert-icon::before { + left: 10px; + top: 5px; + width: 2px; + height: 8px; } -.setup-classic-nav .nav-inner, -.playground-nav .nav-inner, -.dashboard-nav .nav-inner { - position: relative; - max-width: 1280px; - margin: 0 auto; - height: 128px; +.dash-alert-icon::after { + left: 10px; + top: 15px; + width: 2px; + height: 2px; } -.setup-classic-nav .nav-brand, -.playground-nav .nav-brand, -.dashboard-nav .nav-brand { - position: absolute; - left: 0; - top: 34px; +.dash-page .dash-alert p { + font-size: 0.88rem; + line-height: 1.28; } -.setup-classic-nav .walrus-memory-wordmark, -.playground-nav .walrus-memory-wordmark, -.dashboard-nav .walrus-memory-wordmark { - color: #faf8f5; - font-size: 2.23rem; - line-height: 0.85; - font-weight: 900; +.dash-page .dashboard-cta-row { + gap: 14px; + margin-bottom: 20px; } -.setup-classic-nav .nav-brand-logo, -.dashboard-nav .nav-brand-logo { - display: block; - height: 56px; - width: auto; +.dash-page .dashboard-cta { + min-height: 76px; + height: auto; + gap: 14px; + padding: 15px 18px; + border-radius: 12px; } -.setup-classic-nav .nav-user, -.playground-nav .nav-user, -.dashboard-nav .nav-user { - position: absolute; - right: 0; - top: 27px; - height: 52px; - gap: 24px; +.dash-page .dashboard-cta-icon-wrap { + width: 24px; + height: 28px; + margin-top: 1px; } -.setup-classic-nav .nav-address, -.playground-nav .nav-address, -.dashboard-nav .nav-address { - width: 125px; +.dash-page .dashboard-cta-icon { + width: 24px; height: 28px; - display: inline-flex; - align-items: center; - justify-content: center; - border: 0; - border-radius: 4px; - background: #262b30; - color: #faf8f5; - padding: 0 12px; - font-size: 12px; - font-weight: 500; - letter-spacing: 0.6px; - line-height: 0.84; - box-shadow: none; } -.setup-classic-nav .lp-nav-cta, -.playground-nav .lp-nav-cta, -.dashboard-nav .lp-nav-cta { - box-sizing: border-box; - width: 153.04px; - height: 52px; - min-height: 52px; - padding: 10px 30px; - border: 1px solid #faf8f5; - border-radius: 26px; - background: #000000; - color: #faf8f5; - box-shadow: none; - gap: 10px; - display: inline-flex; - align-items: center; - justify-content: center; - font-size: 18px; - font-weight: 500; - letter-spacing: 0.72px; - line-height: 0.84; - text-transform: none; - white-space: nowrap; -} - -.setup-classic-nav .lp-nav-cta svg, -.playground-nav .lp-nav-cta svg, -.dashboard-nav .lp-nav-cta svg { - width: 13.04px; - height: 12.14px; - flex: 0 0 auto; - stroke-width: 1.7; -} - -.setup-classic-nav .lp-nav-cta:hover:not(:disabled), -.playground-nav .lp-nav-cta:hover:not(:disabled), -.dashboard-nav .lp-nav-cta:hover:not(:disabled) { - background: #000000; - border-color: #faf8f5; - color: #faf8f5; - transform: none; - box-shadow: none; -} - -.setup-classic-nav .demo-nav-back, -.playground-nav .demo-nav-back, -.dashboard-nav .demo-nav-back { - color: #8f9294; - font-size: 0.82rem; -} - -.setup-classic-nav .demo-nav-back:hover, -.playground-nav .demo-nav-back:hover, -.dashboard-nav .demo-nav-back:hover { - color: #faf8f5; -} - -.playground-dashboard { - width: min(900px, calc(100% - 48px)); - max-width: 900px; - padding: 34px 0 68px; -} - -.playground-dashboard { - width: min(960px, calc(100% - 48px)); - max-width: 960px; -} - -.setup-classic-container { - width: min(900px, calc(100% - 48px)); - max-width: 900px; - min-height: calc(100vh - 128px); - padding: 34px 0 68px; -} - -.setup-classic-panel { - width: min(520px, 100%); -} - -.playground-dashboard .dashboard-header, -.dash-page .dashboard-header, -.setup-classic-intro { - margin-bottom: 20px; -} - -.playground-dashboard .dashboard-header h2, -.dash-page .dashboard-header h2, -.setup-classic-title { - margin: 0 0 8px; - font-size: 1.54rem; +.dash-page .dashboard-cta-title { + font-size: 1.02rem; font-weight: 800; - line-height: 1.05; - letter-spacing: 0; - color: #faf8f5; + line-height: 1.18; } -.playground-dashboard .dashboard-header p, -.dash-page .dashboard-header p, -.setup-classic-description { - max-width: 680px; - margin-top: 0; - color: #c7c5c1; - font-size: 0.92rem; - line-height: 1.45; +.dash-page .dashboard-cta-subtitle { + margin-top: 4px; + font-size: 0.82rem; + line-height: 1.35; } -.setup-classic-description { - margin: 0 auto 22px; +.dash-page .dashboard-cta-arrow { + width: 16px; + height: 16px; } -.playground-dashboard .card, -.playground-dashboard .demo-step, -.dash-page .card, -.setup-classic-feature-card { +.dash-page .card { + margin-bottom: 20px !important; padding: 20px; - border: 1px solid #54575a; border-radius: 12px; - background: #0a0a0a; - color: #faf8f5; - box-shadow: none; } -.playground-dashboard .card, -.playground-dashboard .demo-step, -.dash-page .card { - margin-bottom: 56px !important; +.dash-page .dashboard-keys-card, +.dash-page .dashboard-quickstart-card, +.dash-page .dashboard-install-card { + min-height: 0; + margin-bottom: 20px !important; } -.playground-dashboard .card-header, .dash-page .card-header { margin-bottom: 14px; gap: 16px; } -.playground-dashboard .card-title, -.playground-dashboard .demo-step-title, .dash-page .card-title, -.setup-classic-feature strong { - color: #faf8f5; +.dash-page .dashboard-keys-card .card-title { font-size: 1.08rem; font-weight: 800; line-height: 1.15; } -.playground-dashboard .card-subtitle, -.dash-page .card-subtitle, -.setup-classic-feature p { - color: #b8bbbe; +.dash-page .card-subtitle { + margin-top: 4px; font-size: 0.82rem; line-height: 1.35; } -.setup-classic-feature { +.dash-page .card-header-actions { gap: 10px; - margin-bottom: 14px; } -.setup-classic-generate, -.setup-classic .setup-import-button, -.playground-dashboard .btn, -.dash-page .btn, -.dash-page .dash-shell .lp-nav-cta { - min-height: 36px; - padding: 0 14px; - border-radius: 10px; - font-size: 0.82rem; +.dash-page .card-header-actions .btn-secondary, +.dash-page .dashboard-keys-refresh, +.dash-page .dashboard-keys-add { + /* Figma node 2325-6980: 52px pills, radius 26, px-30, 18px label, + tracking 0.72px. Both buttons equal. */ + min-height: 52px; + height: 52px; + padding: 10px 30px; + border-radius: 26px; + font-size: 1.125rem; + letter-spacing: 0.72px; } -.setup-classic-generate, -.setup-classic .setup-import-button { - min-height: 42px; - padding: 0 18px; - border-radius: 999px; +.dash-page .key-display, +.dash-page .key-display--white { + padding: 13px 15px; + border-radius: 10px; } -.playground-dashboard .demo-server-info { - display: grid; - grid-template-columns: repeat(2, max-content); - gap: 10px; - margin-bottom: 20px; +.dash-page .key-display .key-label { + font-size: 0.68rem; } -@media (max-width: 640px) { - .playground-dashboard .demo-server-info { - grid-template-columns: 1fr; - } +.dash-page .key-display .key-value { + font-size: 0.78rem; + line-height: 1.5; } -.playground-dashboard .demo-server-tag { - border: 1px solid #54575a; +.dash-page .warning-box { + padding: 13px 15px; border-radius: 10px; - background: rgba(255, 255, 255, 0.08); - padding: 8px 12px; - color: #faf8f5; - box-shadow: none; - font-size: 0.78rem; } -.playground-dashboard .demo-step-badge { - width: 34px; - height: 34px; - border-radius: 9px; - font-size: 0.92rem; +.dash-page .dashboard-quickstart-card .card-header { + margin-bottom: 16px; } -.playground-dashboard .demo-code-block, -.dash-page .dashboard-quickstart-card .demo-code-block, -.dash-page .install-command { +.dash-page .dashboard-quickstart-card pre, +.dash-page .dashboard-quickstart-card .demo-code-block { + min-height: 0; + padding: 18px 20px !important; border-radius: 12px; font-size: 12.5px; line-height: 1.42; - box-shadow: none; } -.dash-page .dashboard-quickstart-card { - min-height: 572px; - padding: 39px; - border-color: #54575a; - border-radius: 24px; - background: #000000; - overflow: clip; +.dash-page .dashboard-quickstart-codewrap { + position: relative; } -.dash-page .dashboard-quickstart-card .card-header { - margin-bottom: 34px; +.dash-page .dashboard-quickstart-card .demo-code-block { + padding-right: 44px !important; } -.dash-page .dashboard-quickstart-card .card-title { - color: #faf8f5; - font-size: 36px; - font-weight: 500; - line-height: 0.88; - letter-spacing: 0; +.dash-page .dashboard-quickstart-copy { + position: absolute; + top: 14px; + right: 12px; + width: 28px; + height: 28px; + border-radius: 0; + background: transparent; } -.dash-page .dashboard-quickstart-card .card-subtitle { - margin-top: 14px; - font-size: 18px; - font-weight: 400; - line-height: 1.3; +.dash-page .install-tabs { + gap: 8px; + margin-bottom: 14px; } -.dash-page .dashboard-header h2 { - color: #faf8f5; - font-family: var(--font-sans); - font-size: 56px; - font-weight: 500; - line-height: 0.88; - letter-spacing: 0; +.dash-page .install-tab, +.dash-page .install-tab:last-child { + width: 64px; + height: 28px; + font-size: 0.78rem; } -.dash-page .dashboard-cta-title { - color: #faf8f5; - font-family: var(--font-sans); - font-size: 24px; - font-weight: 650; - line-height: 1.3; - letter-spacing: 0; +.dash-page .install-command, +.dash-page .install-tabs + .demo-code-block { + padding: 10px 0 !important; + font-size: 0.82rem; } -.dash-page .dashboard-cta-subtitle { - margin-top: 0; - color: #c7c5c1; - font-family: var(--font-sans); - font-size: 18px; - font-weight: 400; - line-height: 1.3; - letter-spacing: 0; +.dash-page .dashboard-install-codewrap { + position: relative; + display: inline-flex; + align-items: center; + gap: 24px; + width: 100%; + max-width: 100%; } -.dash-page .dashboard-keys-card { - min-height: 277px; - padding: 39px 40px; - border-color: #54575a; - border-radius: 24px; - background: #000000; - overflow: clip; - /* /keys auto-scrolls here (WALM-675); offset by .dashboard-nav's sticky - height plus a gap, so the card's top edge isn't flush under the nav - (WALM-743). */ - scroll-margin-top: calc(128px + 24px); +.dash-page .dashboard-install-codewrap .install-command { + display: inline-block; + width: auto; + max-width: calc(100% - 40px); + padding: 10px 0 !important; + white-space: pre; + overflow-x: auto; } -.dash-page .dashboard-keys-card .card-header { - align-items: flex-start; - gap: 24px; - margin-bottom: 52px; +.dash-page .dashboard-install-copy { + position: static; + z-index: 2; + width: 24px; + height: 24px; + padding: 0; + border: 0; + border-radius: 0; + background: transparent; + color: #54575a; + display: grid; + place-items: center; + box-shadow: none; + cursor: pointer; + transform: none; + flex: 0 0 24px; } -.dash-page .dashboard-keys-card .card-title { - color: #faf8f5; - font-family: var(--font-sans); - font-size: 36px; - font-weight: 500; - line-height: 0.88; - letter-spacing: 0; +.dash-page .dashboard-install-copy:hover:not(:disabled) { + background: transparent; + color: #8f9294; + box-shadow: none; } -.dash-page .dashboard-keys-card .card-subtitle { - margin-top: 14px; - color: #b8bbbe; - font-family: var(--font-sans); - font-size: 18px; - font-weight: 400; - line-height: 1.3; +.dash-page .dashboard-install-copy svg { + width: 18px; + height: 18px; + display: block; } -.dash-page .dashboard-keys-card .card-header-actions { - align-self: flex-start; - gap: 20px; +.dash-page .install-command-text { + font-family: var(--font-mono); + color: #faf8f5; + background: transparent; + border: 0; + box-shadow: none; + font-weight: 700; } -.dash-page .dashboard-keys-card .dashboard-keys-refresh, -.dash-page .dashboard-keys-card .dashboard-keys-add { +.dash-page .dashboard-keys-add { height: 52px; min-height: 52px; - border-radius: 26px; padding: 10px 30px; - font-family: var(--font-sans); + gap: 10px; + justify-content: center; + border: 1px solid #faf8f5; + border-radius: 26px; + background: #faf8f5; + color: #000000; font-size: 18px; font-weight: 500; line-height: 0.84; letter-spacing: 0.72px; + white-space: nowrap; + box-shadow: none; } -.dash-page .dashboard-keys-card .dashboard-keys-refresh { - width: 128px; - justify-content: center; +.dash-page .dashboard-keys-add svg { + width: 12.15px; + height: 12.15px; + stroke-width: 1.8; } -.dash-page .dashboard-keys-card .dashboard-keys-refresh svg { - display: none; +/* ── Refresh: transparent + white outline; hover LIGHTENS the fill ── */ +.dash-page .dashboard-keys-refresh, +.dash-page .dashboard-keys-refresh:focus, +.dash-page .dashboard-keys-refresh:focus-visible, +.dash-page .dashboard-keys-refresh:disabled { + background: transparent; + border-color: #faf8f5; + color: #faf8f5 !important; + -webkit-text-fill-color: #faf8f5; + opacity: 1; + transform: none; + box-shadow: none; + transition: background 0.14s ease; } -.dash-page .dashboard-keys-card .dashboard-keys-add { - width: 152px; - gap: 14px; - justify-content: center; +.dash-page .dashboard-keys-refresh:hover:not(:disabled), +.dash-page .dashboard-keys-refresh:active:not(:disabled) { + background: rgba(250, 248, 245, 0.16); + border-color: #faf8f5; + color: #faf8f5 !important; + -webkit-text-fill-color: #faf8f5; + transform: none; + box-shadow: none; } -.dash-page .dashboard-keys-card .dashboard-keys-add svg { +/* ── Add key: white fill; hover BRIGHTENS to the lime accent ── */ +.dash-page .dashboard-keys-add, +.dash-page .dashboard-keys-add:focus, +.dash-page .dashboard-keys-add:focus-visible, +.dash-page .dashboard-keys-add:disabled { + background: #faf8f5; + border-color: #faf8f5; + color: #000000 !important; + -webkit-text-fill-color: #000000; + opacity: 1; + transform: none; + box-shadow: none; + transition: background 0.14s ease, border-color 0.14s ease; +} + +.dash-page .dashboard-keys-add:hover:not(:disabled), +.dash-page .dashboard-keys-add:active:not(:disabled) { + background: #e8ff75; + border-color: #e8ff75; + color: #000000 !important; + -webkit-text-fill-color: #000000; + transform: none; + box-shadow: none; +} + +.dash-page .dashboard-keys-add svg { width: 12.15px; height: 12.15px; stroke-width: 1.8; } -.dash-page .dashboard-keys-card .dashboard-empty-message--account { - display: block; - min-height: 90px; - padding: 24px 0 0 !important; - color: #54575a !important; - font-family: var(--font-sans); - font-size: 21px !important; - font-weight: 400; - line-height: 1.3; - text-align: center; +.dash-page .install-tabs { + gap: 10px; + margin-bottom: 22px; } -.dash-page .dashboard-install-card .card-title { - color: #faf8f5; - font-family: var(--font-sans); - font-size: 36px; +.dash-page .install-tab, +.dash-page .install-tab:last-child { + width: 72px; + height: 28px; + min-height: 28px; + padding: 8px 12px; + border: 0; + outline: 0; + border-radius: 4px; + background: #1d2227; + color: #8f9294; + box-shadow: none; + font-size: 14px; font-weight: 500; - line-height: 0.88; - letter-spacing: 0; + line-height: 0.84; + letter-spacing: 0.14px; + text-transform: lowercase; + transition: background 0.12s ease, color 0.12s ease; } -.dash-page .dashboard-install-card .install-command-text { - font-family: var(--font-mono); +/* Inactive tab: hover BRIGHTENS the text (matches the TS/PY toggle behavior) */ +.dash-page .install-tab:hover:not(.install-tab--active), +.dash-page .install-tab:focus-visible:not(.install-tab--active) { + outline: 0; + background: #262b30; color: #faf8f5; - font-size: 15px; - font-weight: 300; - line-height: 1.4; - letter-spacing: 0.15px; + box-shadow: none; } -.dash-page .dashboard-quickstart-card pre, -.dash-page .dashboard-quickstart-card .demo-code-block { - min-height: 395px; - padding: 31px 39px !important; - border: 1px solid #54575a; - border-radius: 24px; - background: #000000 !important; - font-size: 15px; - line-height: 1.45; +.dash-page .install-tab--active, +.dash-page .install-tab--active:hover, +.dash-page .install-tab--active:focus, +.dash-page .install-tab--active:focus-visible, +.dash-page .install-tab--active:active { + outline: 0; + background: #faf8f5; + color: #000000 !important; + box-shadow: none; } -.playground-dashboard .demo-code-block { - padding: 16px 18px !important; +.dash-page .dashboard-empty-message--account { + width: 100%; + min-height: 86px; + padding: 29px 0 !important; + color: #54575a !important; + font-size: 21px !important; + font-weight: 400; + line-height: 1.3; + text-align: center; } -.setup-classic-divider { - margin: 22px 0 16px; +.dash-page .dashboard-empty-message--account .dashboard-empty-message-link { + display: inline; + padding: 0; + border: none; + background: none; + font: inherit; + color: #faf8f5; + cursor: pointer; + text-decoration-line: underline; + text-decoration-thickness: from-font; + text-underline-position: from-font; } -.setup-classic .setup-import-textarea { - min-height: 78px; - border-radius: 10px; - font-size: 0.82rem; +.dash-page .dashboard-empty-message--account .dashboard-empty-message-link:hover { + opacity: 0.8; } @media (max-width: 860px) { - .setup-classic-nav, - .playground-nav, - .dashboard-nav { - height: 92px; - padding: 0 16px; + .dashboard-nav .nav-inner { + max-width: none; } - .dash-page .dashboard-keys-card { - scroll-margin-top: calc(92px + 16px); + .dash-page .dash-shell { + width: calc(100% - 32px); + padding: 32px 0 56px; } - .setup-classic-nav .nav-inner, - .playground-nav .nav-inner, - .dashboard-nav .nav-inner { - display: flex; - align-items: center; - justify-content: space-between; - height: 92px; - min-height: 92px; - padding: 0; + .dash-page .dashboard-header h2 { + font-size: 1.55rem; } - .setup-classic-nav .nav-brand, - .playground-nav .nav-brand, - .dashboard-nav .nav-brand { - top: 22px; + .dash-page .dashboard-cta { + min-height: 82px; + padding: 16px 18px; } - .setup-classic-nav .walrus-memory-wordmark, - .playground-nav .walrus-memory-wordmark, - .dashboard-nav .walrus-memory-wordmark { - font-size: 1.45rem; + .dash-page .card { + padding: 20px; } +} - .setup-classic-nav .nav-user, - .playground-nav .nav-user, - .dashboard-nav .nav-user { - display: flex; - align-items: center; - top: 18px; - gap: 10px; - } +/* ========== Walrus Memory app flow system pass ========== */ - .setup-classic-nav .nav-address, - .playground-nav .nav-address, - .dashboard-nav .nav-address { - width: auto; - min-width: 112px; - } +.setup-classic-nav, +.playground-nav, +.dashboard-nav { + height: 128px; + padding: 0 50px 0 49px; + background: #000000; + border-bottom: 0; + align-items: flex-start; +} - .setup-classic-nav .lp-nav-cta, - .playground-nav .lp-nav-cta, - .dashboard-nav .lp-nav-cta { - width: auto; - min-height: 44px; - height: 44px; - padding: 0 18px; - font-size: 0.95rem; - } +.setup-classic-nav .nav-inner, +.playground-nav .nav-inner, +.dashboard-nav .nav-inner { + position: relative; + max-width: 1280px; + margin: 0 auto; + height: 128px; +} - .dash-page .dash-shell, - .playground-dashboard, - .setup-classic-container { - width: calc(100% - 32px); - padding: 32px 0 56px; - } +.setup-classic-nav .nav-brand, +.playground-nav .nav-brand, +.dashboard-nav .nav-brand { + position: absolute; + left: 0; + top: 34px; +} - .playground-dashboard .dashboard-header h2, - .dash-page .dashboard-header h2, - .setup-classic-title { - font-size: 1.38rem; - } +.setup-classic-nav .walrus-memory-wordmark, +.playground-nav .walrus-memory-wordmark, +.dashboard-nav .walrus-memory-wordmark { + color: #faf8f5; + font-size: 2.23rem; + line-height: 0.85; + font-weight: 900; } -/* ── Figma 2325-6980: authoritative Delegate-keys header buttons + "+" icon. - Appended last (equal-or-higher specificity than the earlier duplicated - .dash-page rules) so these values win regardless of source-order conflicts. ── */ -.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh, -.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add { - min-height: 52px; +.setup-classic-nav .nav-brand-logo, +.dashboard-nav .nav-brand-logo { + display: block; + height: 56px; + width: auto; +} + +.setup-classic-nav .nav-user, +.playground-nav .nav-user, +.dashboard-nav .nav-user { + position: absolute; + right: 0; + top: 27px; height: 52px; - padding: 10px 30px; - border-radius: 26px; - font-family: var(--font-sans); - font-size: 18px; - font-weight: 500; - line-height: 1; - letter-spacing: 0.72px; + gap: 24px; +} + +.setup-classic-nav .nav-address, +.playground-nav .nav-address, +.dashboard-nav .nav-address { + width: 125px; + height: 28px; display: inline-flex; align-items: center; justify-content: center; + border: 0; + border-radius: 4px; + background: #262b30; + color: #faf8f5; + padding: 0 12px; + font-size: 12px; + font-weight: 500; + letter-spacing: 0.6px; + line-height: 0.84; + box-shadow: none; } -.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh { - width: 127px; - gap: 0; +.setup-classic-nav .lp-nav-cta, +.playground-nav .lp-nav-cta, +.dashboard-nav .lp-nav-cta { + box-sizing: border-box; + width: 153.04px; + height: 52px; + min-height: 52px; + padding: 10px 30px; border: 1px solid #faf8f5; - background: transparent; + border-radius: 26px; + background: #000000; color: #faf8f5; -} - -.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh svg { - display: none; -} - -.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add { - width: auto; + box-shadow: none; gap: 10px; - border: 1px solid #faf8f5; - background: #faf8f5; - color: #000000; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 18px; + font-weight: 500; + letter-spacing: 0.72px; + line-height: 0.84; + text-transform: none; + white-space: nowrap; } -.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add svg { - width: 16px; - height: 16px; - stroke-width: 2.5; - flex-shrink: 0; - display: block; +.setup-classic-nav .lp-nav-cta svg, +.playground-nav .lp-nav-cta svg, +.dashboard-nav .lp-nav-cta svg { + width: 13.04px; + height: 12.14px; + flex: 0 0 auto; + stroke-width: 1.7; } -.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh:hover { - background: rgba(250, 248, 245, 0.16); +.setup-classic-nav .lp-nav-cta:hover:not(:disabled), +.playground-nav .lp-nav-cta:hover:not(:disabled), +.dashboard-nav .lp-nav-cta:hover:not(:disabled) { + background: #000000; border-color: #faf8f5; color: #faf8f5; + transform: none; + box-shadow: none; } -.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add:hover { - background: #e8ff75; - border-color: #e8ff75; - color: #000000; +.setup-classic-nav .demo-nav-back, +.playground-nav .demo-nav-back, +.dashboard-nav .demo-nav-back { + color: #8f9294; + font-size: 0.82rem; } -.dash-page .dashboard-add-key-form { - display: flex; - flex-direction: column; - gap: 16px; - margin-bottom: 20px; - padding: 24px 28px; - border: 1px solid #54575a; - border-radius: 24px; - background: rgba(255, 255, 255, 0.08); - transform-origin: top center; - animation: dashboardInlineReveal 360ms cubic-bezier(0.16, 1, 0.3, 1) both; +.setup-classic-nav .demo-nav-back:hover, +.playground-nav .demo-nav-back:hover, +.dashboard-nav .demo-nav-back:hover { + color: #faf8f5; } -.dash-page .dashboard-add-key-form--closing { - pointer-events: none; - animation: dashboardInlineExit 260ms cubic-bezier(0.32, 0, 0.67, 0) both; +.playground-dashboard { + width: min(900px, calc(100% - 48px)); + max-width: 900px; + padding: 34px 0 68px; } -.dash-page .dashboard-add-key-form--closing .dashboard-add-key-field, -.dash-page .dashboard-add-key-form--closing .dashboard-add-key-note, -.dash-page .dashboard-add-key-form--closing .dashboard-add-key-actions { - animation: dashboardInlineItemExit 180ms cubic-bezier(0.32, 0, 0.67, 0) both; +.playground-dashboard { + width: min(960px, calc(100% - 48px)); + max-width: 960px; } -.dash-page .dashboard-add-key-form--closing .dashboard-add-key-note { - animation-delay: 50ms; +.setup-classic-container { + width: min(900px, calc(100% - 48px)); + max-width: 900px; + min-height: calc(100vh - 128px); + padding: 34px 0 68px; } -.dash-page .dashboard-add-key-form--closing .dashboard-add-key-actions { - animation-delay: 70ms; +.setup-classic-panel { + width: min(520px, 100%); } -.dash-page .dashboard-add-key-field { - display: flex; - flex-direction: column; - gap: 8px; - animation: dashboardInlineItemReveal 300ms cubic-bezier(0.16, 1, 0.3, 1) 50ms both; -} +.playground-dashboard .dashboard-header, +.dash-page .dashboard-header, +.setup-classic-intro { + margin-bottom: 20px; +} -.dash-page .dashboard-add-key-label { +.playground-dashboard .dashboard-header h2, +.dash-page .dashboard-header h2, +.setup-classic-title { + margin: 0 0 8px; + font-size: 1.54rem; + font-weight: 800; + line-height: 1.05; + letter-spacing: 0; color: #faf8f5; - font-size: 18px; - font-weight: 500; - line-height: 1.2; } -.dash-page .dashboard-add-key-input { - width: 100%; - min-height: 50px; - padding: 12px 16px; - border: 1px solid rgba(250, 248, 245, 0.12); - border-radius: 14px; - background: #050505; +.playground-dashboard .dashboard-header p, +.dash-page .dashboard-header p, +.setup-classic-description { + max-width: 680px; + margin-top: 0; + color: #c7c5c1; + font-size: 0.92rem; + line-height: 1.45; +} + +.setup-classic-description { + margin: 0 auto 22px; +} + +.playground-dashboard .card, +.playground-dashboard .demo-step, +.dash-page .card, +.setup-classic-feature-card { + padding: 20px; + border: 1px solid #54575a; + border-radius: 12px; + background: #0a0a0a; color: #faf8f5; - font-family: var(--font-sans); - font-size: 18px; - line-height: 1.2; - outline: none; box-shadow: none; } -.dash-page .dashboard-add-key-input:focus { - border-color: rgba(232, 255, 117, 0.7); - box-shadow: 0 0 0 3px rgba(232, 255, 117, 0.12); +.playground-dashboard .card, +.playground-dashboard .demo-step, +.dash-page .card { + margin-bottom: 56px !important; } -.dash-page .dashboard-add-key-note { - margin: 0; - color: #b8bbbe; - font-size: 18px; - line-height: 1.35; - animation: dashboardInlineItemReveal 300ms cubic-bezier(0.16, 1, 0.3, 1) 90ms both; +.playground-dashboard .card-header, +.dash-page .card-header { + margin-bottom: 14px; + gap: 16px; } -.dash-page .dashboard-add-key-actions { - display: flex; - justify-content: flex-end; - gap: 12px; - margin-top: 2px; - animation: dashboardInlineItemReveal 300ms cubic-bezier(0.16, 1, 0.3, 1) 130ms both; +.playground-dashboard .card-title, +.playground-dashboard .demo-step-title, +.dash-page .card-title, +.setup-classic-feature strong { + color: #faf8f5; + font-size: 1.08rem; + font-weight: 800; + line-height: 1.15; } -@keyframes dashboardInlineReveal { - from { - opacity: 0; - filter: blur(10px); - transform: translate3d(0, -8px, 0) scaleY(0.94); - } +.playground-dashboard .card-subtitle, +.dash-page .card-subtitle, +.setup-classic-feature p { + color: #b8bbbe; + font-size: 0.82rem; + line-height: 1.35; +} - to { - opacity: 1; - filter: blur(0); - transform: translate3d(0, 0, 0) scaleY(1); - } +.setup-classic-feature { + gap: 10px; + margin-bottom: 14px; } -@keyframes dashboardInlineItemReveal { - from { - opacity: 0; - filter: blur(6px); - transform: translate3d(0, 10px, 0); - } +.setup-classic-generate, +.setup-classic .setup-import-button, +.playground-dashboard .btn, +.dash-page .btn, +.dash-page .dash-shell .lp-nav-cta { + min-height: 36px; + padding: 0 14px; + border-radius: 10px; + font-size: 0.82rem; +} - to { - opacity: 1; - filter: blur(0); - transform: translate3d(0, 0, 0); - } +.setup-classic-generate, +.setup-classic .setup-import-button { + min-height: 42px; + padding: 0 18px; + border-radius: 999px; } -@keyframes dashboardInlineExit { - from { - opacity: 1; - filter: blur(0); - transform: translate3d(0, 0, 0) scaleY(1); - } +.playground-dashboard .demo-server-info { + display: grid; + grid-template-columns: repeat(2, max-content); + gap: 10px; + margin-bottom: 20px; +} - to { - opacity: 0; - filter: blur(8px); - transform: translate3d(0, -10px, 0) scaleY(0.92); +@media (max-width: 640px) { + .playground-dashboard .demo-server-info { + grid-template-columns: 1fr; } } -@keyframes dashboardInlineItemExit { - from { - opacity: 1; - filter: blur(0); - transform: translate3d(0, 0, 0); - } +.playground-dashboard .demo-server-tag { + border: 1px solid #54575a; + border-radius: 10px; + background: rgba(255, 255, 255, 0.08); + padding: 8px 12px; + color: #faf8f5; + box-shadow: none; + font-size: 0.78rem; +} - to { - opacity: 0; - filter: blur(5px); - transform: translate3d(0, -8px, 0); - } +.playground-dashboard .demo-step-badge { + width: 34px; + height: 34px; + border-radius: 9px; + font-size: 0.92rem; } -.dash-page .dashboard-add-key-cancel, -.dash-page .dashboard-add-key-create { - min-height: 44px; - padding: 10px 22px; - border-radius: 22px; - font-family: var(--font-sans); - font-size: 16px; - font-weight: 500; - line-height: 1; - letter-spacing: 0; +.playground-dashboard .demo-code-block, +.dash-page .dashboard-quickstart-card .demo-code-block, +.dash-page .install-command { + border-radius: 12px; + font-size: 12.5px; + line-height: 1.42; box-shadow: none; } -.dash-page .dashboard-add-key-create { - min-width: 112px; +.dash-page .dashboard-quickstart-card { + min-height: 572px; + padding: 39px; + border-color: #54575a; + border-radius: 24px; + background: #000000; + overflow: clip; } -.dash-page .dashboard-add-key-cancel { - border: 1px solid #faf8f5; - background: transparent; - color: #faf8f5; +.dash-page .dashboard-quickstart-card .card-header { + margin-bottom: 34px; } -.dash-page .dashboard-add-key-cancel:hover:not(:disabled) { - background: rgba(250, 248, 245, 0.14); +.dash-page .dashboard-quickstart-card .card-title { color: #faf8f5; + font-size: 36px; + font-weight: 500; + line-height: 0.88; + letter-spacing: 0; } -.dash-page .dashboard-add-key-create { - border: 1px solid #faf8f5; - background: #faf8f5; - color: #000000; +.dash-page .dashboard-quickstart-card .card-subtitle { + margin-top: 14px; + font-size: 18px; + font-weight: 400; + line-height: 1.3; } -.dash-page .dashboard-add-key-create:hover:not(:disabled) { - border-color: #e8ff75; - background: #e8ff75; - color: #000000; +.dash-page .dashboard-header h2 { + color: #faf8f5; + font-family: var(--font-sans); + font-size: 56px; + font-weight: 500; + line-height: 0.88; + letter-spacing: 0; } -.dash-page .dashboard-key-ready-block { - margin-bottom: 26px; +.dash-page .dashboard-cta-title { + color: #faf8f5; + font-family: var(--font-sans); + font-size: 24px; + font-weight: 650; + line-height: 1.3; + letter-spacing: 0; } -.dash-page .dashboard-key-ready-warning { - margin-bottom: 16px; - min-height: 56px; - display: flex; - align-items: center; - gap: 14px; - padding: 16px 22px; - border-radius: 4px; +.dash-page .dashboard-cta-subtitle { + margin-top: 0; + color: #c7c5c1; + font-family: var(--font-sans); + font-size: 18px; + font-weight: 400; + line-height: 1.3; + letter-spacing: 0; } -.dash-page .dashboard-key-ready-warning-icon { - flex: 0 0 auto; - color: #000000; -} - -.dash-page .dashboard-key-ready-warning p { - margin: 0; - color: #000000; - font-size: 16px; - font-weight: 500; - line-height: 1.4; +.dash-page .dashboard-keys-card { + min-height: 277px; + padding: 39px 40px; + border-color: #54575a; + border-radius: 24px; + background: #000000; + overflow: clip; + /* /keys auto-scrolls here (WALM-675); offset by .dashboard-nav's sticky + height plus a gap, so the card's top edge isn't flush under the nav + (WALM-743). */ + scroll-margin-top: calc(128px + 24px); } -.dash-page .dashboard-key-ready-warning strong { - color: #000000; - font-weight: 700; +.dash-page .dashboard-keys-card .card-header { + align-items: flex-start; + gap: 24px; + margin-bottom: 52px; } -.dash-page .dashboard-key-ready-display { - padding: 28px; +.dash-page .dashboard-keys-card .card-title { + color: #faf8f5; + font-family: var(--font-sans); + font-size: 36px; + font-weight: 500; + line-height: 0.88; + letter-spacing: 0; } -.dash-page .dashboard-key-ready-display .key-label { - margin-bottom: 18px; +.dash-page .dashboard-keys-card .card-subtitle { + margin-top: 14px; + color: #b8bbbe; + font-family: var(--font-sans); + font-size: 18px; + font-weight: 400; + line-height: 1.3; } -.dash-page .dashboard-key-ready-display .key-value { - margin-bottom: 18px; +.dash-page .dashboard-keys-card .card-header-actions { + align-self: flex-start; + gap: 20px; } -.dash-page .dashboard-key-ready-display .key-actions { - margin-top: 0; - gap: 12px; +.dash-page .dashboard-keys-card .dashboard-keys-refresh, +.dash-page .dashboard-keys-card .dashboard-keys-add { + height: 52px; + min-height: 52px; + border-radius: 26px; + padding: 10px 30px; + font-family: var(--font-sans); + font-size: 18px; + font-weight: 500; + line-height: 0.84; + letter-spacing: 0.72px; } -.dash-page .dashboard-key-list { - display: flex; - flex-direction: column; - gap: 20px; +.dash-page .dashboard-keys-card .dashboard-keys-refresh { + width: 128px; + justify-content: center; } -.dash-page .dashboard-key-list--busy { - opacity: 0.68; - transition: opacity 160ms ease; +.dash-page .dashboard-keys-card .dashboard-keys-refresh svg { + display: none; } -.dash-page .dashboard-key-table-wrap { - width: 100%; - overflow: hidden; - border: 1px solid #54575a; - border-radius: 18px; - background: rgba(255, 255, 255, 0.06); +.dash-page .dashboard-keys-card .dashboard-keys-add { + width: 152px; + gap: 14px; + justify-content: center; } -.dash-page .dashboard-key-table { - width: 100%; - border-collapse: collapse; - table-layout: fixed; +.dash-page .dashboard-keys-card .dashboard-keys-add svg { + width: 12.15px; + height: 12.15px; + stroke-width: 1.8; } -.dash-page .dashboard-key-table th, -.dash-page .dashboard-key-table td { - padding: 14px 18px; - text-align: left; - vertical-align: middle; +.dash-page .dashboard-keys-card .dashboard-empty-message--account { + display: block; + min-height: 90px; + padding: 24px 0 0 !important; + color: #54575a !important; + font-family: var(--font-sans); + font-size: 21px !important; + font-weight: 400; + line-height: 1.3; + text-align: center; } -.dash-page .dashboard-key-table th { - border-bottom: 1px solid rgba(250, 248, 245, 0.12); - color: #b8bbbe; - font-size: 14px; +.dash-page .dashboard-install-card .card-title { + color: #faf8f5; + font-family: var(--font-sans); + font-size: 36px; font-weight: 500; - line-height: 1.2; + line-height: 0.88; + letter-spacing: 0; } -.dash-page .dashboard-key-table td { - border-bottom: 1px solid rgba(250, 248, 245, 0.08); +.dash-page .dashboard-install-card .install-command-text { + font-family: var(--font-mono); color: #faf8f5; - font-size: 14px; - line-height: 1.35; -} - -.dash-page .dashboard-key-table tbody tr:last-child td { - border-bottom: 0; + font-size: 15px; + font-weight: 300; + line-height: 1.4; + letter-spacing: 0.15px; } -.dash-page .dashboard-pagination { - display: flex; - align-items: center; - justify-content: space-between; - flex-wrap: wrap; - gap: 16px; - margin-top: 16px; +.dash-page .dashboard-quickstart-card pre, +.dash-page .dashboard-quickstart-card .demo-code-block { + min-height: 395px; + padding: 31px 39px !important; + border: 1px solid #54575a; + border-radius: 24px; + background: #000000 !important; + font-size: 15px; + line-height: 1.45; } -.dash-page .dashboard-pagination-size { - display: flex; - align-items: center; - gap: 8px; +.playground-dashboard .demo-code-block { + padding: 16px 18px !important; } -.dash-page .dashboard-pagination-size label, -.dash-page .dashboard-pagination-status { - color: #b8bbbe; - font-size: 14px; - line-height: 1.35; +.setup-classic-divider { + margin: 22px 0 16px; } -.dash-page .dashboard-pagination-select { - padding: 6px 10px; - border: 1px solid rgba(250, 248, 245, 0.12); +.setup-classic .setup-import-textarea { + min-height: 78px; border-radius: 10px; - background: rgba(255, 255, 255, 0.06); - color: #faf8f5; - font-size: 14px; - line-height: 1.35; - cursor: pointer; + font-size: 0.82rem; } -.dash-page .dashboard-pagination-select:disabled { - opacity: 0.35; - cursor: not-allowed; -} +@media (max-width: 860px) { + .setup-classic-nav, + .playground-nav, + .dashboard-nav { + height: 92px; + padding: 0 16px; + } -.dash-page .dashboard-pagination-end { - display: flex; - align-items: center; - gap: 16px; -} + .dash-page .dashboard-keys-card { + scroll-margin-top: calc(92px + 16px); + } -.dash-page .dashboard-pagination-controls { - display: flex; - gap: 8px; -} + .setup-classic-nav .nav-inner, + .playground-nav .nav-inner, + .dashboard-nav .nav-inner { + display: flex; + align-items: center; + justify-content: space-between; + height: 92px; + min-height: 92px; + padding: 0; + } -.dash-page .dashboard-pagination-btn { - display: inline-flex; - align-items: center; - justify-content: center; - width: 36px; - height: 36px; - padding: 0; - border: 1px solid rgba(250, 248, 245, 0.12); - border-radius: 10px; - background: transparent; - color: #b8bbbe; - cursor: pointer; -} + .setup-classic-nav .nav-brand, + .playground-nav .nav-brand, + .dashboard-nav .nav-brand { + top: 22px; + } -.dash-page .dashboard-pagination-btn:hover:not(:disabled) { - border-color: #faf8f5; - color: #faf8f5; -} + .setup-classic-nav .walrus-memory-wordmark, + .playground-nav .walrus-memory-wordmark, + .dashboard-nav .walrus-memory-wordmark { + font-size: 1.45rem; + } -.dash-page .dashboard-pagination-btn:disabled { - opacity: 0.35; - cursor: not-allowed; -} + .setup-classic-nav .nav-user, + .playground-nav .nav-user, + .dashboard-nav .nav-user { + display: flex; + align-items: center; + top: 18px; + gap: 10px; + } -.dash-page .dashboard-key-table-select { - width: 62px; -} + .setup-classic-nav .nav-address, + .playground-nav .nav-address, + .dashboard-nav .nav-address { + width: auto; + min-width: 112px; + } -.dash-page .dashboard-key-table th:nth-child(2) { - width: 24%; -} - -.dash-page .dashboard-key-table th:nth-child(4) { - width: 120px; -} + .setup-classic-nav .lp-nav-cta, + .playground-nav .lp-nav-cta, + .dashboard-nav .lp-nav-cta { + width: auto; + min-height: 44px; + height: 44px; + padding: 0 18px; + font-size: 0.95rem; + } -.dash-page .dashboard-key-table-actions { - width: 108px; - text-align: right !important; -} + .dash-page .dash-shell, + .playground-dashboard, + .setup-classic-container { + width: calc(100% - 32px); + padding: 32px 0 56px; + } -.dash-page .dashboard-key-row { - transition: background 0.14s ease, box-shadow 0.14s ease; + .playground-dashboard .dashboard-header h2, + .dash-page .dashboard-header h2, + .setup-classic-title { + font-size: 1.38rem; + } } -.dash-page .dashboard-key-row--selected { - background: rgba(232, 255, 117, 0.08); - box-shadow: inset 0 0 0 1px rgba(232, 255, 117, 0.26); +/* ── Figma 2325-6980: authoritative Delegate-keys header buttons + "+" icon. + Appended last (equal-or-higher specificity than the earlier duplicated + .dash-page rules) so these values win regardless of source-order conflicts. ── */ +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh, +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add { + min-height: 52px; + height: 52px; + padding: 10px 30px; + border-radius: 26px; + font-family: var(--font-sans); + font-size: 18px; + font-weight: 500; + line-height: 1; + letter-spacing: 0.72px; + display: inline-flex; + align-items: center; + justify-content: center; } -.dash-page .dashboard-key-cell-select { - width: 62px; +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh { + width: 127px; + gap: 0; + border: 1px solid #faf8f5; + background: transparent; + color: #faf8f5; } -.dash-page .dashboard-key-name { - min-width: 0; - display: flex; - align-items: center; - flex-wrap: nowrap; - gap: 8px; - color: #e8ff75; - font-size: 15px; - font-weight: 600; - line-height: 1.25; +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh svg { + display: none; } -.dash-page .dashboard-key-name > span:first-child { - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add { + width: auto; + gap: 10px; + border: 1px solid #faf8f5; + background: #faf8f5; + color: #000000; } -.dash-page .dashboard-key-current-badge { - display: inline-flex; - align-items: center; - flex: 0 0 auto; - min-height: 22px; - padding: 3px 8px; - border: 1px solid rgba(232, 255, 117, 0.38); - border-radius: 999px; - color: #e8ff75; - font-size: 12px; - font-weight: 500; - line-height: 1; +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add svg { + width: 16px; + height: 16px; + stroke-width: 2.5; + flex-shrink: 0; + display: block; } -.dash-page .dashboard-key-public { - display: inline-block; - max-width: 100%; +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh:hover { + background: rgba(250, 248, 245, 0.16); + border-color: #faf8f5; color: #faf8f5; - font-family: var(--font-mono); - font-size: 13px; - line-height: 1.45; - overflow: hidden; - text-overflow: ellipsis; - vertical-align: middle; - white-space: nowrap; } -.dash-page .dashboard-key-created { - color: #b8bbbe !important; - white-space: nowrap; +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add:hover { + background: #e8ff75; + border-color: #e8ff75; + color: #000000; } -.dash-page .dashboard-key-row-actions { - text-align: right; +.dash-page .dashboard-add-key-form { + display: flex; + flex-direction: column; + gap: 16px; + margin-bottom: 20px; + padding: 24px 28px; + border: 1px solid #54575a; + border-radius: 24px; + background: rgba(255, 255, 255, 0.08); + transform-origin: top center; + animation: dashboardInlineReveal 360ms cubic-bezier(0.16, 1, 0.3, 1) both; } -.dash-page .dashboard-key-actions { - display: flex; - align-items: center; - justify-content: flex-end; - gap: 8px; +.dash-page .dashboard-add-key-form--closing { + pointer-events: none; + animation: dashboardInlineExit 260ms cubic-bezier(0.32, 0, 0.67, 0) both; } -.dash-page .dashboard-key-row-actions .btn-secondary, -.dash-page .dashboard-key-row-actions .btn-danger { - width: 34px; - min-width: 34px; - height: 34px; - min-height: 34px; - padding: 0; - border-radius: 10px; - font-size: 13px; - line-height: 1; - letter-spacing: 0; - text-transform: none; - box-shadow: none; +.dash-page .dashboard-add-key-form--closing .dashboard-add-key-field, +.dash-page .dashboard-add-key-form--closing .dashboard-add-key-note, +.dash-page .dashboard-add-key-form--closing .dashboard-add-key-actions { + animation: dashboardInlineItemExit 180ms cubic-bezier(0.32, 0, 0.67, 0) both; } -.dash-page .dashboard-key-row-actions .dashboard-key-icon-action { - display: inline-flex; - align-items: center; - justify-content: center; +.dash-page .dashboard-add-key-form--closing .dashboard-add-key-note { + animation-delay: 50ms; } -.dash-page .dashboard-key-row-actions .btn-secondary.dashboard-key-icon-action { - border-color: #faf8f5; - background: #faf8f5; - color: #000000; +.dash-page .dashboard-add-key-form--closing .dashboard-add-key-actions { + animation-delay: 70ms; } -.dash-page .dashboard-key-row-actions .btn-secondary.dashboard-key-icon-action:hover:not(:disabled) { - border-color: #e8ff75; - background: #e8ff75; - color: #000000; +.dash-page .dashboard-add-key-field { + display: flex; + flex-direction: column; + gap: 8px; + animation: dashboardInlineItemReveal 300ms cubic-bezier(0.16, 1, 0.3, 1) 50ms both; } -.dash-page .dashboard-key-row-actions .btn-danger.dashboard-key-icon-action { - border-color: #ff6b6b; - background: #ff6b6b; - color: #ffffff; +.dash-page .dashboard-add-key-label { + color: #faf8f5; + font-size: 18px; + font-weight: 500; + line-height: 1.2; } -.dash-page .dashboard-key-row-actions .btn-danger.dashboard-key-icon-action:hover:not(:disabled) { - border-color: #ff8f8f; - background: #ff8f8f; - color: #ffffff; +.dash-page .dashboard-add-key-input { + width: 100%; + min-height: 50px; + padding: 12px 16px; + border: 1px solid rgba(250, 248, 245, 0.12); + border-radius: 14px; + background: #050505; + color: #faf8f5; + font-family: var(--font-sans); + font-size: 18px; + line-height: 1.2; + outline: none; + box-shadow: none; } -.dash-page .dashboard-key-row-actions .dashboard-key-icon-action--copied { - border-color: #e8ff75; - background: #e8ff75; - color: #000000; +.dash-page .dashboard-add-key-input:focus { + border-color: rgba(232, 255, 117, 0.7); + box-shadow: 0 0 0 3px rgba(232, 255, 117, 0.12); } -.dash-page .dashboard-key-row-actions .btn-secondary svg, -.dash-page .dashboard-key-row-actions .btn-danger svg { - display: block; +.dash-page .dashboard-add-key-note { + margin: 0; + color: #b8bbbe; + font-size: 18px; + line-height: 1.35; + animation: dashboardInlineItemReveal 300ms cubic-bezier(0.16, 1, 0.3, 1) 90ms both; } -.dash-page .dashboard-key-selection-bar { +.dash-page .dashboard-add-key-actions { display: flex; - align-items: center; justify-content: flex-end; - flex-wrap: wrap; - gap: 12px 14px; - min-height: 38px; - margin-bottom: 18px; - padding: 0; - border: 0; - border-radius: 0; - background: transparent; + gap: 12px; + margin-top: 2px; + animation: dashboardInlineItemReveal 300ms cubic-bezier(0.16, 1, 0.3, 1) 130ms both; } -.dash-page .dashboard-key-checkbox { - position: relative; - display: inline-flex; - align-items: center; - gap: 10px; - color: #faf8f5; - font-family: var(--font-sans); - font-size: 14px; - font-weight: 500; - line-height: 1; - cursor: pointer; - user-select: none; -} +@keyframes dashboardInlineReveal { + from { + opacity: 0; + filter: blur(10px); + transform: translate3d(0, -8px, 0) scaleY(0.94); + } -.dash-page .dashboard-key-checkbox { - width: 24px; - height: 24px; - gap: 0; - align-self: center; -} - -.dash-page .dashboard-key-checkbox input { - position: absolute; - width: 1px; - height: 1px; - opacity: 0; - pointer-events: none; -} - -.dash-page .dashboard-key-checkbox-box { - display: inline-flex; - align-items: center; - justify-content: center; - width: 22px; - height: 22px; - flex: 0 0 22px; - border: 1px solid rgba(250, 248, 245, 0.72); - border-radius: 6px; - background: rgba(5, 5, 5, 0.5); - transition: background 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease; + to { + opacity: 1; + filter: blur(0); + transform: translate3d(0, 0, 0) scaleY(1); + } } -.dash-page .dashboard-key-checkbox input:checked + .dashboard-key-checkbox-box { - border-color: #e8ff75; - background: #e8ff75; -} +@keyframes dashboardInlineItemReveal { + from { + opacity: 0; + filter: blur(6px); + transform: translate3d(0, 10px, 0); + } -.dash-page .dashboard-key-checkbox input:checked + .dashboard-key-checkbox-box::after { - content: ""; - width: 7px; - height: 11px; - margin-top: -2px; - border: solid #000000; - border-width: 0 2px 2px 0; - transform: rotate(45deg); + to { + opacity: 1; + filter: blur(0); + transform: translate3d(0, 0, 0); + } } -.dash-page .dashboard-key-checkbox input:focus-visible + .dashboard-key-checkbox-box { - box-shadow: 0 0 0 3px rgba(232, 255, 117, 0.18); -} +@keyframes dashboardInlineExit { + from { + opacity: 1; + filter: blur(0); + transform: translate3d(0, 0, 0) scaleY(1); + } -.dash-page .dashboard-key-checkbox input:disabled + .dashboard-key-checkbox-box { - opacity: 0.48; - cursor: not-allowed; + to { + opacity: 0; + filter: blur(8px); + transform: translate3d(0, -10px, 0) scaleY(0.92); + } } -.dash-page .dashboard-key-selection-status { - display: inline-flex; - align-items: center; - min-height: 36px; - margin-left: 0; - color: #b8bbbe; - font-size: 14px; - line-height: 1; -} +@keyframes dashboardInlineItemExit { + from { + opacity: 1; + filter: blur(0); + transform: translate3d(0, 0, 0); + } -.dash-page .dashboard-key-bulk-actions { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 10px; + to { + opacity: 0; + filter: blur(5px); + transform: translate3d(0, -8px, 0); + } } -.dash-page .dashboard-key-clear-selection, -.dash-page .dashboard-key-remove-selected { - height: 36px; - min-height: 36px; - padding: 0 14px; - border-radius: 18px; - display: inline-flex; - align-items: center; - justify-content: center; - font-size: 13px; +.dash-page .dashboard-add-key-cancel, +.dash-page .dashboard-add-key-create { + min-height: 44px; + padding: 10px 22px; + border-radius: 22px; + font-family: var(--font-sans); + font-size: 16px; + font-weight: 500; line-height: 1; letter-spacing: 0; - text-transform: none; box-shadow: none; } -.dash-page .dashboard-key-clear-selection { - min-width: 64px; -} - -.dash-page .dashboard-key-remove-selected { - min-width: 142px; -} - -.dash-page .dashboard-key-remove-selected svg { - display: block; -} - -.dash-page .dashboard-keys-card .key-display { - display: flex; - flex-direction: column; - gap: 14px; - padding: 24px 28px; - border-radius: 24px; - border-color: #54575a; - background: rgba(255, 255, 255, 0.08); +.dash-page .dashboard-add-key-create { + min-width: 112px; } -.dash-page .dashboard-keys-card .dashboard-key-skeleton { - pointer-events: none; +.dash-page .dashboard-add-key-cancel { + border: 1px solid #faf8f5; + background: transparent; + color: #faf8f5; } -.dash-page .dashboard-key-skeleton-line { - display: inline-block; - border-radius: 999px; +.dash-page .dashboard-add-key-cancel:hover:not(:disabled) { background: rgba(250, 248, 245, 0.14); - animation: dashboardSkeletonPulse 1.2s ease-in-out infinite; -} - -.dash-page .dashboard-key-skeleton-line--check { - width: 22px; - height: 22px; - border-radius: 6px; -} - -.dash-page .dashboard-key-skeleton-line--label { - width: min(170px, 80%); - height: 18px; -} - -.dash-page .dashboard-key-skeleton-line--value { - width: min(210px, 90%); - height: 16px; -} - -.dash-page .dashboard-key-skeleton-line--date { - width: 76px; - height: 16px; -} - -.dash-page .dashboard-key-skeleton-line--actions { - width: 76px; - height: 34px; - margin-top: 2px; -} - -.dash-page .dashboard-credentials-card { - padding: 39px 40px; + color: #faf8f5; } -.dash-page .dashboard-credentials-card .card-header { - margin-bottom: 34px; +.dash-page .dashboard-add-key-create { + border: 1px solid #faf8f5; + background: #faf8f5; + color: #000000; } -.dash-page .dashboard-credentials-card .card-title { - color: #faf8f5; - font-family: var(--font-sans); - font-size: 36px; - font-weight: 500; - line-height: 0.88; - letter-spacing: 0; +.dash-page .dashboard-add-key-create:hover:not(:disabled) { + border-color: #e8ff75; + background: #e8ff75; + color: #000000; } -.dash-page .dashboard-credentials-card .card-subtitle { - margin-top: 14px; - color: #b8bbbe; - font-family: var(--font-sans); - font-size: 18px; - font-weight: 400; - line-height: 1.3; +.dash-page .dashboard-key-ready-block { + margin-bottom: 26px; } -.dash-page .dashboard-credentials-alert { - margin-bottom: 18px; +.dash-page .dashboard-key-ready-warning { + margin-bottom: 16px; min-height: 56px; display: flex; align-items: center; gap: 14px; padding: 16px 22px; - border: 0; border-radius: 4px; - background: #e8ff75; - color: #000000; } -.dash-page .dashboard-credentials-alert-icon { +.dash-page .dashboard-key-ready-warning-icon { flex: 0 0 auto; color: #000000; } -.dash-page .dashboard-credentials-alert p { - display: flex; - flex-wrap: wrap; - gap: 6px 14px; +.dash-page .dashboard-key-ready-warning p { margin: 0; color: #000000; font-size: 16px; @@ -8962,3249 +8892,7467 @@ h1, h2, h3 { line-height: 1.4; } -.dash-page .dashboard-credentials-alert p + p { - margin-top: 8px; - color: #000000; -} - -.dash-page .dashboard-credentials-alert strong { +.dash-page .dashboard-key-ready-warning strong { color: #000000; font-weight: 700; } -.dash-page .dashboard-credentials-alert code { - padding: 2px 6px; - border-radius: 6px; - background: rgba(0, 0, 0, 0.08); - color: #000000; - font-family: var(--font-mono); - font-size: 0.95em; +.dash-page .dashboard-key-ready-display { + padding: 28px; } -/* /keys (WALM-675) — same look as .dashboard-credentials-alert above, but - unscoped: this banner renders outside Dashboard's own .dash-page root - (KeysPage wraps it, not Dashboard), and that class's min-height: 100vh - would otherwise double the page height if reused here. */ -.keys-mismatch-alert { - margin: 24px 24px 0; - min-height: 56px; - display: flex; - align-items: center; - gap: 14px; - padding: 16px 22px; - border: 0; - border-radius: 4px; - background: #e8ff75; - color: #000000; +.dash-page .dashboard-key-ready-display .key-label { + margin-bottom: 18px; } -.keys-mismatch-alert-icon { - flex: 0 0 auto; - color: #000000; +.dash-page .dashboard-key-ready-display .key-value { + margin-bottom: 18px; } -.keys-mismatch-alert p { - display: flex; - flex-wrap: wrap; - gap: 6px 14px; - margin: 0; - color: #000000; - font-size: 16px; - font-weight: 500; - line-height: 1.4; +.dash-page .dashboard-key-ready-display .key-actions { + margin-top: 0; + gap: 12px; } -.keys-mismatch-alert p + p { - margin-top: 8px; - color: #000000; +.dash-page .dashboard-key-list { + display: flex; + flex-direction: column; + gap: 20px; } -.keys-mismatch-alert strong { - color: #000000; - font-weight: 700; +.dash-page .dashboard-key-list--busy { + opacity: 0.68; + transition: opacity 160ms ease; } -.keys-mismatch-alert code { - padding: 2px 6px; - border-radius: 6px; - background: rgba(0, 0, 0, 0.08); - color: #000000; - font-family: var(--font-mono); - font-size: 0.95em; +.dash-page .dashboard-key-table-wrap { + width: 100%; + overflow: hidden; + border: 1px solid #54575a; + border-radius: 18px; + background: rgba(255, 255, 255, 0.06); } -.keys-mismatch-alert-signout { - display: inline; - padding: 0; - border: none; - background: none; - font: inherit; - color: #000000; - cursor: pointer; - text-decoration-line: underline; - text-decoration-thickness: from-font; - text-underline-position: from-font; +.dash-page .dashboard-key-table { + width: 100%; + border-collapse: collapse; + table-layout: fixed; } -.keys-mismatch-alert-signout:hover { - opacity: 0.7; +.dash-page .dashboard-key-table th, +.dash-page .dashboard-key-table td { + padding: 14px 18px; + text-align: left; + vertical-align: middle; } -.dash-page .dashboard-credentials-panel { - overflow: hidden; - border: 1px solid #54575a; - border-radius: 24px; - background: #000000; +.dash-page .dashboard-key-table th { + border-bottom: 1px solid rgba(250, 248, 245, 0.12); + color: #b8bbbe; + font-size: 14px; + font-weight: 500; + line-height: 1.2; } -.dash-page .dashboard-credential-row { - display: grid; - grid-template-columns: minmax(0, 1fr) auto; - gap: 18px; - align-items: center; - padding: 18px 22px; - border-bottom: 1px solid rgba(250, 248, 245, 0.1); +.dash-page .dashboard-key-table td { + border-bottom: 1px solid rgba(250, 248, 245, 0.08); + color: #faf8f5; + font-size: 14px; + line-height: 1.35; } -.dash-page .dashboard-credential-row:last-child { +.dash-page .dashboard-key-table tbody tr:last-child td { border-bottom: 0; } -.dash-page .dashboard-credential-label { +.dash-page .dashboard-pagination { display: flex; align-items: center; + justify-content: space-between; flex-wrap: wrap; + gap: 16px; + margin-top: 16px; +} + +.dash-page .dashboard-pagination-size { + display: flex; + align-items: center; gap: 8px; - color: #b8bbbe; - font-size: 14px; - font-weight: 500; - line-height: 1.25; - letter-spacing: 0; - text-transform: none; } -.dash-page .dashboard-credential-label span { - color: #8f9294; - font-family: var(--font-mono); - font-size: 13px; - font-weight: 400; +.dash-page .dashboard-pagination-size label, +.dash-page .dashboard-pagination-status { + color: #b8bbbe; + font-size: 14px; + line-height: 1.35; } -.dash-page .dashboard-credential-value { - display: block; - margin-top: 10px; +.dash-page .dashboard-pagination-select { + padding: 6px 10px; + border: 1px solid rgba(250, 248, 245, 0.12); + border-radius: 10px; + background: rgba(255, 255, 255, 0.06); color: #faf8f5; - font-family: var(--font-mono); font-size: 14px; - line-height: 1.45; - overflow-wrap: anywhere; + line-height: 1.35; + cursor: pointer; } -.dash-page .dashboard-credential-actions { +.dash-page .dashboard-pagination-select:disabled { + opacity: 0.35; + cursor: not-allowed; +} + +.dash-page .dashboard-pagination-end { display: flex; align-items: center; - justify-content: flex-end; + gap: 16px; +} + +.dash-page .dashboard-pagination-controls { + display: flex; gap: 8px; } -.dash-page .dashboard-credential-icon-button { - width: 34px; - height: 34px; +.dash-page .dashboard-pagination-btn { display: inline-flex; align-items: center; justify-content: center; + width: 36px; + height: 36px; + padding: 0; border: 1px solid rgba(250, 248, 245, 0.12); - border-radius: 12px; - background: rgba(255, 255, 255, 0.08); - color: #faf8f5; + border-radius: 10px; + background: transparent; + color: #b8bbbe; cursor: pointer; - transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease; } -.dash-page .dashboard-credential-icon-button:hover:not(:disabled) { - border-color: rgba(250, 248, 245, 0.24); - background: rgba(255, 255, 255, 0.14); +.dash-page .dashboard-pagination-btn:hover:not(:disabled) { + border-color: #faf8f5; + color: #faf8f5; } -.dash-page .dashboard-credential-icon-button--copied { - border-color: #e8ff75; - background: #e8ff75; - color: #000000; +.dash-page .dashboard-pagination-btn:disabled { + opacity: 0.35; + cursor: not-allowed; } -@keyframes dashboardSkeletonPulse { - 0%, - 100% { - opacity: 0.5; - } - - 50% { - opacity: 1; - } +.dash-page .dashboard-key-table-select { + width: 62px; } -@media (prefers-reduced-motion: reduce) { - .dash-page .dashboard-key-skeleton-line { - animation: none; - } +.dash-page .dashboard-key-table th:nth-child(2) { + width: 24%; } -.dash-page .dashboard-keys-card .dashboard-key-item { - transition: border-color 0.14s ease, background 0.14s ease, box-shadow 0.14s ease; +.dash-page .dashboard-key-table th:nth-child(4) { + width: 120px; } -.dash-page .dashboard-keys-card .dashboard-key-item--selected { - border-color: #e8ff75; - background: rgba(232, 255, 117, 0.08); - box-shadow: inset 0 0 0 1px rgba(232, 255, 117, 0.32); +.dash-page .dashboard-key-table-actions { + width: 108px; + text-align: right !important; } -.dash-page .dashboard-key-item-header { - display: grid; - grid-template-columns: 24px minmax(0, 1fr); - align-items: center; - gap: 12px; +.dash-page .dashboard-key-row { + transition: background 0.14s ease, box-shadow 0.14s ease; } -.dash-page .dashboard-key-item-header .key-label { - min-width: 0; - margin-bottom: 0; - overflow-wrap: anywhere; +.dash-page .dashboard-key-row--selected { + background: rgba(250, 248, 245, 0.04); + box-shadow: none; } -.dash-page .dashboard-key-item-header .key-label span { - margin-left: 8px; - font-weight: 400; +.dash-page .dashboard-key-cell-select { + width: 62px; } -.dash-page .dashboard-keys-card .key-display .key-label { - color: #e8ff75; +.dash-page .dashboard-key-name { + min-width: 0; + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; + color: #faf8f5; font-size: 15px; - font-weight: 600; - line-height: 1.2; - letter-spacing: 0; - text-transform: none; + font-weight: 400; + line-height: 1.25; } -.dash-page .dashboard-keys-card .key-display .key-label span { - color: #e8ff75; - opacity: 0.9; +.dash-page .dashboard-key-name > span:first-child { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } -.dash-page .dashboard-keys-card .key-display .key-value { +.dash-page .dashboard-key-current-badge { + display: inline-flex; + align-items: center; + flex: 0 0 auto; + min-height: 22px; + padding: 3px 8px; + border: 1px solid #54575a; + border-radius: 999px; color: #faf8f5; - font-size: 14px; - line-height: 1.45; - letter-spacing: 0; -} - -.dash-page .dashboard-keys-card .key-display .key-actions { - display: flex; - flex-wrap: wrap; - gap: 10px; - margin-top: 2px; + font-size: 12px; + font-weight: 400; + line-height: 1; } -.dash-page .dashboard-keys-card .key-display .btn-secondary, -.dash-page .dashboard-keys-card .key-display .btn-danger { +.dash-page .dashboard-key-public { + display: inline-block; + max-width: 100%; + color: #faf8f5; + font-family: var(--font-mono); + font-size: 13px; + line-height: 1.45; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: middle; + white-space: nowrap; +} + +.dash-page .dashboard-key-created { + color: #b8bbbe !important; + white-space: nowrap; +} + +.dash-page .dashboard-key-row-actions { + text-align: right; +} + +.dash-page .dashboard-key-actions { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 8px; +} + +.dash-page .dashboard-key-row-actions .btn-secondary, +.dash-page .dashboard-key-row-actions .btn-danger { + width: 34px; + min-width: 34px; + height: 34px; + min-height: 34px; + padding: 0; + border-radius: 10px; + font-size: 13px; + line-height: 1; + letter-spacing: 0; + text-transform: none; + box-shadow: none; +} + +.dash-page .dashboard-key-row-actions .dashboard-key-icon-action { + display: inline-flex; + align-items: center; + justify-content: center; +} + +.dash-page .dashboard-key-row-actions .btn-secondary.dashboard-key-icon-action { + border-color: #faf8f5; + background: #faf8f5; + color: #000000; +} + +.dash-page .dashboard-key-row-actions .btn-secondary.dashboard-key-icon-action:hover:not(:disabled) { + border-color: #e8ff75; + background: #e8ff75; + color: #000000; +} + +.dash-page .dashboard-key-row-actions .btn-danger.dashboard-key-icon-action { + border-color: #ff6b6b; + background: #ff6b6b; + color: #ffffff; +} + +.dash-page .dashboard-key-row-actions .btn-danger.dashboard-key-icon-action:hover:not(:disabled) { + border-color: #ff8f8f; + background: #ff8f8f; + color: #ffffff; +} + +.dash-page .dashboard-key-row-actions .dashboard-key-icon-action--copied { + border-color: #e8ff75; + background: #e8ff75; + color: #000000; +} + +.dash-page .dashboard-key-row-actions .btn-secondary svg, +.dash-page .dashboard-key-row-actions .btn-danger svg { + display: block; +} + +.dash-page .dashboard-key-selection-bar { + display: flex; + align-items: center; + justify-content: flex-end; + flex-wrap: wrap; + gap: 12px 14px; + min-height: 38px; + margin-bottom: 18px; + padding: 0; + border: 0; + border-radius: 0; + background: transparent; +} + +.dash-page .dashboard-key-checkbox { + position: relative; + display: inline-flex; + align-items: center; + gap: 10px; + color: #faf8f5; + font-family: var(--font-sans); + font-size: 14px; + font-weight: 500; + line-height: 1; + cursor: pointer; + user-select: none; +} + +.dash-page .dashboard-key-checkbox { + width: 24px; + height: 24px; + gap: 0; + align-self: center; +} + +.dash-page .dashboard-key-checkbox input { + position: absolute; + width: 1px; + height: 1px; + opacity: 0; + pointer-events: none; +} + +.dash-page .dashboard-key-checkbox-box { + display: inline-flex; + align-items: center; + justify-content: center; + width: 22px; + height: 22px; + flex: 0 0 22px; + border: 1px solid rgba(250, 248, 245, 0.72); + border-radius: 6px; + background: rgba(5, 5, 5, 0.5); + transition: background 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease; +} + +.dash-page .dashboard-key-checkbox input:checked + .dashboard-key-checkbox-box { + border-color: #faf8f5; + background: #faf8f5; +} + +.dash-page .dashboard-key-checkbox input:checked + .dashboard-key-checkbox-box::after { + content: ""; + width: 7px; + height: 11px; + margin-top: -2px; + border: solid #000000; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.dash-page .dashboard-key-checkbox input:focus-visible + .dashboard-key-checkbox-box { + box-shadow: 0 0 0 3px rgba(250, 248, 245, 0.16); +} + +.dash-page .dashboard-key-checkbox input:disabled + .dashboard-key-checkbox-box { + opacity: 0.48; + cursor: not-allowed; +} + +.dash-page .dashboard-key-selection-status { + display: inline-flex; + align-items: center; min-height: 36px; - padding: 8px 14px; + margin-left: 0; + color: #b8bbbe; + font-size: 14px; + line-height: 1; +} + +.dash-page .dashboard-key-bulk-actions { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 10px; +} + +.dash-page .dashboard-key-clear-selection, +.dash-page .dashboard-key-remove-selected { + height: 36px; + min-height: 36px; + padding: 0 14px; border-radius: 18px; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 13px; + line-height: 1; + letter-spacing: 0; + text-transform: none; + box-shadow: none; +} + +.dash-page .dashboard-key-clear-selection { + min-width: 64px; +} + +.dash-page .dashboard-key-remove-selected { + min-width: 142px; +} + +.dash-page .dashboard-key-remove-selected svg { + display: block; +} + +.dash-page .dashboard-keys-card .key-display { + display: flex; + flex-direction: column; + gap: 14px; + padding: 24px 28px; + border-radius: 24px; + border-color: #54575a; + background: rgba(255, 255, 255, 0.08); +} + +.dash-page .dashboard-keys-card .dashboard-key-skeleton { + pointer-events: none; +} + +.dash-page .dashboard-key-skeleton-line { + display: inline-block; + border-radius: 999px; + background: rgba(250, 248, 245, 0.14); + animation: dashboardSkeletonPulse 1.2s ease-in-out infinite; +} + +.dash-page .dashboard-key-skeleton-line--check { + width: 22px; + height: 22px; + border-radius: 6px; +} + +.dash-page .dashboard-key-skeleton-line--label { + width: min(170px, 80%); + height: 18px; +} + +.dash-page .dashboard-key-skeleton-line--value { + width: min(210px, 90%); + height: 16px; +} + +.dash-page .dashboard-key-skeleton-line--date { + width: 76px; + height: 16px; +} + +.dash-page .dashboard-key-skeleton-line--actions { + width: 76px; + height: 34px; + margin-top: 2px; +} + +.dash-page .dashboard-credentials-card { + padding: 39px 40px; +} + +.dash-page .dashboard-credentials-card .card-header { + margin-bottom: 34px; +} + +.dash-page .dashboard-credentials-card .card-title { + color: #faf8f5; + font-family: var(--font-sans); + font-size: 36px; + font-weight: 500; + line-height: 0.88; + letter-spacing: 0; +} + +.dash-page .dashboard-credentials-card .card-subtitle { + margin-top: 14px; + color: #b8bbbe; + font-family: var(--font-sans); + font-size: 18px; + font-weight: 400; + line-height: 1.3; +} + +.dash-page .dashboard-credentials-alert { + margin-bottom: 18px; + min-height: 56px; + display: flex; + align-items: center; + gap: 14px; + padding: 16px 22px; + border: 0; + border-radius: 4px; + background: #e8ff75; + color: #000000; +} + +.dash-page .dashboard-credentials-alert-icon { + flex: 0 0 auto; + color: #000000; +} + +.dash-page .dashboard-credentials-alert p { + display: flex; + flex-wrap: wrap; + gap: 6px 14px; + margin: 0; + color: #000000; + font-size: 16px; + font-weight: 500; + line-height: 1.4; +} + +.dash-page .dashboard-credentials-alert p + p { + margin-top: 8px; + color: #000000; +} + +.dash-page .dashboard-credentials-alert strong { + color: #000000; + font-weight: 700; +} + +.dash-page .dashboard-credentials-alert code { + padding: 2px 6px; + border-radius: 6px; + background: rgba(0, 0, 0, 0.08); + color: #000000; + font-family: var(--font-mono); + font-size: 0.95em; +} + +/* /keys (WALM-675) — same look as .dashboard-credentials-alert above, but + unscoped: this banner renders outside Dashboard's own .dash-page root + (KeysPage wraps it, not Dashboard), and that class's min-height: 100vh + would otherwise double the page height if reused here. */ +.keys-mismatch-alert { + margin: 24px 24px 0; + min-height: 56px; + display: flex; + align-items: center; + gap: 14px; + padding: 16px 22px; + border: 0; + border-radius: 4px; + background: #e8ff75; + color: #000000; +} + +.keys-mismatch-alert-icon { + flex: 0 0 auto; + color: #000000; +} + +.keys-mismatch-alert p { + display: flex; + flex-wrap: wrap; + gap: 6px 14px; + margin: 0; + color: #000000; + font-size: 16px; + font-weight: 500; + line-height: 1.4; +} + +.keys-mismatch-alert p + p { + margin-top: 8px; + color: #000000; +} + +.keys-mismatch-alert strong { + color: #000000; + font-weight: 700; +} + +.keys-mismatch-alert code { + padding: 2px 6px; + border-radius: 6px; + background: rgba(0, 0, 0, 0.08); + color: #000000; + font-family: var(--font-mono); + font-size: 0.95em; +} + +.keys-mismatch-alert-signout { + display: inline; + padding: 0; + border: none; + background: none; + font: inherit; + color: #000000; + cursor: pointer; + text-decoration-line: underline; + text-decoration-thickness: from-font; + text-underline-position: from-font; +} + +.keys-mismatch-alert-signout:hover { + opacity: 0.7; +} + +.dash-page .dashboard-credentials-panel { + overflow: hidden; + border: 1px solid #54575a; + border-radius: 24px; + background: #000000; +} + +.dash-page .dashboard-credential-row { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 18px; + align-items: center; + padding: 18px 22px; + border-bottom: 1px solid rgba(250, 248, 245, 0.1); +} + +.dash-page .dashboard-credential-row:last-child { + border-bottom: 0; +} + +.dash-page .dashboard-credential-label { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; + color: #b8bbbe; + font-size: 14px; + font-weight: 500; + line-height: 1.25; + letter-spacing: 0; + text-transform: none; +} + +.dash-page .dashboard-credential-label span { + color: #8f9294; + font-family: var(--font-mono); + font-size: 13px; + font-weight: 400; +} + +.dash-page .dashboard-credential-value { + display: block; + margin-top: 10px; + color: #faf8f5; + font-family: var(--font-mono); + font-size: 14px; + line-height: 1.45; + overflow-wrap: anywhere; +} + +.dash-page .dashboard-credential-actions { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 8px; +} + +.dash-page .dashboard-credential-icon-button { + width: 34px; + height: 34px; + display: inline-flex; + align-items: center; + justify-content: center; + border: 1px solid rgba(250, 248, 245, 0.12); + border-radius: 12px; + background: rgba(255, 255, 255, 0.08); + color: #faf8f5; + cursor: pointer; + transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease, translate 0.16s var(--copy-status-ease); +} + +.dash-page .dashboard-credential-icon-button:hover:not(:disabled) { + border-color: rgba(250, 248, 245, 0.24); + background: rgba(255, 255, 255, 0.14); +} + +.dash-page .dashboard-credential-icon-button--copied { + border-color: #e8ff75; + background: #e8ff75; + color: #000000; +} + +@keyframes dashboardSkeletonPulse { + 0%, + 100% { + opacity: 0.5; + } + + 50% { + opacity: 1; + } +} + +@media (prefers-reduced-motion: reduce) { + .dash-page .dashboard-key-skeleton-line { + animation: none; + } +} + +.dash-page .dashboard-keys-card .dashboard-key-item { + transition: border-color 0.14s ease, background 0.14s ease, box-shadow 0.14s ease; +} + +.dash-page .dashboard-keys-card .dashboard-key-item--selected { + border-color: #e8ff75; + background: rgba(232, 255, 117, 0.08); + box-shadow: inset 0 0 0 1px rgba(232, 255, 117, 0.32); +} + +.dash-page .dashboard-key-item-header { + display: grid; + grid-template-columns: 24px minmax(0, 1fr); + align-items: center; + gap: 12px; +} + +.dash-page .dashboard-key-item-header .key-label { + min-width: 0; + margin-bottom: 0; + overflow-wrap: anywhere; +} + +.dash-page .dashboard-key-item-header .key-label span { + margin-left: 8px; + font-weight: 400; +} + +.dash-page .dashboard-keys-card .key-display .key-label { + color: #e8ff75; + font-size: 15px; + font-weight: 600; + line-height: 1.2; + letter-spacing: 0; + text-transform: none; +} + +.dash-page .dashboard-keys-card .key-display .key-label span { + color: #e8ff75; + opacity: 0.9; +} + +.dash-page .dashboard-keys-card .key-display .key-value { + color: #faf8f5; + font-size: 14px; + line-height: 1.45; + letter-spacing: 0; +} + +.dash-page .dashboard-keys-card .key-display .key-actions { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-top: 2px; +} + +.dash-page .dashboard-keys-card .key-display .btn-secondary, +.dash-page .dashboard-keys-card .key-display .btn-danger { + min-height: 36px; + padding: 8px 14px; + border-radius: 18px; + font-size: 13px; + line-height: 1; + letter-spacing: 0; + text-transform: none; +} + +.dash-page .dashboard-keys-card .key-display .btn-danger { + min-width: 88px; +} + +.dash-page .dashboard-keys-card .key-display .btn-secondary svg, +.dash-page .dashboard-keys-card .key-display .btn-danger svg { + display: block; +} + +@media (max-width: 860px) { + .dash-page .dashboard-credentials-card { + padding: 28px 24px; + } + + .dash-page .dashboard-credentials-card .card-header { + margin-bottom: 22px; + } + + .dash-page .dashboard-credentials-alert p { + display: block; + } + + .dash-page .dashboard-credentials-alert p span { + display: block; + margin-top: 6px; + } + + .dash-page .dashboard-credential-row { + grid-template-columns: 1fr; + gap: 14px; + padding: 16px; + } + + .dash-page .dashboard-credential-actions { + justify-content: flex-start; + } + + .dash-page .dashboard-key-table-wrap { + overflow: visible; + border: 0; + border-radius: 0; + background: transparent; + } + + .dash-page .dashboard-key-table, + .dash-page .dashboard-key-table thead, + .dash-page .dashboard-key-table tbody, + .dash-page .dashboard-key-table tr, + .dash-page .dashboard-key-table td { + display: block; + width: 100%; + } + + .dash-page .dashboard-key-table thead { + display: none; + } + + .dash-page .dashboard-key-table tr { + margin-bottom: 14px; + padding: 16px; + border: 1px solid #54575a; + border-radius: 18px; + background: rgba(255, 255, 255, 0.08); + } + + .dash-page .dashboard-key-table tbody tr:last-child { + margin-bottom: 0; + } + + .dash-page .dashboard-pagination { + align-items: stretch; + justify-content: flex-start; + } + + .dash-page .dashboard-pagination-end { + justify-content: space-between; + width: 100%; + } + + .dash-page .dashboard-key-table td { + display: grid; + grid-template-columns: 92px minmax(0, 1fr); + gap: 12px; + align-items: start; + padding: 8px 0; + border-bottom: 0; + } + + .dash-page .dashboard-key-table td::before { + content: attr(data-label); + color: #8f9294; + font-size: 13px; + line-height: 1.35; + } + + .dash-page .dashboard-key-list--skeleton .dashboard-key-table td { + grid-template-columns: 1fr; + } + + .dash-page .dashboard-key-list--skeleton .dashboard-key-table td::before { + display: none; + } + + .dash-page .dashboard-key-cell-select { + align-items: center !important; + } + + .dash-page .dashboard-key-row-actions { + text-align: left; + } + + .dash-page .dashboard-key-actions { + justify-content: flex-start; + } + + .dash-page .dashboard-key-row-actions .btn-secondary, + .dash-page .dashboard-key-row-actions .btn-danger { + flex: 0 0 34px; + } + + .dash-page .dashboard-key-selection-bar { + align-items: stretch; + flex-direction: column; + } + + .dash-page .dashboard-key-selection-status { + margin-left: 0; + } + + .dash-page .dashboard-key-bulk-actions { + width: 100%; + } + + .dash-page .dashboard-key-clear-selection, + .dash-page .dashboard-key-remove-selected { + flex: 1 1 0; + } +} + +.dash-page .dashboard-quickstart-card pre, +.dash-page .dashboard-quickstart-card .demo-code-block { + overflow-x: clip; + white-space: pre-wrap; + word-break: break-word; +} + +.dash-page .dashboard-quickstart-card pre code, +.dash-page .dashboard-quickstart-card .demo-code-block code, +.dash-page .dashboard-quickstart-card .demo-code-block span { + white-space: pre-wrap !important; + word-break: break-word; +} + +.dash-page .dashboard-install-card { + padding: 39px 40px; +} + +.dash-page .dashboard-install-card .card-header { + margin-bottom: 34px; +} + +.dash-page .dashboard-install-card .card-subtitle { + margin-top: 14px; + color: #b8bbbe; + font-size: 18px; + font-weight: 400; + line-height: 1.3; +} + +.dash-page .dashboard-install-card .install-tabs { + margin-bottom: 28px; +} + +.dash-page .dashboard-install-card .install-tab, +.dash-page .dashboard-install-card .install-tab:last-child { + line-height: 1; +} + +.dash-page .dashboard-install-card .dashboard-install-codewrap { + gap: 10px; +} + +.dash-page .dashboard-install-card .dashboard-install-codewrap .install-command { + padding: 0 !important; + overflow-x: clip; + white-space: normal; + overflow-wrap: anywhere; +} + +.dash-page .dashboard-install-card .dashboard-install-copy { + width: 24px; + height: 24px; + flex: 0 0 24px; + border-radius: 8px; + background: rgba(255, 255, 255, 0.08); + color: #faf8f5; +} + +.dash-page .dashboard-install-card .dashboard-install-copy svg { + width: 12px; + height: 12px; +} + +.dash-page .dashboard-install-card .dashboard-install-copy:hover:not(:disabled) { + background: rgba(255, 255, 255, 0.14); + color: #faf8f5; +} + +/* ── Figma 2325-6980: even, generous block spacing. The CTA row was only ~20px + below; align it with the 56px card gaps so the whole stack breathes like the + design (Figma's literal 36px sits between much taller cards). ── */ +.dash-page .dashboard-cta-row { + gap: 30px; + margin-bottom: 56px; +} + +.dash-page .dashboard-cta-row--primary { + margin-bottom: 30px; +} + +.dash-page .dashboard-section-head { + order: 2; + margin-bottom: 16px; +} + +.dash-page .dashboard-section-head h3 { + margin: 0 0 4px; + font-size: 1.15rem; + font-weight: 600; + color: #faf8f5; + letter-spacing: 0; +} + +.dash-page .dashboard-section-head p { + margin: 0; + font-size: 0.9rem; + color: #8f9294; +} + +.dash-page .dashboard-cta-row--resources { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +/* One consistent card style across Dashboard + Playground: match the CTA cards + (12px radius, subtle border + translucent bg) so content/step cards stop + looking like a different component. */ +.dash-page .card, +.playground-dashboard .card { + border-radius: 12px !important; + border: 1px solid rgba(250, 248, 245, 0.1) !important; + background: rgba(255, 255, 255, 0.08) !important; +} + +/* Mobile: stack the Resources cards instead of cramming 3 columns. Placed after + the --resources rule so it wins inside the breakpoint. */ +@media (max-width: 860px) { + .dash-page .dashboard-cta-row--resources { + grid-template-columns: 1fr; + } +} + +/* Dashboard CTA cards: final pass against the two-card design comp. This lives + after the duplicated dashboard rules so the CTA spacing stays deterministic. */ +.dash-page .dashboard-cta-row { + gap: 28px; + margin-bottom: 56px; +} + +.dash-page .dashboard-cta-row--primary { + grid-template-columns: 1fr; + margin-top: 24px; + margin-bottom: 30px; +} + +.dash-page .dashboard-cta-row--resources { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.dash-page .dashboard-cta-row > :only-child { + grid-column: 1 / -1; +} + +.dash-page .dashboard-cta { + grid-template-columns: 36px minmax(0, 1fr) 21px; + min-height: 104px; + height: auto; + gap: 22px; + padding: 26px 27px; + border-radius: 22px; +} + +.dash-page .dashboard-cta-icon-wrap { + width: 36px; + height: 40px; +} + +.dash-page .dashboard-cta-icon { + width: 36px; + height: 40px; +} + +.dash-page .dashboard-cta-title { + line-height: 1.18; +} + +.dash-page .dashboard-cta-subtitle { + margin-top: 8px; + line-height: 1.2; +} + +.dash-page .dashboard-cta-arrow { + width: 21px; + height: 21px; + margin-top: 0; +} + +@media (max-width: 860px) { + .dash-page .dashboard-cta-row, + .dash-page .dashboard-cta-row--primary, + .dash-page .dashboard-cta-row--resources { + grid-template-columns: 1fr; + gap: 14px; + } + + .dash-page .dashboard-cta-row { + margin-bottom: 24px; + } + + .dash-page .dashboard-cta-row--primary { + margin-top: 18px; + margin-bottom: 24px; + } + + .dash-page .dashboard-cta { + grid-template-columns: 30px minmax(0, 1fr) 18px; + min-height: 92px; + gap: 16px; + padding: 21px 22px; + border-radius: 18px; + } + + .dash-page .dashboard-cta-icon-wrap, + .dash-page .dashboard-cta-icon { + width: 30px; + height: 34px; + } + + .dash-page .dashboard-cta-subtitle { + margin-top: 5px; + } +} + +/* Dashboard major-section rhythm. Keep large cards on one shared vertical gap + instead of mixing JSX inline margins with older dashboard density rules. */ +.dash-page { + --dashboard-major-gap: 56px; + --dashboard-related-gap: 30px; + --dashboard-mobile-major-gap: 24px; +} + +.dash-page .dashboard-cta-row--primary { + margin-bottom: var(--dashboard-related-gap); +} + +.dash-page .dashboard-section-head { + margin-bottom: 16px; +} + +.dash-page .dashboard-cta-row--resources, +.dash-page .dashboard-credentials-card, +.dash-page .dashboard-keys-card, +.dash-page .dashboard-quickstart-card { + margin-bottom: var(--dashboard-major-gap) !important; +} + +.dash-page .dashboard-install-card { + margin-bottom: 0 !important; +} + +@media (max-width: 860px) { + .dash-page .dashboard-cta-row--primary, + .dash-page .dashboard-cta-row--resources, + .dash-page .dashboard-credentials-card, + .dash-page .dashboard-keys-card, + .dash-page .dashboard-quickstart-card { + margin-bottom: var(--dashboard-mobile-major-gap) !important; + } +} + +/* ── Alert: icon + text as one centered flex row (replaces the + absolutely-positioned icon, which left an 8px gap and felt off-center). ── */ +.dash-page .dash-alert { + display: flex; + align-items: center; + gap: 14px; + padding: 16px 22px; + min-height: 56px; +} + +.dash-page .dash-alert .dash-alert-icon { + position: relative; + left: auto; + top: auto; + transform: none; + flex: 0 0 auto; + width: 24px; + height: 24px; + color: #000000; + background: transparent; + clip-path: none; + display: block; +} + +.dash-page .dash-alert .dash-alert-icon::before, +.dash-page .dash-alert .dash-alert-icon::after { + content: none; +} + +.dash-page .dash-alert p { + font-size: 16px; + line-height: 1.4; +} + +/* Dashboard heading subtitles: keep these at the same scale as card subtitles. */ +.dash-page .dashboard-header p, +.dash-page .dashboard-section-head p { + color: #b8bbbe; + font-size: 18px; + font-weight: 400; + line-height: 1.3; +} + +.dash-page .dashboard-header, +.dash-page .dash-alert, +.dash-page .dashboard-cta-row--primary, +.dash-page .dashboard-section-head, +.dash-page .dashboard-cta-row--resources, +.dash-page .dashboard-credentials-card, +.dash-page .dashboard-keys-card, +.dash-page .dashboard-quickstart-card, +.dash-page .dashboard-install-card { + animation: dashboardReveal 420ms cubic-bezier(0.16, 1, 0.3, 1) both; +} + +.dash-page .dashboard-header { + animation-delay: 20ms; +} + +.dash-page .dash-alert { + animation-delay: 55ms; +} + +.dash-page .dashboard-cta-row--primary { + animation-delay: 90ms; +} + +.dash-page .dashboard-section-head { + animation-delay: 125ms; +} + +.dash-page .dashboard-cta-row--resources { + animation-delay: 160ms; +} + +.dash-page .dashboard-credentials-card { + animation-delay: 195ms; +} + +.dash-page .dashboard-keys-card { + animation-delay: 230ms; +} + +.dash-page .dashboard-quickstart-card { + animation-delay: 265ms; +} + +.dash-page .dashboard-install-card { + animation-delay: 300ms; +} + +.dash-page .dashboard-cta-row--primary { + animation: none !important; + opacity: 1; + filter: none; + transform: none; +} + +@keyframes dashboardReveal { + from { + opacity: 0; + filter: blur(5px); + transform: translate3d(0, 10px, 0) scale(0.992); + } + + to { + opacity: 1; + filter: blur(0); + transform: translate3d(0, 0, 0) scale(1); + } +} + +.dashboard-nav .lp-nav-cta { + line-height: 1; +} + +.dashboard-nav .lp-nav-cta svg { + display: block; + margin-top: 1px; +} + +.dash-page .dashboard-confirm-backdrop { + position: fixed; + inset: 0; + z-index: 2000; + display: grid; + place-items: center; + padding: 24px; + background: rgba(0, 0, 0, 0.68); + backdrop-filter: blur(14px); + animation: dashboardConfirmBackdropIn 140ms ease both; +} + +.dash-page .dashboard-confirm-dialog { + width: min(480px, 100%); + padding: 28px 28px 24px; + display: grid; + grid-template-columns: minmax(0, 1fr); + gap: 22px; + border: 1px solid #262b30; + border-radius: 6px; + background: #000000; + color: #faf8f5; + box-shadow: none; + animation: dashboardConfirmDialogIn 280ms cubic-bezier(0.16, 1, 0.3, 1) both; +} + +.dash-page .dashboard-confirm-copy h3 { + margin: 0; + color: #faf8f5; + font-family: Ratch, sans-serif; + font-size: 32px; + font-weight: 400; + line-height: 0.95; + letter-spacing: 0; +} + +.dash-page .dashboard-confirm-copy p { + margin: 14px 0 0; + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 16px; + font-weight: 400; + line-height: 1.5; +} + +.dash-page .dashboard-confirm-actions { + display: flex; + justify-content: flex-end; + gap: 12px; +} + +.dash-page .dashboard-confirm-actions .btn, +.dash-page .dashboard-confirm-cancel, +.dash-page .dashboard-confirm-remove { + min-height: 44px; + padding: 0 18px; + border: 1px solid #54575a; + border-radius: 26px; + background: transparent; + color: #faf8f5; + font-family: "Google Sans Code", var(--font-mono); + font-size: 14px; + font-weight: 400; + line-height: 1; + letter-spacing: 0.5px; + text-transform: uppercase; + box-shadow: none; +} + +.dash-page .dashboard-confirm-actions .btn:hover:not(:disabled), +.dash-page .dashboard-confirm-cancel:hover:not(:disabled) { + border-color: #faf8f5; + background: #faf8f5; + color: #000000; +} + +.dash-page .dashboard-confirm-actions .btn-danger, +.dash-page .dashboard-confirm-remove { + border-color: #ff9aa0; + background: transparent; + color: #ff9aa0; +} + +.dash-page .dashboard-confirm-actions .btn-danger:hover:not(:disabled), +.dash-page .dashboard-confirm-remove:hover:not(:disabled) { + border-color: #ff9aa0; + background: #ff9aa0; + color: #000000; +} + +.dash-page .dashboard-confirm-remove:disabled, +.dash-page .dashboard-confirm-actions .btn:disabled { + color: #8f9294; +} + +.dash-page .sd-preview-content { + margin-top: 16px; + padding: 16px 18px; + border: 1px solid #262b30; + border-radius: 6px; + background: #000000; + color: #faf8f5; + font-family: "Google Sans Code", var(--font-mono); + font-size: 14px; + font-weight: 300; + line-height: 1.5; +} + +.dash-page .dashboard-account-ready-dialog { + display: flex; + width: min(560px, 100%); + flex-direction: column; + align-items: flex-start; + flex-shrink: 0; + padding: 0; + gap: 0; +} + +.dash-page .dashboard-account-ready-body { + display: flex; + padding: 24px 24px 16px; + flex-direction: column; + align-items: flex-start; + gap: 10px; + align-self: stretch; +} + +.dash-page .dashboard-account-ready-body h3, +.dash-page .dashboard-account-ready-body p { + margin: 0; +} + +.dash-page .dashboard-account-ready-actions { + padding: 16px 24px; + gap: 12px; + align-self: stretch; + border-top: 1px solid rgba(250, 248, 245, 0.1); +} + +.dash-page .dashboard-account-ready-console { + min-height: 48px; + min-width: 152px; + padding: 0 22px; + border-radius: 24px; + font-size: 16px; + font-weight: 500; + line-height: 1; + letter-spacing: 0; + display: inline-flex; + align-items: center; + justify-content: center; + text-decoration: none; +} + +@media (max-width: 860px) { + .dash-page .dashboard-account-ready-actions { + flex-direction: column-reverse; + } + + .dash-page .dashboard-account-ready-console { + width: 100%; + } +} + +@keyframes dashboardConfirmBackdropIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes dashboardConfirmDialogIn { + from { + opacity: 0; + filter: blur(6px); + transform: translate3d(0, 10px, 0) scale(0.98); + } + + to { + opacity: 1; + filter: blur(0); + transform: translate3d(0, 0, 0) scale(1); + } +} + +@media (max-width: 860px) { + .dash-page .dashboard-header p, + .dash-page .dashboard-section-head p { + font-size: 16px; + } + + .dash-page .dashboard-confirm-dialog { + gap: 20px; + padding: 22px; + } + + .dash-page .dashboard-confirm-copy h3 { + font-size: 28px; + } + + .dash-page .dashboard-confirm-copy p { + font-size: 16px; + } + + .dash-page .dashboard-confirm-actions { + flex-direction: column-reverse; + margin-top: 4px; + } + + .dash-page .dashboard-confirm-actions .btn, + .dash-page .dashboard-confirm-cancel, + .dash-page .dashboard-confirm-remove { + width: 100%; + } + + /* Re-assert the sectioned dialog's zero outer padding — it comes after + .dashboard-confirm-dialog's mobile padding above at equal specificity. */ + .dash-page .dashboard-account-ready-dialog { + gap: 0; + padding: 0; + } +} + +@media (prefers-reduced-motion: reduce) { + .wm-route-pending img, + .dash-page .dashboard-header, + .dash-page .dash-alert, + .dash-page .dashboard-cta-row--primary, + .dash-page .dashboard-section-head, + .dash-page .dashboard-cta-row--resources, + .dash-page .dashboard-credentials-card, + .dash-page .dashboard-keys-card, + .dash-page .dashboard-quickstart-card, + .dash-page .dashboard-install-card, + .dash-page .dashboard-add-key-form, + .dash-page .dashboard-add-key-field, + .dash-page .dashboard-add-key-note, + .dash-page .dashboard-add-key-actions, + .dash-page .dashboard-confirm-backdrop, + .dash-page .dashboard-confirm-dialog { + animation: none; + } +} + +/* ── Sign-in screen (Figma 2556:112) ───────────────────────── */ +.wm-signin { + position: fixed; + inset: 0; + z-index: 1000; + background: #050608; + overflow: hidden; + display: grid; + place-items: center; + font-family: var(--font-sans); +} + +.wm-signin--page { + position: relative; + inset: auto; + z-index: 0; + min-height: 100vh; + min-height: 100dvh; + overflow: clip; +} + +.wm-signin-backdrop { + position: absolute; + inset: 0; + z-index: 0; +} + +.wm-signin-aurora { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; + opacity: 1; + z-index: 0; + pointer-events: none; +} + +.wm-signin::after { + content: ""; + position: absolute; + inset: 0; + z-index: 1; + pointer-events: none; + background: linear-gradient( + 90deg, + rgba(5, 6, 8, 0) 0%, + rgba(5, 6, 8, 0) 42%, + rgba(5, 6, 8, 0.5) 62%, + rgba(5, 6, 8, 0.74) 82%, + rgba(5, 6, 8, 0.74) 100% + ); +} + +.wm-signin-close { + position: absolute; + top: 28px; + right: 28px; + z-index: 3; + width: 42px; + height: 42px; + display: grid; + place-items: center; + border: 1px solid rgba(250, 248, 245, 0.18); + border-radius: 50%; + background: rgba(255, 255, 255, 0.06); + color: #faf8f5; + cursor: pointer; +} + +.wm-signin-close svg { + transform: rotate(45deg); +} + +.wm-signin-inner { + position: relative; + z-index: 2; + width: min(1480px, calc(100% - 112px)); + display: grid; + grid-template-columns: minmax(520px, 640px) minmax(560px, 1fr); + align-items: center; + gap: clamp(64px, 5.2vw, 96px); +} + +.wm-signin-card { + width: clamp(520px, 33vw, 640px); + max-width: 100%; + aspect-ratio: 900 / 1010; + padding: clamp(52px, 5.3vh, 76px) 0 clamp(42px, 4.8vh, 62px); + border-radius: 18px; + border: 0; + background: + radial-gradient(82% 48% at 87% 2%, rgba(0, 91, 153, 0.78) 0%, rgba(0, 60, 112, 0.5) 35%, rgba(0, 17, 31, 0) 72%), + radial-gradient(78% 45% at 1% 16%, rgba(129, 120, 178, 0.44) 0%, rgba(43, 55, 90, 0.28) 44%, rgba(0, 12, 22, 0) 78%), + linear-gradient(180deg, rgba(12, 34, 61, 0.96) 0%, rgba(0, 64, 96, 0.8) 46%, rgba(0, 14, 22, 0.95) 74%, #01060a 100%); + backdrop-filter: blur(30px); + -webkit-backdrop-filter: blur(30px); + text-align: center; + box-shadow: none; +} + +.wm-signin-logo { + display: block; + width: min(330px, 46%); + max-width: none; + height: auto; + margin: 0 auto; +} + +.wm-signin-sub { + width: min(610px, 78%); + margin: clamp(28px, 3.7vh, 42px) auto clamp(42px, 5.4vh, 58px); + color: #faf8f5; + font-size: clamp(23px, 1.55vw, 34px); + font-weight: 400; + line-height: 1.34; +} + +.wm-page .wm-signin-google, +.wm-page .wm-signin-wallet button { + width: 100%; + min-height: clamp(62px, 6vh, 86px); + padding: 0 clamp(30px, 3.2vw, 48px); + border-radius: 999px; + border: 2px solid rgba(250, 248, 245, 0.94); + background: transparent; + color: #faf8f5; + font-family: var(--font-sans); + font-size: clamp(20px, 1.18vw, 26px); + font-weight: 500; + letter-spacing: 0; + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + cursor: pointer; + box-sizing: border-box; +} + +.wm-signin-google { + position: relative; + width: min(552px, 62%); + margin: 0 auto clamp(22px, 2.3vh, 28px); + border-color: #faf8f5; +} + +.wm-page .wm-signin-google { + width: min(552px, 62%); +} + +.wm-signin-google svg { + position: absolute; + left: clamp(30px, 10%, 48px); + flex: 0 0 auto; + width: clamp(27px, 1.65vw, 34px); + height: clamp(27px, 1.65vw, 34px); +} + +.wm-signin-google:hover { + background: rgba(255, 255, 255, 0.08); +} + +.wm-signin-wallet { + display: block; + width: min(552px, 62%); + margin: 0 auto; +} + +.wm-signin-wallet button { + background: transparent !important; + border: 2px solid rgba(250, 248, 245, 0.94) !important; + border-radius: 999px !important; + box-shadow: none !important; +} + +.wm-signin-wallet button, +.wm-signin-wallet button * { + color: #faf8f5 !important; +} + +.wm-signin-wallet button:hover { + background: rgba(255, 255, 255, 0.08) !important; +} + +.wm-signin-tos { + width: min(360px, 64%); + margin: clamp(38px, 5vh, 54px) auto 0; + color: #8f9294; + font-size: clamp(13px, 0.9vw, 18px); + font-weight: 400; + line-height: 1.34; +} + +.wm-signin-tos a { + color: #faf8f5; + text-decoration: underline; +} + +.wm-signin-trusted { + text-align: center; +} + +.wm-signin-trusted h2 { + margin: 0 0 44px; + color: #faf8f5; + font-size: 72px; + line-height: 0.9; + font-weight: 500; + letter-spacing: 0; + text-align: center; +} + +.wm-signin-trusted h2 span { + color: transparent; + background: linear-gradient(93deg, #383bff 0%, #9a57ff 48%, #eda0ff 98%); + -webkit-background-clip: text; + background-clip: text; +} + +.wm-signin-logos { + display: grid; + grid-template-columns: repeat(3, auto); + justify-content: center; + justify-items: center; + align-items: center; + gap: 36px 52px; +} + +.wm-signin-logos img { + height: auto; + max-width: 100%; + object-fit: contain; + opacity: 0.92; +} + +@media (max-width: 900px) { + .wm-signin-inner { + grid-template-columns: 1fr; + gap: 40px; + justify-items: center; + width: calc(100% - 40px); + } + + .wm-signin-card { + width: min(100%, 640px); + aspect-ratio: auto; + min-height: min(760px, calc(100vh - 72px)); + padding: 64px 0 50px; + } + + .wm-signin-logo { + width: min(330px, 58%); + } + + .wm-signin-sub { + width: min(520px, 82%); + font-size: clamp(25px, 6.2vw, 34px); + margin: 36px auto 58px; + } + + .wm-page .wm-signin-google, + .wm-page .wm-signin-wallet { + width: min(440px, 82%); + } + + .wm-signin-google, + .wm-signin-wallet button { + min-height: 72px; + font-size: clamp(22px, 5.4vw, 30px); + } + + .wm-signin-google svg { + position: static; + left: auto; + } + + .wm-signin-tos { + width: min(360px, 72%); + margin-top: 54px; + font-size: clamp(14px, 3.4vw, 20px); + } + + .wm-signin-trusted { + display: none; + } +} + +/* Setup flow: align the create-key screen with the dashboard visual system. */ +.setup-classic { + background: #000000; +} + +.setup-classic-container { + width: min(1100px, calc(100% - 64px)); + max-width: 1100px; + min-height: calc(100vh - 128px); + padding: 34px 0 68px; +} + +.setup-classic-panel { + width: min(560px, 100%); + margin: 0 auto; +} + +.setup-classic-title { + margin: 0 0 14px; + color: #faf8f5; + font-size: 36px; + font-weight: 500; + line-height: 0.98; + letter-spacing: 0; +} + +.setup-classic-description { + max-width: 560px; + margin: 0 auto 38px; + color: #b8bbbe; + font-size: 18px; + font-weight: 400; + line-height: 1.35; +} + +.setup-classic-feature-card { + margin-bottom: 34px !important; + padding: 30px; + border: 1px solid #54575a !important; + border-radius: 24px !important; + background: #000000 !important; + box-shadow: none !important; +} + +.setup-classic-feature { + margin-bottom: 26px; +} + +.setup-classic-feature strong { + color: #faf8f5; + font-size: 24px; + font-weight: 650; + line-height: 1.18; + letter-spacing: 0; +} + +.setup-classic-feature p { + margin: 8px 0 0; + color: #b8bbbe; + font-size: 18px; + font-weight: 400; + line-height: 1.3; + letter-spacing: 0; +} + +.setup-classic-generate { + width: 236px; + height: 52px; + min-height: 52px; + padding: 0 30px; + border-radius: 26px; + background: #faf8f5; + border-color: #faf8f5; + color: #000000; + font-size: 18px; + font-weight: 650; + line-height: 0.84; + letter-spacing: 0; +} + +.setup-classic-generate:hover:not(:disabled) { + background: #e8ff75; + border-color: #e8ff75; + color: #000000; + transform: none; +} + +.setup-classic-actions { + display: flex; + flex-direction: column; + align-items: center; + gap: 26px; +} + +.setup-classic-import-trigger { + padding: 0; + border: 0; + background: transparent; + color: #8f9294; + font: inherit; + font-size: 18px; + font-weight: 400; + line-height: 1.3; + letter-spacing: 0; + text-decoration: none; + cursor: pointer; + box-shadow: none; +} + +.setup-classic-import-trigger:hover:not(:disabled) { + color: #faf8f5; + background: transparent; + transform: none; + box-shadow: none; +} + +.setup-classic-import-screen { + text-align: center; +} + +.setup-classic-divider { + margin: 30px 0 22px; + color: #8f9294; + font-size: 18px; + font-weight: 400; + line-height: 1.3; +} + +.setup-classic .setup-import-textarea { + min-height: 112px; + padding: 20px; + border: 1px solid #54575a; + border-radius: 16px; + background: #000000; + color: #faf8f5; + font-size: 18px; + line-height: 1.4; +} + +.setup-classic .setup-import-textarea:focus { + border-color: #8f9294; + box-shadow: none; +} + +.setup-classic-import-actions { + display: block; + margin-top: 22px; +} + +.setup-classic .setup-import-button { + width: 100%; + height: 62px; + min-height: 62px; + margin-top: 22px; + padding: 0 30px; + border-radius: 31px; + background: #e8ff75; + border-color: #e8ff75; + color: #000000; + font-size: 18px; + font-weight: 650; + line-height: 0.84; + letter-spacing: 0; +} + +.setup-classic-import-actions .setup-import-button { + margin-top: 0; +} + +.setup-classic-back-button { + width: 132px; + height: 62px; + min-height: 62px; + border-radius: 31px; + border: 1px solid #faf8f5; + background: transparent; + color: #faf8f5; + font-size: 18px; + font-weight: 650; + line-height: 0.84; + box-shadow: none; +} + +.setup-classic-back-button:hover:not(:disabled) { + background: rgba(255, 255, 255, 0.08); + color: #faf8f5; + transform: none; + box-shadow: none; +} + +.setup-classic-error { + margin-top: 14px; + padding: 14px 16px; + border: 1px solid rgba(255, 107, 107, 0.35); + border-radius: 16px; + background: rgba(255, 107, 107, 0.1); + color: #ff8f8f; + font-size: 16px; + line-height: 1.35; +} + +.setup-classic-state { + min-height: 320px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 72px 0; + text-align: center; +} + +.setup-classic-spinner { + width: 44px; + height: 44px; + margin-bottom: 26px; + color: #faf8f5; + border-width: 4px; + opacity: 1; +} + +.setup-classic-state-title { + margin: 0 0 10px; + color: #faf8f5; + font-size: 24px; + font-weight: 500; + line-height: 1.25; +} + +.setup-classic-state-subtitle { + margin: 0; + color: #b8bbbe; + font-size: 18px; + font-weight: 400; + line-height: 1.35; +} + +.setup-classic-state-heading { + margin: 0 0 12px; + color: #faf8f5; + font-size: 36px; + font-weight: 500; + line-height: 0.98; +} + +.setup-classic-ready-screen { + text-align: left; +} + +.setup-classic-ready-screen .setup-classic-title { + margin-bottom: 34px; + text-align: center; +} + +.setup-classic-ready-warning { + min-height: 56px; + display: flex; + align-items: center; + gap: 14px; + margin-bottom: 24px; + padding: 16px 22px; + border: 0; + border-radius: 4px; + background: #e8ff75; +} + +.setup-classic .setup-classic-ready-warning { + border-radius: 4px; +} + +.setup-classic-ready-warning-icon { + flex: 0 0 auto; + color: #000000; +} + +.setup-classic-ready-warning p { + margin: 0; + color: #000000; + font-size: 16px; + font-weight: 500; + line-height: 1.4; +} + +.setup-classic-ready-warning strong { + color: #000000; + font-weight: 700; +} + +.setup-key-panel { + overflow: hidden; + margin-bottom: 24px; + border: 1px solid #54575a; + border-radius: 24px; + background: #000000; +} + +.setup-key-row { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 18px; + align-items: center; + padding: 22px 28px; + border-bottom: 1px solid rgba(250, 248, 245, 0.1); +} + +.setup-key-row:last-child { + border-bottom: 0; +} + +.setup-key-main { + min-width: 0; +} + +.setup-key-label { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; + color: #b8bbbe; + font-size: 16px; + font-weight: 500; + line-height: 1.25; +} + +.setup-key-label span { + color: #8f9294; + font-size: 14px; + font-weight: 400; +} + +.setup-key-value { + display: block; + margin-top: 12px; + color: #faf8f5; + font-family: var(--font-mono); + font-size: 15px; + font-weight: 400; + line-height: 1.45; + overflow-wrap: anywhere; +} + +.setup-key-actions { + display: flex; + justify-content: flex-end; +} + +.setup-key-copy-button { + width: 40px; + height: 40px; + min-height: 40px; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0; + border: 1px solid rgba(250, 248, 245, 0.12); + border-radius: 14px; + background: rgba(255, 255, 255, 0.08); + color: #faf8f5; + cursor: pointer; + box-shadow: none; +} + +.setup-key-copy-button:hover:not(:disabled) { + border-color: rgba(250, 248, 245, 0.24); + background: rgba(255, 255, 255, 0.14); + color: #faf8f5; +} + +.setup-key-copy-button--copied { + border-color: #e8ff75; + background: #e8ff75; + color: #000000; +} + +.setup-classic-ready-error { + margin-bottom: 20px; +} + +.setup-classic-error-action { + display: inline-flex; + margin-top: 12px; + color: #faf8f5; + text-decoration: none; +} + +.setup-classic-confirm { + position: relative; + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 26px; + color: #faf8f5; + font-size: 16px; + font-weight: 400; + line-height: 1.3; + cursor: pointer; +} + +.setup-classic-confirm input { + position: absolute; + opacity: 0; + pointer-events: none; +} + +.setup-classic-confirm-box { + width: 22px; + height: 22px; + flex: 0 0 auto; + margin-top: 0; + transform: translateY(-1px); + border: 1px solid #54575a; + border-radius: 6px; + background: #000000; + transition: background 0.14s ease, border-color 0.14s ease; +} + +.setup-classic-confirm-box::after { + content: ""; + display: block; + width: 7px; + height: 11px; + margin: 3px auto 0; + border: solid #000000; + border-width: 0 2px 2px 0; + opacity: 0; + transform: rotate(45deg); +} + +.setup-classic-confirm input:checked + .setup-classic-confirm-box { + border-color: #e8ff75; + background: #e8ff75; +} + +.setup-classic-confirm input:checked + .setup-classic-confirm-box::after { + opacity: 1; +} + +.setup-classic-confirm input:focus-visible + .setup-classic-confirm-box { + outline: 2px solid #e8ff75; + outline-offset: 3px; +} + +.setup-classic-confirm-text { + min-width: 0; + display: block; +} + +.setup-classic-register { + width: 100%; + height: 62px; + min-height: 62px; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0 30px; + border: 1px solid #e8ff75; + border-radius: 31px; + background: #e8ff75; + color: #000000; + font-family: var(--font-sans); + font-size: 18px; + font-weight: 650; + line-height: 0.84; + letter-spacing: 0; + cursor: pointer; + box-shadow: none !important; + transform: none !important; + transition: none !important; + animation: none !important; +} + +.setup-classic-register:hover, +.setup-classic-register:hover:not(:disabled), +.setup-classic-register:active, +.setup-classic-register:active:not(:disabled) { + background: #e8ff75; + border-color: #e8ff75; + color: #000000; + transform: none !important; + box-shadow: none !important; +} + +.setup-classic-register:focus, +.setup-classic-register:focus-visible { + outline: none; + transform: none !important; + box-shadow: none !important; +} + +.setup-classic-register:disabled { + border-color: rgba(232, 255, 117, 0.18); + background: rgba(232, 255, 117, 0.22); + color: rgba(0, 0, 0, 0.42); + cursor: not-allowed; + transform: none; + box-shadow: none; +} + +.setup-classic-register:disabled:hover { + border-color: rgba(232, 255, 117, 0.18); + background: rgba(232, 255, 117, 0.22); + color: rgba(0, 0, 0, 0.42); + transform: none; + box-shadow: none; +} + +.setup-classic .setup-import-button:hover:not(:disabled) { + background: #e8ff75; + border-color: #e8ff75; + color: #000000; + transform: none; +} + +@media (max-width: 860px) { + .setup-classic-nav .nav-brand-logo, + .dashboard-nav .nav-brand-logo { + height: 44px; + } + + .setup-classic-container { + width: calc(100% - 32px); + min-height: calc(100vh - 92px); + padding: 32px 0 56px; + } + + .setup-classic-panel { + width: 100%; + } + + .setup-classic-title { + font-size: 30px; + } + + .setup-classic-description, + .setup-classic-feature p, + .setup-classic-divider { + font-size: 16px; + } + + .setup-classic-feature-card { + padding: 24px; + border-radius: 20px !important; + } + + .setup-classic-feature strong { + font-size: 22px; + } + + .setup-key-row { + grid-template-columns: 1fr; + padding: 20px; + } + + .setup-key-actions { + justify-content: flex-start; + } + + .setup-classic-generate { + width: 100%; + } + + .setup-classic-import-actions { + flex-direction: column-reverse; + gap: 12px; + } + + .setup-classic-back-button, + .setup-classic-import-actions .setup-import-button { + width: 100%; + } +} + +/* Playground final override. This is intentionally last because the file still + contains older duplicated dashboard/playground passes above. */ +.playground-nav .nav-brand-logo { + display: block; + height: 56px; + width: auto; +} + +.playground-nav .demo-nav-back { + min-height: 28px; + display: inline-flex; + align-items: center; + gap: 8px; + color: #b8bbbe; + font-size: 16px; + font-weight: 500; + letter-spacing: 0.2px; + text-decoration: none; +} + +.playground-nav .demo-nav-icon { + display: none; + flex: 0 0 auto; + stroke-width: 1.8; +} + +.playground-nav .demo-nav-back:hover { + color: #faf8f5; +} + +.playground-dashboard { + width: min(1100px, calc(100% - 64px)) !important; + max-width: 1100px !important; + padding: 34px 0 68px !important; +} + +.playground-dashboard .dashboard-header { + max-width: 880px; + margin-bottom: 28px !important; + animation: dashboardReveal 360ms cubic-bezier(0.16, 1, 0.3, 1) both; +} + +.playground-dashboard .dashboard-header h2 { + margin: 0 0 14px; + color: #faf8f5; + font-family: var(--font-sans); + font-size: 56px !important; + font-weight: 500; + line-height: 0.88; + letter-spacing: 0; +} + +.playground-dashboard .dashboard-header p { + max-width: 860px; + margin: 0; + color: #b8bbbe; + font-size: 18px !important; + font-weight: 400; + line-height: 1.35; +} + +.playground-dashboard .dashboard-header code, +.playground-dashboard .demo-doc-link { + color: #e8ff75; + font-weight: 500; +} + +.playground-dashboard .demo-server-info { + display: flex !important; + flex-wrap: wrap; + gap: 12px; + margin-bottom: 42px; + animation: dashboardReveal 360ms cubic-bezier(0.16, 1, 0.3, 1) 45ms both; +} + +.playground-dashboard .demo-server-tag { + min-height: 40px; + display: inline-flex; + align-items: center; + gap: 8px; + padding: 0 14px; + border: 1px solid #54575a; + border-radius: 12px; + background: rgba(255, 255, 255, 0.08); + color: #b8bbbe; + font-family: var(--font-mono); + font-size: 13px; + font-weight: 400; + line-height: 1.2; + box-shadow: none; +} + +.playground-dashboard .demo-tag-value, +.playground-dashboard .demo-tag-value--server, +.playground-dashboard .demo-tag-value--key, +.playground-dashboard .demo-tag-value--sdk { + color: #e8ff75; + font-weight: 500; +} + +.playground-dashboard .demo-server-tag--namespace { + padding-right: 10px; +} + +.playground-dashboard .demo-namespace-input { + width: auto; + min-width: 74px; + padding: 0; + border: 0; + outline: none; + background: transparent; + color: #faf8f5; + font-family: var(--font-mono); + font-size: 13px; + font-weight: 500; +} + +.playground-dashboard .card.demo-step { + margin-bottom: 42px !important; + padding: 32px !important; + border: 1px solid #54575a !important; + border-radius: 24px !important; + background: rgba(255, 255, 255, 0.08) !important; + color: #faf8f5; + box-shadow: none !important; + animation: dashboardReveal 360ms cubic-bezier(0.16, 1, 0.3, 1) both; +} + +.playground-dashboard .card.demo-step:hover { + border-color: #54575a !important; + box-shadow: none !important; +} + +.playground-dashboard .card-header { + align-items: flex-start; + gap: 24px; + margin-bottom: 24px !important; +} + +.playground-dashboard .card-header > :last-child { + flex: 0 0 auto; +} + +.playground-dashboard .demo-step-header-row { + min-width: 0; + align-items: flex-start; + gap: 18px; +} + +.playground-dashboard .demo-step-badge { + width: 40px !important; + height: 40px !important; + border: 1px solid #54575a; + border-radius: 12px !important; + background: #000000; + color: #faf8f5; + font-family: var(--font-mono); + font-size: 15px; + font-weight: 500; + line-height: 1; + box-shadow: none; +} + +.playground-dashboard .demo-step-badge--highlight { + border-color: #e8ff75; + background: #e8ff75; + color: #000000; +} + +.playground-dashboard .card-title, +.playground-dashboard .demo-step-title { + color: #faf8f5; + font-family: var(--font-sans); + font-size: 28px !important; + font-weight: 650; + line-height: 1.05; + letter-spacing: 0; +} + +.playground-dashboard .card-subtitle { + margin-top: 8px; + color: #b8bbbe; + font-family: var(--font-sans); + font-size: 17px !important; + font-weight: 400; + line-height: 1.3; +} + +.playground-dashboard .btn { + min-width: 84px; + min-height: 44px !important; + height: 44px; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 2px 22px 0; + border-radius: 22px; + font-family: var(--font-sans); + font-size: 16px; + font-weight: 550; + line-height: 1; + letter-spacing: 0; + box-shadow: none !important; + transform: none !important; + transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease; +} + +.playground-dashboard .btn-primary, +.playground-dashboard .btn-primary:hover:not(:disabled), +.playground-dashboard .btn-primary:active:not(:disabled) { + border: 1px solid #e8ff75; + background: #e8ff75; + color: #000000; + transform: none !important; + box-shadow: none !important; +} + +.playground-dashboard .btn-primary:disabled { + border-color: rgba(232, 255, 117, 0.18); + background: rgba(232, 255, 117, 0.22); + color: rgba(0, 0, 0, 0.42); +} + +.playground-dashboard .btn-primary.demo-run-button--loading:disabled { + border-color: #e8ff75; + background: #e8ff75; + color: #000000; + opacity: 1; +} + +.playground-dashboard .demo-button-spinner { + width: 14px; + height: 14px; + border-color: rgba(0, 0, 0, 0.28); + border-top-color: #000000; +} + +.playground-dashboard .input-group { + margin-bottom: 18px !important; +} + +.playground-dashboard .input-group label, +.playground-dashboard .demo-info-label, +.playground-dashboard .demo-result-label, +.playground-dashboard .demo-error-label { + display: block; + margin-bottom: 12px; + color: #b8bbbe; + font-family: var(--font-sans); + font-size: 17px !important; + font-weight: 400; + line-height: 1.3; + letter-spacing: 0; +} + +.playground-dashboard .input { + min-height: 52px; + padding: 13px 16px; + border: 1px solid #54575a; + border-radius: 14px; + background: #000000; + color: #faf8f5; + font-family: var(--font-sans); + font-size: 16px; + font-weight: 400; + line-height: 1.4; + box-shadow: none; +} + +.playground-dashboard textarea.input { + min-height: 108px; + resize: vertical; +} + +.playground-dashboard .input:focus { + border-color: #e8ff75; + outline: none; + box-shadow: 0 0 0 3px rgba(232, 255, 117, 0.12); +} + +.playground-dashboard .input::placeholder { + color: #8f9294; +} + +.playground-dashboard select.input { + width: 152px; + flex: 0 0 152px; +} + +.playground-dashboard select.input option { + background: #000000; + color: #faf8f5; +} + +.playground-dashboard .demo-code-block { + margin: 0; + padding: 24px 28px !important; + border: 1px solid #54575a; + border-radius: 24px !important; + background: #000000 !important; + color: #faf8f5 !important; + font-family: var(--font-mono); + font-size: 14px !important; + font-weight: 400; + line-height: 1.5 !important; + white-space: pre-wrap !important; + word-break: break-word; + overflow-x: hidden; + box-shadow: none !important; +} + +.playground-dashboard .demo-code-block code { + white-space: inherit !important; +} + +.playground-dashboard .demo-code-block--spaced { + margin-bottom: 18px; +} + +.playground-dashboard .demo-info-panel, +.playground-dashboard .demo-ai-panel, +.playground-dashboard .demo-result-panel, +.playground-dashboard .demo-error-panel, +.playground-dashboard .demo-phase-indicator { + margin-bottom: 18px; + padding: 20px; + border-radius: 20px; + background: #000000; + color: #b8bbbe; + box-shadow: none; +} + +.playground-dashboard .demo-info-panel:last-child, +.playground-dashboard .demo-ai-panel:last-child, +.playground-dashboard .demo-result-panel:last-child, +.playground-dashboard .demo-error-panel:last-child, +.playground-dashboard .demo-phase-indicator:last-child { + margin-bottom: 0; +} + +.playground-dashboard .demo-info-panel, +.playground-dashboard .demo-ai-panel, +.playground-dashboard .demo-phase-indicator { + border: 1px solid #54575a; +} + +.playground-dashboard .demo-result-panel { + border: 1px solid rgba(232, 255, 117, 0.44); +} + +.playground-dashboard .demo-error-panel { + border: 1px solid rgba(255, 110, 116, 0.55); +} + +.playground-dashboard .demo-result-label { + color: #e8ff75; +} + +.playground-dashboard .demo-error-label, +.playground-dashboard .demo-error-pre { + color: #ff878d; +} + +.playground-dashboard .demo-result-pre, +.playground-dashboard .demo-error-pre { + margin: 0; + color: #faf8f5; + font-family: var(--font-mono); + font-size: 14px; + line-height: 1.55; + white-space: pre-wrap; + word-break: break-word; +} + +.playground-dashboard .demo-ai-answer { + color: #faf8f5; + font-size: 16px; + line-height: 1.55; +} + +.playground-dashboard .demo-phase-indicator { + display: flex; + align-items: center; + gap: 12px; + color: #faf8f5; +} + +.playground-dashboard .demo-llm-controls { + display: flex; + gap: 12px; + margin-bottom: 10px; +} + +.playground-dashboard .demo-llm-controls input { + flex: 1; +} + +.playground-dashboard .demo-field-note { + color: #b8bbbe; + font-family: var(--font-sans); + font-size: 17px !important; + font-weight: 400; + line-height: 1.3; +} + +.playground-dashboard .demo-ready-pill { + min-height: 28px; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0 12px; + border-radius: 14px; + background: #e8ff75; + color: #000000; + font-size: 13px; + font-weight: 600; +} + +.playground-dashboard .demo-memory-item { + display: grid; + grid-template-columns: 48px minmax(0, 1fr); + gap: 12px; + align-items: baseline; + margin-bottom: 10px; + color: #b8bbbe; + font-family: var(--font-mono); + font-size: 13px; + line-height: 1.45; +} + +.playground-dashboard .demo-memory-item:last-child { + margin-bottom: 0; +} + +.playground-dashboard .demo-memory-score { + color: #e8ff75; +} + +.playground-dashboard .demo-details-summary { + margin-bottom: 10px; + color: #b8bbbe; + cursor: pointer; + font-size: 14px; + line-height: 1.3; +} + +.playground-dashboard .demo-system-prompt { + color: #b8bbbe !important; + font-size: 13px !important; +} + +.playground-dashboard .demo-mode-divider { + margin: 56px 0 30px; + color: #b8bbbe; + font-family: var(--font-sans); + font-size: 17px !important; + font-weight: 400; + line-height: 1.3; + text-align: center; +} + +@media (max-width: 860px) { + .setup-classic-nav, + .playground-nav, + .dashboard-nav { + height: 80px; + padding: 0 14px; + } + + .setup-classic-nav .nav-inner, + .playground-nav .nav-inner, + .dashboard-nav .nav-inner { + height: 80px; + min-height: 80px; + } + + .setup-classic-nav .nav-brand, + .playground-nav .nav-brand, + .dashboard-nav .nav-brand { + top: 22px; + } + + .setup-classic-nav .nav-brand-logo, + .playground-nav .nav-brand-logo, + .dashboard-nav .nav-brand-logo { + height: 36px; + } + + .setup-classic-nav .nav-user, + .playground-nav .nav-user, + .dashboard-nav .nav-user { + top: 21px; + height: 38px; + gap: 8px; + } + + .setup-classic-nav .nav-address, + .playground-nav .nav-address, + .dashboard-nav .nav-address { + min-width: 96px; + height: 34px; + padding: 0 10px; + font-size: 11px; + letter-spacing: 0.45px; + } + + .setup-classic-nav .lp-nav-cta, + .playground-nav .lp-nav-cta, + .dashboard-nav .lp-nav-cta { + height: 38px; + min-height: 38px; + padding: 0 14px; + border-radius: 19px; + font-size: 14px; + letter-spacing: 0.3px; + gap: 8px; + } + + .setup-classic-nav .lp-nav-cta svg, + .playground-nav .lp-nav-cta svg, + .dashboard-nav .lp-nav-cta svg { + width: 12px; + height: 12px; + } + + .playground-nav .demo-nav-label { + display: none; + } + + .playground-nav .demo-nav-icon { + display: block; + } + + .playground-nav .demo-nav-back { + width: 38px !important; + min-width: 38px !important; + height: 38px !important; + min-height: 38px !important; + padding: 0 !important; + border: 1px solid #54575a; + border-radius: 19px; + background: #000000; + color: #faf8f5; + justify-content: center; + } + + .dash-page .dash-shell, + .playground-dashboard, + .setup-classic-container { + width: calc(100% - 28px) !important; + padding: 28px 0 48px !important; + } + + .dash-page .card, + .playground-dashboard .card.demo-step { + padding: 24px !important; + border-radius: 20px !important; + } + + .dash-page .card-header, + .playground-dashboard .card-header { + gap: 18px; + margin-bottom: 28px !important; + } + + .dash-page .card-title, + .playground-dashboard .card-title, + .playground-dashboard .demo-step-title { + font-size: 28px !important; + line-height: 1; + } + + .dash-page .card-subtitle, + .playground-dashboard .card-subtitle { + font-size: 16px !important; + line-height: 1.32; + } + + .playground-dashboard .dashboard-header h2 { + font-size: 38px !important; + line-height: 0.96; + } + + .playground-dashboard .dashboard-header p { + font-size: 16px !important; + } + + .dash-page .card-header-actions .btn-secondary, + .dash-page .card-header-actions .lp-nav-cta, + .playground-dashboard .btn { + min-height: 44px !important; + height: 44px; + padding: 0 16px; + border-radius: 22px; + font-size: 15px; + letter-spacing: 0.25px; + } + + .playground-dashboard .btn { + width: 100%; + } + + .playground-dashboard .demo-llm-controls { + flex-direction: column; + } + + .playground-dashboard select.input { + width: 100%; + flex-basis: auto; + } + + .dash-page .dashboard-keys-card { + padding: 24px !important; + } + + .dash-page .dashboard-keys-card .card-header { + flex-direction: column; + align-items: stretch; + } + + .dash-page .dashboard-keys-card .card-header-actions { + width: 100%; + max-width: 100%; + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 12px; + align-self: stretch; + } + + .dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh, + .dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add { + width: 100%; + min-width: 0; + } +} + +@media (max-width: 820px) { + .setup-classic-nav, + .playground-nav, + .dashboard-nav { + height: 72px; + padding: 0 10px; + } + + .setup-classic-nav .nav-inner, + .playground-nav .nav-inner, + .dashboard-nav .nav-inner { + height: 72px; + min-height: 72px; + } + + .setup-classic-nav .nav-brand, + .playground-nav .nav-brand, + .dashboard-nav .nav-brand { + top: 20px; + } + + .setup-classic-nav .nav-brand-logo, + .playground-nav .nav-brand-logo, + .dashboard-nav .nav-brand-logo { + height: 32px; + } + + .setup-classic-nav .nav-user, + .playground-nav .nav-user, + .dashboard-nav .nav-user { + top: 18px; + height: 36px; + gap: 6px; + } + + .setup-classic-nav .nav-address, + .playground-nav .nav-address, + .dashboard-nav .nav-address { + min-width: 86px; + height: 32px; + padding: 0 8px; + font-size: 10.5px; + letter-spacing: 0.35px; + } + + .setup-classic-nav .lp-nav-cta, + .playground-nav .lp-nav-cta, + .dashboard-nav .lp-nav-cta { + height: 36px; + min-height: 36px; + padding: 0 12px; + border-radius: 18px; + font-size: 13px; + gap: 7px; + } + + .setup-classic-nav .lp-nav-cta svg, + .playground-nav .lp-nav-cta svg, + .dashboard-nav .lp-nav-cta svg { + width: 11px; + height: 11px; + } + + .playground-nav .demo-nav-back { + width: 36px !important; + min-width: 36px !important; + height: 36px !important; + min-height: 36px !important; + border-radius: 18px; + } + + .playground-nav .demo-nav-icon { + width: 16px; + height: 16px; + } +} + +/* ============================================================ + Delete old memories card — mirrors the Delegate + keys card; order places it last in the dash-shell flex flow. + ============================================================ */ + +/* The install card zeroes its bottom margin (it used to be the last card + on the page), so the cleanup card supplies its own top gap to keep the + 56px card rhythm — and, as the new last card, zeroes its own bottom. + Shell/type mirror the keys+install cards' final design; the generic + 860px rules (24px padding, 28px title, 44px pills — all !important) + cover mobile the same way they do for those cards. */ +.dash-page .dashboard-cleanup-card { + order: 7; + margin-top: 56px; + margin-bottom: 0 !important; + padding: 39px 40px; + border-color: #54575a; + border-radius: 24px; + background: #000000; + overflow: clip; +} + +.dash-page .dashboard-cleanup-card .card-header { + align-items: flex-start; + gap: 24px; + margin-bottom: 34px; +} + +.dash-page .dashboard-cleanup-card .card-title { + color: #faf8f5; + font-family: var(--font-sans); + font-size: 36px; + font-weight: 500; + line-height: 0.88; + letter-spacing: 0; +} + +.dash-page .dashboard-cleanup-card .card-subtitle { + margin-top: 14px; + color: #b8bbbe; + font-family: var(--font-sans); + font-size: 18px; + font-weight: 400; + line-height: 1.3; +} + +.dash-page .dashboard-cleanup-card .card-header-actions { + align-self: flex-start; + gap: 20px; +} + +.dash-page .dashboard-cleanup-load { + min-height: 52px; + height: 52px; + padding: 10px 30px; + border: 1px solid #faf8f5; + border-radius: 26px; + background: transparent; + color: #faf8f5; + font-family: var(--font-sans); + font-size: 18px; + font-weight: 500; + line-height: 1; + letter-spacing: 0.72px; +} + +.dash-page .dashboard-cleanup-load:hover:not(:disabled) { + background: rgba(250, 248, 245, 0.16); + border-color: #faf8f5; + color: #faf8f5; +} + +/* Old-memories banner — first thing in the shell: below the navbar, + above the "Welcome" header (all other dash-shell orders start at 0). */ +.dash-page .dash-alert--cleanup { + order: -1; + margin-bottom: 40px !important; +} + +/* App-wide mount (T3: once in AppContent, direct child of .app) — pages + render their own navbars below it, so keep the page column width and a + slim gap instead of the in-shell 48px alert margin. */ +.app > .dash-alert--cleanup { + width: min(1240px, calc(100% - 48px)); + margin: 16px auto; + margin-bottom: 16px !important; /* base .dash-alert forces 48px */ +} + +.dash-alert--cleanup .dash-alert-dismiss { + margin-left: auto; + flex-shrink: 0; +} + +/* Header delete button matches the card-header pill spec (52px, radius 26, + px-30, 18px label — same as Refresh/Add key) in danger colors. */ +.dash-page .dashboard-cleanup-delete { + display: inline-flex; + align-items: center; + gap: 8px; + min-height: 52px; + height: 52px; + padding: 10px 30px; + border-radius: 26px; + font-size: 1.125rem; + letter-spacing: 0.72px; +} + +.dash-page .dashboard-cleanup-error { + background: rgba(248, 113, 113, 0.08); + border: 1px solid rgba(248, 113, 113, 0.2); + border-radius: var(--radius-md); + padding: 12px 16px; + margin: 0 0 18px; + color: var(--danger); + font-size: 16px; + line-height: 1.4; + word-break: break-word; +} + +/* Body copy matches the final card-subtitle scale (18px / 1.3). */ +.dash-page .dashboard-cleanup-status { + margin: 0; + color: #b8bbbe; + font-size: 18px; + font-weight: 400; + line-height: 1.3; +} + +/* Keep cleanup actions in step with the 44px mobile header pills. */ +@media (max-width: 860px) { + .dash-page .dashboard-cleanup-load { + min-height: 44px; + height: 44px; + padding: 0 16px; + border-radius: 22px; + font-size: 15px; + letter-spacing: 0.25px; + } + + .dash-page .dashboard-cleanup-delete { + min-height: 44px; + height: 44px; + padding: 0 16px; + border-radius: 22px; + font-size: 15px; + letter-spacing: 0.25px; + } +} + +/* ========== Admin Dashboard ========== */ + +/* The admin route uses the same navigation, shell, cards, type scale, spacing, + radii, and controls as the authenticated dashboard. Keep this section to + admin-only data presentation instead of recreating the dashboard theme. */ +.dash-page.admin-dashboard-page { + padding: 0; +} + +.admin-dashboard-container { + margin: 0 auto; +} + +.admin-dashboard-page .dashboard-header { + margin-bottom: var(--dashboard-related-gap); +} + +.admin-panels, +.admin-wallets-section, +.admin-activity-section { + display: flex; + flex-direction: column; +} + +.admin-panels { + gap: var(--dashboard-major-gap); +} + +.admin-wallets-section, +.admin-activity-section { + gap: var(--dashboard-related-gap); +} + +.admin-panels .card, +.admin-wallets-section .card, +.admin-activity-section .card { + min-height: 0; + margin-bottom: 0 !important; +} + +/* Sign in */ +.admin-key-entry-shell { + display: flex; + justify-content: center; + padding-top: 26px; +} + +.dash-page .admin-key-entry-card { + width: min(560px, 100%); + min-height: 0; + margin-bottom: 0 !important; +} + +.admin-key-entry-form { + display: flex; + flex-direction: column; + gap: 24px; +} + +.dash-page .admin-key-banner, +.dash-page .admin-key-error { + color: #ff8f8f; + font-size: 14px; + line-height: 1.35; +} + +.dash-page .admin-key-banner { + margin-bottom: 20px; + padding: 14px 16px; + border: 1px solid rgba(248, 113, 113, 0.36); + border-radius: 14px; + background: rgba(248, 113, 113, 0.1); +} + +.dash-page .admin-key-error { + margin-top: 2px; +} + +.dash-page .admin-key-input-error, +.dash-page .admin-key-input-error:focus { + border-color: rgba(248, 113, 113, 0.72); + box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.1); +} + +.dash-page .admin-key-submit-btn:disabled { + border-color: rgba(250, 248, 245, 0.14); + background: rgba(250, 248, 245, 0.14); + color: #8f9294; + cursor: not-allowed; +} + +/* Tables */ +.admin-table-wrapper { + width: 100%; + overflow-x: auto; + border: 1px solid #54575a; + border-radius: 18px; + background: rgba(255, 255, 255, 0.06); +} + +.admin-table { + width: 100%; + border-collapse: collapse; +} + +.dash-page .admin-table th, +.dash-page .admin-table td { + padding: 14px 18px; + text-align: left; + vertical-align: middle; +} + +.dash-page .admin-table th { + border-bottom: 1px solid rgba(250, 248, 245, 0.12); + color: #b8bbbe; + font-size: 14px; + font-weight: 500; + line-height: 1.2; + white-space: nowrap; +} + +.dash-page .admin-table td { + border-bottom: 1px solid rgba(250, 248, 245, 0.08); + color: #faf8f5; + font-size: 14px; + line-height: 1.35; +} + +.admin-table tbody tr:last-child td { + border-bottom: 0; +} + +.dash-page .admin-table .admin-table-empty { + padding: 28px 18px; + color: #8f9294; + text-align: center; +} + +.admin-table-monospace { + font-family: var(--font-mono); + font-size: 13px; + white-space: nowrap; +} + +.dash-page .admin-status-badge { + display: inline-flex; + align-items: center; + min-height: 22px; + padding: 3px 8px; + border: 1px solid rgba(250, 248, 245, 0.2); + border-radius: 999px; + font-family: var(--font-sans); + font-size: 12px; + font-weight: 500; + line-height: 1; + letter-spacing: 0; + text-transform: capitalize; +} + +.dash-page .admin-status-badge--healthy { + border-color: rgba(74, 222, 128, 0.38); + color: #4ade80; +} + +.dash-page .admin-status-badge--warning { + border-color: rgba(251, 191, 36, 0.38); + color: #fbbf24; +} + +.dash-page .admin-status-badge--critical { + border-color: rgba(255, 143, 143, 0.38); + color: #ff8f8f; +} + +.dash-page .admin-timestamp { + margin-top: 16px; + color: #b8bbbe; + font-size: 14px; + line-height: 1.35; +} + +/* Wallet and configuration rows */ +.admin-sponsor-content, +.admin-config-items { + display: flex; + flex-direction: column; +} + +.dash-page .admin-sponsor-item, +.dash-page .admin-config-item { + display: flex; + align-items: center; + justify-content: space-between; + gap: 24px; + min-height: 58px; + padding: 14px 0; + border-bottom: 1px solid rgba(250, 248, 245, 0.08); +} + +.admin-sponsor-item:last-child, +.admin-config-item:last-child { + border-bottom: 0; +} + +.dash-page .admin-sponsor-label, +.dash-page .admin-config-label { + color: #b8bbbe; + font-size: 18px; + font-weight: 400; + line-height: 1.3; +} + +.dash-page .admin-sponsor-value, +.dash-page .admin-config-value { + color: #faf8f5; + font-family: var(--font-mono); + font-size: 15px; + line-height: 1.4; + text-align: right; +} + + +/* Error controls */ +.admin-errors-controls { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 20px; +} + +.dash-page .admin-limit-label, +.dash-page .admin-pagination-status { + color: #b8bbbe; + font-size: 14px; + line-height: 1.35; +} + +.dash-page .admin-limit-select { + min-height: 36px; + padding: 0 36px 0 14px; + border: 1px solid rgba(250, 248, 245, 0.12); + border-radius: 10px; + background: #050505; + color: #faf8f5; + font-family: var(--font-sans); + font-size: 14px; +} + +.admin-error-timestamp { + white-space: nowrap; +} + +.admin-error-message { + display: flex; + align-items: center; + gap: 10px; + min-width: 280px; +} + +.dash-page .admin-error-msg-btn { + flex: 1; + min-width: 0; + padding: 0; + border: 0; + background: transparent; + color: #faf8f5; + font-size: 14px; + line-height: 1.35; + text-align: left; + cursor: pointer; +} + +.dash-page .admin-error-msg-btn:hover { + color: #e8ff75; +} + +.dash-page .admin-copy-btn, +.dash-page .admin-pagination-btn, +.dash-page .admin-error-modal-close { + display: inline-flex; + align-items: center; + justify-content: center; + border: 1px solid rgba(250, 248, 245, 0.12); + background: transparent; + color: #b8bbbe; + cursor: pointer; +} + +.dash-page .admin-copy-btn { + width: 34px; + min-width: 34px; + height: 34px; + padding: 0; + border-radius: 10px; +} + +.dash-page .admin-copy-btn:hover, +.dash-page .admin-pagination-btn:hover:not(:disabled), +.dash-page .admin-error-modal-close:hover { + border-color: #faf8f5; + color: #faf8f5; +} + +.admin-pagination { + display: flex; + align-items: center; + justify-content: space-between; + gap: 20px; + margin-top: 20px; +} + +.admin-pagination-controls { + display: flex; + gap: 8px; +} + +.dash-page .admin-pagination-btn { + width: 36px; + height: 36px; + padding: 0; + border-radius: 10px; +} + +.dash-page .admin-pagination-btn:disabled { + opacity: 0.35; + cursor: not-allowed; +} + +/* Error modal */ +.admin-error-modal-overlay { + position: fixed; + inset: 0; + z-index: 2000; + display: grid; + place-items: center; + padding: 24px; + background: rgba(0, 0, 0, 0.78); +} + +.dash-page .admin-error-modal { + display: flex; + flex-direction: column; + width: min(640px, 100%); + max-height: 80vh; + overflow: hidden; + border: 1px solid #54575a; + border-radius: 24px; + background: #0a0a0a; +} + +.dash-page .admin-error-modal-header, +.dash-page .admin-error-modal-footer { + display: flex; + align-items: center; + padding: 24px 28px; +} + +.dash-page .admin-error-modal-header { + justify-content: space-between; + border-bottom: 1px solid rgba(250, 248, 245, 0.1); +} + +.dash-page .admin-error-modal-header h3 { + margin: 0; + color: #faf8f5; + font-size: 24px; + font-weight: 500; + line-height: 1.2; +} + +.dash-page .admin-error-modal-close { + width: 36px; + height: 36px; + padding: 0; + border-radius: 10px; + font-size: 24px; +} + +.admin-error-modal-content { + flex: 1; + overflow-y: auto; + padding: 28px; +} + +.dash-page .admin-error-modal-timestamp { + margin: 0 0 14px; + color: #b8bbbe; + font-size: 14px; +} + +.dash-page .admin-error-modal-message { + margin: 0; + padding: 16px; + border: 1px solid rgba(250, 248, 245, 0.1); + border-radius: 14px; + background: #050505; + color: #faf8f5; + font-family: var(--font-mono); font-size: 13px; - line-height: 1; - letter-spacing: 0; - text-transform: none; + line-height: 1.5; + white-space: pre-wrap; + word-break: break-word; } -.dash-page .dashboard-keys-card .key-display .btn-danger { - min-width: 88px; +.dash-page .admin-error-modal-footer { + justify-content: flex-end; + border-top: 1px solid rgba(250, 248, 245, 0.1); } -.dash-page .dashboard-keys-card .key-display .btn-secondary svg, -.dash-page .dashboard-keys-card .key-display .btn-danger svg { - display: block; +.dash-page .admin-copy-full-btn { + min-height: 44px; + padding: 10px 22px; + border: 1px solid #faf8f5; + border-radius: 22px; + background: #faf8f5; + color: #000000; + font-size: 16px; + font-weight: 500; + cursor: pointer; } -@media (max-width: 860px) { - .dash-page .dashboard-credentials-card { - padding: 28px 24px; - } +.dash-page .admin-copy-full-btn:hover { + border-color: #e8ff75; + background: #e8ff75; +} - .dash-page .dashboard-credentials-card .card-header { - margin-bottom: 22px; - } +.admin-window-toggle { + display: flex; + gap: 8px; +} - .dash-page .dashboard-credentials-alert p { - display: block; - } +.dash-page .admin-activity-card .admin-window-toggle .btn { + height: 40px; + min-height: 40px; + padding: 0 16px; + border: 1px solid #54575a; + border-radius: 20px; + background: transparent; + color: #faf8f5; + font-family: "Google Sans Code", var(--font-mono); + font-size: 13px; + font-weight: 400; + letter-spacing: 0.64px; + line-height: 1; + text-transform: uppercase; + box-shadow: none; +} - .dash-page .dashboard-credentials-alert p span { - display: block; - margin-top: 6px; - } +.dash-page .admin-activity-card .admin-window-toggle .admin-window-btn--active, +.dash-page .admin-activity-card .admin-window-toggle .admin-window-btn--active:hover { + border-color: #faf8f5; + background: #faf8f5; + color: #000000; +} - .dash-page .dashboard-credential-row { - grid-template-columns: 1fr; - gap: 14px; - padding: 16px; - } +.admin-burn-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 16px; +} - .dash-page .dashboard-credential-actions { - justify-content: flex-start; - } +.admin-burn-column { + display: flex; + flex-direction: column; + gap: 8px; + min-width: 0; + padding: 16px; + border: 1px solid #262b30; + border-radius: 6px; +} - .dash-page .dashboard-key-table-wrap { - overflow: visible; - border: 0; - border-radius: 0; - background: transparent; - } +.admin-burn-label { + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 14px; + font-weight: 400; + line-height: 1.3; +} - .dash-page .dashboard-key-table, - .dash-page .dashboard-key-table thead, - .dash-page .dashboard-key-table tbody, - .dash-page .dashboard-key-table tr, - .dash-page .dashboard-key-table td { - display: block; - width: 100%; - } +.admin-burn-value { + color: #faf8f5; + font-family: "Google Sans Code", var(--font-mono); + font-size: 20px; + font-weight: 400; + line-height: 1.2; +} - .dash-page .dashboard-key-table thead { - display: none; - } +.admin-burn-meta { + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 13px; + font-weight: 400; + line-height: 1.35; +} - .dash-page .dashboard-key-table tr { - margin-bottom: 14px; - padding: 16px; - border: 1px solid #54575a; - border-radius: 18px; - background: rgba(255, 255, 255, 0.08); - } +.dash-page .admin-pace { + align-self: flex-start; + text-transform: none; + letter-spacing: 0; + font-family: "Google Sans Flex", sans-serif; +} - .dash-page .dashboard-key-table tbody tr:last-child { - margin-bottom: 0; - } +.dash-page .admin-pace--faster { + border-color: rgba(255, 154, 160, 0.7); + color: #ff9aa0; +} - .dash-page .dashboard-pagination { - align-items: stretch; - justify-content: flex-start; - } +.dash-page .admin-pace--slower { + border-color: rgba(74, 222, 128, 0.45); + color: #4ade80; +} - .dash-page .dashboard-pagination-end { - justify-content: space-between; - width: 100%; - } +.dash-page .admin-pace--same, +.dash-page .admin-pace--unknown { + border-color: #54575a; + color: #b1b4b6; +} - .dash-page .dashboard-key-table td { - display: grid; - grid-template-columns: 92px minmax(0, 1fr); - gap: 12px; - align-items: start; - padding: 8px 0; - border-bottom: 0; - } +.admin-sparkline { + width: 100%; + height: 64px; + margin-top: 4px; + color: #faf8f5; +} - .dash-page .dashboard-key-table td::before { - content: attr(data-label); - color: #8f9294; - font-size: 13px; - line-height: 1.35; - } +.admin-action-list { + display: flex; + flex-direction: column; +} - .dash-page .dashboard-key-list--skeleton .dashboard-key-table td { - grid-template-columns: 1fr; - } +.admin-action-row { + display: flex; + justify-content: space-between; + gap: 16px; + padding: 12px 0; + border-bottom: 1px solid #262b30; + color: #faf8f5; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; + font-weight: 400; + line-height: 1.35; +} - .dash-page .dashboard-key-list--skeleton .dashboard-key-table td::before { - display: none; - } +.admin-action-row:last-child { + border-bottom: 0; +} - .dash-page .dashboard-key-cell-select { - align-items: center !important; +.admin-activity-note { + margin: 16px 0 0; + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 13px; + font-weight: 400; + line-height: 1.45; +} + +/* Loading and error states */ +.dash-page .admin-loading { + padding: 48px 20px; + color: #b8bbbe; + font-size: 18px; + line-height: 1.3; + text-align: center; +} + +.dash-page .admin-error { + padding: 16px; + border: 1px solid rgba(248, 113, 113, 0.28); + border-radius: 14px; + background: rgba(248, 113, 113, 0.1); + color: #ff8f8f; + font-size: 16px; + line-height: 1.4; +} + +@media (max-width: 860px) { + .admin-dashboard-page .dashboard-header { + margin-bottom: var(--dashboard-mobile-major-gap); } - .dash-page .dashboard-key-row-actions { - text-align: left; + .admin-panels, + .admin-wallets-section, + .admin-activity-section { + gap: var(--dashboard-mobile-major-gap); } - .dash-page .dashboard-key-actions { - justify-content: flex-start; + .admin-burn-grid { + grid-template-columns: 1fr; } - .dash-page .dashboard-key-row-actions .btn-secondary, - .dash-page .dashboard-key-row-actions .btn-danger { - flex: 0 0 34px; + .admin-key-entry-shell { + padding-top: 0; } - .dash-page .dashboard-key-selection-bar { - align-items: stretch; + .dash-page .admin-sponsor-item, + .dash-page .admin-config-item { + align-items: flex-start; flex-direction: column; + gap: 6px; } - .dash-page .dashboard-key-selection-status { - margin-left: 0; + .dash-page .admin-sponsor-value, + .dash-page .admin-config-value { + max-width: 100%; + overflow-wrap: anywhere; + text-align: left; + } +} + +@media (max-width: 640px) { + .admin-error-modal-overlay { + padding: 16px; } - .dash-page .dashboard-key-bulk-actions { - width: 100%; + .dash-page .admin-error-modal { + max-height: 90vh; + border-radius: 20px; } - .dash-page .dashboard-key-clear-selection, - .dash-page .dashboard-key-remove-selected { - flex: 1 1 0; + .dash-page .admin-error-modal-header, + .dash-page .admin-error-modal-footer, + .admin-error-modal-content { + padding: 20px; } } -.dash-page .dashboard-quickstart-card pre, -.dash-page .dashboard-quickstart-card .demo-code-block { - overflow-x: clip; - white-space: pre-wrap; - word-break: break-word; +.dash-page .dash-alert--info { + min-height: 0; + align-items: flex-start; + gap: 12px; + margin-bottom: 28px !important; + padding: 14px 18px; + border: 1px solid var(--dash-panel-border); + border-radius: var(--radius-md); + background: var(--dash-panel); + color: var(--dash-subtle); } -.dash-page .dashboard-quickstart-card pre code, -.dash-page .dashboard-quickstart-card .demo-code-block code, -.dash-page .dashboard-quickstart-card .demo-code-block span { - white-space: pre-wrap !important; - word-break: break-word; +.dash-page .dash-alert--info .dash-alert-icon { + width: 20px; + height: 20px; + margin-top: 2px; + color: var(--dash-yellow); } -.dash-page .dashboard-install-card { - padding: 39px 40px; +.dash-page .dash-alert--info p { + color: var(--dash-subtle); + font-size: 15px; + font-weight: 400; + line-height: 1.5; } -.dash-page .dashboard-install-card .card-header { - margin-bottom: 34px; +.dash-page .dash-alert-link { + padding: 0; + border: 0; + background: none; + color: var(--dash-yellow); + font: inherit; + text-decoration: underline; + text-underline-offset: 2px; + cursor: pointer; } -.dash-page .dashboard-install-card .card-subtitle { - margin-top: 14px; - color: #b8bbbe; - font-size: 18px; - font-weight: 400; - line-height: 1.3; +.dash-page .dash-alert-link:hover { + text-decoration-thickness: 2px; } -.dash-page .dashboard-install-card .install-tabs { - margin-bottom: 28px; +.dash-page .dashboard-key-current-badge { + white-space: nowrap; } -.dash-page .dashboard-install-card .install-tab, -.dash-page .dashboard-install-card .install-tab:last-child { - line-height: 1; -} +@media (max-width: 640px) { + .dash-page .dash-alert--info { + padding: 12px 14px; + } -.dash-page .dashboard-install-card .dashboard-install-codewrap { - gap: 10px; + .dash-page .dash-alert--info p { + font-size: 14px; + } } -.dash-page .dashboard-install-card .dashboard-install-codewrap .install-command { - padding: 0 !important; - overflow-x: clip; - white-space: normal; - overflow-wrap: anywhere; +.dash-page .connect-wm { + order: 0; } -.dash-page .dashboard-install-card .dashboard-install-copy { - width: 24px; - height: 24px; - flex: 0 0 24px; - border-radius: 8px; - background: rgba(255, 255, 255, 0.08); - color: #faf8f5; +.dash-page .dashboard-section-head, +.dash-page .dashboard-cta-row--resources { + order: 7; } -.dash-page .dashboard-install-card .dashboard-install-copy svg { - width: 12px; - height: 12px; +.dash-page .dashboard-cleanup-card { + order: 8; } -.dash-page .dashboard-install-card .dashboard-install-copy:hover:not(:disabled) { - background: rgba(255, 255, 255, 0.14); +.dash-page .connect-wm-console { color: #faf8f5; } -/* ── Figma 2325-6980: even, generous block spacing. The CTA row was only ~20px - below; align it with the 56px card gaps so the whole stack breathes like the - design (Figma's literal 36px sits between much taller cards). ── */ -.dash-page .dashboard-cta-row { - gap: 30px; - margin-bottom: 56px; +.dash-page .connect-wm-memories-copy a { + color: #16161d; + text-decoration: underline; } -.dash-page .dashboard-cta-row--primary { - margin-bottom: 30px; +/* Sept 2026 — Memory Dashboard. Content column is 816px, matching the Figma frame. + The navbar has no fill in the design, so the purple glow runs through it. */ +.dash-page { + --font-mono: "Google Sans Code", "JetBrains Mono", monospace; + font-family: "Google Sans Flex", sans-serif; + background: + radial-gradient(ellipse 95% 760px at 50% -80px, rgba(62, 28, 150, 0.92) 0%, rgba(39, 18, 104, 0.62) 34%, rgba(14, 6, 36, 0.28) 62%, rgba(0, 0, 0, 0) 78%), + #000000; } -.dash-page .dashboard-section-head { - order: 2; - margin-bottom: 16px; +.dash-page .dashboard-nav { + position: sticky; + top: 0; + z-index: 80; + background: transparent; + border-bottom: 1px solid transparent; + transition: background-color 240ms ease, border-color 240ms ease, box-shadow 240ms ease; } -.dash-page .dashboard-section-head h3 { - margin: 0 0 4px; - font-size: 1.15rem; - font-weight: 600; - color: #faf8f5; - letter-spacing: 0; +.dash-page .dashboard-nav.dashboard-nav--solid { + background: rgba(0, 0, 0, 0.92); + border-bottom-color: rgba(250, 248, 245, 0.08); + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45); + backdrop-filter: blur(24px) saturate(1.3); + -webkit-backdrop-filter: blur(24px) saturate(1.3); } -.dash-page .dashboard-section-head p { - margin: 0; - font-size: 0.9rem; - color: #8f9294; +.dash-page .dash-shell { + width: min(816px, calc(100% - 40px)); + max-width: 816px; + padding: 18px 0 96px; } -.dash-page .dashboard-cta-row--resources { - grid-template-columns: repeat(3, minmax(0, 1fr)); +.dashboard-nav .nav-address { + width: auto; + min-height: 28px; + gap: 9px; + padding: 0 10px; + border: 0; + background: rgba(0, 0, 0, 0.5); + color: #faf8f5; + font-family: var(--font-mono); + font-size: 12px; + font-weight: 300; + letter-spacing: 0.6px; + cursor: pointer; } -/* One consistent card style across Dashboard + Playground: match the CTA cards - (12px radius, subtle border + translucent bg) so content/step cards stop - looking like a different component. */ -.dash-page .card, -.playground-dashboard .card { - border-radius: 12px !important; - border: 1px solid rgba(250, 248, 245, 0.1) !important; - background: rgba(255, 255, 255, 0.08) !important; +.dashboard-nav .nav-address svg { + width: 10px; + height: 10px; + flex: 0 0 auto; } -/* Mobile: stack the Resources cards instead of cramming 3 columns. Placed after - the --resources rule so it wins inside the breakpoint. */ -@media (max-width: 860px) { - .dash-page .dashboard-cta-row--resources { - grid-template-columns: 1fr; - } +.dashboard-nav .lp-nav-cta { + width: auto; + min-width: 148px; + border-color: #54575a; + background: transparent; + font-family: var(--font-mono); + font-size: 16px; + font-weight: 400; + letter-spacing: 0.64px; + text-transform: uppercase; } -/* Dashboard CTA cards: final pass against the two-card design comp. This lives - after the duplicated dashboard rules so the CTA spacing stays deterministic. */ -.dash-page .dashboard-cta-row { - gap: 28px; - margin-bottom: 56px; +.dashboard-nav .lp-nav-cta:hover:not(:disabled) { + background: #faf8f5; + border-color: #faf8f5; + color: #000000; } -.dash-page .dashboard-cta-row--primary { - grid-template-columns: 1fr; - margin-top: 24px; - margin-bottom: 30px; +.dash-page #delegate-keys, +.dash-page #sdk-quickstart, +.dash-page #namespaces, +.dash-page #cleanup { + scroll-margin-top: 148px; } -.dash-page .dashboard-cta-row--resources { - grid-template-columns: repeat(3, minmax(0, 1fr)); +.dash-page .connect-wm { + order: 1; + width: 100%; + margin: 36px auto 48px; + gap: 28px; } -.dash-page .dashboard-cta-row > :only-child { - grid-column: 1 / -1; -} +.dash-page .dash-alert { order: 2; } +.dash-page .dashboard-keys-card.sept-section { order: 3; } +.dash-page .dashboard-section-head, +.dash-page .dashboard-resource-grid { order: 4; } +.dash-page .dashboard-credentials-card { order: 5; } +.dash-page #namespaces { order: 4; } +.dash-page #sdk-quickstart { order: 7; } +.dash-page .dashboard-cleanup-card { order: 8; } -.dash-page .dashboard-cta { - grid-template-columns: 36px minmax(0, 1fr) 21px; - min-height: 104px; - height: auto; - gap: 22px; - padding: 26px 27px; - border-radius: 22px; +.dash-page .connect-wm-hero h2 { + font-size: 72px; + font-weight: 425; + line-height: 0.95; } -.dash-page .dashboard-cta-icon-wrap { - width: 36px; - height: 40px; +.dash-page .connect-wm-hero p { + margin-top: 8px; + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 18px; + font-weight: 400; + line-height: 1.5; } -.dash-page .dashboard-cta-icon { - width: 36px; - height: 40px; +.dash-page .connect-wm-paths { + grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); + gap: 28px; + margin-top: 28px; } -.dash-page .dashboard-cta-title { - line-height: 1.18; +.dash-page .connect-wm-path { + position: relative; + min-height: 110px; + gap: 6px; + padding: 19px 22px 16px; + overflow: hidden; + border: 1px solid #262b30; + border-radius: 6px; + background: transparent; + font-family: "Google Sans Flex", sans-serif; + text-transform: none; } -.dash-page .dashboard-cta-subtitle { - margin-top: 8px; - line-height: 1.2; +.dash-page .connect-wm-path:hover { + border-color: #54575a; } -.dash-page .dashboard-cta-arrow { - width: 21px; - height: 21px; - margin-top: 0; +.dash-page .connect-wm-path--active, +.dash-page .connect-wm-path--active:hover { + border-color: #faf8f5; } -@media (max-width: 860px) { - .dash-page .dashboard-cta-row, - .dash-page .dashboard-cta-row--primary, - .dash-page .dashboard-cta-row--resources { - grid-template-columns: 1fr; - gap: 14px; - } - - .dash-page .dashboard-cta-row { - margin-bottom: 24px; - } - - .dash-page .dashboard-cta-row--primary { - margin-top: 18px; - margin-bottom: 24px; - } - - .dash-page .dashboard-cta { - grid-template-columns: 30px minmax(0, 1fr) 18px; - min-height: 92px; - gap: 16px; - padding: 21px 22px; - border-radius: 18px; - } - - .dash-page .dashboard-cta-icon-wrap, - .dash-page .dashboard-cta-icon { - width: 30px; - height: 34px; - } - - .dash-page .dashboard-cta-subtitle { - margin-top: 5px; - } +.dash-page .connect-wm-path-title { + justify-content: flex-start; + width: auto; + color: #faf8f5; + font-size: 18px; + font-weight: 400; + line-height: 1.3; } -/* Dashboard major-section rhythm. Keep large cards on one shared vertical gap - instead of mixing JSX inline margins with older dashboard density rules. */ -.dash-page { - --dashboard-major-gap: 56px; - --dashboard-related-gap: 30px; - --dashboard-mobile-major-gap: 24px; +.dash-page .connect-wm-path-copy { + max-width: 286px; + color: #8f9294; + font-size: 15px; + font-weight: 400; + line-height: 1.4; } -.dash-page .dashboard-cta-row--primary { - margin-bottom: var(--dashboard-related-gap); +.dash-page .connect-wm-stack { + position: absolute; + top: 16px; + right: 8px; + display: flex; + align-items: center; } -.dash-page .dashboard-section-head { - margin-bottom: 16px; +.dash-page .connect-wm-stack::after { + content: ""; + position: absolute; + top: 0; + right: 0; + width: 56px; + height: 34px; + background: linear-gradient(90deg, rgba(0, 0, 0, 0), #000000 78%); + pointer-events: none; } -.dash-page .dashboard-cta-row--resources, -.dash-page .dashboard-credentials-card, -.dash-page .dashboard-keys-card, -.dash-page .dashboard-quickstart-card { - margin-bottom: var(--dashboard-major-gap) !important; +.dash-page .connect-wm-mark { + width: 34px; + height: 34px; + margin-left: -10px; + display: grid; + place-items: center; + border-radius: 50%; + background: #111111; + box-shadow: 0 0 0 2px #000000; + color: #faf8f5; } -.dash-page .dashboard-install-card { - margin-bottom: 0 !important; +.dash-page .connect-wm-mark:first-child { + margin-left: 0; } -@media (max-width: 860px) { - .dash-page .dashboard-cta-row--primary, - .dash-page .dashboard-cta-row--resources, - .dash-page .dashboard-credentials-card, - .dash-page .dashboard-keys-card, - .dash-page .dashboard-quickstart-card { - margin-bottom: var(--dashboard-mobile-major-gap) !important; - } +.dash-page .connect-wm-mark img, +.dash-page .connect-wm-mark svg { + width: 18px; + height: 18px; + object-fit: contain; } -/* ── Alert: icon + text as one centered flex row (replaces the - absolutely-positioned icon, which left an 8px gap and felt off-center). ── */ -.dash-page .dash-alert { +.dash-page .connect-wm-tabbar { display: flex; align-items: center; - gap: 14px; - padding: 16px 22px; - min-height: 56px; + flex-wrap: nowrap; + gap: 10px; + height: 46px; + min-height: 46px; + margin-bottom: 36px; + padding: 0 10px; + border: 1px solid #262b30; + border-radius: 6px; + overflow-x: auto; } -.dash-page .dash-alert .dash-alert-icon { - position: relative; - left: auto; - top: auto; - transform: none; - flex: 0 0 auto; - width: 24px; +.dash-page .connect-wm-tab { + gap: 6px; height: 24px; + min-height: 24px; + padding: 0 10px; + border-radius: 3px; + background: #1d2227; + color: #8f9294; + font-family: "Google Sans Code", var(--font-mono); + font-size: 13px; + font-weight: 400; + letter-spacing: 0.26px; + line-height: 1; + text-transform: uppercase; +} + +.dash-page .connect-wm-tab:hover:not(.connect-wm-tab--active) { + color: #faf8f5; +} + +.dash-page .connect-wm-tab--active { + background: #faf8f5; color: #000000; - background: transparent; - clip-path: none; - display: block; } -.dash-page .dash-alert .dash-alert-icon::before, -.dash-page .dash-alert .dash-alert-icon::after { - content: none; +.dash-page .connect-wm-icon--codex { + width: 18px; + height: 18px; } -.dash-page .dash-alert p { - font-size: 16px; - line-height: 1.4; +.dash-page .connect-wm-client-badge .connect-wm-icon--codex { + width: 58px; + height: 58px; } -/* Dashboard heading subtitles: keep these at the same scale as card subtitles. */ -.dash-page .dashboard-header p, -.dash-page .dashboard-section-head p { - color: #b8bbbe; - font-size: 18px; - font-weight: 400; - line-height: 1.3; +.dash-page .connect-wm-mark .connect-wm-icon--codex { + width: 26px; + height: 26px; } -.dash-page .dashboard-header, -.dash-page .dash-alert, -.dash-page .dashboard-cta-row--primary, -.dash-page .dashboard-section-head, -.dash-page .dashboard-cta-row--resources, -.dash-page .dashboard-credentials-card, -.dash-page .dashboard-keys-card, -.dash-page .dashboard-quickstart-card, -.dash-page .dashboard-install-card { - animation: dashboardReveal 420ms cubic-bezier(0.16, 1, 0.3, 1) both; +.dash-page .connect-wm-tab-mark, +.dash-page .connect-wm-tab-mark svg, +.dash-page .connect-wm-tab-mark img { + width: 12px; + height: 12px; } -.dash-page .dashboard-header { - animation-delay: 20ms; +.dash-page .connect-wm-tab-mark img { + object-fit: contain; } -.dash-page .dash-alert { - animation-delay: 55ms; +.dash-page .connect-wm-tab-mark:has(.connect-wm-icon--codex) { + display: inline-flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; } -.dash-page .dashboard-cta-row--primary { - animation-delay: 90ms; +.dash-page .connect-wm-tab-mark img.connect-wm-icon--codex { + width: 16px; + height: 16px; + transform: none; } -.dash-page .dashboard-section-head { - animation-delay: 125ms; +.dash-page .connect-wm-guide:has(.connect-wm-client) { + position: relative; + --connect-line-x: 74px; } -.dash-page .dashboard-cta-row--resources { - animation-delay: 160ms; +.dash-page .connect-wm-guide:has(.connect-wm-client)::before { + content: ""; + position: absolute; + left: var(--connect-line-x); + top: 47px; + z-index: 0; + width: 1px; + height: 35px; + background: #262b30; + transform: translateX(-50%); + pointer-events: none; } -.dash-page .dashboard-credentials-card { - animation-delay: 195ms; +.dash-page .connect-wm-guide:has(.connect-wm-client) .connect-wm-client, +.dash-page .connect-wm-guide:has(.connect-wm-client) .connect-wm-timeline li, +.dash-page .connect-wm-guide:not(:has(.connect-wm-client)) .connect-wm-timeline li { + margin-left: calc(var(--connect-line-x) - 35.5px); } -.dash-page .dashboard-keys-card { - animation-delay: 230ms; +.dash-page .connect-wm-guide:not(:has(.connect-wm-client)) { + position: relative; + --connect-line-x: 40px; } -.dash-page .dashboard-quickstart-card { - animation-delay: 265ms; +.dash-page .connect-wm-guide:not(:has(.connect-wm-client))::before { + content: ""; + position: absolute; + left: var(--connect-line-x); + top: 47px; + z-index: 0; + width: 1px; + height: 32px; + background: #262b30; + transform: translateX(-50%); + pointer-events: none; } -.dash-page .dashboard-install-card { - animation-delay: 300ms; +.dash-page .connect-wm-client { + position: relative; + z-index: 1; + display: grid; + grid-template-columns: 71px minmax(0, 1fr); + align-items: center; + gap: 35px; + margin-bottom: 40px; } -.dash-page .dashboard-cta-row--primary { - animation: none !important; - opacity: 1; - filter: none; - transform: none; +.dash-page .connect-wm-client::after { + content: ""; + position: absolute; + left: 35px; + top: 71px; + bottom: -40px; + width: 1px; + background: #262b30; } -@keyframes dashboardReveal { - from { - opacity: 0; - filter: blur(5px); - transform: translate3d(0, 10px, 0) scale(0.992); - } +.dash-page .connect-wm-client-badge { + width: 71px; + height: 71px; + margin: 0; + display: grid; + place-items: center; + border: 1px solid rgba(250, 248, 245, 0.55); + border-radius: 50%; + background: #000000; +} - to { - opacity: 1; - filter: blur(0); - transform: translate3d(0, 0, 0) scale(1); - } +.dash-page .connect-wm-client-badge img, +.dash-page .connect-wm-client-badge svg { + width: 41px; + height: 41px; + object-fit: contain; } -.dashboard-nav .lp-nav-cta { +.dash-page .connect-wm-client h3 { + font-size: 36px; + font-weight: 400; line-height: 1; } -.dashboard-nav .lp-nav-cta svg { - display: block; - margin-top: 1px; +.dash-page .connect-wm-timeline { + gap: 56px; } -.dash-page .dashboard-confirm-backdrop { - position: fixed; - inset: 0; - z-index: 2000; - display: grid; - place-items: center; - padding: 24px; - background: rgba(0, 0, 0, 0.68); - backdrop-filter: blur(14px); - animation: dashboardConfirmBackdropIn 140ms ease both; +.dash-page .connect-wm-timeline li { + align-items: start; + grid-template-columns: 71px minmax(0, 1fr); + gap: 35px; } -.dash-page .dashboard-confirm-dialog { - width: min(440px, 100%); - padding: 28px; - display: grid; - grid-template-columns: minmax(0, 1fr); - gap: 24px; - border: 1px solid rgba(250, 248, 245, 0.1); - border-radius: 12px; - background: rgba(255, 255, 255, 0.08); - color: #faf8f5; - box-shadow: 0 28px 90px rgba(0, 0, 0, 0.55); - animation: dashboardConfirmDialogIn 280ms cubic-bezier(0.16, 1, 0.3, 1) both; +.dash-page .connect-wm-timeline li > div { + min-width: 0; } -.dash-page .dashboard-confirm-copy h3 { - margin: 0; +.dash-page .connect-wm-timeline--solo { + margin-top: 8px; +} + +.dash-page .connect-wm-timeline li:not(:last-child)::before { + left: 35px; + top: 33px; + bottom: -56px; + background: #262b30; +} + +.dash-page .connect-wm-num { + width: 33px; + height: 33px; + margin: -2px auto 0; + border-color: rgba(250, 248, 245, 0.7); + background: #000000; + font-family: "Google Sans Code", var(--font-mono); + font-size: 13px; + font-weight: 300; +} + +.dash-page .connect-wm-timeline h3 { + margin-bottom: 6px; + font-size: 28px; + font-weight: 400; + line-height: 1; +} + +.dash-page .connect-wm-timeline p { + color: #8f9294; + font-size: 15px; + font-weight: 400; + line-height: 1.4; +} + +.dash-page .connect-wm-timeline p code { color: #faf8f5; - font-size: 24px; - font-weight: 600; - line-height: 1.12; - letter-spacing: 0; + font-family: "Google Sans Code", var(--font-mono); + font-weight: 500; } -.dash-page .dashboard-confirm-copy p { - margin: 10px 0 0; - color: #b8bbbe; - font-size: 18px; - font-weight: 400; - line-height: 1.35; +.dash-page .connect-wm-code code { + font-family: "Google Sans Code", var(--font-mono); + font-weight: 300; } -.dash-page .dashboard-confirm-actions { +.dash-page .connect-wm-code { display: flex; - justify-content: flex-end; - gap: 12px; + align-items: center; + border: 1px solid #262b30; + border-radius: 6px; + background: #000000; } -.dash-page .dashboard-confirm-cancel, -.dash-page .dashboard-confirm-remove { - min-height: 48px; - padding: 0 22px; - border-radius: 24px; - font-size: 16px; - font-weight: 500; - line-height: 1; - letter-spacing: 0; +.dash-page .connect-wm-copy { + position: static; + flex: 0 0 auto; + margin-right: 14px; + transform: none; } -.dash-page .dashboard-confirm-cancel { - min-width: 104px; +.dash-page .connect-wm-code pre { + flex: 1; + min-width: 0; + padding: 18px 16px 18px 22px; + overflow: hidden; + white-space: pre-wrap; + overflow-wrap: anywhere; + font-size: 15px; + font-weight: 300; + line-height: 1.4; + letter-spacing: 0.15px; } -.dash-page .dashboard-confirm-remove { - min-width: 112px; - border-color: #ff6b6b; - background: #ff6b6b; - color: #fff; +.dash-page .connect-wm-code--source pre, +.dash-page .connect-wm-code--source code { + overflow-x: auto; + overflow-y: hidden; + white-space: pre; + overflow-wrap: normal; + word-break: normal; + scrollbar-width: none; } -.dash-page .dashboard-confirm-remove:hover:not(:disabled) { - border-color: #ff8f8f; - background: #ff8f8f; - color: #fff; +.dash-page .connect-wm-code--source pre::-webkit-scrollbar { + display: none; + height: 0; } -.dash-page .dashboard-confirm-remove:disabled { - color: rgba(255, 255, 255, 0.72); +.dash-page .connect-wm-code--source .hljs-keyword, +.dash-page .connect-wm-code--source .hljs-string, +.dash-page .connect-wm-code--source .hljs-comment, +.dash-page .connect-wm-code--source .hljs-attr, +.dash-page .connect-wm-code--source .hljs-property, +.dash-page .connect-wm-code--source .hljs-number, +.dash-page .connect-wm-code--source .hljs-literal { + font-weight: 400; } -.dash-page .dashboard-account-ready-dialog { - display: flex; - width: min(560px, 100%); - flex-direction: column; - align-items: flex-start; - flex-shrink: 0; - padding: 0; - gap: 0; +.dash-page .connect-wm-console { + align-self: flex-start; + height: 52px; + margin: 8px 0 8px 90px; + padding: 0 28px; + border: 1px solid #54575a; + border-radius: 26px; + background: transparent; + font-family: var(--font-mono); + font-size: 16px; + font-weight: 400; + letter-spacing: 0.64px; } -.dash-page .dashboard-account-ready-body { - display: flex; - padding: 16px 24px; - flex-direction: column; - align-items: flex-start; - gap: 10px; - align-self: stretch; +.dash-page .connect-wm-console:hover { + border-color: #faf8f5; } -.dash-page .dashboard-account-ready-body h3, -.dash-page .dashboard-account-ready-body p { - margin: 0; +.dash-page .connect-wm-memories { + display: block; + min-height: 349px; + margin-top: 12px; + padding: 0; + border-radius: 6px; + background: + linear-gradient(90deg, #e7e3f6 0 36%, rgba(231, 227, 246, 0.94) 46%, rgba(231, 227, 246, 0) 62%), + url('/sept2026/memories-card.png') center / 100% 100% no-repeat; } -.dash-page .dashboard-account-ready-actions { - padding: 16px 24px; - gap: 12px; - align-self: stretch; - border-top: 1px solid rgba(250, 248, 245, 0.1); +.dash-page .connect-wm-memories-copy { + width: min(280px, 48%); + padding: 48px 0 40px 48px; } -.dash-page .dashboard-account-ready-console { - min-height: 48px; - min-width: 152px; - padding: 0 22px; - border-radius: 24px; - font-size: 16px; - font-weight: 500; - line-height: 1; - letter-spacing: 0; - display: inline-flex; - align-items: center; - justify-content: center; - text-decoration: none; +.dash-page .connect-wm-memories-copy h3 { + color: #000000; + font-size: 44px; + font-weight: 425; + line-height: 0.95; } -@media (max-width: 860px) { - .dash-page .dashboard-account-ready-actions { - flex-direction: column-reverse; - } +.dash-page .connect-wm-memories-copy p { + max-width: 248px; + margin-top: 18px; + color: #5e5f5b; + font-size: 18px; + font-weight: 400; + line-height: 1.5; +} - .dash-page .dashboard-account-ready-console { - width: 100%; - } +.dash-page .connect-wm-memories-copy a { + margin-top: 56px; + color: #000000; + font-family: var(--font-mono); + font-size: 15px; + font-weight: 300; + letter-spacing: 0.6px; + text-transform: uppercase; + text-decoration-thickness: 1px; + text-underline-offset: 6px; } -@keyframes dashboardConfirmBackdropIn { - from { - opacity: 0; - } +.dash-page .sept-section.card { + margin: 0 0 56px !important; + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; + box-shadow: none !important; +} - to { - opacity: 1; - } +.dash-page .sept-section .card-header { + align-items: flex-end; + margin-bottom: 18px; } -@keyframes dashboardConfirmDialogIn { - from { - opacity: 0; - filter: blur(6px); - transform: translate3d(0, 10px, 0) scale(0.98); - } +.dash-page .sept-section .card-title { + font-family: Ratch, sans-serif; + font-size: 44px; + font-weight: 425; + line-height: 0.95; +} - to { - opacity: 1; - filter: blur(0); - transform: translate3d(0, 0, 0) scale(1); - } +.dash-page .sept-section .card-subtitle { + max-width: 778px; + margin-top: 8px; + color: #b1b4b6; + font-size: 18px; + font-weight: 400; + line-height: 1.5; } -@media (max-width: 860px) { - .dash-page .dashboard-header p, - .dash-page .dashboard-section-head p { - font-size: 16px; - } +.dash-page .dashboard-keys-card .card-header { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + grid-template-areas: + "title actions" + "sub sub"; + align-items: start; + column-gap: 24px; + row-gap: 8px; +} - .dash-page .dashboard-confirm-dialog { - gap: 20px; - padding: 22px; - } +.dash-page .dashboard-keys-card .card-header > div:first-child { + display: contents; +} - .dash-page .dashboard-confirm-copy h3 { - font-size: 24px; - } +.dash-page .dashboard-keys-card .card-title { + grid-area: title; +} - .dash-page .dashboard-confirm-copy p { - font-size: 16px; - } +.dash-page .dashboard-keys-card .card-subtitle { + grid-area: sub; + max-width: none; +} - .dash-page .dashboard-confirm-actions { - flex-direction: column-reverse; - margin-top: 4px; - } +.dash-page #delegate-keys .card-subtitle, +.dash-page #delegate-keys .dashboard-empty-message, +.dash-page #delegate-keys .dashboard-empty-message-link, +.dash-page #delegate-keys .dashboard-key-table td, +.dash-page #delegate-keys .dashboard-key-name, +.dash-page #delegate-keys label, +.dash-page #delegate-keys p { + font-family: "Google Sans Flex", sans-serif; +} - .dash-page .dashboard-confirm-cancel, - .dash-page .dashboard-confirm-remove { - width: 100%; - } +.dash-page #delegate-keys.dashboard-keys-card { + margin-top: 48px !important; +} - /* Re-assert the sectioned dialog's zero outer padding — it comes after - .dashboard-confirm-dialog's mobile padding above at equal specificity. */ - .dash-page .dashboard-account-ready-dialog { - gap: 0; - padding: 0; - } +.dash-page .dashboard-keys-card .card-title { + line-height: 1; } -@media (prefers-reduced-motion: reduce) { - .wm-route-pending img, - .dash-page .dashboard-header, - .dash-page .dash-alert, - .dash-page .dashboard-cta-row--primary, - .dash-page .dashboard-section-head, - .dash-page .dashboard-cta-row--resources, - .dash-page .dashboard-credentials-card, - .dash-page .dashboard-keys-card, - .dash-page .dashboard-quickstart-card, - .dash-page .dashboard-install-card, - .dash-page .dashboard-add-key-form, - .dash-page .dashboard-add-key-field, - .dash-page .dashboard-add-key-note, - .dash-page .dashboard-add-key-actions, - .dash-page .dashboard-confirm-backdrop, - .dash-page .dashboard-confirm-dialog { - animation: none; - } +.dash-page .dashboard-keys-card .card-header-actions { + grid-area: actions; + align-self: center; + margin-top: 0; } -/* ── Sign-in screen (Figma 2556:112) ───────────────────────── */ -.wm-signin { - position: fixed; - inset: 0; - z-index: 1000; - background: #050608; - overflow: hidden; - display: grid; - place-items: center; - font-family: var(--font-sans); +.dash-page .dashboard-keys-card { + overflow: visible; +} + +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh, +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh:hover, +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh:focus, +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh:focus-visible { + display: inline-flex; + align-items: center; + gap: 8px; + width: auto; + min-width: 0; + min-height: 0; + height: auto; + padding: 0; + border: 0; + border-radius: 0; + background: transparent; + color: #faf8f5 !important; + -webkit-text-fill-color: #faf8f5; + font-family: var(--font-mono); + font-size: 15px; + font-weight: 300; + letter-spacing: 0.6px; + line-height: 1; + text-transform: uppercase; + box-shadow: none; } -.wm-signin--page { - position: relative; - inset: auto; - z-index: 0; - min-height: 100vh; - min-height: 100dvh; - overflow: clip; +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh span { + border-bottom: 1px solid rgba(250, 248, 245, 0.55); + padding-bottom: 1px; } -.wm-signin-backdrop { - position: absolute; - inset: 0; - z-index: 0; +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh svg { + display: block; + width: 13px; + height: 13px; + flex: 0 0 auto; + stroke-width: 1.75; } -.wm-signin-aurora { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - object-fit: cover; - object-position: center; - opacity: 1; - z-index: 0; - pointer-events: none; +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add, +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add:focus, +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add:focus-visible { + width: auto; + height: 52px; + min-height: 52px; + padding: 10px 26px; + border: 1px solid #54575a; + border-radius: 26px; + background: transparent; + color: #faf8f5 !important; + -webkit-text-fill-color: #faf8f5; + font-family: var(--font-mono); + font-size: 16px; + font-weight: 400; + letter-spacing: 0.64px; + text-transform: uppercase; + box-shadow: none; } -.wm-signin::after { - content: ""; - position: absolute; - inset: 0; - z-index: 1; - pointer-events: none; - background: linear-gradient( - 90deg, - rgba(5, 6, 8, 0) 0%, - rgba(5, 6, 8, 0) 42%, - rgba(5, 6, 8, 0.5) 62%, - rgba(5, 6, 8, 0.74) 82%, - rgba(5, 6, 8, 0.74) 100% - ); +.dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add:hover:not(:disabled) { + border-color: #faf8f5; + background: #faf8f5; + color: #000000 !important; + -webkit-text-fill-color: #000000; } -.wm-signin-close { - position: absolute; - top: 28px; - right: 28px; - z-index: 3; - width: 42px; - height: 42px; - display: grid; - place-items: center; - border: 1px solid rgba(250, 248, 245, 0.18); - border-radius: 50%; - background: rgba(255, 255, 255, 0.06); - color: #faf8f5; - cursor: pointer; +.dash-page .dashboard-key-table th.dashboard-key-table-actions { + color: transparent; + font-size: 0; } -.wm-signin-close svg { - transform: rotate(45deg); +.dash-page .dashboard-keys-refresh:hover:not(:disabled) { + background: transparent; + color: #ffffff; } -.wm-signin-inner { - position: relative; - z-index: 2; - width: min(1480px, calc(100% - 112px)); - display: grid; - grid-template-columns: minmax(520px, 640px) minmax(560px, 1fr); - align-items: center; - gap: clamp(64px, 5.2vw, 96px); +.dash-page .dashboard-keys-add { + border-color: #54575a; + background: transparent; + color: #faf8f5; + font-family: var(--font-mono); + font-size: 16px; + font-weight: 400; + letter-spacing: 0.64px; + text-transform: uppercase; } -.wm-signin-card { - width: clamp(520px, 33vw, 640px); - max-width: 100%; - aspect-ratio: 900 / 1010; - padding: clamp(52px, 5.3vh, 76px) 0 clamp(42px, 4.8vh, 62px); - border-radius: 18px; +.dash-page .dashboard-keys-add:hover:not(:disabled) { + border-color: #faf8f5; + background: #faf8f5; + color: #000000; +} + +.dash-page .dashboard-key-table-wrap { border: 0; - background: - radial-gradient(82% 48% at 87% 2%, rgba(0, 91, 153, 0.78) 0%, rgba(0, 60, 112, 0.5) 35%, rgba(0, 17, 31, 0) 72%), - radial-gradient(78% 45% at 1% 16%, rgba(129, 120, 178, 0.44) 0%, rgba(43, 55, 90, 0.28) 44%, rgba(0, 12, 22, 0) 78%), - linear-gradient(180deg, rgba(12, 34, 61, 0.96) 0%, rgba(0, 64, 96, 0.8) 46%, rgba(0, 14, 22, 0.95) 74%, #01060a 100%); - backdrop-filter: blur(30px); - -webkit-backdrop-filter: blur(30px); - text-align: center; - box-shadow: none; + border-radius: 0; + background: transparent; } -.wm-signin-logo { - display: block; - width: min(330px, 46%); - max-width: none; - height: auto; - margin: 0 auto; +.dash-page .dashboard-key-table th { + padding: 0 12px 10px 0; + border-bottom: 1px solid #262b30; + color: #8f9294; + font-family: var(--font-mono); + font-size: 12px; + font-weight: 300; + letter-spacing: 0.4px; + text-transform: uppercase; } -.wm-signin-sub { - width: min(610px, 78%); - margin: clamp(28px, 3.7vh, 42px) auto clamp(42px, 5.4vh, 58px); - color: #faf8f5; - font-size: clamp(23px, 1.55vw, 34px); - font-weight: 400; - line-height: 1.34; +.dash-page .dashboard-key-table td { + padding: 16px 12px 16px 0; + border-bottom: 1px solid #262b30; + font-size: 15px; } -.wm-page .wm-signin-google, -.wm-page .wm-signin-wallet button { - width: 100%; - min-height: clamp(62px, 6vh, 86px); - padding: 0 clamp(30px, 3.2vw, 48px); - border-radius: 999px; - border: 2px solid rgba(250, 248, 245, 0.94); - background: transparent; +.dash-page .dashboard-key-name { color: #faf8f5; - font-family: var(--font-sans); - font-size: clamp(20px, 1.18vw, 26px); - font-weight: 500; - letter-spacing: 0; - display: flex; - align-items: center; - justify-content: center; - gap: 12px; - cursor: pointer; - box-sizing: border-box; + font-weight: 400; } -.wm-signin-google { - position: relative; - width: min(552px, 62%); - margin: 0 auto clamp(22px, 2.3vh, 28px); - border-color: #faf8f5; +.dash-page .dashboard-key-public { + display: inline-flex; + align-items: center; + height: 28px; + padding: 0 12px; + border-radius: 4px; + background: #262b30; + color: #faf8f5; + font-size: 12px; + font-weight: 300; + letter-spacing: 0.6px; } -.wm-page .wm-signin-google { - width: min(552px, 62%); +.dash-page .dashboard-key-created { + color: #8f9294 !important; + font-weight: 400; } -.wm-signin-google svg { - position: absolute; - left: clamp(30px, 10%, 48px); - flex: 0 0 auto; - width: clamp(27px, 1.65vw, 34px); - height: clamp(27px, 1.65vw, 34px); +.dash-page .dashboard-key-checkbox-box { + width: 20px; + height: 20px; + flex-basis: 20px; + border: 1px solid #262b30; + border-radius: 4px; + background: transparent; } -.wm-signin-google:hover { - background: rgba(255, 255, 255, 0.08); +.dash-page .dashboard-key-row-actions .dashboard-key-icon-action { + width: 22px; + min-width: 22px; + height: 22px; + min-height: 22px; + padding: 0; + border: 0; + border-radius: 0; + background: transparent; + color: #faf8f5; } -.wm-signin-wallet { - display: block; - width: min(552px, 62%); - margin: 0 auto; +.dash-page .dashboard-key-row-actions .btn-danger.dashboard-key-icon-action, +.dash-page .dashboard-key-row-actions .btn-secondary.dashboard-key-icon-action, +.dash-page .dashboard-key-row-actions .btn-secondary.dashboard-key-icon-action:hover:not(:disabled), +.dash-page .dashboard-key-row-actions .btn-danger.dashboard-key-icon-action:hover:not(:disabled) { + border: 0; + background: transparent; + color: #faf8f5; } -.wm-signin-wallet button { - background: transparent !important; - border: 2px solid rgba(250, 248, 245, 0.94) !important; - border-radius: 999px !important; - box-shadow: none !important; +.dash-page .dashboard-section-head { + margin: 8px 0 18px; } -.wm-signin-wallet button, -.wm-signin-wallet button * { - color: #faf8f5 !important; +.dash-page .dashboard-section-head h3 { + font-family: Ratch, sans-serif; + font-size: 44px; + font-weight: 425; + line-height: 0.95; } -.wm-signin-wallet button:hover { - background: rgba(255, 255, 255, 0.08) !important; +.dash-page .dashboard-section-head p { + margin-top: 8px; + color: #b1b4b6; + font-size: 18px; + font-weight: 400; + line-height: 1.5; } -.wm-signin-tos { - width: min(360px, 64%); - margin: clamp(38px, 5vh, 54px) auto 0; - color: #8f9294; - font-size: clamp(13px, 0.9vw, 18px); - font-weight: 400; - line-height: 1.34; +.dash-page .dashboard-resource-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 24px; + margin-bottom: 64px; } -.wm-signin-tos a { +.dash-page .dashboard-resource { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 12px; + min-height: 110px; + padding: 19px 16px 16px 22px; + border: 1px solid #262b30; + border-radius: 6px; + background: transparent; color: #faf8f5; - text-decoration: underline; + text-decoration: none; } -.wm-signin-trusted { - text-align: center; +.dash-page .dashboard-resource:hover { + border-color: #54575a; } -.wm-signin-trusted h2 { - margin: 0 0 44px; - color: #faf8f5; - font-size: 72px; - line-height: 0.9; - font-weight: 500; - letter-spacing: 0; - text-align: center; +.dash-page .dashboard-resource strong { + display: block; + font-size: 18px; + font-weight: 400; + line-height: 1.3; } -.wm-signin-trusted h2 span { - color: transparent; - background: linear-gradient(93deg, #383bff 0%, #9a57ff 48%, #eda0ff 98%); - -webkit-background-clip: text; - background-clip: text; +.dash-page .dashboard-resource em { + display: block; + max-width: 150px; + margin-top: 8px; + color: #8f9294; + font-style: normal; + font-size: 15px; + font-weight: 400; + line-height: 1.4; } -.wm-signin-logos { +.dash-page .dashboard-resource-icon { display: grid; - grid-template-columns: repeat(3, auto); - justify-content: center; - justify-items: center; - align-items: center; - gap: 36px 52px; + flex: 0 0 48px; + place-items: center; + width: 48px; + height: 48px; + border: 1px solid #262b30; + border-radius: 6px; } -.wm-signin-logos img { - height: auto; - max-width: 100%; +.dash-page .dashboard-resource-icon img, +.dash-page .dashboard-resource-icon svg { + width: 24px; + height: 24px; object-fit: contain; - opacity: 0.92; } -@media (max-width: 900px) { - .wm-signin-inner { - grid-template-columns: 1fr; - gap: 40px; - justify-items: center; - width: calc(100% - 40px); +@media (max-width: 860px) { + .dash-page .connect-wm-tabbar { + height: auto; + flex-wrap: wrap; + padding: 8px 10px; } - .wm-signin-card { - width: min(100%, 640px); - aspect-ratio: auto; - min-height: min(760px, calc(100vh - 72px)); - padding: 64px 0 50px; + .dash-page .connect-wm-hero h2 { + font-size: 36px; } - .wm-signin-logo { - width: min(330px, 58%); + .dash-page .sept-section .card-title, + .dash-page .dashboard-section-head h3, + .dash-page .connect-wm-memories-copy h3 { + font-size: 36px; } - .wm-signin-sub { - width: min(520px, 82%); - font-size: clamp(25px, 6.2vw, 34px); - margin: 36px auto 58px; + .dash-page .dashboard-keys-card .card-header { + grid-template-columns: 1fr; + grid-template-areas: + "title" + "sub" + "actions"; } - .wm-page .wm-signin-google, - .wm-page .wm-signin-wallet { - width: min(440px, 82%); + .dash-page .dashboard-keys-card .card-header-actions { + justify-content: flex-start; } - .wm-signin-google, - .wm-signin-wallet button { - min-height: 72px; - font-size: clamp(22px, 5.4vw, 30px); + .dash-page .connect-wm-paths, + .dash-page .dashboard-resource-grid { + grid-template-columns: 1fr; } - .wm-signin-google svg { - position: static; - left: auto; + + + .dash-page .connect-wm-console { + margin-left: 0; + height: auto; + min-height: 52px; + white-space: normal; + text-align: center; } - .wm-signin-tos { - width: min(360px, 72%); - margin-top: 54px; - font-size: clamp(14px, 3.4vw, 20px); + .dash-page .connect-wm-memories { + min-height: 420px; + background-position: right center; + background-size: cover; } - .wm-signin-trusted { - display: none; + .dash-page .connect-wm-memories-copy { + width: min(100%, 320px); + padding: 28px 20px 24px; } } -/* Setup flow: align the create-key screen with the dashboard visual system. */ -.setup-classic { - background: #000000; +/* Pre-migration cleanup uses the same open section as Delegate keys, not a card. */ +.dash-page .dashboard-cleanup-card.card { + margin-top: 28px; + margin-bottom: 0 !important; + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; + box-shadow: none !important; + overflow: visible; } -.setup-classic-container { - width: min(1100px, calc(100% - 64px)); - max-width: 1100px; - min-height: calc(100vh - 128px); - padding: 34px 0 68px; +.dash-page .dashboard-cleanup-card .card-title { + font-family: Ratch, sans-serif; + font-size: 44px; + font-weight: 425; + line-height: 0.95; + letter-spacing: 0; } -.setup-classic-panel { - width: min(560px, 100%); - margin: 0 auto; +.dash-page .dashboard-cleanup-card .card-subtitle, +.dash-page .dashboard-cleanup-status { + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 18px; + font-weight: 400; + line-height: 1.5; } -.setup-classic-title { - margin: 0 0 14px; - color: #faf8f5; - font-size: 36px; - font-weight: 500; - line-height: 0.98; - letter-spacing: 0; +.dash-page .dash-alert--info, +.dash-page .dashboard-cleanup-card .sd-warning { + display: flex; + flex-wrap: nowrap; + align-items: flex-start; + gap: 12px; + margin: 8px 0 28px; + padding: 16px 18px; + border: 1px solid rgba(232, 255, 117, 0.45); + border-radius: 6px; + background: transparent; + color: #e8ff75; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; + font-weight: 400; + line-height: 1.5; } -.setup-classic-description { - max-width: 560px; - margin: 0 auto 38px; - color: #b8bbbe; - font-size: 18px; +.dash-page .dash-alert--info { + margin-bottom: 36px !important; +} + +.dash-page .dash-alert--info p, +.dash-page .dashboard-cleanup-card .sd-warning span { + flex: 1; + min-width: 0; + margin: 0; + color: #e8ff75; + font-family: inherit; + font-size: inherit; font-weight: 400; - line-height: 1.35; + line-height: inherit; } -.setup-classic-feature-card { - margin-bottom: 34px !important; - padding: 30px; - border: 1px solid #54575a !important; - border-radius: 24px !important; - background: #000000 !important; - box-shadow: none !important; +.dash-page .dash-alert--info .dash-alert-icon, +.dash-page .dashboard-cleanup-card .sd-warning svg { + width: 18px; + height: 18px; + margin-top: 2px; + color: #e8ff75; + flex: 0 0 auto; } -.setup-classic-feature { - margin-bottom: 26px; +.dash-page .dash-alert-link, +.dash-page .dashboard-cleanup-card .sd-warning a { + color: #e8ff75; + font: inherit; + text-decoration: underline; + text-underline-offset: 3px; } -.setup-classic-feature strong { - color: #faf8f5; - font-size: 24px; - font-weight: 650; - line-height: 1.18; - letter-spacing: 0; +.dash-page .dash-alert-link:hover, +.dash-page .dashboard-cleanup-card .sd-warning a:hover { + text-decoration-thickness: 2px; } -.setup-classic-feature p { - margin: 8px 0 0; - color: #b8bbbe; - font-size: 18px; - font-weight: 400; - line-height: 1.3; - letter-spacing: 0; +.dash-page .dashboard-cleanup-card .sd-load-prompt { + justify-content: flex-start; + margin-top: 0; } -.setup-classic-generate { - width: 236px; - height: 52px; +.dash-page .dashboard-cleanup-load, +.dash-page .dashboard-cleanup-load:hover:not(:disabled) { min-height: 52px; - padding: 0 30px; + height: 52px; + padding: 10px 28px; + border: 1px solid #54575a; border-radius: 26px; - background: #faf8f5; - border-color: #faf8f5; - color: #000000; - font-size: 18px; - font-weight: 650; - line-height: 0.84; - letter-spacing: 0; + background: transparent; + color: #faf8f5; + font-family: "Google Sans Code", "JetBrains Mono", monospace; + font-size: 16px; + font-weight: 400; + letter-spacing: 0.64px; + text-transform: uppercase; } -.setup-classic-generate:hover:not(:disabled) { - background: #e8ff75; - border-color: #e8ff75; +.dash-page .dashboard-cleanup-load:hover:not(:disabled) { + border-color: #faf8f5; + background: #faf8f5; color: #000000; - transform: none; } -.setup-classic-actions { - display: flex; - flex-direction: column; - align-items: center; - gap: 26px; +/* Add-key form follows the same flat Sept 2026 controls, not the old gray card. */ +.dash-page .dashboard-add-key-form { + gap: 18px; + margin-bottom: 28px; + padding: 22px 22px 18px; + border: 1px solid #262b30; + border-radius: 6px; + background: transparent; } -.setup-classic-import-trigger { - padding: 0; - border: 0; - background: transparent; - color: #8f9294; - font: inherit; - font-size: 18px; +.dash-page .dashboard-add-key-label { + color: #faf8f5; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; font-weight: 400; - line-height: 1.3; - letter-spacing: 0; - text-decoration: none; - cursor: pointer; - box-shadow: none; + line-height: 1.4; } -.setup-classic-import-trigger:hover:not(:disabled) { +.dash-page .dashboard-add-key-input { + min-height: 48px; + padding: 12px 14px; + border: 1px solid #262b30; + border-radius: 6px; + background: #000000; color: #faf8f5; - background: transparent; - transform: none; - box-shadow: none; + font-family: "Google Sans Flex", sans-serif; + font-size: 16px; + font-weight: 400; } -.setup-classic-import-screen { - text-align: center; +.dash-page .dashboard-add-key-input:focus { + border-color: #8f9294; + box-shadow: none; } -.setup-classic-divider { - margin: 30px 0 22px; +.dash-page .dashboard-add-key-note { + max-width: 640px; color: #8f9294; - font-size: 18px; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; font-weight: 400; - line-height: 1.3; + line-height: 1.5; } -.setup-classic .setup-import-textarea { - min-height: 112px; - padding: 20px; - border: 1px solid #54575a; - border-radius: 16px; - background: #000000; - color: #faf8f5; - font-size: 18px; - line-height: 1.4; +.dash-page .dashboard-add-key-actions { + gap: 12px; + margin-top: 4px; } -.setup-classic .setup-import-textarea:focus { - border-color: #8f9294; +.dash-page .dashboard-add-key-cancel, +.dash-page .dashboard-add-key-create, +.dash-page .dashboard-add-key-cancel:hover:not(:disabled), +.dash-page .dashboard-add-key-create:hover:not(:disabled) { + min-height: 52px; + height: 52px; + padding: 10px 26px; + border: 1px solid #54575a; + border-radius: 26px; + background: transparent; + color: #faf8f5; + font-family: "Google Sans Code", "JetBrains Mono", monospace; + font-size: 16px; + font-weight: 400; + letter-spacing: 0.64px; + text-transform: uppercase; box-shadow: none; } -.setup-classic-import-actions { - display: block; - margin-top: 22px; +.dash-page .dashboard-add-key-create { + border-color: #faf8f5; } -.setup-classic .setup-import-button { - width: 100%; - height: 62px; - min-height: 62px; - margin-top: 22px; - padding: 0 30px; - border-radius: 31px; - background: #e8ff75; - border-color: #e8ff75; +.dash-page .dashboard-add-key-cancel:hover:not(:disabled), +.dash-page .dashboard-add-key-create:hover:not(:disabled) { + border-color: #faf8f5; + background: #faf8f5; color: #000000; - font-size: 18px; - font-weight: 650; - line-height: 0.84; - letter-spacing: 0; } -.setup-classic-import-actions .setup-import-button { - margin-top: 0; +.dash-page .dashboard-namespaces-card .dashboard-key-table-wrap { + overflow: hidden; } -.setup-classic-back-button { - width: 132px; - height: 62px; - min-height: 62px; - border-radius: 31px; - border: 1px solid #faf8f5; - background: transparent; - color: #faf8f5; - font-size: 18px; - font-weight: 650; - line-height: 0.84; - box-shadow: none; +.dash-page .dashboard-namespaces-card .dashboard-namespace-table th:nth-child(2), +.dash-page .dashboard-namespaces-card .dashboard-namespace-table td:nth-child(2) { + width: 120px; + text-align: right; } -.setup-classic-back-button:hover:not(:disabled) { - background: rgba(255, 255, 255, 0.08); +.dash-page .dashboard-namespaces-card .dashboard-namespace-table a { color: #faf8f5; - transform: none; - box-shadow: none; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; + font-weight: 400; + line-height: 1.4; + text-decoration: none; + overflow-wrap: anywhere; } -.setup-classic-error { - margin-top: 14px; - padding: 14px 16px; - border: 1px solid rgba(255, 107, 107, 0.35); - border-radius: 16px; - background: rgba(255, 107, 107, 0.1); - color: #ff8f8f; - font-size: 16px; - line-height: 1.35; +.dash-page .dashboard-namespaces-card .dashboard-namespace-table a:hover { + text-decoration: underline; + text-underline-offset: 3px; } -.setup-classic-state { - min-height: 320px; - display: flex; - flex-direction: column; +.dash-page .dashboard-namespaces-card .dashboard-namespace-count { + color: #8f9294; + font-variant-numeric: tabular-nums; +} + +.dash-page .dashboard-namespace-error { + margin: 0 0 12px; + color: #e8ff75; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; + line-height: 1.5; +} + +.dash-page .connect-wm-timeline .connect-wm-console { + display: inline-flex; align-items: center; justify-content: center; - padding: 72px 0; - text-align: center; + align-self: flex-start; + margin: 28px 0 0; + line-height: 1; } -.setup-classic-spinner { - width: 44px; - height: 44px; - margin-bottom: 26px; - color: #faf8f5; - border-width: 4px; - opacity: 1; +.dash-page .connect-wm-sdk-tabs { + height: 46px; + min-height: 46px; + margin: 2px 0 12px; } -.setup-classic-state-title { - margin: 0 0 10px; - color: #faf8f5; - font-size: 24px; - font-weight: 500; - line-height: 1.25; +.dash-page .connect-wm-import { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 10px; + margin-top: 18px; } -.setup-classic-state-subtitle { - margin: 0; - color: #b8bbbe; - font-size: 18px; +.dash-page .connect-wm-import label { + color: #8f9294; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; font-weight: 400; - line-height: 1.35; } -.setup-classic-state-heading { - margin: 0 0 12px; +.dash-page .connect-wm-import textarea { + width: 100%; + min-height: 0; + padding: 18px 22px; + border: 1px solid #262b30; + border-radius: 6px; + background: #000000; color: #faf8f5; - font-size: 36px; - font-weight: 500; - line-height: 0.98; + font-family: "Google Sans Code", var(--font-mono); + font-size: 15px; + font-weight: 300; + line-height: 1.4; + letter-spacing: 0.15px; + resize: none; } -.setup-classic-ready-screen { - text-align: left; +.dash-page .connect-wm-import textarea::placeholder { + color: #8f9294; } -.setup-classic-ready-screen .setup-classic-title { - margin-bottom: 34px; - text-align: center; +.dash-page .connect-wm-import textarea:focus { + outline: none; + border-color: #8f9294; } -.setup-classic-ready-warning { - min-height: 56px; +.dash-page .connect-wm-import-error { + margin: 0; + color: #e8ff75; + font-size: 14px; +} + +.playground-key-gate { + order: 0; display: flex; - align-items: center; - gap: 14px; - margin-bottom: 24px; - padding: 16px 22px; - border: 0; - border-radius: 4px; - background: #e8ff75; + flex-direction: column; + gap: 22px; + width: 100%; + min-width: 0; + max-width: 100%; + margin: 36px 0 84px; } -.setup-classic .setup-classic-ready-warning { - border-radius: 4px; +.playground-key-note { + display: flex; + flex-direction: column; + align-items: stretch; + gap: 20px; + margin: 0; + padding: 24px 28px; + border: 1px solid rgba(232, 255, 117, 0.45); + border-radius: 6px; + background: transparent; + color: #e8ff75; } -.setup-classic-ready-warning-icon { +.playground-key-note-line { + display: flex; + align-items: flex-start; + gap: 10px; +} + +.playground-key-note svg { flex: 0 0 auto; - color: #000000; + margin-top: 2px; } -.setup-classic-ready-warning p { +.playground-key-note p { margin: 0; - color: #000000; - font-size: 16px; - font-weight: 500; - line-height: 1.4; + color: #e8ff75; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; + font-weight: 400; + line-height: 1.45; } -.setup-classic-ready-warning strong { - color: #000000; - font-weight: 700; +.playground-key-form { + display: flex; + flex-direction: column; + align-items: stretch; + gap: 10px; + width: 100%; + min-width: 0; } -.setup-key-panel { - overflow: hidden; - margin-bottom: 24px; - border: 1px solid #54575a; - border-radius: 24px; - background: #000000; +.playground-key-form label, +.playground-key-form a { + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; + font-weight: 400; + line-height: 1.4; } -.setup-key-row { - display: grid; - grid-template-columns: minmax(0, 1fr) auto; - gap: 18px; - align-items: center; - padding: 22px 28px; - border-bottom: 1px solid rgba(250, 248, 245, 0.1); +.playground-key-form a { + text-decoration: underline; + text-underline-offset: 3px; } -.setup-key-row:last-child { - border-bottom: 0; +.playground-key-form a:hover { + color: #faf8f5; } -.setup-key-main { +.playground-key-row { + display: flex; + align-items: center; + gap: 10px; + width: 100%; min-width: 0; } -.setup-key-label { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 8px; - color: #b8bbbe; - font-size: 16px; - font-weight: 500; - line-height: 1.25; +.playground-key-row input { + flex: 1; + min-width: 0; + height: 44px; + padding: 0 14px; + border: 1px solid #262b30; + border-radius: 6px; + background: #000000; + color: #faf8f5; + font-family: "Google Sans Code", ui-monospace, monospace; + font-size: 14px; } -.setup-key-label span { +.playground-key-row input::placeholder { color: #8f9294; - font-size: 14px; - font-weight: 400; } -.setup-key-value { - display: block; - margin-top: 12px; +.playground-key-row input:focus { + outline: none; + border-color: #8f9294; +} + +.playground-key-row button { + flex: 0 0 auto; + height: 44px; + padding: 0 18px; + border: 1px solid #54575a; + border-radius: 999px; + background: transparent; color: #faf8f5; - font-family: var(--font-mono); - font-size: 15px; - font-weight: 400; - line-height: 1.45; - overflow-wrap: anywhere; + font-family: "Google Sans Code", ui-monospace, monospace; + font-size: 13px; + letter-spacing: 0.06em; + text-transform: uppercase; + cursor: pointer; } -.setup-key-actions { - display: flex; - justify-content: flex-end; +.playground-key-row button:hover:not(:disabled) { + border-color: #faf8f5; } -.setup-key-copy-button { - width: 40px; - height: 40px; - min-height: 40px; - display: inline-flex; - align-items: center; - justify-content: center; - padding: 0; - border: 1px solid rgba(250, 248, 245, 0.12); - border-radius: 14px; - background: rgba(255, 255, 255, 0.08); - color: #faf8f5; - cursor: pointer; - box-shadow: none; +.playground-key-row button:disabled { + opacity: 0.4; + cursor: default; } -.setup-key-copy-button:hover:not(:disabled) { - border-color: rgba(250, 248, 245, 0.24); - background: rgba(255, 255, 255, 0.14); - color: #faf8f5; +.playground-key-error { + margin: 0; + color: #ff9aa0; + font-family: "Google Sans Flex", sans-serif; + font-size: 14px; } -.setup-key-copy-button--copied { - border-color: #e8ff75; - background: #e8ff75; - color: #000000; +.playground-done { + margin-top: 72px; + text-align: center; } -.setup-classic-ready-error { - margin-bottom: 20px; +.playground-done h2, +.playground-done p, +.playground-done a { + font-family: "Google Sans Flex", sans-serif; + font-weight: 400; } -.setup-classic-error-action { - display: inline-flex; - margin-top: 12px; +.playground-done h2 { + margin: 0 0 12px; color: #faf8f5; - text-decoration: none; + font-size: 32px; + line-height: 1.2; } -.setup-classic-confirm { - position: relative; - display: flex; - align-items: center; - gap: 12px; - margin-bottom: 26px; +.playground-done p { + margin: 0; + color: #b1b4b6; + font-size: 18px; + line-height: 1.5; +} + +.playground-done a { color: #faf8f5; - font-size: 16px; - font-weight: 400; - line-height: 1.3; - cursor: pointer; + text-underline-offset: 3px; } -.setup-classic-confirm input { - position: absolute; - opacity: 0; - pointer-events: none; +.dash-page .connect-wm-import { + width: 100%; + min-width: 0; + max-width: 100%; } -.setup-classic-confirm-box { - width: 22px; - height: 22px; - flex: 0 0 auto; - margin-top: 0; - transform: translateY(-1px); - border: 1px solid #54575a; - border-radius: 6px; - background: #000000; - transition: background 0.14s ease, border-color 0.14s ease; +.dash-page .connect-wm-import .connect-wm-console { + margin-left: 0; + max-width: 100%; } -.setup-classic-confirm-box::after { - content: ""; - display: block; - width: 7px; - height: 11px; - margin: 3px auto 0; - border: solid #000000; - border-width: 0 2px 2px 0; - opacity: 0; - transform: rotate(45deg); +@media (max-width: 860px) { + .playground-key-note { + padding: 16px; + } + + .playground-key-row { + flex-direction: column; + align-items: stretch; + } + + .playground-key-row input, + .playground-key-row button, + .dash-page .connect-wm-import textarea, + .dash-page .connect-wm-import .connect-wm-console { + width: 100%; + } } -.setup-classic-confirm input:checked + .setup-classic-confirm-box { - border-color: #e8ff75; - background: #e8ff75; +.dash-page .playground-dashboard { + width: min(816px, calc(100% - 40px)) !important; + max-width: 816px !important; + padding: 18px 0 96px !important; } -.setup-classic-confirm input:checked + .setup-classic-confirm-box::after { - opacity: 1; +.dash-page .playground-dashboard .dashboard-header { + margin-bottom: 56px; + text-align: center; } -.setup-classic-confirm input:focus-visible + .setup-classic-confirm-box { - outline: 2px solid #e8ff75; - outline-offset: 3px; +.dash-page .playground-dashboard .dashboard-header h2 { + font-family: Ratch, sans-serif !important; + font-size: 72px !important; + font-weight: 400 !important; + line-height: 0.95 !important; + color: #faf8f5; } -.setup-classic-confirm-text { - min-width: 0; - display: block; +.dash-page .playground-dashboard .dashboard-header p { + max-width: 640px; + margin-right: auto; + margin-left: auto; + color: #b1b4b6 !important; + font-family: "Google Sans Flex", sans-serif !important; + font-size: 18px !important; + font-weight: 400 !important; + line-height: 1.5 !important; } -.setup-classic-register { - width: 100%; - height: 62px; - min-height: 62px; - display: inline-flex; - align-items: center; - justify-content: center; - padding: 0 30px; - border: 1px solid #e8ff75; - border-radius: 31px; - background: #e8ff75; - color: #000000; - font-family: var(--font-sans); - font-size: 18px; - font-weight: 650; - line-height: 0.84; - letter-spacing: 0; - cursor: pointer; +.dash-page .playground-dashboard .card.demo-step { + margin-bottom: 104px !important; + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; box-shadow: none !important; - transform: none !important; - transition: none !important; - animation: none !important; } -.setup-classic-register:hover, -.setup-classic-register:hover:not(:disabled), -.setup-classic-register:active, -.setup-classic-register:active:not(:disabled) { - background: #e8ff75; - border-color: #e8ff75; - color: #000000; - transform: none !important; - box-shadow: none !important; +.dash-page .playground-dashboard .dashboard-header h2 { + font-family: Ratch, sans-serif; + font-size: 44px; + font-weight: 400; + line-height: 0.95; + color: #faf8f5; } -.setup-classic-register:focus, -.setup-classic-register:focus-visible { - outline: none; - transform: none !important; - box-shadow: none !important; +.dash-page .playground-dashboard .dashboard-header p, +.dash-page .playground-dashboard .demo-step-subtitle, +.dash-page .playground-dashboard .card-subtitle { + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 16px; + font-weight: 400; + line-height: 1.5; } -.setup-classic-register:disabled { - border-color: rgba(232, 255, 117, 0.18); - background: rgba(232, 255, 117, 0.22); - color: rgba(0, 0, 0, 0.42); - cursor: not-allowed; - transform: none; - box-shadow: none; +.dash-page .playground-dashboard .demo-server-info { + display: flex; + flex-wrap: wrap; + gap: 10px; } -.setup-classic-register:disabled:hover { - border-color: rgba(232, 255, 117, 0.18); - background: rgba(232, 255, 117, 0.22); - color: rgba(0, 0, 0, 0.42); - transform: none; +.dash-page .playground-dashboard .demo-server-tag, +.dash-page .playground-dashboard .card, +.dash-page .playground-dashboard .demo-step { + border: 1px solid #262b30; + border-radius: 6px; + background: transparent; box-shadow: none; } -.setup-classic .setup-import-button:hover:not(:disabled) { - background: #e8ff75; - border-color: #e8ff75; - color: #000000; - transform: none; +.dash-page .playground-dashboard .demo-step-title, +.dash-page .playground-dashboard .card-title { + font-family: Ratch, sans-serif !important; + font-size: 44px !important; + font-weight: 400 !important; + line-height: 0.95 !important; + letter-spacing: 0 !important; + text-transform: none; + color: #faf8f5; } -@media (max-width: 860px) { - .setup-classic-nav .nav-brand-logo, - .dashboard-nav .nav-brand-logo { - height: 44px; - } +.dash-page .playground-dashboard .card-subtitle, +.dash-page .playground-dashboard .demo-step-subtitle, +.dash-page .playground-dashboard .input-group label { + font-family: "Google Sans Flex", sans-serif !important; + font-size: 18px !important; + font-weight: 400 !important; + line-height: 1.5 !important; + color: #b1b4b6 !important; +} - .setup-classic-container { - width: calc(100% - 32px); - min-height: calc(100vh - 92px); - padding: 32px 0 56px; - } +.dash-page .playground-dashboard .demo-code-block, +.dash-page .playground-dashboard .demo-code-block code, +.dash-page .playground-dashboard .demo-code-block span, +.dash-page .playground-dashboard .demo-result-pre, +.dash-page .playground-dashboard .demo-error-pre { + font-family: "Google Sans Code", ui-monospace, monospace !important; + font-size: 15px !important; + font-weight: 500 !important; + line-height: 1.55 !important; +} - .setup-classic-panel { - width: 100%; - } +.dash-page .playground-dashboard .demo-code-block, +.dash-page .playground-dashboard .demo-result-pre, +.dash-page .playground-dashboard .demo-error-pre { + border-color: #3c414a !important; + background: #1c1f26 !important; + color: #ffffff !important; +} - .setup-classic-title { - font-size: 30px; - } +.dash-page .playground-dashboard .input-group + .demo-code-slot, +.dash-page .playground-dashboard .demo-info-panel + .demo-code-slot { + position: relative; +} - .setup-classic-description, - .setup-classic-feature p, - .setup-classic-divider { - font-size: 16px; - } +.dash-page .playground-dashboard .input-group + .demo-code-slot::before, +.dash-page .playground-dashboard .demo-info-panel + .demo-code-slot::before { + content: ""; + position: absolute; + left: 50%; + top: -23px; + z-index: 1; + width: 1px; + height: 23px; + background: #262b30; + transform: translateX(-50%); + pointer-events: none; +} - .setup-classic-feature-card { - padding: 24px; - border-radius: 20px !important; - } +.dash-page .playground-dashboard .demo-info-panel + .demo-code-slot::before { + top: -18px; + height: 18px; +} - .setup-classic-feature strong { - font-size: 22px; - } +.dash-page .playground-dashboard .input-group > input.input { + margin-bottom: 5px; +} - .setup-key-row { - grid-template-columns: 1fr; - padding: 20px; - } +.dash-page .playground-dashboard .demo-step-badge { + width: 33px; + height: 33px; + border: 1px solid rgba(250, 248, 245, 0.7); + border-radius: 50% !important; + background: #000000 !important; + color: #faf8f5; + font-family: "Google Sans Code", var(--font-mono); + font-size: 13px; + font-weight: 300; +} + +.dash-page .playground-dashboard .demo-step-badge--highlight { + border-color: #faf8f5 !important; + background: #faf8f5 !important; + color: #000000 !important; +} + +.dash-page .playground-dashboard .btn-primary, +.dash-page .playground-dashboard .btn-primary:hover:not(:disabled) { + min-height: 40px; + border: 1px solid #54575a; + border-radius: 26px; + background: transparent; + color: #faf8f5; + font-family: "Google Sans Code", var(--font-mono); + font-size: 14px; + font-weight: 400; + letter-spacing: 0.5px; + text-transform: uppercase; + box-shadow: none; + transform: none; +} - .setup-key-actions { - justify-content: flex-start; - } +.dash-page .playground-dashboard .btn-primary:hover:not(:disabled) { + border-color: #faf8f5; + background: #faf8f5; + color: #000000; +} - .setup-classic-generate { - width: 100%; - } +.dash-page .playground-dashboard .input, +.dash-page .playground-dashboard textarea.input { + border: 1px solid #262b30; + border-radius: 6px; + background: #000000; + color: #faf8f5; + box-shadow: none; +} - .setup-classic-import-actions { - flex-direction: column-reverse; - gap: 12px; - } +.dash-page .playground-dashboard .demo-code-block, +.dash-page .playground-dashboard .demo-result-pre, +.dash-page .playground-dashboard .demo-error-pre { + overflow: hidden; + border: 1px solid #3c414a !important; + border-radius: 6px; + background: #1c1f26 !important; + color: #ffffff !important; + white-space: pre-wrap; + overflow-wrap: anywhere; + box-shadow: none; +} - .setup-classic-back-button, - .setup-classic-import-actions .setup-import-button { - width: 100%; - } +.dash-page .playground-dashboard .demo-result-pre { + margin: 0; + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; + box-shadow: none !important; } -/* Playground final override. This is intentionally last because the file still - contains older duplicated dashboard/playground passes above. */ -.playground-nav .nav-brand-logo { - display: block; - height: 56px; - width: auto; +.dash-page .playground-dashboard .demo-error-panel { + margin-top: 16px; + padding: 14px 16px; + border: 1px solid rgba(255, 138, 144, 0.7); + border-radius: 6px; + background: transparent; } -.playground-nav .demo-nav-back { - min-height: 28px; - display: inline-flex; - align-items: center; - gap: 8px; - color: #b8bbbe; - font-size: 16px; +.dash-page .playground-dashboard .demo-error-label { + margin: 0 0 4px; + color: #ff9aa0; + font-family: "Google Sans Flex", sans-serif; + font-size: 13px; font-weight: 500; - letter-spacing: 0.2px; - text-decoration: none; + letter-spacing: 0.02em; } -.playground-nav .demo-nav-icon { - display: none; - flex: 0 0 auto; - stroke-width: 1.8; +.dash-page .playground-dashboard .demo-error-pre { + margin: 0; + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; + color: #ffd4d6 !important; + font-family: "Google Sans Flex", sans-serif !important; + font-size: 15px !important; + font-weight: 400 !important; + line-height: 1.45 !important; + box-shadow: none !important; } -.playground-nav .demo-nav-back:hover { +.dash-page .dashboard-credentials-panel, +.dash-page .dashboard-quickstart-card, +.dash-page .demo-code-block, +.dash-page .playground-dashboard .demo-code-block, +.dash-page .playground-dashboard .demo-result-pre, +.playground-dashboard .demo-code-block, +.playground-dashboard .card.demo-step { + border-radius: 6px !important; +} + +.dash-page .playground-nav .demo-nav-back { color: #faf8f5; + font-family: "Google Sans Code", var(--font-mono); + font-size: 13px; + letter-spacing: 0.4px; + text-decoration: none; + text-transform: uppercase; } -.playground-dashboard { - width: min(1100px, calc(100% - 64px)) !important; - max-width: 1100px !important; - padding: 34px 0 68px !important; +/* MCP and Claude consent screens. Same column and type as the dashboard, + without the setup wizard's rounded cards. */ +.mcp-connect .mcp-connect-panel { + width: 100%; + font-family: "Google Sans Flex", sans-serif; + font-weight: 400; + text-transform: none; } -.playground-dashboard .dashboard-header { - max-width: 880px; - margin-bottom: 28px !important; - animation: dashboardReveal 360ms cubic-bezier(0.16, 1, 0.3, 1) both; +.mcp-connect .setup-classic-intro { + margin-bottom: 0; + text-align: center; } -.playground-dashboard .dashboard-header h2 { +.mcp-connect .setup-classic-title { margin: 0 0 14px; color: #faf8f5; - font-family: var(--font-sans); - font-size: 56px !important; - font-weight: 500; - line-height: 0.88; + font-family: "Google Sans Flex", sans-serif; + font-size: 40px; + font-weight: 400; + line-height: 1.15; letter-spacing: 0; + text-align: center; + text-transform: none; } -.playground-dashboard .dashboard-header p { - max-width: 860px; - margin: 0; - color: #b8bbbe; - font-size: 18px !important; +.mcp-connect .setup-classic-description { + max-width: 640px; + margin: 0 auto 36px; + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 18px; font-weight: 400; - line-height: 1.35; + line-height: 1.5; + text-align: center; } -.playground-dashboard .dashboard-header code, -.playground-dashboard .demo-doc-link { - color: #e8ff75; +.mcp-connect .setup-classic-description strong, +.mcp-connect .mcp-client-name { + color: #faf8f5; + font-family: inherit; font-weight: 500; } -.playground-dashboard .demo-server-info { - display: flex !important; - flex-wrap: wrap; - gap: 12px; - margin-bottom: 42px; - animation: dashboardReveal 360ms cubic-bezier(0.16, 1, 0.3, 1) 45ms both; +.mcp-connect .mcp-unverified { + color: #8f9294; } -.playground-dashboard .demo-server-tag { - min-height: 40px; - display: inline-flex; - align-items: center; - gap: 8px; - padding: 0 14px; - border: 1px solid #54575a; - border-radius: 12px; - background: rgba(255, 255, 255, 0.08); - color: #b8bbbe; - font-family: var(--font-mono); - font-size: 13px; +.mcp-connect .setup-classic-feature-card { + margin-bottom: 28px !important; + padding: 24px 28px !important; + border: 1px solid #262b30 !important; + border-radius: 6px !important; + background: transparent !important; + box-shadow: none !important; + text-align: left; +} + +.mcp-connect .mcp-kicker { + margin: 0 0 10px; + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 18px; font-weight: 400; - line-height: 1.2; - box-shadow: none; + letter-spacing: 0; + text-transform: none; } -.playground-dashboard .demo-tag-value, -.playground-dashboard .demo-tag-value--server, -.playground-dashboard .demo-tag-value--key, -.playground-dashboard .demo-tag-value--sdk { - color: #e8ff75; - font-weight: 500; +.mcp-connect .mcp-perms { + margin: 0 0 8px; + padding: 0; + list-style: none; + color: #faf8f5; + font-family: "Google Sans Flex", sans-serif; + font-size: 18px; + font-weight: 400; + line-height: 1.5; } -.playground-dashboard .demo-server-tag--namespace { - padding-right: 10px; +.mcp-connect .mcp-perms li { + margin: 0 0 8px; } -.playground-dashboard .demo-namespace-input { - width: auto; - min-width: 74px; - padding: 0; - border: 0; - outline: none; - background: transparent; +.mcp-connect .mcp-code, +.mcp-connect code { color: #faf8f5; - font-family: var(--font-mono); - font-size: 13px; - font-weight: 500; + font-family: "Google Sans Code", ui-monospace, monospace; + font-size: 0.92em; + font-weight: 400; } -.playground-dashboard .card.demo-step { - margin-bottom: 42px !important; - padding: 32px !important; - border: 1px solid #54575a !important; - border-radius: 24px !important; - background: rgba(255, 255, 255, 0.08) !important; +.mcp-connect .mcp-details summary { + display: flex; + align-items: center; + justify-content: space-between; + margin: 0; + cursor: pointer; + list-style: none; +} + +.mcp-connect .mcp-details summary::-webkit-details-marker { + display: none; +} + +.mcp-connect .mcp-details summary::after { + content: ""; + width: 7px; + height: 7px; + margin-right: 4px; + border-right: 1.5px solid #8f9294; + border-bottom: 1.5px solid #8f9294; + transform: rotate(45deg) translateY(-2px); +} + +.mcp-connect .mcp-details[open] summary::after { + transform: rotate(-135deg) translateY(-2px); +} + +.mcp-connect .mcp-details-body { + margin-top: 14px; +} + +.mcp-connect .mcp-rule { + height: 1px; + margin: 16px 0 18px; + background: #262b30; +} + +.mcp-connect .mcp-detail { + display: flex; + flex-direction: column; + gap: 6px; + margin-bottom: 16px; +} + +.mcp-connect .mcp-detail:last-child { + margin-bottom: 0; +} + +.mcp-connect .mcp-detail-label { + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; + font-weight: 400; + letter-spacing: 0; + text-transform: none; +} + +.mcp-connect .mcp-detail-value { color: #faf8f5; - box-shadow: none !important; - animation: dashboardReveal 360ms cubic-bezier(0.16, 1, 0.3, 1) both; + font-family: "Google Sans Code", ui-monospace, monospace; + font-size: 15px; + font-weight: 400; + line-height: 1.45; + overflow-wrap: anywhere; } -.playground-dashboard .card.demo-step:hover { - border-color: #54575a !important; - box-shadow: none !important; +.mcp-connect .mcp-error { + color: #ff9aa0; } -.playground-dashboard .card-header { - align-items: flex-start; - gap: 24px; - margin-bottom: 24px !important; +.mcp-connect .mcp-ok { + color: #b6f5c3; } -.playground-dashboard .card-header > :last-child { - flex: 0 0 auto; +.mcp-connect .mcp-warn { + color: #f4ff8a; } -.playground-dashboard .demo-step-header-row { - min-width: 0; - align-items: flex-start; - gap: 18px; +.mcp-connect .setup-classic-actions { + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 12px; } -.playground-dashboard .demo-step-badge { - width: 40px !important; - height: 40px !important; - border: 1px solid #54575a; - border-radius: 12px !important; - background: #000000; +.mcp-connect .mcp-btn { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 44px; + padding: 0 22px; + border: 1px solid #faf8f5; + border-radius: 999px; + background: transparent; color: #faf8f5; - font-family: var(--font-mono); + font-family: "Google Sans Code", ui-monospace, monospace; font-size: 15px; - font-weight: 500; + font-weight: 400; + letter-spacing: 0.06em; line-height: 1; - box-shadow: none; + text-decoration: none; + text-transform: uppercase; + cursor: pointer; } -.playground-dashboard .demo-step-badge--highlight { - border-color: #e8ff75; - background: #e8ff75; +.mcp-connect .mcp-btn:hover { + background: #faf8f5; color: #000000; } -.playground-dashboard .card-title, -.playground-dashboard .demo-step-title { - color: #faf8f5; - font-family: var(--font-sans); - font-size: 28px !important; - font-weight: 650; - line-height: 1.05; - letter-spacing: 0; +.mcp-connect .mcp-btn--ghost { + border-color: #54575a; + color: #8f9294; } -.playground-dashboard .card-subtitle { - margin-top: 8px; - color: #b8bbbe; - font-family: var(--font-sans); - font-size: 17px !important; +.mcp-connect .mcp-prompt-intro { + margin: 0 0 14px; + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 18px; font-weight: 400; - line-height: 1.3; + line-height: 1.5; } -.playground-dashboard .btn { - min-width: 84px; - min-height: 44px !important; - height: 44px; - display: inline-flex; +.mcp-connect .mcp-prompt { + margin: 0; + max-height: 240px; + padding: 16px; + overflow: auto; + border: 1px solid #3c414a; + border-radius: 6px; + background: #1c1f26; + color: #ffffff; + font-family: "Google Sans Code", ui-monospace, monospace; + font-size: 13px; + line-height: 1.55; + white-space: pre-wrap; + overflow-wrap: anywhere; +} + +.mcp-connect .mcp-prompt-actions { + display: flex; + flex-wrap: wrap; align-items: center; - justify-content: center; - padding: 2px 22px 0; - border-radius: 22px; - font-family: var(--font-sans); + gap: 16px; + margin-top: 14px; +} + +.mcp-connect .mcp-link { + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; font-size: 16px; - font-weight: 550; - line-height: 1; - letter-spacing: 0; - box-shadow: none !important; - transform: none !important; - transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease; + font-weight: 400; + text-decoration: underline; + text-underline-offset: 3px; } -.playground-dashboard .btn-primary, -.playground-dashboard .btn-primary:hover:not(:disabled), -.playground-dashboard .btn-primary:active:not(:disabled) { - border: 1px solid #e8ff75; - background: #e8ff75; - color: #000000; - transform: none !important; - box-shadow: none !important; +.mcp-connect .mcp-link:hover { + color: #faf8f5; } -.playground-dashboard .btn-primary:disabled { - border-color: rgba(232, 255, 117, 0.18); - background: rgba(232, 255, 117, 0.22); - color: rgba(0, 0, 0, 0.42); +@media (max-width: 860px) { + .dash-page .dashboard-key-table tr { + margin-bottom: 0; + padding: 6px 0 2px; + border: 0; + border-bottom: 1px solid #262b30; + border-radius: 0; + background: transparent; + } + + .dash-page .dashboard-key-table tbody tr:last-child { + border-bottom: 0; + } + + .dash-page .dashboard-key-table td, + .dash-page .dashboard-key-table td::before { + font-family: "Google Sans Flex", sans-serif; + } + + .dash-page .dashboard-key-table td { + padding: 12px 0; + border-bottom: 0; + color: #faf8f5; + } + + .dash-page .dashboard-key-table td::before { + color: #8f9294; + font-size: 14px; + font-weight: 400; + } } -.playground-dashboard .btn-primary.demo-run-button--loading:disabled { - border-color: #e8ff75; - background: #e8ff75; - color: #000000; - opacity: 1; +html { + scrollbar-width: none; } -.playground-dashboard .demo-button-spinner { - width: 14px; - height: 14px; - border-color: rgba(0, 0, 0, 0.28); - border-top-color: #000000; +html::-webkit-scrollbar { + display: none; + width: 0; + height: 0; } -.playground-dashboard .input-group { - margin-bottom: 18px !important; +html:has(.signin-proposed), +body:has(.signin-proposed) { + height: 100%; + overflow: hidden; } -.playground-dashboard .input-group label, -.playground-dashboard .demo-info-label, -.playground-dashboard .demo-result-label, -.playground-dashboard .demo-error-label { - display: block; - margin-bottom: 12px; - color: #b8bbbe; - font-family: var(--font-sans); - font-size: 17px !important; - font-weight: 400; - line-height: 1.3; - letter-spacing: 0; +.signin-proposed { + position: fixed; + inset: 0; + container-type: size; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + background: #000000; + color: #faf8f5; } -.playground-dashboard .input { - min-height: 52px; - padding: 13px 16px; - border: 1px solid #54575a; - border-radius: 14px; +.signin-fit { + position: relative; + container-type: size; + flex: 0 0 auto; +} + +.signin-fit--desktop { + width: min(100vw, calc(100vh * 1440 / 966)); + height: min(100vh, calc(100vw * 966 / 1440)); +} + +.signin-fit--mobile { + display: none; +} + +.signin-stage { + position: absolute; + top: 0; + left: 0; + overflow: hidden; background: #000000; color: #faf8f5; - font-family: var(--font-sans); - font-size: 16px; + font-family: "Google Sans Flex", sans-serif; font-weight: 400; - line-height: 1.4; - box-shadow: none; + transform-origin: top left; } -.playground-dashboard textarea.input { - min-height: 108px; - resize: vertical; +.signin-stage--desktop { + width: 1440px; + height: 966px; + transform: scale(calc(100cqw / 1440px)); } -.playground-dashboard .input:focus { - border-color: #e8ff75; - outline: none; - box-shadow: 0 0 0 3px rgba(232, 255, 117, 0.12); +.signin-stage--mobile { + width: 375px; + height: 888px; + transform: scale(calc(100cqw / 375px)); } -.playground-dashboard .input::placeholder { - color: #8f9294; +.signin-glow { + position: absolute; + pointer-events: none; + background-repeat: no-repeat; + background-size: 100% 100%; } -.playground-dashboard select.input { - width: 152px; - flex: 0 0 152px; +.signin-stage--desktop .signin-glow { + left: -187px; + top: -252px; + width: 1814px; + height: 776px; + background-image: url('/signin/glow-desktop.png'); } -.playground-dashboard select.input option { - background: #000000; - color: #faf8f5; +.signin-stage--mobile .signin-glow { + left: -272px; + top: -157px; + width: 920px; + height: 394px; + background-image: url('/signin/glow-mobile.png'); } -.playground-dashboard .demo-code-block { - margin: 0; - padding: 24px 28px !important; - border: 1px solid #54575a; - border-radius: 24px !important; - background: #000000 !important; - color: #faf8f5 !important; - font-family: var(--font-mono); - font-size: 14px !important; - font-weight: 400; - line-height: 1.5 !important; - white-space: pre-wrap !important; - word-break: break-word; - overflow-x: hidden; - box-shadow: none !important; +.signin-hero, +.signin-slot, +.signin-screen, +.signin-glow { + pointer-events: none; } -.playground-dashboard .demo-code-block code { - white-space: inherit !important; +.signin-logo, +.signin-stage h1, +.signin-sub, +.signin-tos, +.signin-trusted, +.signin-btn, +.signin-wallet, +.signin-allium, +.signin-partner { + z-index: 5; } -.playground-dashboard .demo-code-block--spaced { - margin-bottom: 18px; +.signin-logo { + position: absolute; + display: block; + width: 117px; + height: 53.929px; } -.playground-dashboard .demo-info-panel, -.playground-dashboard .demo-ai-panel, -.playground-dashboard .demo-result-panel, -.playground-dashboard .demo-error-panel, -.playground-dashboard .demo-phase-indicator { - margin-bottom: 18px; - padding: 20px; - border-radius: 20px; - background: #000000; - color: #b8bbbe; - box-shadow: none; +.signin-stage--desktop .signin-logo { + left: 50px; + top: 35px; } -.playground-dashboard .demo-info-panel:last-child, -.playground-dashboard .demo-ai-panel:last-child, -.playground-dashboard .demo-result-panel:last-child, -.playground-dashboard .demo-error-panel:last-child, -.playground-dashboard .demo-phase-indicator:last-child { - margin-bottom: 0; +.signin-logo--pin, +.signin-glow--pin, +.signin-bloom--pin { + display: none; +} + +@media (min-width: 720px) { + .signin-stage--desktop { + background: transparent; + } + + .signin-stage--desktop .signin-logo, + .signin-stage--desktop .signin-glow { + display: none; + } + + .signin-glow--pin { + display: block; + position: fixed; + z-index: 0; + background-image: url('/signin/glow-desktop.png'); + } + + .signin-fit--desktop { + z-index: 1; + } + + .signin-logo--pin { + display: block; + position: fixed; + top: 28px; + z-index: 30; + width: calc(117px * min(100cqw, 100cqh * 1440 / 966) / 1440px); + height: calc(53.929px * min(100cqw, 100cqh * 1440 / 966) / 1440px); + } + + /* Same ellipse as Figma, but outside the stage so the blur is not cut off + at the stage edge and the purple continues into the right corner. */ + .signin-bloom--pin { + display: block; + position: fixed; + z-index: 0; + width: calc(368px * min(100cqw, 100cqh * 1440 / 966) / 1440px); + height: calc(480px * min(100cqw, 100cqh * 1440 / 966) / 1440px); + top: calc( + (100cqh - min(100cqh, 100cqw * 966 / 1440)) / 2 + + 224px * min(100cqw, 100cqh * 1440 / 966) / 1440px + ); + border-radius: 50%; + background: linear-gradient(to bottom, #2f43cb, #9550c2); + filter: blur(calc(387px * min(100cqw, 100cqh * 1440 / 966) / 1440px)); + pointer-events: none; + } +} + +/* Pin right only while the window is at least as tall as a 14-inch fullscreen + (1512×982). The spare width there is about 48px, so the laptop still meets + the edge. */ +@media (min-width: 720px) and (aspect-ratio <= 1512 / 982) { + .signin-fit--desktop { + margin-left: auto; + } + + .signin-glow--pin { + top: calc(-252px * 100cqw / 1440px); + left: calc(-187px * 100cqw / 1440px); + width: calc(1814px * 100cqw / 1440px); + height: calc(776px * 100cqw / 1440px); + } + + .signin-logo--pin { + left: calc( + (100cqw - min(100cqw, 100cqh * 1440 / 966)) + + 50px * min(100cqw, 100cqh * 1440 / 966) / 1440px + ); + } + + .signin-bloom--pin { + left: calc( + (100cqw - min(100cqw, 100cqh * 1440 / 966)) + + 882px * min(100cqw, 100cqh * 1440 / 966) / 1440px + ); + } } -.playground-dashboard .demo-info-panel, -.playground-dashboard .demo-ai-panel, -.playground-dashboard .demo-phase-indicator { - border: 1px solid #54575a; +/* Shorter than a 14-inch window: grow the whole stage to the window width + so the laptop meets the right edge. The bottom of the artboard clips. */ +@media (min-width: 720px) and (aspect-ratio > 1512 / 982) { + .signin-proposed { + align-items: flex-start; + } + + .signin-fit--desktop { + width: 100vw; + height: calc(100vw * 966 / 1440); + margin-left: 0; + } + + .signin-glow--pin { + top: calc(-252px * 100cqw / 1440px); + left: calc(-187px * 100cqw / 1440px); + width: calc(1814px * 100cqw / 1440px); + height: calc(776px * 100cqw / 1440px); + } + + .signin-logo--pin { + top: calc(28px * 100cqw / 1440px); + left: calc(50px * 100cqw / 1440px); + width: calc(117px * 100cqw / 1440px); + height: calc(53.929px * 100cqw / 1440px); + } + + .signin-bloom--pin { + top: calc(224px * 100cqw / 1440px); + left: calc(882px * 100cqw / 1440px); + width: calc(368px * 100cqw / 1440px); + height: calc(480px * 100cqw / 1440px); + filter: blur(calc(387px * 100cqw / 1440px)); + } } -.playground-dashboard .demo-result-panel { - border: 1px solid rgba(232, 255, 117, 0.44); +.signin-stage--mobile .signin-logo { + left: 30px; + top: 25px; } -.playground-dashboard .demo-error-panel { - border: 1px solid rgba(255, 110, 116, 0.55); +.signin-stage h1 { + position: absolute; + margin: 0; + color: #faf8f5; + font-family: Ratch, sans-serif; + font-weight: 425; + line-height: 0.95; } -.playground-dashboard .demo-result-label { - color: #e8ff75; +.signin-stage--desktop h1 { + left: 100px; + top: 229px; + width: 503px; + font-size: 72px; } -.playground-dashboard .demo-error-label, -.playground-dashboard .demo-error-pre { - color: #ff878d; +.signin-stage--mobile h1 { + left: 20px; + top: 149px; + width: 335px; + font-size: 44px; + text-align: center; } -.playground-dashboard .demo-result-pre, -.playground-dashboard .demo-error-pre { +.signin-sub, +.signin-tos, +.signin-trusted { + position: absolute; margin: 0; - color: #faf8f5; - font-family: var(--font-mono); - font-size: 14px; - line-height: 1.55; - white-space: pre-wrap; - word-break: break-word; + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-weight: 400; + line-height: 1.5; } -.playground-dashboard .demo-ai-answer { - color: #faf8f5; - font-size: 16px; - line-height: 1.55; +.signin-stage--desktop .signin-sub { + left: 100px; + top: 387px; + width: 503px; + font-size: 18px; } -.playground-dashboard .demo-phase-indicator { - display: flex; +.signin-stage--mobile .signin-sub { + left: 31px; + top: 591px; + width: 313px; + font-size: 15px; + text-align: center; +} + +.signin-btn, +.signin-wallet, +.signin-wallet button { + position: absolute; + display: inline-flex; align-items: center; + justify-content: center; gap: 12px; - color: #faf8f5; + width: 297px; + height: 52px; + padding: 0 30px; + border: 1px solid #54575a !important; + border-radius: 26px !important; + background: transparent !important; + color: #faf8f5 !important; + font-family: "Google Sans Code", ui-monospace, monospace !important; + font-size: 16px !important; + font-weight: 400 !important; + letter-spacing: 0.64px !important; + line-height: 0.84 !important; + white-space: nowrap !important; + text-transform: uppercase !important; + text-decoration: none !important; + cursor: pointer; + box-shadow: none !important; } -.playground-dashboard .demo-llm-controls { - display: flex; - gap: 12px; - margin-bottom: 10px; +.signin-wallet { + padding: 0; + border: 0 !important; + background: transparent !important; } -.playground-dashboard .demo-llm-controls input { - flex: 1; +.signin-wallet button { + position: static; + width: 297px !important; + min-width: 297px !important; + max-width: 297px !important; } -.playground-dashboard .demo-field-note { - color: #b8bbbe; - font-family: var(--font-sans); - font-size: 17px !important; - font-weight: 400; - line-height: 1.3; +.signin-btn, +.signin-wallet button { + transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease; } -.playground-dashboard .demo-ready-pill { - min-height: 28px; - display: inline-flex; - align-items: center; - justify-content: center; - padding: 0 12px; - border-radius: 14px; - background: #e8ff75; - color: #000000; - font-size: 13px; - font-weight: 600; +.signin-btn:hover, +.signin-wallet button:hover { + border-color: #faf8f5 !important; + background: #faf8f5 !important; + color: #000000 !important; } -.playground-dashboard .demo-memory-item { - display: grid; - grid-template-columns: 48px minmax(0, 1fr); - gap: 12px; - align-items: baseline; - margin-bottom: 10px; - color: #b8bbbe; - font-family: var(--font-mono); - font-size: 13px; - line-height: 1.45; +.signin-btn svg { + display: block; + width: 21px; + height: 21px; + flex: 0 0 21px; } -.playground-dashboard .demo-memory-item:last-child { - margin-bottom: 0; +.signin-wallet button * { + font-family: inherit !important; + letter-spacing: inherit !important; + text-transform: inherit !important; + color: inherit !important; } -.playground-dashboard .demo-memory-score { - color: #e8ff75; +.signin-stage--desktop .signin-btn--google { + left: 100px; + top: 443px; } -.playground-dashboard .demo-details-summary { - margin-bottom: 10px; - color: #b8bbbe; - cursor: pointer; - font-size: 14px; - line-height: 1.3; +.signin-stage--desktop .signin-wallet { + left: 100px; + top: 505px; } -.playground-dashboard .demo-system-prompt { - color: #b8bbbe !important; - font-size: 13px !important; +.signin-stage--mobile .signin-btn--google { + left: 39px; + top: 662px; } -.playground-dashboard .demo-mode-divider { - margin: 56px 0 30px; - color: #b8bbbe; - font-family: var(--font-sans); - font-size: 17px !important; - font-weight: 400; - line-height: 1.3; - text-align: center; +.signin-stage--mobile .signin-wallet { + left: 39px; + top: 724px; } -@media (max-width: 860px) { - .setup-classic-nav, - .playground-nav, - .dashboard-nav { - height: 80px; - padding: 0 14px; - } +.signin-stage--desktop .signin-tos { + left: 100px; + top: 587px; + width: 503px; + font-size: 12px; +} - .setup-classic-nav .nav-inner, - .playground-nav .nav-inner, - .dashboard-nav .nav-inner { - height: 80px; - min-height: 80px; - } +.signin-stage--mobile .signin-tos { + left: 51px; + top: 803px; + width: 273px; + font-size: 11px; + text-align: center; +} - .setup-classic-nav .nav-brand, - .playground-nav .nav-brand, - .dashboard-nav .nav-brand { - top: 22px; - } +.signin-proposed .signin-tos a { + color: #faf8f5; + text-decoration: underline; + text-underline-offset: 2px; +} - .setup-classic-nav .nav-brand-logo, - .playground-nav .nav-brand-logo, - .dashboard-nav .nav-brand-logo { - height: 36px; - } +.signin-stage--desktop .signin-trusted { + left: 100px; + top: 692px; + width: 503px; + font-size: 18px; +} - .setup-classic-nav .nav-user, - .playground-nav .nav-user, - .dashboard-nav .nav-user { - top: 21px; - height: 38px; - gap: 8px; - } +.signin-trusted strong { + color: #faf8f5; + font-weight: 600; +} - .setup-classic-nav .nav-address, - .playground-nav .nav-address, - .dashboard-nav .nav-address { - min-width: 96px; - height: 34px; - padding: 0 10px; - font-size: 11px; - letter-spacing: 0.45px; - } +.signin-allium, +.signin-partner { + position: absolute; + display: block; +} - .setup-classic-nav .lp-nav-cta, - .playground-nav .lp-nav-cta, - .dashboard-nav .lp-nav-cta { - height: 38px; - min-height: 38px; - padding: 0 14px; - border-radius: 19px; - font-size: 14px; - letter-spacing: 0.3px; - gap: 8px; - } +.signin-allium { + left: 99px; + top: 744px; + width: 97.41px; + height: 28.51px; + overflow: hidden; +} - .setup-classic-nav .lp-nav-cta svg, - .playground-nav .lp-nav-cta svg, - .dashboard-nav .lp-nav-cta svg { - width: 12px; - height: 12px; - } +.signin-allium img { + position: absolute; + width: 95.94%; + height: 91.67%; + left: 1.42%; + top: 4.17%; + max-width: none; +} - .playground-nav .demo-nav-label { - display: none; - } +.signin-partner--inflectiv { + left: 224.79px; + top: 746.38px; + width: 110.73px; + height: 23.76px; +} - .playground-nav .demo-nav-icon { - display: block; - } +.signin-partner--talus { + left: 364px; + top: 750.53px; + width: 85.64px; + height: 14.85px; +} - .playground-nav .demo-nav-back { - width: 38px !important; - min-width: 38px !important; - height: 38px !important; - min-height: 38px !important; - padding: 0 !important; - border: 1px solid #54575a; - border-radius: 19px; - background: #000000; - color: #faf8f5; - justify-content: center; - } +.signin-partner--tatum { + left: 479.29px; + top: 746.38px; + width: 96.82px; + height: 19.6px; +} - .dash-page .dash-shell, - .playground-dashboard, - .setup-classic-container { - width: calc(100% - 28px) !important; - padding: 28px 0 48px !important; - } +.signin-screen, +.signin-tile { + position: absolute; + pointer-events: none; +} - .dash-page .card, - .playground-dashboard .card.demo-step { - padding: 24px !important; - border-radius: 20px !important; - } +.signin-tile { + display: block; + max-width: none; +} - .dash-page .card-header, - .playground-dashboard .card-header { - gap: 18px; - margin-bottom: 28px !important; - } +.signin-screen { + overflow: hidden; +} - .dash-page .card-title, - .playground-dashboard .card-title, - .playground-dashboard .demo-step-title { - font-size: 28px !important; - line-height: 1; - } +.signin-screen img { + position: absolute; + max-width: none; +} - .dash-page .card-subtitle, - .playground-dashboard .card-subtitle { - font-size: 16px !important; - line-height: 1.32; - } +.signin-screen-fade { + position: absolute; + inset: 0; +} - .playground-dashboard .dashboard-header h2 { - font-size: 38px !important; - line-height: 0.96; - } +.signin-stage--desktop .signin-screen { + left: 746px; + top: 230px; + width: 885px; + height: 531px; + border-radius: 24px; + z-index: 2; +} - .playground-dashboard .dashboard-header p { - font-size: 16px !important; - } +.signin-stage--desktop .signin-screen img { + width: 103.47%; + height: 100%; + left: -3.44%; + top: 0; +} - .dash-page .card-header-actions .btn-secondary, - .dash-page .card-header-actions .lp-nav-cta, - .playground-dashboard .btn { - min-height: 44px !important; - height: 44px; - padding: 0 16px; - border-radius: 22px; - font-size: 15px; - letter-spacing: 0.25px; - } +.signin-stage--desktop .signin-screen-fade { + background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 90.395%, #000000 100%); +} - .playground-dashboard .btn { - width: 100%; - } +.signin-stage--mobile .signin-screen { + left: 4.07px; + top: 292px; + width: 366.87px; + height: 228.11px; + border-radius: 10.31px; + z-index: 2; +} - .playground-dashboard .demo-llm-controls { - flex-direction: column; - } +.signin-stage--mobile .signin-screen img { + width: 107.23%; + height: 100%; + left: -3.57%; + top: 0; +} - .playground-dashboard select.input { - width: 100%; - flex-basis: auto; - } +.signin-stage--mobile .signin-screen-fade { + background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 90.395%, #000000 100%); +} - .dash-page .dashboard-keys-card { - padding: 24px !important; - } +.signin-stage--desktop .signin-tile--back { + left: 1057.1px; + top: 153px; + width: 189.48px; + height: 184.32px; + z-index: 1; +} - .dash-page .dashboard-keys-card .card-header { - flex-direction: column; - align-items: stretch; - } +.signin-stage--desktop .signin-tile--left { + left: 691px; + top: 582.46px; + width: 222.38px; + height: 224.12px; + z-index: 3; +} - .dash-page .dashboard-keys-card .card-header-actions { - width: 100%; - max-width: 100%; - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 12px; - align-self: stretch; - } +.signin-stage--mobile .signin-tile--left { + left: 54.49px; + top: 245.1px; + width: 99.08px; + height: 99.86px; + z-index: 1; +} - .dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-refresh, - .dash-page .dashboard-keys-card .card-header-actions .dashboard-keys-add { - width: 100%; - min-width: 0; - } +.signin-stage--desktop .signin-tile--right { + left: 1218px; + top: 624px; + width: 208.26px; + height: 232.85px; + z-index: 4; } -@media (max-width: 820px) { - .setup-classic-nav, - .playground-nav, - .dashboard-nav { - height: 72px; - padding: 0 10px; - } +.signin-stage--mobile .signin-tile--right { + left: 219.1px; + top: 463.31px; + width: 92.79px; + height: 103.74px; + z-index: 4; +} - .setup-classic-nav .nav-inner, - .playground-nav .nav-inner, - .dashboard-nav .nav-inner { - height: 72px; - min-height: 72px; +@media (max-width: 719px) { + .signin-proposed { + align-items: center; + justify-content: center; + overflow: hidden; } - .setup-classic-nav .nav-brand, - .playground-nav .nav-brand, - .dashboard-nav .nav-brand { - top: 20px; + .signin-stage--mobile { + background: transparent; } - .setup-classic-nav .nav-brand-logo, - .playground-nav .nav-brand-logo, - .dashboard-nav .nav-brand-logo { - height: 32px; + .signin-stage--mobile .signin-logo, + .signin-stage--mobile .signin-glow { + display: none; } - .setup-classic-nav .nav-user, - .playground-nav .nav-user, - .dashboard-nav .nav-user { - top: 18px; - height: 36px; - gap: 6px; + .signin-glow--pin { + display: block; + position: fixed; + z-index: 0; + top: calc(-157px * 100cqw / 375px); + left: calc(-272px * 100cqw / 375px); + width: calc(920px * 100cqw / 375px); + height: calc(394px * 100cqw / 375px); + background-image: url('/signin/glow-mobile.png'); } - .setup-classic-nav .nav-address, - .playground-nav .nav-address, - .dashboard-nav .nav-address { - min-width: 86px; - height: 32px; - padding: 0 8px; - font-size: 10.5px; - letter-spacing: 0.35px; + .signin-logo--pin { + display: block; + position: fixed; + z-index: 30; + top: calc(25px * min(100cqw, 100cqh * 375 / 888) / 375px); + left: calc(30px * min(100cqw, 100cqh * 375 / 888) / 375px); + width: calc(100px * min(100cqw, 100cqh * 375 / 888) / 375px); + height: calc(46px * min(100cqw, 100cqh * 375 / 888) / 375px); } - .setup-classic-nav .lp-nav-cta, - .playground-nav .lp-nav-cta, - .dashboard-nav .lp-nav-cta { - height: 36px; - min-height: 36px; - padding: 0 12px; - border-radius: 18px; - font-size: 13px; - gap: 7px; + .signin-fit--desktop { + display: none; } - .setup-classic-nav .lp-nav-cta svg, - .playground-nav .lp-nav-cta svg, - .dashboard-nav .lp-nav-cta svg { - width: 11px; - height: 11px; + .signin-fit--mobile { + display: block; + z-index: 1; + width: min(100vw, calc(100vh * 375 / 888)); + height: min(100vh, calc(100vw * 888 / 375)); } +} - .playground-nav .demo-nav-back { - width: 36px !important; - min-width: 36px !important; - height: 36px !important; - min-height: 36px !important; - border-radius: 18px; - } +.dash-page .dashboard-key-selection-status { + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; + font-weight: 400; +} - .playground-nav .demo-nav-icon { - width: 16px; - height: 16px; - } +.dash-page .dashboard-key-clear-selection, +.dash-page .dashboard-key-remove-selected, +.dash-page .dashboard-key-clear-selection:hover:not(:disabled), +.dash-page .dashboard-key-remove-selected:hover:not(:disabled), +.dash-page .dashboard-key-clear-selection:focus, +.dash-page .dashboard-key-remove-selected:focus { + height: 44px; + min-height: 44px; + padding: 0 18px; + border-radius: 999px; + background: transparent; + box-shadow: none; + transform: none; + font-family: var(--font-mono); + font-size: 14px; + font-weight: 400; + letter-spacing: 0.06em; + line-height: 1; + text-transform: uppercase; + gap: 8px; } -/* ============================================================ - Delete old memories card — mirrors the Delegate - keys card; order places it last in the dash-shell flex flow. - ============================================================ */ +.dash-page .dashboard-key-clear-selection { + border: 1px solid #54575a; + color: #faf8f5; +} -/* The install card zeroes its bottom margin (it used to be the last card - on the page), so the cleanup card supplies its own top gap to keep the - 56px card rhythm — and, as the new last card, zeroes its own bottom. - Shell/type mirror the keys+install cards' final design; the generic - 860px rules (24px padding, 28px title, 44px pills — all !important) - cover mobile the same way they do for those cards. */ -.dash-page .dashboard-cleanup-card { - order: 7; - margin-top: 56px; - margin-bottom: 0 !important; - padding: 39px 40px; - border-color: #54575a; - border-radius: 24px; - background: #000000; - overflow: clip; +.dash-page .dashboard-key-clear-selection:hover:not(:disabled) { + border-color: #faf8f5; + background: #faf8f5; + color: #000000; } -.dash-page .dashboard-cleanup-card .card-header { - align-items: flex-start; - gap: 24px; - margin-bottom: 34px; +.dash-page .dashboard-key-remove-selected { + border: 1px solid rgba(255, 154, 160, 0.55); + color: #ff9aa0; } -.dash-page .dashboard-cleanup-card .card-title { +.dash-page .dashboard-key-remove-selected:hover:not(:disabled) { + border-color: #ff9aa0; + background: transparent; + color: #ffb4b8; +} + +/* Admin uses the same open Sept 2026 sections as the dashboard and playground: + Ratch titles, Google Sans body, flat tables, 6px panels. No boxed cards. */ +.admin-dashboard-page .dashboard-header { + margin: 18px 0 72px; + text-align: center; +} + +.admin-dashboard-page .admin-panels { + gap: 80px; +} + +.admin-dashboard-page .admin-activity-section, +.admin-dashboard-page .admin-wallets-section { + gap: 56px; +} + +.admin-dashboard-page .dashboard-header h2 { + margin: 0; color: #faf8f5; - font-family: var(--font-sans); - font-size: 36px; - font-weight: 500; - line-height: 0.88; + font-family: Ratch, sans-serif; + font-size: 72px; + font-weight: 400; + line-height: 0.95; letter-spacing: 0; } -.dash-page .dashboard-cleanup-card .card-subtitle { - margin-top: 14px; - color: #b8bbbe; - font-family: var(--font-sans); +.admin-dashboard-page .dashboard-header p { + max-width: 640px; + margin: 10px auto 0; + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; font-size: 18px; font-weight: 400; - line-height: 1.3; + line-height: 1.5; +} + +.admin-dashboard-page .dashboard-keys-card { + min-height: 0; + overflow: visible; +} + +.admin-dashboard-page .sept-section, +.admin-dashboard-page .sept-section.card { + order: 0; + margin: 0 !important; +} + +.admin-dashboard-page .admin-activity-card .card-header > .admin-window-toggle { + grid-area: actions; + align-self: center; +} + +.admin-dashboard-page .admin-window-toggle { + display: inline-flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; + height: auto; + min-height: 46px; + margin: 0; + padding: 8px; + border: 1px solid #262b30; + border-radius: 6px; + background: transparent; +} + +.admin-memory-summary { + margin: 0 0 16px; + color: #faf8f5; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; + font-weight: 400; + line-height: 1.45; +} + +.admin-memory-bars { + display: flex; + align-items: flex-end; + gap: 4px; + height: 180px; + padding-top: 22px; + box-sizing: border-box; + border-bottom: 1px solid #262b30; +} + +.admin-memory-bar { + display: flex; + flex: 1 1 0; + align-items: flex-end; + min-width: 0; + height: 100%; } -.dash-page .dashboard-cleanup-card .card-header-actions { - align-self: flex-start; - gap: 20px; +.admin-memory-bar-fill { + position: relative; + width: 100%; + border-radius: 3px 3px 0 0; + background: #faf8f5; } -.dash-page .dashboard-cleanup-load { - min-height: 52px; - height: 52px; - padding: 10px 30px; - border: 1px solid #faf8f5; - border-radius: 26px; - background: transparent; - color: #faf8f5; - font-family: var(--font-sans); - font-size: 18px; - font-weight: 500; +.admin-memory-bar-count { + position: absolute; + left: 50%; + bottom: calc(100% + 4px); + transform: translateX(-50%); + color: #b1b4b6; + font-family: "Google Sans Code", var(--font-mono); + font-size: 11px; + font-weight: 300; line-height: 1; - letter-spacing: 0.72px; } -.dash-page .dashboard-cleanup-load:hover:not(:disabled) { - background: rgba(250, 248, 245, 0.16); - border-color: #faf8f5; - color: #faf8f5; +.admin-memory-bar-fill--zero { + height: 2px !important; + background: #262b30; } -/* Old-memories banner — first thing in the shell: below the navbar, - above the "Welcome" header (all other dash-shell orders start at 0). */ -.dash-page .dash-alert--cleanup { - order: -1; - margin-bottom: 40px !important; +.admin-memory-bar-fill--latest { + background: #e8ff75; } -/* App-wide mount (T3: once in AppContent, direct child of .app) — pages - render their own navbars below it, so keep the page column width and a - slim gap instead of the in-shell 48px alert margin. */ -.app > .dash-alert--cleanup { - width: min(1240px, calc(100% - 48px)); - margin: 16px auto; - margin-bottom: 16px !important; /* base .dash-alert forces 48px */ +.admin-memory-axis { + position: relative; + height: 18px; + margin-top: 8px; + color: #8f9294; + font-family: "Google Sans Code", var(--font-mono); + font-size: 11px; + font-weight: 300; + letter-spacing: 0.2px; } -.dash-alert--cleanup .dash-alert-dismiss { - margin-left: auto; - flex-shrink: 0; +.admin-memory-axis span { + position: absolute; + transform: translateX(-50%); + white-space: nowrap; } -/* Header delete button matches the card-header pill spec (52px, radius 26, - px-30, 18px label — same as Refresh/Add key) in danger colors. */ -.dash-page .dashboard-cleanup-delete { - display: inline-flex; - align-items: center; - gap: 8px; - min-height: 52px; - height: 52px; - padding: 10px 30px; - border-radius: 26px; - font-size: 1.125rem; - letter-spacing: 0.72px; +.admin-dashboard-page .admin-activity-card .admin-window-toggle .btn, +.admin-dashboard-page .admin-activity-card .admin-window-toggle .btn:hover { + height: 24px; + min-height: 24px; + padding: 0 10px; + border: 0; + border-radius: 3px; + background: #1d2227; + color: #8f9294; + font-family: "Google Sans Code", var(--font-mono); + font-size: 13px; + font-weight: 400; + letter-spacing: 0.26px; + line-height: 1; + text-transform: uppercase; + box-shadow: none; + transform: none; } -.dash-page .dashboard-cleanup-error { - background: rgba(248, 113, 113, 0.08); - border: 1px solid rgba(248, 113, 113, 0.2); - border-radius: var(--radius-md); - padding: 12px 16px; - margin: 0 0 18px; - color: var(--danger); - font-size: 16px; - line-height: 1.4; - word-break: break-word; +.admin-dashboard-page .admin-activity-card .admin-window-toggle .admin-window-btn--active, +.admin-dashboard-page .admin-activity-card .admin-window-toggle .admin-window-btn--active:hover { + background: #faf8f5; + color: #000000; } -/* Body copy matches the final card-subtitle scale (18px / 1.3). */ -.dash-page .dashboard-cleanup-status { - margin: 0; - color: #b8bbbe; - font-size: 18px; - font-weight: 400; - line-height: 1.3; +.admin-dashboard-page .admin-burn-grid { + gap: 24px; } -/* Keep cleanup actions in step with the 44px mobile header pills. */ -@media (max-width: 860px) { - .dash-page .dashboard-cleanup-load { - min-height: 44px; - height: 44px; - padding: 0 16px; - border-radius: 22px; - font-size: 15px; - letter-spacing: 0.25px; - } +.admin-dashboard-page .admin-burn-column { + gap: 8px; + padding: 18px 18px 16px; + border: 1px solid #262b30; + border-radius: 6px; + background: transparent; +} - .dash-page .dashboard-cleanup-delete { - min-height: 44px; - height: 44px; - padding: 0 16px; - border-radius: 22px; - font-size: 15px; - letter-spacing: 0.25px; - } +.admin-dashboard-page .admin-burn-label, +.admin-dashboard-page .admin-burn-meta, +.admin-dashboard-page .admin-activity-note, +.admin-dashboard-page .admin-action-row, +.admin-dashboard-page .admin-loading, +.admin-dashboard-page .admin-timestamp, +.admin-dashboard-page .admin-limit-label, +.admin-dashboard-page .admin-pagination-status, +.admin-dashboard-page .admin-sponsor-label, +.admin-dashboard-page .admin-config-label { + font-family: "Google Sans Flex", sans-serif; + font-weight: 400; } -/* ========== Admin Dashboard ========== */ +.admin-dashboard-page .admin-burn-label { + color: #b1b4b6; + font-size: 15px; +} -/* The admin route uses the same navigation, shell, cards, type scale, spacing, - radii, and controls as the authenticated dashboard. Keep this section to - admin-only data presentation instead of recreating the dashboard theme. */ -.dash-page.admin-dashboard-page { - padding: 0; +.admin-dashboard-page .admin-burn-value, +.admin-dashboard-page .admin-table-monospace, +.admin-dashboard-page .admin-sponsor-value, +.admin-dashboard-page .admin-config-value { + color: #faf8f5; + font-family: "Google Sans Code", var(--font-mono); + font-weight: 300; + letter-spacing: 0.2px; } -.admin-dashboard-container { - margin: 0 auto; +.admin-dashboard-page .admin-burn-value { + font-size: 20px; + line-height: 1.2; } -.admin-dashboard-page .dashboard-header { - margin-bottom: var(--dashboard-related-gap); +.admin-dashboard-page .admin-burn-meta, +.admin-dashboard-page .admin-activity-note, +.admin-dashboard-page .admin-timestamp { + color: #8f9294; + font-size: 14px; + line-height: 1.45; } -.admin-panels, -.admin-wallets-section { - display: flex; - flex-direction: column; +.admin-dashboard-page .admin-activity-note { + margin-top: 18px; } -.admin-panels { - gap: var(--dashboard-major-gap); +.admin-dashboard-page .admin-action-row { + padding: 14px 0; + border-bottom-color: #262b30; + color: #faf8f5; + font-size: 15px; } -.admin-wallets-section { - gap: var(--dashboard-related-gap); +.admin-dashboard-page .admin-table-wrapper { + margin-top: 8px; + border: 0; + border-radius: 0; + background: transparent; } -.admin-panels .card, -.admin-wallets-section .card { - min-height: 0; - margin-bottom: 0 !important; +.admin-dashboard-page .admin-table th { + padding: 0 12px 10px 0; + border-bottom: 1px solid #262b30; + color: #8f9294; + font-family: "Google Sans Code", var(--font-mono); + font-size: 12px; + font-weight: 300; + letter-spacing: 0.4px; + text-transform: uppercase; } -/* Sign in */ -.admin-key-entry-shell { - display: flex; - justify-content: center; - padding-top: 26px; +.admin-dashboard-page .admin-table td { + padding: 16px 12px 16px 0; + border-bottom: 1px solid #262b30; + color: #faf8f5; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; + font-weight: 400; } -.dash-page .admin-key-entry-card { - width: min(560px, 100%); - min-height: 0; - margin-bottom: 0 !important; +.admin-dashboard-page .admin-table-monospace { + font-size: 13px; } -.admin-key-entry-form { - display: flex; - flex-direction: column; - gap: 24px; +.admin-dashboard-page .admin-balance-total { + margin-top: 2px; + color: #8f9294; + font-family: "Google Sans Flex", sans-serif; + font-size: 12px; } -.dash-page .admin-key-banner, -.dash-page .admin-key-error { - color: #ff8f8f; - font-size: 14px; - line-height: 1.35; +.admin-dashboard-page .admin-status-badge { + min-height: 22px; + padding: 2px 8px; + border: 1px solid #262b30; + border-radius: 4px; + background: transparent; + font-family: "Google Sans Code", var(--font-mono); + font-size: 11px; + font-weight: 300; + letter-spacing: 0.4px; + text-transform: uppercase; } -.dash-page .admin-key-banner { - margin-bottom: 20px; - padding: 14px 16px; - border: 1px solid rgba(248, 113, 113, 0.36); - border-radius: 14px; - background: rgba(248, 113, 113, 0.1); +.admin-dashboard-page .admin-status-badge--healthy { + border-color: rgba(134, 239, 172, 0.45); + color: #86efac; } -.dash-page .admin-key-error { - margin-top: 2px; +.admin-dashboard-page .admin-status-badge--warning { + border-color: rgba(232, 255, 117, 0.55); + color: #e8ff75; } -.dash-page .admin-key-input-error, -.dash-page .admin-key-input-error:focus { - border-color: rgba(248, 113, 113, 0.72); - box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.1); +.admin-dashboard-page .admin-status-badge--critical { + border-color: rgba(255, 154, 160, 0.6); + color: #ff9aa0; } -.dash-page .admin-key-submit-btn:disabled { - border-color: rgba(250, 248, 245, 0.14); - background: rgba(250, 248, 245, 0.14); - color: #8f9294; - cursor: not-allowed; +.admin-dashboard-page .admin-pace { + text-transform: none; + letter-spacing: 0; + font-family: "Google Sans Flex", sans-serif; + font-size: 12px; } -/* Tables */ -.admin-table-wrapper { - width: 100%; - overflow-x: auto; - border: 1px solid #54575a; - border-radius: 18px; - background: rgba(255, 255, 255, 0.06); +.admin-dashboard-page .admin-pace--faster { + border-color: rgba(255, 154, 160, 0.6); + color: #ff9aa0; } -.admin-table { - width: 100%; - border-collapse: collapse; +.admin-dashboard-page .admin-pace--slower { + border-color: rgba(134, 239, 172, 0.45); + color: #86efac; } -.dash-page .admin-table th, -.dash-page .admin-table td { - padding: 14px 18px; - text-align: left; - vertical-align: middle; +.admin-dashboard-page .admin-sponsor-item, +.admin-dashboard-page .admin-config-item { + min-height: 52px; + border-bottom-color: #262b30; } -.dash-page .admin-table th { - border-bottom: 1px solid rgba(250, 248, 245, 0.12); - color: #b8bbbe; - font-size: 14px; - font-weight: 500; - line-height: 1.2; - white-space: nowrap; +.admin-dashboard-page .admin-sponsor-label, +.admin-dashboard-page .admin-config-label { + color: #b1b4b6; + font-size: 15px; } -.dash-page .admin-table td { - border-bottom: 1px solid rgba(250, 248, 245, 0.08); - color: #faf8f5; - font-size: 14px; - line-height: 1.35; +.admin-dashboard-page .admin-sponsor-value, +.admin-dashboard-page .admin-config-value { + font-size: 15px; } -.admin-table tbody tr:last-child td { - border-bottom: 0; +.admin-dashboard-page .admin-limit-select { + min-height: 36px; + border: 1px solid #262b30; + border-radius: 6px; + background: #000000; + color: #faf8f5; + font-family: "Google Sans Flex", sans-serif; + font-size: 15px; } -.dash-page .admin-table .admin-table-empty { - padding: 28px 18px; - color: #8f9294; - text-align: center; +.admin-dashboard-page .admin-copy-btn, +.admin-dashboard-page .admin-pagination-btn, +.admin-dashboard-page .admin-error-modal-close { + border-color: #262b30; + border-radius: 6px; + color: #b1b4b6; } -.admin-table-monospace { - font-family: var(--font-mono); - font-size: 13px; - white-space: nowrap; +.admin-dashboard-page .admin-copy-btn:hover, +.admin-dashboard-page .admin-pagination-btn:hover:not(:disabled), +.admin-dashboard-page .admin-error-modal-close:hover { + border-color: #faf8f5; + color: #faf8f5; } -.dash-page .admin-status-badge { - display: inline-flex; - align-items: center; - min-height: 22px; - padding: 3px 8px; - border: 1px solid rgba(250, 248, 245, 0.2); - border-radius: 999px; - font-family: var(--font-sans); - font-size: 12px; - font-weight: 500; - line-height: 1; - letter-spacing: 0; - text-transform: capitalize; +.admin-dashboard-page .admin-error-msg-btn:hover { + color: #e8ff75; } -.dash-page .admin-status-badge--healthy { - border-color: rgba(74, 222, 128, 0.38); - color: #4ade80; +.admin-dashboard-page .admin-error-modal { + border: 1px solid #262b30; + border-radius: 6px; + background: #000000; } -.dash-page .admin-status-badge--warning { - border-color: rgba(251, 191, 36, 0.38); - color: #fbbf24; +.admin-dashboard-page .admin-error-modal-header h3 { + font-family: Ratch, sans-serif; + font-size: 32px; + font-weight: 400; + line-height: 1; } -.dash-page .admin-status-badge--critical { - border-color: rgba(255, 143, 143, 0.38); - color: #ff8f8f; +.admin-dashboard-page .admin-error-modal-message { + border: 1px solid #3c414a; + border-radius: 6px; + background: #1c1f26; + font-family: "Google Sans Code", var(--font-mono); } -.dash-page .admin-timestamp { - margin-top: 16px; - color: #b8bbbe; +.admin-dashboard-page .admin-copy-full-btn { + min-height: 44px; + border: 1px solid #54575a; + border-radius: 26px; + background: transparent; + color: #faf8f5; + font-family: "Google Sans Code", var(--font-mono); font-size: 14px; - line-height: 1.35; + font-weight: 400; + letter-spacing: 0.5px; + text-transform: uppercase; } -/* Wallet and configuration rows */ -.admin-sponsor-content, -.admin-config-items { - display: flex; - flex-direction: column; +.admin-dashboard-page .admin-copy-full-btn:hover { + border-color: #faf8f5; + background: #faf8f5; + color: #000000; } -.dash-page .admin-sponsor-item, -.dash-page .admin-config-item { - display: flex; - align-items: center; - justify-content: space-between; - gap: 24px; - min-height: 58px; - padding: 14px 0; - border-bottom: 1px solid rgba(250, 248, 245, 0.08); +.admin-dashboard-page .admin-key-entry-shell { + justify-content: flex-start; + padding-top: 0; } -.admin-sponsor-item:last-child, -.admin-config-item:last-child { - border-bottom: 0; +.admin-dashboard-page .admin-key-entry-card { + width: 100%; } -.dash-page .admin-sponsor-label, -.dash-page .admin-config-label { - color: #b8bbbe; - font-size: 18px; - font-weight: 400; - line-height: 1.3; +.admin-dashboard-page .admin-key-entry-form { + gap: 18px; + padding: 22px 22px 18px; + border: 1px solid #262b30; + border-radius: 6px; } -.dash-page .admin-sponsor-value, -.dash-page .admin-config-value { - color: #faf8f5; - font-family: var(--font-mono); - font-size: 15px; - line-height: 1.4; - text-align: right; +.admin-dashboard-page .admin-key-banner, +.admin-dashboard-page .admin-key-error, +.admin-dashboard-page .admin-error { + border-radius: 6px; + font-family: "Google Sans Flex", sans-serif; } +@media (max-width: 860px) { + .admin-dashboard-page .dashboard-header { + margin-bottom: 48px; + } -/* Error controls */ -.admin-errors-controls { - display: flex; - align-items: center; - gap: 12px; - margin-bottom: 20px; -} + .admin-dashboard-page .admin-panels, + .admin-dashboard-page .admin-activity-section, + .admin-dashboard-page .admin-wallets-section { + gap: 40px; + } -.dash-page .admin-limit-label, -.dash-page .admin-pagination-status { - color: #b8bbbe; - font-size: 14px; - line-height: 1.35; + .admin-dashboard-page .dashboard-header h2 { + font-size: 36px; + } + + .admin-dashboard-page .admin-activity-card .card-header > .admin-window-toggle { + justify-self: start; + } } -.dash-page .admin-limit-select { - min-height: 36px; - padding: 0 36px 0 14px; - border: 1px solid rgba(250, 248, 245, 0.12); - border-radius: 10px; - background: #050505; +/* ── Copy button with status feedback (admin) ───────────────────────── */ +.copy-btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + flex-shrink: 0; + border: 1px solid #262b30; + border-radius: 6px; + background: transparent; + color: #b1b4b6; + cursor: pointer; + transition: color 160ms ease, border-color 160ms ease, background-color 160ms ease; +} +.copy-btn--icon { + width: 28px; + height: 28px; + padding: 0; +} +.copy-btn:hover { + border-color: #faf8f5; color: #faf8f5; - font-family: var(--font-sans); - font-size: 14px; +} +.copy-btn:focus-visible { + outline: 2px solid #e8ff75; + outline-offset: 2px; +} +.copy-btn--done, +.copy-btn--done:hover { + border-color: rgba(134, 239, 172, 0.6); + background: rgba(134, 239, 172, 0.08); + color: #86efac; +} +.copy-btn--error, +.copy-btn--error:hover { + border-color: rgba(255, 154, 160, 0.6); + background: rgba(255, 154, 160, 0.08); + color: #ff9aa0; +} +.copy-btn-icon { + display: inline-flex; +} +.copy-btn--done .copy-btn-icon, +.copy-btn--error .copy-btn-icon { + animation: copy-btn-pop 260ms cubic-bezier(0.34, 1.56, 0.64, 1); +} +.copy-btn-live { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0 0 0 0); + white-space: nowrap; +} +@keyframes copy-btn-pop { + 0% { transform: scale(0.4) rotate(-12deg); opacity: 0; } + 100% { transform: scale(1) rotate(0); opacity: 1; } +} +@media (prefers-reduced-motion: reduce) { + .copy-btn--done .copy-btn-icon, + .copy-btn--error .copy-btn-icon { + animation: none; + } } -.admin-error-timestamp { +/* ── Copy status: icon crossfade, check draw, label blur, press ─────── */ +:root { + --copy-status-ease: cubic-bezier(0.23, 1, 0.32, 1); +} +/* .btn already transitions `all`; other buttons keep their own lists. */ +.copy-status-button:where(:not(.btn)) { + transition: translate 0.16s var(--copy-status-ease); +} +.copy-status-button:active:not(:disabled) { + translate: 0 1px; +} +.copy-status-icon { + display: inline-grid; + flex-shrink: 0; + width: var(--copy-status-size, 14px); + height: var(--copy-status-size, 14px); +} +.copy-status-icon > svg { + grid-area: 1 / 1; + width: 100%; + height: 100%; + opacity: 0; + transform: scale(0.92); + transition: opacity 0.36s var(--copy-status-ease), transform 0.36s var(--copy-status-ease); +} +.copy-status-icon--idle > [data-icon='idle'], +.copy-status-icon--copied > [data-icon='copied'], +.copy-status-icon--error > [data-icon='error'] { + opacity: 1; + transform: scale(1); +} +.copy-status-icon [data-icon='copied'] path { + stroke-dasharray: 1; + stroke-dashoffset: 1; + transition: stroke-dashoffset 0.26s var(--copy-status-ease); +} +.copy-status-icon--copied [data-icon='copied'] path { + stroke-dashoffset: 0; +} +.copy-status-label { + display: inline-grid; +} +.copy-status-label > span { + grid-area: 1 / 1; white-space: nowrap; + opacity: 0; + transform: translateY(3px); + filter: blur(3px); + transition: opacity 0.36s var(--copy-status-ease), transform 0.36s var(--copy-status-ease), filter 0.36s var(--copy-status-ease); +} +.copy-status-label > [data-active] { + opacity: 1; + transform: none; + filter: none; +} +@media (prefers-reduced-motion: reduce) { + .copy-status-button:active:not(:disabled) { + translate: none; + } + .copy-status-icon > svg, + .copy-status-icon [data-icon='copied'] path, + .copy-status-label > span { + transition: none; + } } -.admin-error-message { - display: flex; + +/* ── Error details modal ─────────────────────────────────────────────── */ +.admin-dashboard-page .admin-error-details { + display: grid; + gap: 0; + margin: 0 0 20px; +} +.admin-dashboard-page .admin-error-detail-row { + display: grid; + grid-template-columns: 96px 1fr; align-items: center; - gap: 10px; - min-width: 280px; + gap: 12px; + padding: 10px 0; + border-bottom: 1px solid #1c1f26; } - -.dash-page .admin-error-msg-btn { - flex: 1; +.admin-dashboard-page .admin-error-detail-row dt { + color: #8f9294; + font-family: "Google Sans Code", var(--font-mono); + font-size: 11px; + letter-spacing: 0.4px; + text-transform: uppercase; +} +.admin-dashboard-page .admin-error-detail-row dd { + display: flex; + align-items: center; + gap: 8px; min-width: 0; - padding: 0; - border: 0; - background: transparent; + margin: 0; color: #faf8f5; font-size: 14px; - line-height: 1.35; - text-align: left; - cursor: pointer; } - -.dash-page .admin-error-msg-btn:hover { - color: #e8ff75; +.admin-dashboard-page .admin-detail-mono { + font-family: "Google Sans Code", var(--font-mono); + font-size: 13px; } - -.dash-page .admin-copy-btn, -.dash-page .admin-pagination-btn, -.dash-page .admin-error-modal-close { +.admin-dashboard-page .admin-detail-muted { + color: #8f9294; +} +.admin-dashboard-page .admin-detail-link { display: inline-flex; align-items: center; justify-content: center; - border: 1px solid rgba(250, 248, 245, 0.12); - background: transparent; - color: #b8bbbe; - cursor: pointer; + flex-shrink: 0; + width: 28px; + height: 28px; + border: 1px solid #262b30; + border-radius: 6px; + color: #b1b4b6; } - -.dash-page .admin-copy-btn { - width: 34px; - min-width: 34px; - height: 34px; - padding: 0; - border-radius: 10px; +.admin-dashboard-page .admin-detail-link:hover { + border-color: #faf8f5; + color: #faf8f5; +} +.admin-dashboard-page .admin-error-detail-message-head { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; + color: #8f9294; + font-family: "Google Sans Code", var(--font-mono); + font-size: 11px; + letter-spacing: 0.4px; + text-transform: uppercase; +} +.admin-dashboard-page .admin-error-modal-message--empty { + color: #b1b4b6; + font-family: "Google Sans Flex", sans-serif; + font-size: 14px; + white-space: normal; +} +.admin-dashboard-page .admin-copy-full-btn.copy-btn { + min-height: 44px; + padding: 0 20px; + border-radius: 26px; +} +/* A flex child only scrolls once it may shrink below its content. */ +.admin-error-modal-content { + min-height: 0; } -.dash-page .admin-copy-btn:hover, -.dash-page .admin-pagination-btn:hover:not(:disabled), -.dash-page .admin-error-modal-close:hover { - border-color: #faf8f5; +/* ── Click-to-copy text (admin) ─────────────────────────────────────── */ +.copy-text { + position: relative; + display: inline-flex; + align-items: center; + gap: 6px; + max-width: 100%; + padding: 2px 4px; + margin: -2px -4px; + border: 0; + border-radius: 4px; + background: transparent; + color: inherit; + font: inherit; + text-align: left; + cursor: copy; + transition: color 160ms ease, background-color 160ms ease; +} +.copy-text:hover { color: #faf8f5; + background: rgba(250, 248, 245, 0.06); } - -.admin-pagination { - display: flex; - align-items: center; - justify-content: space-between; - gap: 20px; - margin-top: 20px; +.copy-text:focus-visible { + outline: 2px solid #e8ff75; + outline-offset: 1px; } - -.admin-pagination-controls { - display: flex; - gap: 8px; +.copy-text-value { + min-width: 0; + white-space: nowrap; } - -.dash-page .admin-pagination-btn { - width: 36px; - height: 36px; - padding: 0; - border-radius: 10px; +.copy-text--wrap .copy-text-value { + white-space: normal; + overflow-wrap: anywhere; } - -.dash-page .admin-pagination-btn:disabled { - opacity: 0.35; - cursor: not-allowed; +.copy-text-icon { + display: inline-flex; + flex-shrink: 0; + color: #8f9294; + opacity: 0; + transition: opacity 120ms ease; } - -/* Error modal */ -.admin-error-modal-overlay { - position: fixed; - inset: 0; - z-index: 2000; - display: grid; - place-items: center; - padding: 24px; - background: rgba(0, 0, 0, 0.78); +.copy-text:hover .copy-text-icon, +.copy-text:focus-visible .copy-text-icon, +.copy-text--done .copy-text-icon, +.copy-text--error .copy-text-icon { + opacity: 1; } - -.dash-page .admin-error-modal { - display: flex; - flex-direction: column; - width: min(640px, 100%); - max-height: 80vh; - overflow: hidden; - border: 1px solid #54575a; - border-radius: 24px; - background: #0a0a0a; +.copy-text--done, +.copy-text--done:hover { + color: #86efac; } - -.dash-page .admin-error-modal-header, -.dash-page .admin-error-modal-footer { - display: flex; - align-items: center; - padding: 24px 28px; +.copy-text--done .copy-text-icon { + color: #86efac; + animation: copy-btn-pop 260ms cubic-bezier(0.34, 1.56, 0.64, 1); } - -.dash-page .admin-error-modal-header { - justify-content: space-between; - border-bottom: 1px solid rgba(250, 248, 245, 0.1); +.copy-text--error, +.copy-text--error:hover { + color: #ff9aa0; } - -.dash-page .admin-error-modal-header h3 { - margin: 0; - color: #faf8f5; - font-size: 24px; - font-weight: 500; - line-height: 1.2; +.copy-text--error .copy-text-icon { + color: #ff9aa0; + animation: copy-btn-pop 260ms cubic-bezier(0.34, 1.56, 0.64, 1); } - -.dash-page .admin-error-modal-close { - width: 36px; - height: 36px; - padding: 0; - border-radius: 10px; - font-size: 24px; +.copy-text-chip { + position: absolute; + left: 50%; + bottom: calc(100% + 6px); + padding: 2px 8px; + border: 1px solid rgba(134, 239, 172, 0.45); + border-radius: 999px; + background: #0a0a0a; + color: #86efac; + font-family: "Google Sans Code", var(--font-mono); + font-size: 11px; + letter-spacing: 0.3px; + white-space: nowrap; + pointer-events: none; + animation: copy-text-chip 1600ms ease forwards; } - -.admin-error-modal-content { - flex: 1; - overflow-y: auto; - padding: 28px; +.copy-text--error .copy-text-chip { + border-color: rgba(255, 154, 160, 0.5); + color: #ff9aa0; } - -.dash-page .admin-error-modal-timestamp { - margin: 0 0 14px; - color: #b8bbbe; - font-size: 14px; +@keyframes copy-text-chip { + 0% { opacity: 0; transform: translate(-50%, 4px); } + 12% { opacity: 1; transform: translate(-50%, 0); } + 75% { opacity: 1; transform: translate(-50%, 0); } + 100% { opacity: 0; transform: translate(-50%, -4px); } } - -.dash-page .admin-error-modal-message { - margin: 0; - padding: 16px; - border: 1px solid rgba(250, 248, 245, 0.1); - border-radius: 14px; - background: #050505; - color: #faf8f5; - font-family: var(--font-mono); - font-size: 13px; - line-height: 1.5; - white-space: pre-wrap; - word-break: break-word; +@media (prefers-reduced-motion: reduce) { + .copy-text-icon, + .copy-text-chip { + animation: none !important; + transition: none; + } } -.dash-page .admin-error-modal-footer { - justify-content: flex-end; - border-top: 1px solid rgba(250, 248, 245, 0.1); +/* A pasted delegate private key is masked like a password field. */ +.connect-wm-secret { + -webkit-text-security: disc; } -.dash-page .admin-copy-full-btn { - min-height: 44px; - padding: 10px 22px; - border: 1px solid #faf8f5; - border-radius: 22px; - background: #faf8f5; - color: #000000; - font-size: 16px; - font-weight: 500; - cursor: pointer; -} +/* ── Phone layout: signed-in nav and Connect Walrus Memory ─────────── */ +@media (max-width: 640px) { + /* Matches the Connect Walrus Memory hero; 72px clips "Playground". */ + .dash-page .playground-dashboard .dashboard-header h2 { + font-size: 40px !important; + } -.dash-page .admin-copy-full-btn:hover { - border-color: #e8ff75; - background: #e8ff75; -} + /* On desktop the timeline line hangs from the first tab. The tabs wrap + here, so the timeline starts flush left with a narrower rail. */ + .dash-page .connect-wm-guide:has(.connect-wm-client)::before, + .dash-page .connect-wm-guide:not(:has(.connect-wm-client))::before { + display: none; + } -/* Loading and error states */ -.dash-page .admin-loading { - padding: 48px 20px; - color: #b8bbbe; - font-size: 18px; - line-height: 1.3; - text-align: center; -} + .dash-page .connect-wm-guide:has(.connect-wm-client) .connect-wm-client, + .dash-page .connect-wm-guide:has(.connect-wm-client) .connect-wm-timeline li, + .dash-page .connect-wm-guide:not(:has(.connect-wm-client)) .connect-wm-timeline li { + margin-left: 0; + } -.dash-page .admin-error { - padding: 16px; - border: 1px solid rgba(248, 113, 113, 0.28); - border-radius: 14px; - background: rgba(248, 113, 113, 0.1); - color: #ff8f8f; - font-size: 16px; - line-height: 1.4; -} + .dash-page .connect-wm-tabbar { + margin-bottom: 28px; + } -@media (max-width: 860px) { - .admin-dashboard-page .dashboard-header { - margin-bottom: var(--dashboard-mobile-major-gap); + .dash-page .connect-wm-client { + grid-template-columns: 48px minmax(0, 1fr); + gap: 16px; + margin-bottom: 32px; } - .admin-panels, - .admin-wallets-section { - gap: var(--dashboard-mobile-major-gap); + .dash-page .connect-wm-client::after { + left: 24px; + top: 48px; + bottom: -32px; } - .admin-key-entry-shell { - padding-top: 0; + .dash-page .connect-wm-client-badge { + width: 48px; + height: 48px; } - .dash-page .admin-sponsor-item, - .dash-page .admin-config-item { - align-items: flex-start; - flex-direction: column; - gap: 6px; + .dash-page .connect-wm-client-badge img, + .dash-page .connect-wm-client-badge svg { + width: 28px; + height: 28px; } - .dash-page .admin-sponsor-value, - .dash-page .admin-config-value { - max-width: 100%; - overflow-wrap: anywhere; - text-align: left; + .dash-page .connect-wm-client h3 { + font-size: 28px; } -} -@media (max-width: 640px) { - .admin-error-modal-overlay { - padding: 16px; + .dash-page .connect-wm-timeline { + gap: 40px; } - .dash-page .admin-error-modal { - max-height: 90vh; - border-radius: 20px; + .dash-page .connect-wm-timeline li { + grid-template-columns: 48px minmax(0, 1fr); + gap: 16px; } - .dash-page .admin-error-modal-header, - .dash-page .admin-error-modal-footer, - .admin-error-modal-content { - padding: 20px; + .dash-page .connect-wm-timeline li:not(:last-child)::before { + left: 24px; + bottom: -40px; } -} -.dash-page .dash-alert--info { - min-height: 0; - align-items: flex-start; - gap: 12px; - margin-bottom: 28px !important; - padding: 14px 18px; - border: 1px solid var(--dash-panel-border); - border-radius: var(--radius-md); - background: var(--dash-panel); - color: var(--dash-subtle); -} + .dash-page .connect-wm-timeline h3 { + font-size: 24px; + } -.dash-page .dash-alert--info .dash-alert-icon { - width: 20px; - height: 20px; - margin-top: 2px; - color: var(--dash-yellow); -} + /* Commands keep one per line and scroll sideways instead of breaking + mid-word; the copy button stays pinned at the top right. */ + .dash-page .connect-wm-code { + align-items: flex-start; + } -.dash-page .dash-alert--info p { - color: var(--dash-subtle); - font-size: 15px; - font-weight: 400; - line-height: 1.5; -} + .dash-page .connect-wm-code pre { + padding: 14px 8px 14px 14px; + overflow-x: auto; + white-space: pre; + overflow-wrap: normal; + font-size: 13px; + scrollbar-width: none; + } -.dash-page .dash-alert-link { - padding: 0; - border: 0; - background: none; - color: var(--dash-yellow); - font: inherit; - text-decoration: underline; - text-underline-offset: 2px; - cursor: pointer; + .dash-page .connect-wm-copy { + margin: 7px 6px 0 0; + } } -.dash-page .dash-alert-link:hover { - text-decoration-thickness: 2px; -} +@media (max-width: 480px) { + /* The client icons sit above the title instead of over it. */ + .dash-page .connect-wm-stack { + position: relative; + top: auto; + right: auto; + order: -1; + margin-bottom: 2px; + } -.dash-page .dashboard-key-current-badge { - white-space: nowrap; + .dash-page .connect-wm-stack::after { + display: none; + } + + .dash-page .connect-wm-mark { + width: 28px; + height: 28px; + } + + .dash-page .connect-wm-mark img, + .dash-page .connect-wm-mark svg { + width: 16px; + height: 16px; + } } -@media (max-width: 640px) { - .dash-page .dash-alert--info { - padding: 12px 14px; +@media (max-width: 420px) { + /* Sign out collapses to its icon so the address no longer runs into the logo. */ + .setup-classic-nav .lp-nav-cta, + .playground-nav .lp-nav-cta, + .dashboard-nav .lp-nav-cta { + width: 36px; + min-width: 36px; + padding: 0; + justify-content: center; + gap: 0; } - .dash-page .dash-alert--info p { - font-size: 14px; + .setup-classic-nav .nav-cta-label, + .playground-nav .nav-cta-label, + .dashboard-nav .nav-cta-label { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0 0 0 0); + white-space: nowrap; } } diff --git a/apps/app/src/pages/AdminDashboard.tsx b/apps/app/src/pages/AdminDashboard.tsx index e7914f273..31da751c6 100644 --- a/apps/app/src/pages/AdminDashboard.tsx +++ b/apps/app/src/pages/AdminDashboard.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react' import { Link } from 'react-router-dom' import { LogOut } from 'lucide-react' import { useQueryClient } from '@tanstack/react-query' +import { AdminActivityPanel } from '../components/AdminActivity' import { AdminKeyEntry } from '../components/AdminKeyEntry' import { AdminWalletBalances } from '../components/AdminWalletBalances' import { AdminUploadErrors } from '../components/AdminUploadErrors' @@ -16,6 +17,14 @@ export default function AdminDashboard() { const [isSubmitting, setIsSubmitting] = useState(false) const [isRestoring, setIsRestoring] = useState(true) const [banner, setBanner] = useState(undefined) + const [navSolid, setNavSolid] = useState(false) + + useEffect(() => { + const onScroll = () => setNavSolid(window.scrollY > 220) + onScroll() + window.addEventListener('scroll', onScroll, { passive: true }) + return () => window.removeEventListener('scroll', onScroll) + }, []) useEffect(() => { const stored = sessionStorage.getItem(ADMIN_KEY_STORAGE) @@ -60,6 +69,10 @@ export default function AdminDashboard() { // actually valid. Rather than leave three "Invalid API key" cards sitting // on screen waiting for someone to notice and click Logout, drop straight // back to the login form with an explicit reason. + const activityPreview = + import.meta.env.DEV && + new URLSearchParams(window.location.search).get('preview') === 'activity' + const handleInvalidKey = () => { sessionStorage.removeItem(ADMIN_KEY_STORAGE) queryClient.removeQueries({ queryKey: ['admin'] }) @@ -69,10 +82,10 @@ export default function AdminDashboard() { return (
-